前回はファイル形式について記述したので、今回はファイル展開方法について。
1.WAFファイルと同じ階層に新規フォルダを作成する。フォルダ名はWAFファイル名に「 waff folder」を追加したもの。
2.WAFファイルを読み込みながら、「url 」と「data」を取り出して別ファイルに書き出していく。この時のファイル名およびパスは、urlから取得してwaff folderからの相対パスにします。
3.トップページへのエイリアス・ファイルを作成する。
4.すべてのファイルの作成日をWAFファイルの作成日に変更する。
再現の難しいサイト
リンクがCGIで構築されているサイト。CGIは追跡していない。よって、ファイルがあってもリンク切れと認識されている可能があります。
例)http://www.hoge.co.jp/cgi-bin/common/hage.cgi?http://www.hoge.co.jp/news/200204/03/fuge.html
巨大なエイリアス・ファイルの問題
どうやら、OSX 10.7 Lion以降はエイリアスのファイルサイズが大きく、自分の環境では1.5MBまでになってます。WAFファイルが数十KBなのに、waff folder内は1MB越えなんてアホな状況です。気になる方は、エイリアスを削除してください。
使い方
下のスクリプトをドロップレットで保存して下さい。
それにWAFファイル(複数可)をドロップする。
waff folderの直下にあるエイリアス・ファイルを開けば、SafariなどでWebページが開きます。
waffspliter.scpt
(*
waffを読み込み分解するスクリプト
入力ファイル(waff形式)と同じフォルダ階層に、拡張子なしの入力ファイル名と同じ名称のフォルダを
作成し、入力ファイル内のアーカイブを分解して書き出す。
*)
on open theList
toControl(theList)
end open
on run
choose file with prompt "Webアーカイブ・ファイルを選んでください" without invisibles
toControl({result})
end run
on adding folder items to theFolder after receiving theList
toControl(theList)
end adding folder items to
on toControl(theList)
repeat with curItem in theList
set theFileInfo to info for curItem
if (folder of theFileInfo) is true then
--folder
else
try
--item
wafsplit(curItem) of me
on error
display alert "異常発生" message POSIX path of curItem as warning
end try
end if
end repeat
--処理終了の通知
if (count of theList) is 1 then
display notification name of (info for first item of theList) with title "End of work" sound name "beep"
else
set msg to (count of theList) & " Files" as string
display notification msg with title "End of work" sound name "beep"
end if
end toControl
on wafsplit(theFile)
--作業フォルダ名称の初期化
set theWorkFolder to ""
--最初のURL(ファイル)の初期化
set theFirstFile to ""
set typeList to {}
--WAFFの分解ループ
set fp1 to open for access theFile
try
set fileSize to get eof fp1
set readSize to 0
--ファイルサイズの確認
if fileSize is less than 12 then
display alert "サイズ不正です" message POSIX path of theFile
close access fp1
return
end if
--ヘッダーのデータタイプを読む
set dataType to read fp1 for 4 as text
set readSize to readSize + 4
--ファイル形式の確認
if dataType is not ".WAF" then
display alert "処理対象外ファイルです" message POSIX path of theFile
close access fp1
return
end if
--ヘッダーのデータサイズを読む
set dataSize to read fp1 for 4 as integer
set readSize to readSize + 4
--ヘッダーのデータ内容を読む(dataSizeは8バイト減算)
set dataContents to read fp1 for dataSize - 8 as data
set readSize to readSize + dataSize - 8
log "debug dataType=" & dataType & " readSize=" & readSize & " fileSize=" & fileSize
--作業フォルダの作成
set theWorkFolder to makeWorkFolder(theFile) of me
set theUrl to ""
repeat while readSize is less than fileSize
--データタイプを読む
set dataType to read fp1 for 4 as text
set readSize to readSize + 4
--データサイズを読む
set dataSize to read fp1 for 4 as integer
set readSize to readSize + 4
if dataType is "mime" then
--データ内容を読む
set dataContents to read fp1 for dataSize as text
set readSize to readSize + dataSize
else if dataType is "url " then
--データ内容を読む
set dataContents to read fp1 for dataSize - 1 as text -- null除外
set readSize to readSize + dataSize
set theUrl to dataContents
set dataContents to read fp1 for 1 as text -- null分進める
else if dataType is "ntry" then
--データ内容を読む(dataNtryへ格納)
set dataContents to read fp1 for dataSize - 8 as data
set dataNtry1 to read fp1 for 4 as integer
set dataNtry2 to read fp1 for 4 as integer
set dataNtry to dataNtry1 - dataNtry2 - 128
set readSize to readSize + dataSize
else if dataType is "data" then
--データ内容を読む(dataNtryのサイズより)
set dataSize to dataNtry
set dataContents to read fp1 for dataSize as data
set readSize to readSize + dataSize
--ファイルを保存
log "debug theUrl=" & theUrl & " readSize=" & readSize
if theUrl is not "" then
set theNewFile to saveFile(theWorkFolder, theUrl, dataContents)
--最初のURLを記憶
if theFirstFile is "" then
set theFirstFile to theNewFile
end if
set theUrl to ""
else
--データ構造がおかしい場合しか、ありえない。
display alert "URLが見当たらない" message "POS=" & readSize as warning
close access fp1
return
end if
else if dataType is "post" then
--データ内容を読む(XXXXを含む)
set dataContents to read fp1 for dataSize as data
set readSize to readSize + dataSize
set dataSize to 128
set dataContents to read fp1 for dataSize as text
set readSize to readSize + dataSize
else
set end of typeList to dataType
--データ内容を読む
set dataContents to read fp1 for dataSize as data
set readSize to readSize + dataSize
end if
log "debug unknown dataType=" & typeList as string
log "debug readSize=" & readSize & " fileSize=" & fileSize
end repeat
on error errMsg number errNum
close access fp1
display alert errMsg & "code=" & errNum as warning
-- if errNum is -39 then
-- log "debug readSize=" & readSize & " fileSize=" & fileSize
-- end if
error errMsg number errNum
end try
close access fp1
--閲覧開始用のエイリアス作成
if theFirstFile is not "" then
saveEntryShortcut(theWorkFolder, theFirstFile)
end if
--ファイル日付の修正(全体)
setAllFileDate(theWorkFolder, theFile)
end wafsplit
on saveFile(theWorkFolder, theUrl, theData)
--URLをフルパスのファイル名に変換
set theFilename to filenameFromUrl(theUrl) of me
--作業フォルダの下にフルパスのフォルダを作成
do shell script "cd " & quoted form of POSIX path of theWorkFolder & " &&" & "mkdir -p " & "./`dirname " & quoted form of theFilename & "`"
--ファイル名に作業フォルダのパスを追加
set theNewFile to theWorkFolder & strings 2 thru end of replaceText(theFilename, "/", ":") as string
--ファイルが既にある場合、リターンする
tell application "Finder"
set theExists to exists file theNewFile
end tell
if theExists is yes then
return
end if
--ファイルの書き込み
set fp to open for access theNewFile write permission yes
try
write theData to fp as data
on error errMsg number errNum
close access fp
display alert errMsg & "code=" & errNum as warning
error errMsg number errNum
end try
close access fp
return alias theNewFile
end saveFile
on filenameFromUrl(theUrl)
set pos to (offset of "://" in theUrl) + (length of "://")
set parmPos to (offset of "?" in theUrl)
set theFilename to text pos thru (parmPos - 1) of theUrl
--set theFilename to replaceText(theFilename, "/", "_") of me
set theFilename to "/" & theFilename
--ディレクトリの場合は、index.htmlを想定する
if theFilename ends with "/" then
set theFilename to theFilename & "index.html"
end if
return theFilename
end filenameFromUrl
on makeWorkFolder(theFile)
--拡張子の取り出し
set fileInfo to info for theFile
if name extension of fileInfo is not missing value then
set theExtension to "." & name extension of fileInfo
else
set theExtension to ""
end if
--theFileによるフォルダ名作成
set theBaseFolder to do shell script "basename " & quoted form of POSIX path of theFile & " " & quoted form of theExtension
if theBaseFolder is "" then
display alert "フォルダ名の生成失敗" message POSIX path of theFile as warning
return ""
end if
set theBaseFolder to theBaseFolder & " waff folder"
tell application "Finder"
set theNewFolder to make new folder at alias ((theFile as string) & "::") with properties {name:theBaseFolder}
set theNewFolder to theNewFolder as string -- Finderのfile形式なのでstringに変換
end tell
--作成日付の修正
setFileDate(theNewFolder as alias, theFile as alias)
return alias theNewFolder
end makeWorkFolder
on saveEntryShortcut(theWorkFolder, theEntryFile)
set fileInfo to info for theEntryFile
--theEntryFile に拡張子がなくTEXTファイルの時は、.htmlを追加。
if name extension of fileInfo is missing value then
tell application "Finder"
set name extension of file theEntryFile to "html"
end tell
end if
tell application "Finder"
set theNewFile to make new alias at folder theWorkFolder to theEntryFile with properties {name:name of fileInfo}
set theNewFile to theNewFile as string -- Finderのfile形式なのでstringに変換
end tell
return alias theNewFile
end saveEntryShortcut
(*ファイル日付の全体設定*)
on setAllFileDate(theFolder, theSourceFile)
set theCommand1 to "x=`/Developer/Tools/GetFileInfo -d " & quoted form of POSIX path of theSourceFile & "`"
set theCommand2 to "cd " & quoted form of POSIX path of theFolder
set theCommand3 to "find . -print0 | xargs -0 /Developer/Tools/SetFile -d \"$x\""
set theCommand to theCommand1 & " && " & theCommand2 & " && " & theCommand3
do shell script theCommand
end setAllFileDate
--定番関数
(*ファイル日付の設定*)
on setFileDate(theFile, theSourceFile)
set theCommand to "x=`/Developer/Tools/GetFileInfo -d " & quoted form of POSIX path of theSourceFile & "` && " & "/Developer/Tools/SetFile -d \"$x\" " & quoted form of POSIX path of theFile
do shell script theCommand
end setFileDate
(*文字列の置換*)
on replaceText(theText, serchStr, replaceStr)
set tmp to AppleScript's text item delimiters
set AppleScript's text item delimiters to serchStr
set theList to every text item of theText
set AppleScript's text item delimiters to replaceStr
set theText to theList as string
set AppleScript's text item delimiters to tmp
return theText
end replaceText
実行結果
デバッグコードも入ってるけど、気にしない。
動作環境
OSX 10.9.2以降
要 Xcode(/Developer/Tools/)
実行環境
Finder 10.9.2/Apple/iMac10,1/OSX 10.9.2