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 以上が必要。