January 28, 2005

WinInetの接続周りの見直し

WinInetのAPIを調べたら、キャッシュが有効になっていた。
キャッシュが効くと困るので、修正。
あと、接続が常に直接接続となっていたので、レジストリの設定を参照するようにした。

投稿者 Takenori : 03:10 AM | コメント (0) | トラックバック

January 27, 2005

公開開始

そこそこまともに動くようになったと思うので、公開を開始した。

公開前に変更&追加したこと
一部エラーメッセージの変更。
アクセス時にエラーが発生した場合、エラーログを出力するようにした。
設定ウィンドウの表示位置を画面中央になるようにした。

投稿者 Takenori : 10:39 PM | コメント (0) | トラックバック

January 26, 2005

新着日記もチェック

新着日記もチェックにも対応した。

インストール後、初回起動時は常に新着日記があると表示。
Alert Windowで「mixiを開く」もしくは「Close」がクリックされたら、見たとみなす。
仕様はそんなところ。

投稿者 Takenori : 10:53 PM | コメント (0) | トラックバック

January 25, 2005

機能追加&変更

変更項目
接続時のエラーメッセージを詳細に表示するように変更。
Alertウィンドウが自動的に消えないように変更。
ログイン時のレスポンスのリダイレクトURLを認識し、そのURLを読み込むように変更。
その時、boost::regexの正規表現でまたハマる。
<と>は別にエスケープしなくても良いようだ。と言うか、しないようにしないとヒットしない?
不必要なエスケープを減らしたらヒットするようになった。
チェックサイクルの時間をインターバルに変更。(以前は定期的に実行)

追加機能
チェックサイクルを1分、2分、3分、5分、10分、15分、20分、30分、1時間の中から選択できるように機能追加。

ソース上の変更
設定ウィンドウの各コントロールの設定を、前は呼び出し元が行っていたが、設定ウィンドウが表示される時に、自分で取得、設定を行うように変更。また、同時に設定ウィンドウのプロパティもなくす。

投稿者 Takenori : 01:59 AM | コメント (0) | トラックバック

January 21, 2005

とりあえず完成

実装した機能は以下の通り
新着メッセージ、新着コメントを定期的に確認。
確認サイクルは固定。
アラートウィンドウは一定期間で非表示に。
非表示になるまで時間は固定。
ログイン用メールアドレス、パスワードの設定。
タスクトレイへのアイコンの登録。
イマイチなアイコン。

要求システムは次のとおりのはず。
Internet Explorer 5.5 以降
Windows 2000 もしくはWindows Me 以降
とりあえず、XP と 2000 では動作確認している。

その他制限事項
IEを普段使っている場合、自動ログインが切れてしまう。IEは使わずにFirefox使ったほうが良いと思われ。


他に対応したいこと
インストーラー
マルチユーザー
新着日記、新着コミュニティー書き込み、新着レビューの確認。
確認サイクルの指定。
アラートウィンドウを自動的に非表示するかどうか。また、その時間。
自動的に非表示された場合、タスクバーのアイコンで未チェックかどうか明示。
アイコンがイマイチなので、何とかしたい。
確認の一時停止。(ユーザーの操作がない場合など)
メッセージやコメントへのダイレクトリンクをアラートウィンドウに表示する。
それぐらいだったかな。

投稿者 Takenori : 12:00 AM | コメント (0) | トラックバック

January 20, 2005

C++でWinINet

perlの場合、かなりお気楽に使えるが、C/C++で使うとなると、少し事情が違った。
まず、perlの場合読み込みバッファは自動的に確保してくれるので、気にしなくても良かったが、Cの場合は明示的に確保しないといけない。
で、HttpQueryInfo( hHttpRequest, HTTP_QUERY_CONTENT_LENGTH, BufSizeText, &BufSizeTextSize, NULL); とコールするが、サイズが返ってこない。
仕方ないので、512KBぐらい確保して読み込み処理をするが、1回のInternetReadFile コールではすべてのデータを取得しきれない時があるようだ。
そこで、次のようにして読み込むこととした。

read_buff = new char[htmlSize];
memset( read_buff, 0, htmlSize );
DWORD curPos = 0, ReadSizeAll = 0;
int bootstrap = 0;
while(1)
{
    BOOL ret;
    ret = InternetReadFile( hHttpRequest, &read_buff[curPos], (htmlSize-ReadSizeAll), &ReadSize);
    if(ret && (ReadSize == 0)) break;
    curPos += ReadSize;
    ReadSizeAll += ReadSize;
    bootstrap++;
    if( bootstrap > TRY_MAX) break;
}

curPos と ReadSizeAll は同じだから両方は必要ないかも。
他はperlの時とだいたい同じでいけた。
ラッパークラスとかあると便利かも。

投稿者 Takenori : 07:11 PM | コメント (0) | トラックバック

バッファからの行読み込み

自作の関数ではなく、STLのstrstreamとgetlineを使えば、簡単に実現できることが判明。
次のような感じ。

char *read_buff = new char[html_size];
unsigned long read_size_all;
// read_buffへWinINetを使って読み込み処理
std::istrstream read_stream( read_buff, read_size_all );
while( std::getline( read_stream, line ) )
{// 何か処理
}

std::istrstreamではなく、std::strstreamにしたらなぜかうまくいかなかった。(これでしばらく悩んだ)
std::ios::in を指定すれば同じだと思っていたのだが、違うのだろうか?
まあ、出来たからいいか。

投稿者 Takenori : 07:02 PM | コメント (0) | トラックバック

January 15, 2005

perl でWin32 Inet

次のようにすれば、perlでWin32 Inetを使いmixiからログイン後のHTMLデータを取得できる。

use Win32::Internet;
$email = 'your_addr@yourhost.ne.jp';
$password = 'your_password';
$next_url = '/home.pl';
$target_url = 'mixi.jp';
$target_object = 'login.pl';
$post_req = 'email=%EMAIL%&password=%PASSWORD%&next_url=%NEXT_URL%';
$success_login = 0;
$INET = new Win32::Internet();    # WinInetのインスタンスを得る
if( defined( $INET ) ) {
    local $HTTP;
    $INET->HTTP( $HTTP, $target_url );
    if( defined( $HTTP ) ) {
        $send_command = $post_req;
        $send_command =~ s/%EMAIL%/$email/g;
        $send_command =~ s/%PASSWORD%/$password/g;
        $send_command =~ s/%NEXT_URL%/$next_url/g;
        {
            my $REQ;
            my $params;
            $params{"path"} = $target_object."?".$send_command;
            $params{"flags"} = INTERNET_FLAG_RELOAD;
            $params{"method"} = "POST";
            $HTTP->OpenRequest( $REQ, \%params );
            if( defined( $REQ ) ) {
                $REQ->SendRequest( $send_command )
                $file = $REQ->ReadEntireFile();
                $REQ->Close();
                @read_data = split( /\n/, $file );
                foreach( @read_data ) {
                    chomp;
                    if( /url=\/check.pl\?n=\%2Fhome.pl/ ) {
                        $success_login = 1;
                    }
                }
            }
        }
        if( $success_login ) {
            my $REQ;
            my $params;
            $params{"path"} = 'check.pl?n=\%2Fhome.pl';
            $params{"flags"} = INTERNET_FLAG_RELOAD;
            $params{"method"} = "GET";
            $HTTP->OpenRequest( $REQ, \%params );
            if( defined( $REQ ) ) {
                $REQ->SendRequest();
                $file = $REQ->ReadEntireFile();
                $REQ->Close();
                @read_data = split( /\n/, $file );
                foreach( @read_data ) {
                    chomp;
                    print $_."\n";
                }
            }
        }
    }
    $HTTP->Close();
}
$INET->Close();

perlでWin32 Inetを使えばプロトタイプを書いたり、そのまま使ったりするのに意外と便利。
と言うか、他のモジュールでHTML取得するスクリプト書いたことないんだけど。
ま、Winなら問題ないし、いいでしょ。

投稿者 Takenori : 10:13 PM | コメント (0) | トラックバック

boost::regexで悩む

L"\<a href=view_diary\.pl\?id=([0-9]+)\>"
と書いた正規表現が通らない。
あるはずなのにヒットしない。
perlでやるとヒットする。
なぜだ?としばらく悩んで気づいた。
L"\\<a href=view_diary\\.pl\\?id=([0-9]+)\\>"
と\マーク自体をエスケープしないといけないことを。
でも、ここが出来たら後は細かいところと全体の結合だな。
HTTPでHTMLを取得するところは、Win32 Inetを使ってperlでプロトタイプを書き、動作することを確認しているので、これはC++に書き換えなければならないが。

投稿者 Takenori : 09:57 PM | コメント (0) | トラックバック

January 14, 2005

libiconvを使おうとしたが

まず、libiconvをソースからmakeしようとしたが、うまくいかなかった。
で、バイナリのやつを使おうとしたけど、よくわからなかった。
で、いろいろと検索するとKaoriYa.netにiconv.dllをVCでビルドした物があったので、これを使うことにした。
そして、使ってみるが、文字列などによってうまくいくときといかない時がある。
iconv.cを見ると、その辺りはなんか面倒なことをしている。
この辺りでかなりiconvを使う気が減衰。
NKF32.DLLを使ってSHIFT_JISにした後、MultiByteToWideCharでUnicode(UTF-16)に変換しようかと思った。
だが、MultiByteToWideCharを使って、いきなりEUC-JPからUnicodeへ変換できない物かと考えて調べてみた。
調べるとEUC-JPのコードページは、51932 とある。キャラクタセットの認識および、Windowsコードページ一覧を参照のこと。
つまり、MultiByteToWideCharでコードページ 51932 を使えばうまくいくかと思ったが、変換できず。
文字コード掲示板過去ログにもそのことが書いてあった。
ConvertINetMultiByteToUnicodeを使うしかない様子。
で、ConvertINetMultiByteToUnicodeを使おうとするが、MSDNに必要なヘッダーファイルの記述がない。
いろいろ調べてMLANG.IDLから、MLang.h だろうと思い、MLang.hをinclude。
しかし、リンク時にエラーになる。
DLLはmlang.dllだと記述されているので、検索し発見。
mlang.dll からC++Builder用のインポートライブラリを作る。
implib mlang.lib mlang.dll
と、コマンドラインで入力すれば、mlang.libが出来るので、これをプロジェクトに追加。
メイクが通るようになった。
初めはうまく動かなかったが、キチンとリファレンス読んで書いたらうまく動くようになった。
その部分のコードは次のような感じ。
なお、エラー処理は省いている。

#define CP_EUCJP 51932
FILE *ifp, *ofp;
ifp = fopen( "test.html", "rb" );
ofp = fopen( "unicode.html", "wb" );
if( ifp && ofp ) {
    char inbuf[1024*64];
    wchar_t *outbuf = (wchar_t*)malloc(1024*64);
    wchar_t *out_base = outbuf;
    int out_cnt;
    DWORD dwMode = 0;
    while( fgets( inbuf, 1024*64, ifp ) != NULL )
    {
        out_cnt = 1024*32;
        outbuf = out_base;
        ConvertINetMultiByteToUnicode( &dwMode, CP_EUCJP, inbuf, NULL, outbuf, &out_cnt );
        fwrite( out_base, 1, out_cnt*2, ofp );
    }
    fclose(ifp);
    fclose(ofp);
}

今回はファイルからなのでfgetsで読んでいるけど、実際はInternetReadFileで読むから行読み込みを行う物が必要だな。
確か、昔作った記憶があるけど・・・探さないと。

ConvertINetMultiByteToUnicode を使用するには、Internet Explorer 5.5 以降、Windows 95、Windows NT 4.0以降が必要。

投稿者 Takenori : 04:27 PM | コメント (0) | トラックバック

文字コードの変換

mixiからHTMLを取得した後、文字コードの変換が必要だ。
しかも、面倒なことにmixiはEUC-JPで返してくる。
それで、まず思い付いたのがNKFだ。
これのWin32ライブラリ版がないか探したところNKF32.DLLがあった。
でも、UTF-8対応版ではない。

もう一つはlibiconvだ。
GNU Win32から取得し、試そうとするがlibintlも必要と言われたのでDL。
自動認識がないのが難点だな。

これは強引にEUC-JPでやるか? と思ったけど、boost::regexを使おうと思ったらUnicodeにする必要があるようだ。
文字コード認識の良さそうなライブラリを探すが、どれが良いかイマイチよくわからない。と言うか、知らない。
で、HTMLのcharsetを頼りに認識を行うのであれば、正規表現で簡単に取得できる。
これで行こうかと思ったが、面倒なのでEUC-JP決め打ちでいいかと思った。
このツールは、mixiに変更が合った場合認識できなくなる可能性が高い。
なら、文字コードは決め打ちでも問題ないと考えたからだ。

で、結局iconvでEUC-JP からUTF-16LEへ変換することにした。

投稿者 Takenori : 03:55 PM | コメント (0) | トラックバック

ブラウザでURLを開く

HINSTANCE hInstShell = ShellExecute( hWnd, "open", "http://taregeturl.com/", NULL, NULL, SW_SHOWDEFAULT );
とやれば、標準ブラウザで http://taregeturl.com/ が開かれる。
引数の意味などはShellExecuteを参照のこと。

投稿者 Takenori : 02:39 PM | コメント (0) | トラックバック

Application Dataフォルダの取得

SHGetSpecialFolderPathで、ユーザーごとのApplication Dataフォルダ ( CSIDL_LOCAL_APPDATA ) を取得するためには、Internet Explorer 5、Windows 2000 もしくはWindows Me 以上が必要。

投稿者 Takenori : 02:34 PM | コメント (0) | トラックバック

Total : Today : Yesterday :