2008年7月5日土曜日

@wikiのデータバックアップをperlで自動化してみる

まず、ブラウザから保存までの過程を行い、パケットをキャプチャします。
今回、対象とするサイトはこちらです。キャプチャはWiresharkなどでも良いですが、今回はTCPのフローまで見る必要はありません。HTTPのリクエストヘッダさえ分かれば大丈夫なので、Live HTTP Headersなどで見たほうが便利です。(このソフトを使えばHTTPリクエストをGUI上で自由に変更できます。どのヘッダが必要か不要かも分かるので便利です)で、キャプチャしたものが以下のものです↓
Content-Length以下にはwikiidとpassというパスワードを送っています。submitのURLエンコードは「ダウンロード」という文字列を表しています。
ちなみにwikiidの項とpassの項とCookieは適当です。



POST /_mng/backup.php HTTP/1.1
Host: www34.atwiki.jp
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008052906 Firefox/3.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://www34.atwiki.jp/_mng/backup2.php
Cookie: PHPSESSID=5684723debae48752efea5555565acdd
Content-Type: application/x-www-form-urlencoded
Content-Length: 93

wikiid=***********&pass=*******&submit=%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89




次にLive HTTP Headersのリプレイ機能を使って必要なヘッダが何かを判断します。まずCookieが必須かどうかを調べる必要があります。なぜならCookieが必要だった場合はCookie取得の処理が追加されるからです。いらなそうなヘッダを削除→リプレイで目的の結果になるかを確認 を繰り返してください。で、調べた結果、不要だということが分かりました。つまりPerlスクリプトではCookieヘッダは発行しません。ちなみにこの鯖はContent-Typeを指定しないとトップに戻されるようです。


-------------- wiki_back.pl ----------------------------------

#!/usr/bin/perl
use Net::HTTP;

### Initial Setting ###########################

$server ="www34.atwiki.jp";

###############################################


$header{'Host'} = "$server";
$header{'User-Agent'} = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008052906 Firefox/3.0';
$header{'Accept'} = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
$header{'Accept-Language'} = 'ja,en-us;q=0.7,en;q=0.3';
$header{'Accept-Encoding'} = 'gzip,deflate';
$header{'Referer'} = 'http://www34.atwiki.jp/_mng/backup2.php';
$header{'Content-Type'} = 'application/x-www-form-urlencoded';
$content = 'wikiid=***********&pass=*******&submit=%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89';

$s = Net::HTTP->new(Host => "$server") || die $@;
$s->max_line_length(0);
$s->keep_alive(300);

$s->write_request( POST => '/_mng/backup.php' , %header , $content );


($code, $mess, %h) = $s->read_response_headers;
unless($code eq "200"){
die "erorr!!";
}

open (FH,">back.zip") or die $!;
binmode FH;

while (1) {
my $buf;
my $n = $s->read_entity_body($buf, 1024);
die "read failed: $!" unless defined $n;
last unless $n;
print FH $buf;
}

close FH;


print "\n$code $mess\n";
foreach $key(keys %h){

print $key," ";
print $h{$key},"\n";

}


-------------- wiki_back.pl ----------------------------------




※注意
Windows環境下ではファイルをopenした後に必ずファイルをバイナリモードにして下さい。
バイナリモードの指定は
binmode FH;
と引数にファイルハンドルを指定します。これを行わないと0D(CR)の後に0A(LF)が追加されてしまいます。
UNIX環境下ではこの指定は不要です。



ちなみに鯖からのレスポンスヘッダ内でContent-dispositionというヘッダがあります。このスクリプト内ではback.zipという名前でファイルを作成していますが、普通ブラウザではこの項を見てファイル名を決定します。↓はhoge.zipの例
Content-disposition attachment; filename=hoge.zip

0 件のコメント: