〜 ネットワーク 〜
サーバーからリソースをダウンロード (要WININET.DLL)

HSP3からHSPInet.DLLが標準で同梱されており、
このDLLの命令を使うことでインターネット上のデータを取り込むことが出来ます。
便利なものですが、作成した実行ファイルと共にDLLを同梱する必要があるので、
様々な理由により「なんとかDLLナシで実現できないか」と思う人たちの為の参考Tips。
HSPInet.DLLは、Windows標準搭載のWinInet.DLLのラッパーDLLなので、
WinInet.DLLのAPI関数を直接呼び出すことで、
HSPInet.DLLを同梱することなく実現させることが可能となります。

今回はFTPサーバーからリソースをダウンロードしてファイル保存するftpget命令に取って代わる
WinInet.DLLのAPI関数FtpGetFileを使ったサンプルモジュールを紹介します。
API関数FtpGetFileに指定するのは第1引数から順に、
「セッションハンドル」「取得リソース名」「保存ファイル名」「上書き禁止フラグ」「ファイル属性」
「取得方法」「コールバック関数に渡すアプリケーション定義値」です。
セッションハンドルはサーバーと接続した際のログインセッションハンドルを、
取得リソース名はサーバー内の取得元リソース名(を格納した変数ポインタ)を、
保存ファイル名はダウンロードしたデータの保存ファイル名(を格納した変数のポインタ)を、
上書き禁止フラグは既に同名ファイルが存在する際にダウンロードしないなら禁止フラグに1を、
ファイル属性は保存ファイルに付ける下記のファイル属性値を、
FILE_ATTRIBUTE_READONLY0x0001書き込みや削除が行えない読取専用ファイル。
FILE_ATTRIBUTE_HIDDEN0x0002通常のディレクトリリスティングでは表示されない隠しファイル。
FILE_ATTRIBUTE_SYSTEM0x0004OSのシステムファイル。
FILE_ATTRIBUTE_ARCHIVE0x0020バックアップや削除のためのマークとして使用するアーカイブファイル。
FILE_ATTRIBUTE_NORMAL0x0080特に属性を持たないファイル。
FILE_ATTRIBUTE_TEMPORARY0x0100必要がなくなった段階ですぐに削除すべき一時ファイル。
FILE_ATTRIBUTE_OFFLINE0x1000データがオフラインの記憶装置へ物理的に移動されたことを示すファイル。
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED0x2000「インデックスサービス」の対象ではないファイル。(Windows2000〜)
取得方法は下記の転送モードとダウンロード方法を組み合わせて指定し、
FTP_TRANSFER_TYPE_UNKNOWN0x0000デフォルトモード(バイナリー)で転送。
FTP_TRANSFER_TYPE_ASCII
INTERNET_FLAG_TRANSFER_ASCII
0x0001テキストファイル用のアスキーモードで転送。
FTP_TRANSFER_TYPE_BINARY
INTERNET_FLAG_TRANSFER_BINARY
0x0002データそのままのバイナリーモードで転送。
INTERNET_FLAG_MUST_CACHE_REQUEST
INTERNET_FLAG_NEED_FILE
0x00000010キャッシュできない時は一時ファイルを作る。
INTERNET_FLAG_HYPERLINK0x00000400ネットワークから再読込を決定する時はリロードを強制する。
INTERNET_FLAG_RESYNCHRONIZE0x00000800FTP・Gopherまたは変更があるHTTPリソースはリロード。
INTERNET_FLAG_DONT_CACHE
INTERNET_FLAG_NO_CACHE_WRITE
0x04000000キャッシュに加えない。
INTERNET_FLAG_RELOAD0x80000000キャッシュを使わずサーバーからダウンロード。
コールバックする値は0を、それぞれ指定しましょう。 正常に保存まで完了すると1が、上書禁止フラグを立てていたりリソースが存在しない場合等は0が返ります。 大抵のデータはバイナリーモードでの転送で問題ありませんが、 テキストファイルの場合はOS依存の改行コードの違いにより、元の形式から変わってしまうことがあるので、 その場合はアスキーモードで転送するようにしてください。 カレントディレクトリ以外のリソースをダウンロードするには対象ディレクトリを変更する必要があります。 コチラを参考にしてカレントディレクトリを予め変更しておいてください。 今回のやり方でHSPプログラムでデータを表示させたりする時は、 ダウンロードしたファイルを読み込む形になるので、場合によっては面倒かもしれません。 コチラのやり方なら、HSPの変数内にデータをダウンロードする為、都合が良い場合があることでしょう。 ケースバイケースで使い分けてみてください。

inetinit
[パラメータなし]インターネットサービスを開始するだけである為、パラメータは必要ない。

inetend
[パラメータなし]インターネットハンドルを解放するだけの為、パラメータは必要ない。
尚、終了時に自動的に呼び出されるので命令を実行する必要はない。

inetlogin サーバー, ユーザー情報, サービス, オプション
サーバーホストサーバーアドレスまたはIPアドレス文字列を指定する。
ユーザー情報ログインユーザー名とパスワードをコロンで区切った形式で指定する。
サービス接続するサービス(1:FTP 2:Gopher 3:HTTP)を指定する。
尚、省略すればFTP接続を行う。
オプションFTPでパッシブモード利用する時、HTTPでHTTPS通信する時は1を指定する。
それ以外の時は0または省略する。

inetlogout
[パラメータなし]サーバーとの接続を解除するだけの為、パラメータは必要ない。
尚、終了時に自動的に呼び出されるので命令を実行する必要はない。

ftpget 取得名, 保存名, 転送モード, 上書フラグ
取得名取得するリソース名を指定する。尚、statには失敗した(=0)か成功した(=1)かのフラグが返る。
保存名保存するファイル名を指定する。
転送モード転送モード(0:バイナリー 1:アスキー)を指定する。省略時はバイナリーモード。
上書フラグ既に同名ファイルが存在する時に上書きする(=0)か否(=1)かを指定する。省略時は上書きする。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
	ll_libload wininet, "wininet.dll"
	ll_getproc InternetOpen, "InternetOpenA", wininet
	ll_getproc InternetCloseHandle, "InternetCloseHandle", wininet
	ll_getproc InternetConnect, "InternetConnectA", wininet
	ll_getproc FtpGetFile, "FtpGetFileA", wininet

#module
#deffunc inetinit
	mref stt, 64
	prm = 0, 0, 0, 0, 0
	agent = "hspbc"
	ll_getptr agent : ll_ret prm
	ll_callfunc prm, 5, InternetOpen@
	ll_ret hinet : stt = hinet
	return

#deffunc inetend onexit
	if hinet : ll_callfunc hinet, 1, InternetCloseHandle@
	return

#deffunc inetlogin str, str, int, int
	mref server, 32 : mref info, 33 : mref service, 2 : mref option, 3 : mref stt, 64
	instr i, info, ":"
	strlen i.1, info
	strmid user, info, , i
	strmid pass, info, i + 1, i.1 - i - 1
	if hinet = 0 : inetinit
	if user = "" : i.0 = 0 : else : ll_getptr user : ll_ret i.0
	if pass = "" : i.1 = 0 : else : ll_getptr pass : ll_ret i.1
	switch service
	case 2:  i.2 = 0x0002, 0 : swbreak
	case 3:  i.2 = 0x0003, 0 : swbreak
	default: i.2 = 0x0001, option ! 0 * 0x08000000
	swend
	ll_getptr server : ll_ret i.5
	prm = hinet, i.5, 0, i.0, i.1, i.2, i.3, 0
	ll_callfunc prm, 8, InternetConnect@
	ll_ret hsess : stt = hsess
	return

#deffunc inetlogout onexit
	if hsess : ll_callfunc hsess, 1, InternetCloseHandle@
	return	

#deffunc ftpget str, str, int, int
	mref getname, 32 : mref savename, 33 : mref mode, 2 : mref norewrite, 3
	mref stt, 64
	prm = hsess, 0, 0, norewrite, 0x0020, mode, 0
	ll_getptr getname : ll_ret prm.1
	ll_getptr savename : ll_ret prm.2
	ll_callfunc prm, 7, FtpGetFile@
	ll_ret prm : stt = prm
	return
#global

	sdim v, 128, 5
	pos  10,  10 : mes "FTPサーバー"
	pos 150,  10 : input v.0, 150, 22
	pos  10,  40 : mes "ユーザー名"
	pos 150,  40 : input v.1, 150, 22
	pos  10,  70 : mes "パスワード"
	pos 150,  70 : input v.2, 150, 22
	pos  10, 100 : mes "取得ファイル名"
	pos 150, 100 : input v.3, 150, 22
	pos  10, 130 : mes "保存ファイル名"
	pos 150, 130 : input v.4, 150, 22
	pos 150, 160 : button "取得", *connect
	stop

*connect
	inetlogin v, v.1 + ":" + v.2
	if stat {
		ftpget v.3, v.4
		if stat {
			dialog "保存しました"
		} else {
			dialog "接続には成功しましたがファイル保存しませんでした"
		}
	} else {
		dialog "接続に失敗しました"
	}
	stop

inetinit
[パラメータなし]インターネットサービスを開始するだけである為、パラメータは必要ない。

inetend
[パラメータなし]インターネットハンドルを解放するだけの為、パラメータは必要ない。
尚、終了時に自動的に呼び出されるので命令を実行する必要はない。

inetlogin サーバー, ユーザー, パスワード, サービス, オプション
サーバーホストサーバーアドレスまたはIPアドレス文字列を指定する。
ユーザーログインユーザー名を指定する。
パスワードログインパスワードを指定する。
サービス接続するサービス(1:FTP 2:Gopher 3:HTTP)を指定する。
尚、省略すればFTP接続を行う。
オプションFTPでパッシブモード利用する時、HTTPでHTTPS通信する時は1を指定する。
それ以外の時は0または省略する。

inetlogout
[パラメータなし]サーバーとの接続を解除するだけの為、パラメータは必要ない。
尚、終了時に自動的に呼び出されるので命令を実行する必要はない。

ftpget 取得名, 保存名, 転送モード, 上書フラグ
取得名取得するリソース名を指定する。尚、statには失敗した(=0)か成功した(=1)かのフラグが返る。
保存名保存するファイル名を指定する。
転送モード転送モード(0:バイナリー 1:アスキー)を指定する。省略時はバイナリーモード。
上書フラグ既に同名ファイルが存在する時に上書きする(=0)か否(=1)かを指定する。省略時は上書きする。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#uselib "wininet.dll"
#cfunc	global InternetOpen "InternetOpenA" sptr, int, int, int, int
#func	global InternetCloseHandle "InternetCloseHandle" int
#cfunc	global InternetConnect "InternetConnectA" int, sptr, int, int, int, int, int, int
#cfunc	global FtpGetFile "FtpGetFileA" int, sptr, sptr, int, int, int, int

#module
#deffunc inetinit
	hinet = InternetOpen("hspbc")
	return hinet

#deffunc inetend onexit
	if hinet : InternetCloseHandle hinet
	return

#deffunc inetlogin str server, str user, str pass, int service, int option, local i, local s
	if hinet = 0 : inetinit
	s = user, pass
	if user = "" : i.0 = 0 : else : i.0 = varptr(s.0)
	if pass = "" : i.1 = 0 : else : i.1 = varptr(s.1)
	switch service
	case 2:  i.2 = 0x0002, 0 : swbreak
	case 3:  i.2 = 0x0003, 0 : swbreak
	default: i.2 = 0x0001, (option ! 0) * 0x08000000
	swend
	hsess = InternetConnect(hinet, server, , i.0, i.1, i.2, i.3)
	return hsess

#deffunc inetlogout onexit
	if hsess : InternetCloseHandle hsess
	return

#deffunc ftpget str getname, str savename, int mode, int norewrite
	return FtpGetFile(hsess, getname, savename, norewrite, 0x0020, mode)
#global

	sdim v, 128, 5
	pos  10,  10 : mes "FTPサーバー"
	pos 150,  10 : input v.0, 150, 20
	pos  10,  40 : mes "ユーザー名"
	pos 150,  40 : input v.1, 150, 20
	pos  10,  70 : mes "パスワード"
	pos 150,  70 : input v.2, 150, 20
	pos  10, 100 : mes "取得ファイル名"
	pos 150, 100 : input v.3, 150, 20
	pos  10, 130 : mes "保存ファイル名"
	pos 150, 130 : input v.4, 150, 20
	pos 150, 160 : button gosub "取得", *connect
	stop

*connect
	inetlogin v, v.1, v.2
	if stat {
		ftpget v.3, v.4
		if stat {
			dialog "保存しました"
		} else {
			dialog "接続には成功しましたがファイル保存しませんでした"
		}
	} else {
		dialog "接続に失敗しました"
	}
	return