Last Update: Jan.13,2006

C Source Library

「LSI C-86 Ver.3.30c 試食版」を使用しています。

■ Macintosh から送信された添付ファイルを識別

/*
 *  inspect.c : Macintosh から送信された添付ファイルを識別
 *
 *  Copyright (c) 2001 AOK. 
 *
 *      2001.1.24 - 初版
 *
 *      使い方: INSPECT 入力ファイル名
 *
 * Macintosh を使っている友人から送られてきた添付ファイルが開けない
 * 経験はありませんか。Macintosh は Windows と違い、ファイルに拡張
 * 子をつける必要がありません。そのため、そのデータがどのような形式
 * であるのかを拡張子のみで判断している Windows では解釈できないの
 * です。たとえば、OutLook Express などのメールソフトで受信した時、
 * 次のようなファイルが添付されていることはありませんか?
 *
 *      %xxxxxxxx (nnn バイト) 
 *      xxxxxxxx (mmm KB) 
 *
 * これは、AppleDouble と呼ばれる形式で、2つでひとつのファイルを表
 * しています。Windows で必要なのは下のファイルのみですが、そのファ
 * イルに関するさまざまな情報が上のファイルに入っています。
 * この頭に % のついたファイルを INSPECT.EXE にドラッグ&ドロップす
 * るとファイルの様々な情報とともに、Macintosh 特有のファイルタイプ
 * とクリエーターと呼ばれる識別子を読み取り、このデータを作成したア
 * プリケーションとデータの形式、および、拡張子を推測します。
 * 拡張子がわかれば、下のファイルにその拡張子を付けて保存して、該当
 * するアプリケーションがインストールされている環境であれば開くこと
 * が出来るようになります(該当するアプリケーションがない場合は開け
 * ません)。また、拡張子が分からない場合でも、アプリケーションから
 * 直接開くことが出来ます。
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "applefil.h"   /* original:applefile.h  see:RFC1740 */

/* BIG-ENDIAN -> LITTLE-ENDIAN */
#define B2L32(x) (((x)>>24)|(((x)>>8)&0xFF00)|(((x)<<8)&0xFF0000)|((x)<<24))
#define B2L16(x) (((x)>>8)|((x)<<8))

#define LINE() puts("-------------------------------------------------------")

typedef struct {
    char* text;
    char* comment;
} DATA;

/* ファイル タイプのデータベース */
const DATA d_type[] = {
    { "..CT","サイテックスCT画像 (.sct)" },
    { "3DMF","QuickDraw 3D Meta File" },
    { "8BPS","Photoshop 画像 (.psd)" },
    { "????","タイプ不明" },
    { "AB65","Adobe Page Maker 6.5J (.p65)" },
    { "AD3D","Adobe Dimension書類" },
    { "AD3F","Adobe Dimensions (.dim)" },
    { "AGD2","FREEHAND 7.0J (.fh7)" },
    { "AGD3","FREEHAND 8.0J (.fh8)" },
    { "AIFC","AIFF圧縮サウンド" },
    { "AIFF","AIFFサウンド (.aiff)" },
    { "ALB2","Aldus Page Maker 2.0J" },
    { "ALB3","Aldus Page Maker 3.0J (.pm3)" },
    { "ALB4","Aldus Page Maker 4.0/4.5J (.pm4)" },
    { "ALB5","Aldus Page Maker 5.0J (.pm5)" },
    { "ALB6","Adobe Page Maker 6.0J (.pm6)" },
    { "ALTV","Quick View (.qv)" },
    { "APPL","アプリケーション" },
    { "ArCv","AutoSqueeze" },
    { "BINA","MS-DOSバイナリ形式" },
    { "BMPp","BMP形式 (.bmp)" },
    { "CDBJ","ClarisWorks J 4.0 データベース" },
    { "CGRJ","ClarisWorks J 4.0 ドロー" },
    { "COMP","ShrinkToFit" },
    { "CPTJ","ClarisWorks J 4.0 ペイント" },
    { "CSSJ","ClarisWorks J 4.0 表計算" },
    { "CWCM","ClarisWorks (Communication) (.cwk)" },
    { "CWDB","ClarisWorks (Database) (.cwk)" },
    { "CWGR","ClarisWorks (Drawing & Printing) (.cwk)" },
    { "CWPJ","ClarisWorks J 4.0 ワープロ" },
    { "CWSS","ClarisWorks (Spreadsheet) (.cwk)" },
    { "CWWP","ClarisWorks (Word Processing) (.cwk)" },
    { "DD01","DiskDoubler" },
    { "DDAR","DiskDoubler" },
    { "DDF.","DiskDoubler" },
    { "DDf.","DiskDoubler" },
    { "DEXE","Windowsアプリケーション(実行ファイル)" },
    { "EGD7","EGWord 8.0" },
    { "EPSF","EPSF画像 (.eps)" },
    { "EggP","Adobe After Effects (.aep)" },
    { "FMP3","FileMakerPro 3J" },
    { "Film","Film Strip形式" },
    { "GIFf","GIF画像 (.gif)" },
    { "Gzip","GNU Gzip 圧縮ファイル (.gz)" },
    { "HELP","Helpファイル" },
    { "ILBM","IFF形式 (.iff)" },
    { "JPEG","JPEG画像 (.jpg .jpeg)" },
    { "LARC","LHarc圧縮形式" },
    { "LHA ","LHa圧縮形式" },
    { "MPEG","MPEGファイル (.mpg .mpeg)" },
    { "MPG ","MPEGファイル" },
    { "MV93","MacroMedia Director 4.0ムービー" },
    { "MV95","MacroMedia Director 5.0ムービー" },
    { "MV97","Macromedia Director 6.0J (.dir)" },
    { "Midi","MIDI形式 (.mid)" },
    { "MooV","QuickTimeムービー (.mov .qt .qtvr)" },
    { "NSPL","Netscapeプラグイン" },
    { "PACT","CompactPro圧縮形式" },
    { "PCDI","Photo CD" },
    { "PDF ","PDF形式 (.pdf)" },
    { "PICS","PICS形式(連番PICT)" },
    { "PICT","PICT画像 (.pct .pict)" },
    { "PIT ","PackIt" },
    { "PNTG","Mac Paint画像" },
    { "PPSS", "PowerPoint 98 スライドショー" },
    { "PREF","プレファレンス" },
    { "PROJ","Adobe Premiere (.ppj)" },
    { "PRS2","Persuasion 3.0 2.1プレゼンテーション" },
    { "PRS3","Persuasion 3.0 プレゼンテーション" },
    { "PUBF","Aldus Page Maker 2.0 (.pub)" },
    { "PXR ","Pixar画像" },
    { "Pack","Diamond" },
    { "RIFF","Metacreation Painter 5.0J (.rif)" },
    { "SAnF","Scenary Animator書類" },
    { "SCRN","スタートアップスクリーン" },
    { "SIT!","StuffIt 1.5.1圧縮形式 (.sit)" },
    { "SIT2","StuffIt Deluxe圧縮形式" },
    { "SIT5","StuffIt アーカイブ (.sit)" },
    { "SITD","StuffIt Deluxe (.sit)" },
    { "SLD3","Microsoft PowerPoint 4.0 (.ppt)" },
    { "SLD8","Microsoft PowerPoint 98 (.ppt)" },
    { "SMED","SMI EDICOLOR 2.2J (.ec2)" },
    { "SPA ","Macromedia Flash 2J (.fla)" },
    { "SPn3","SuperPaint 3.5J" },
    { "STrk","サウンド (.mod)" },
    { "Smal","Compress It" },
    { "TARF","圧縮ファイル (.tar)" },
    { "TEXT","テキスト形式" },
    { "TIFF","TIFF画像  (.tif .tiff)" },
    { "TPIC","TGA画像 (.tga)" },
    { "TPIC","PIC形式 (X68000とは異なる)" },
    { "ULAW","オーディオ形式 (.au .snd .ulw)" },
    { "VWMD","MacroMedia Director 3.0ムービー" },
    { "W8BN","Microsoft Word 98 (.doc)" },
    { "WAVE","WAVEサウンド (.wav)" },
    { "WDBN","Microsoft Word (.doc)" },
    { "XDOC","Quark XPress 文書" },
    { "XLS ","Microsoft Excel (.xls)" },
    { "XLS3","Microsoft Excel (.xls)" },
    { "XLS4","Microsoft Excel ワークシート" },
    { "XLS5","Microsoft Excel ブック" },
    { "XLS8","Microsoft Excel 98 ワークシート" },
    { "XPRF","Metacreation Expressions (.xpr)" },
    { "XPRa","QuarkXPress 3.1J/3.3J (.qxd)" },
    { "WSit","ホームページPro3 サイト定義書類" },
    { "ZIP ","Zip圧縮ファイル (.zip)" },
    { "ZIVM","MacCompress(M) (.z)" },
    { "ZIVU","MacCompress(U)" },
    { "aCf2","Font Grapher書類" },
    { "cdev","コントロールパネル書類" },
    { "dDoc","MacDraw形式" },
    { "dImg","ディスクイメージ" },
    { "drw2","Canvas 3.5" },
    { "drw5","Canvas 5.0.2J" },
    { "drwt","Canvas 5.0.2J テンプレート" },
    { "jB1 ","Sound Edit 16 サウンド" },
    { "mArc","ArcMac" },
    { "pref","プレファレンス" },
    { "pzr2","Metacreation Poser 20J (.pzr)" },
    { "rsrc","リソースデータ" },
    { "ttro","TeachText Read Only形式" },
    { "zooM","Zoom" },
    { "","" }
};

/* クリエータのデータベース */
const DATA d_crtr[] = {
    { "8BIM","Adobe Photoshop 3.0J" },
    { "<SL>","Silverlining 5.6" },
    { "AD3D","Adobe Dimensions 2.0" },
    { "AFTB","Afterburner" },
    { "AI5J","Adobe Illustrator 5.5" },
    { "AK65","Adobe Page Maker 6.5J" },
    { "ALD2","Aldus Page Maker 2.0" },
    { "ALD3","Aldus Page Maker 3.0J" },
    { "ALD4","Aldus Page Maker 4.5" },
    { "ALK4","Aldus Page Maker 4.0/4.5J" },
    { "ALK5","Aldus Page Maker 5.0" },
    { "ALK6","Adobe Page Maker 6.0" },
    { "ALTV","Quick View" },
    { "ART3","Adobe Illustrator 3.0" },
    { "ART5","Adobe Illustrator 5.0/7.0" },
    { "ARTY","Adobe Illustrator 1.1" },
    { "ARTZ","Adobe Illustrator 88" },
    { "ASFL","Font Downloader" },
    { "BKCT","Magic Works Ver 2.0" },
    { "BOBO","ClarisWorks" },
    { "Blwd","ホームページPro3" },
    { "BnHq","BinHex 5.0" },
    { "Bry2","KPT Bryce 2" },
    { "CARO","Adobe Acrobat Reader 3.0" },
    { "CPCT","Compact Pro J-1.50" },
    { "CSOm","Eudora 1.3.8/Pro" },
    { "CWIE","Code Warrior IDE" },
    { "CWKJ","ClarisWorks J 4.0" },
    { "DAD5","Canvas 5.0.2J" },
    { "DDAP","DiskDoubler" },
    { "DSEA","DiskDoubler" },
    { "DSTL","Acrobat Distiller 3.0J" },
    { "EGW7","EGWord 8.0" },
    { "EWd3","KPT Bryce" },
    { "EXPr","Metacreation Expressions" },
    { "EXTR","Compactor" },
    { "Edt7","Edit 7" },
    { "FH70","FREEHAND 7.0J" },
    { "FH80","FREEHAND 8.0J" },
    { "FMJ3","File Maker Pro" },
    { "FSX3","Metacreation Painter 5.0J" },
    { "FTCh","Fetch" },
    { "FXTC","Adobe After Effects" },
    { "GJBU","MacBinary 1.0" },
    { "GKON","Graphic Converter" },
    { "GSBM","Drive 7" },
    { "Gzip","" },
    { "JEDT","Jedit" },
    { "JVWR","JPEGView" },
    { "Jdw ","Compress It" },
    { "LARC","MacLHa" },
    { "LVIn","LogoVista Internet" },
    { "LW3D","LightWave 3D Ver 5.0" },
    { "LWMD","LightWave 3D Ver 5.0" },
    { "LZIV","MacCompress" },
    { "MD93","MacroMedia Director 4" },
    { "MD95","MacroMedia Director 5" },
    { "MD97","Macromedia Director 6.0J" },
    { "MFL2","Macromedia Flash 2" },
    { "MGIC","Color Magicial III" },
    { "MMDR","MacroMedia Director 3" },
    { "MOSS","Netscape Navigator" },
    { "MRIP","TScript 4.0" },
    { "MSIE","Internet Explorer 3.0" },
    { "MSWD","Microsoft Word" },
    { "Mooz","Zoom" },
    { "PIT ","PackIt" },
    { "PLP2","Persuasion 3.0" },
    { "PLP3","Persuasion 3.0" },
    { "PNnu","Norton Utility" },
    { "PPT3","Microsoft PowerPoint" },
    { "Pack","Diamond" },
    { "Pnut","茄子R" },
    { "PrMr","Adobe Premiere" },
    { "RSED","Res Edit" },
    { "Roku","六角大王 Ver 5.5" },
    { "SAnP","Scenary Animator 1.2" },
    { "SCS!","SCSI Probe" },
    { "SEDA","SMI EDICOLOR 2.2J" },
    { "SIT!","StuffIt" },
    { "SITx","StuffIt Expander" },
    { "SNdm","" },
    { "SPNT","SuperPaint 3.5J" },
    { "STF ","ShrinkToFit" },
    { "STrk","" },
    { "StMl","Adobe PageMill" },
    { "TAR!","" },
    { "TVOD","Movie Player" },
    { "TrAS","AutoSqueeze" },
    { "UMcp","UMCP" },
    { "VIPR","Video Monitor Pro" },
    { "VisP","Vistapro" },
    { "WMLR","Will Mail" },
    { "Wrap","ShrinkWrap" },
    { "XCEL","Microsoft Excel" },
    { "XDOC","QuarkXPress 3.1J/3.3J" },
    { "XPRa","Quark Xpress 3.1" },
    { "ZBAS","Future BASIC 1.0x/II" },
    { "ZIP ","" },
    { "aCa2","Font Grapher 3.3" },
    { "arc*","ArcMac" },
    { "arc@","ArcMac" },
    { "aust","StuffIt" },
    { "cNif","ComNifty" },
    { "dPro","MacDraw Pro" },
    { "gfBr","GIF Builder" },
    { "jB・x","Sound Edit 16" },
    { "mMPG","MPEGファイル" },
    { "mPAK","Mpack 1.5J" },
    { "ttxt","SimpleText" },
    { "viOj","Metacreation Poser 2" },
    { "xxxX","Shade III Light 1.2.5" },
    { "zooM","Zoom" },
    { "","" }
};

ASHeader header;        /* AppleSingle Header */
ASEntry *pentry = NULL;

const char *data_search(int flag, const char* s)
{
    int i;
    if (flag == 0)
    {
        for (i=0; i<sizeof(d_type)/sizeof(d_type[0]); i++)
        {
            if (strcmp(s, d_type[i].text) == 0)
                return d_type[i].comment;               
        }
        return d_type[i].comment;
    }
    else
    {
        for (i=0; i<sizeof(d_crtr)/sizeof(d_crtr[0]); i++)
        {
            if (strcmp(s, d_crtr[i].text) == 0)
                return d_crtr[i].comment;               
        }
        return d_crtr[i].comment;
    }
    return NULL;
}

int read_header(FILE *fp)
{
    if (fread(&header.magicNum, sizeof(uint32), 1, fp) != 1)
        return 0;
    if (fread(&header.versionNum, sizeof(uint32), 1, fp) != 1)
        return 0;
    if (fread(&header.filler, sizeof(uchar8), 16, fp) != 16)
        return 0;
    if (fread(&header.numEntries, sizeof(uint16), 1, fp) != 1)
        return 0;

    header.magicNum   = B2L32(header.magicNum);
    header.versionNum = B2L32(header.versionNum);
    header.numEntries = B2L16(header.numEntries);
    
    if ((header.magicNum != 0x00051600) && (header.magicNum != 0x00051607))
    {
        printf("入力ファイルの形式が違います.\n");
        return 0;
    }
        
    printf("ファイル形式:0x%08lX\n", header.magicNum);
    printf("バージョン :0x%08lX\n", header.versionNum);
    printf("エントリー数:%u\n", header.numEntries);
    
    return 1;
}

int read_entries(FILE *fp)
{
    int i;
    pentry = (ASEntry *)malloc(sizeof(ASEntry) * header.numEntries);
    if (pentry == NULL)
        return 0;
    if (fread(pentry, sizeof(ASEntry), header.numEntries, fp) != header.numEntries)
    {
        free(pentry);
        pentry = NULL;
        return 0;
    }
    
    for (i = 0; i < header.numEntries; i++)
    {
        (pentry+i)->entryID     = B2L32((pentry+i)->entryID);
        (pentry+i)->entryOffset = B2L32((pentry+i)->entryOffset);
        (pentry+i)->entryLength = B2L32((pentry+i)->entryLength);
        
        printf(" [%u] ID:%2lu   Offset:0x%08lX   Length:%6lu byte\n",
            i+1, (pentry+i)->entryID, (pentry+i)->entryOffset, (pentry+i)->entryLength);
    }
    
    return 1;
}

void read_data(FILE *fp)
{
    int i;
    char *buf = NULL;
    char type[5], crtr[5];
    for (i = 0; i < header.numEntries; i++)
    {
        fseek(fp, (pentry+i)->entryOffset, SEEK_SET);
        switch ((pentry+i)->entryID)
        {
        case AS_REALNAME:
            buf = (char *)malloc((pentry+i)->entryLength + 1);
            fread(buf, (pentry+i)->entryLength, 1, fp);
            *(buf+(pentry+i)->entryLength) = '\0'; 
            printf("ファイル名 :%s\n", buf);
            free(buf);
            break;
        case AS_FINDERINFO:
            fread(type, sizeof(char), 4, fp);
            fread(crtr, sizeof(char), 4, fp);
            type[4] = crtr[4] = '\0';
            printf("タイプ   :%s -> %s\n", type, data_search(0, type));
            printf("クリエーター:%s -> %s\n", crtr, data_search(1, crtr));
            break;
        default:
            break;
        }
    }
}

/* メインルーチン */
int main(int argc, char **argv)
{
    FILE *fp = NULL;
    char *p  = NULL;
    
    puts("AppleSingle Header Inspector Copyright (c) 2001 AOK");
    if (argc < 2)
    {
        puts("Syntax is: INSPECT file");
        return 0;
    }
    
    if ((fp = fopen(*++argv, "rb")) == NULL)
        return 0;
    
    LINE();
    
    p = strrchr(*argv, '\\');
    if (p != NULL)
        printf("入力ファイル:%s\n", ++p);

    LINE();
    if (read_header(fp))
    {
        LINE();
        if (read_entries(fp))
        {
            LINE();
            read_data(fp);
            free(pentry);
            LINE();
        }
    }
    
    fclose(fp); 
    
    return 0;
}