You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
902 lines
26 KiB
902 lines
26 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
openurl.c
|
|
|
|
Abstract:
|
|
|
|
Tests InternetOpenUrl()
|
|
|
|
Author:
|
|
|
|
Richard L Firth (rfirth) 29-May-1995
|
|
|
|
Revision History:
|
|
|
|
29-May-1995 rfirth
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <io.h>
|
|
#include <fcntl.h>
|
|
#include <windows.h>
|
|
#include <wininet.h>
|
|
#include <catlib.h>
|
|
|
|
#ifndef _CRTAPI1
|
|
#define _CRTAPI1
|
|
#endif
|
|
|
|
#define IS_ARG(c) (((c) == '-') || ((c) == '/'))
|
|
|
|
#define VERSION_STRING "1.0"
|
|
|
|
#define URL_CONTEXT 0x55785875 // UxXu
|
|
#define DEFAULT_BUFFER_LENGTH 1021 // odd number for fun!
|
|
|
|
//
|
|
// prototypes
|
|
//
|
|
|
|
void _CRTAPI1 main(int, char**);
|
|
void usage(void);
|
|
void _CRTAPI1 my_cleanup(void);
|
|
void my_callback(HINTERNET, DWORD, DWORD, LPVOID, DWORD);
|
|
void default_url_test(LPSTR, DWORD, DWORD);
|
|
void open_urls(LPSTR*, int, LPSTR, DWORD, DWORD);
|
|
void get_url_data(HINTERNET);
|
|
void ftp_find(HINTERNET);
|
|
void gopher_find(HINTERNET);
|
|
void read_data(HINTERNET);
|
|
void get_request_flags(HINTERNET);
|
|
|
|
//
|
|
// data
|
|
//
|
|
|
|
BOOL Verbose = FALSE;
|
|
HINTERNET InternetHandle = NULL;
|
|
INTERNET_STATUS_CALLBACK PreviousCallback;
|
|
HINTERNET hCancel;
|
|
BOOL AsyncMode = FALSE;
|
|
HANDLE AsyncEvent = NULL;
|
|
DWORD AsyncResult;
|
|
DWORD AsyncError;
|
|
BOOL UseQueryData = FALSE;
|
|
BOOL NoDump = FALSE;
|
|
DWORD BufferLength = DEFAULT_BUFFER_LENGTH;
|
|
DWORD ReadLength = DEFAULT_BUFFER_LENGTH;
|
|
|
|
LPSTR default_urls[] = {
|
|
|
|
//
|
|
// WEB
|
|
//
|
|
|
|
"http://www.microsoft.com",
|
|
"http://www.microsoft.com/pages/misc/whatsnew.htm",
|
|
|
|
//
|
|
// gopher
|
|
//
|
|
|
|
"gopher://gopher.microsoft.com",
|
|
"gopher://gopher.microsoft.com/11/msft/",
|
|
"gopher://gopher.microsoft.com/00\\welcome.txt",
|
|
"gopher://gopher.tc.umn.edu/11Information%20About%20Gopher%09%09%2B",
|
|
"gopher://spinaltap.micro.umn.edu/11/computer",
|
|
"gopher://mudhoney.micro.umn.edu:4325/7",
|
|
"gopher://mudhoney.micro.umn.edu:4325/7%09gopher",
|
|
"gopher://spinaltap.micro.umn.edu/7mindex:lotsoplaces%09gopher%09%2b",
|
|
|
|
//
|
|
// FTP
|
|
//
|
|
|
|
"ftp://ftp.microsoft.com",
|
|
"ftp://ftp.microsoft.com/MSNBRO.TXT",
|
|
"ftp://ftp.microsoft.com/Services/"
|
|
};
|
|
|
|
#define NUMBER_OF_DEFAULT_URLS (sizeof(default_urls)/sizeof(default_urls[0]))
|
|
|
|
//
|
|
// functions
|
|
//
|
|
|
|
void _CRTAPI1 main(int argc, char** argv) {
|
|
|
|
BOOL ok;
|
|
LPSTR urls[64];
|
|
int numberOfUrls = 0;
|
|
BOOL fCallback = FALSE;
|
|
LPSTR headers = NULL;
|
|
BOOL expectingHeaders = FALSE;
|
|
DWORD accessMethod = INTERNET_OPEN_TYPE_PRECONFIG;
|
|
LPSTR proxyServer = NULL;
|
|
BOOL expectingProxy = FALSE;
|
|
DWORD context = 0;
|
|
DWORD flags = 0;
|
|
LPSTR endptr;
|
|
|
|
printf("\n"
|
|
"OpenUrl Version " VERSION_STRING " " __DATE__ "\n"
|
|
"\n"
|
|
);
|
|
|
|
for (--argc, ++argv; argc; --argc, ++argv) {
|
|
if (IS_ARG(**argv)) {
|
|
switch (tolower(*++*argv)) {
|
|
case '?':
|
|
usage();
|
|
break;
|
|
|
|
case 'a':
|
|
++*argv;
|
|
if (**argv == 'l') {
|
|
accessMethod = INTERNET_OPEN_TYPE_DIRECT;
|
|
} else if (**argv == 'p') {
|
|
accessMethod = INTERNET_OPEN_TYPE_PROXY;
|
|
if (*++*argv) {
|
|
proxyServer = *argv;
|
|
} else {
|
|
expectingProxy = TRUE;
|
|
}
|
|
} else {
|
|
printf("error: unrecognised access type: '%c'\n", **argv);
|
|
usage();
|
|
}
|
|
break;
|
|
|
|
case 'b':
|
|
BufferLength = (DWORD)strtol(++*argv, &endptr, 0);
|
|
if (*endptr == 'K' || *endptr == 'k') {
|
|
BufferLength *= 1024;
|
|
}
|
|
break;
|
|
|
|
case 'c':
|
|
fCallback = TRUE;
|
|
break;
|
|
|
|
case 'd':
|
|
NoDump = TRUE;
|
|
break;
|
|
|
|
case 'e':
|
|
flags |= INTERNET_FLAG_EXISTING_CONNECT;
|
|
break;
|
|
|
|
case 'h':
|
|
if (*++*argv) {
|
|
headers = *argv;
|
|
} else {
|
|
expectingHeaders = TRUE;
|
|
}
|
|
break;
|
|
|
|
case 'l':
|
|
ReadLength = (DWORD)strtol(++*argv, &endptr, 0);
|
|
if (*endptr == 'K' || *endptr == 'k') {
|
|
ReadLength *= 1024;
|
|
}
|
|
break;
|
|
|
|
case 'n':
|
|
flags |= INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE;
|
|
break;
|
|
|
|
case 'p':
|
|
flags |= INTERNET_FLAG_PASSIVE;
|
|
break;
|
|
|
|
case 'q':
|
|
UseQueryData = TRUE;
|
|
break;
|
|
|
|
case 'r':
|
|
flags |= INTERNET_FLAG_RAW_DATA;
|
|
break;
|
|
|
|
case 'v':
|
|
Verbose = TRUE;
|
|
break;
|
|
|
|
case 'x':
|
|
context = URL_CONTEXT;
|
|
break;
|
|
|
|
case 'y':
|
|
AsyncMode = TRUE;
|
|
break;
|
|
|
|
default:
|
|
printf("unknown command line flag: '%c'\n", **argv);
|
|
usage();
|
|
}
|
|
} else if (expectingProxy) {
|
|
proxyServer = *argv;
|
|
expectingProxy = FALSE;
|
|
} else if (expectingHeaders) {
|
|
headers = *argv;
|
|
expectingHeaders = FALSE;
|
|
} else {
|
|
if (numberOfUrls == sizeof(urls)/sizeof(urls[0]) - 1) {
|
|
break;
|
|
}
|
|
urls[numberOfUrls++] = *argv;
|
|
}
|
|
}
|
|
|
|
if (BufferLength < ReadLength) {
|
|
BufferLength = ReadLength;
|
|
}
|
|
|
|
//
|
|
// exit function
|
|
//
|
|
|
|
atexit(my_cleanup);
|
|
|
|
if (AsyncMode) {
|
|
|
|
//
|
|
// create an auto-reset, initially unsignalled event
|
|
//
|
|
|
|
AsyncEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if (!AsyncEvent) {
|
|
print_error("OpenUrl", "CreateEvent()");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
//
|
|
// get a handle to the internet - local, gateway or CERN proxy
|
|
//
|
|
|
|
InternetHandle = InternetOpen("OpenUrl",
|
|
accessMethod,
|
|
proxyServer,
|
|
NULL,
|
|
AsyncMode ? INTERNET_FLAG_ASYNC : 0
|
|
);
|
|
if (InternetHandle == NULL) {
|
|
print_error("openurl()", "InternetOpen()");
|
|
exit(1);
|
|
}
|
|
|
|
if (Verbose) {
|
|
printf("InternetOpen() returns handle %x\n", InternetHandle);
|
|
}
|
|
|
|
//
|
|
// let's have a status callback
|
|
//
|
|
|
|
if (fCallback) {
|
|
PreviousCallback = InternetSetStatusCallback(InternetHandle, my_callback);
|
|
if (Verbose) {
|
|
printf("previous Internet callback = %x\n", PreviousCallback);
|
|
}
|
|
}
|
|
|
|
if (numberOfUrls == 0) {
|
|
default_url_test(headers, flags, context);
|
|
} else {
|
|
open_urls(urls, numberOfUrls, headers, flags, context);
|
|
}
|
|
|
|
if (Verbose) {
|
|
printf("closing InternetHandle (%x)\n", InternetHandle);
|
|
}
|
|
ok = InternetCloseHandle(InternetHandle);
|
|
if (!ok) {
|
|
print_error("openurl()", "InternetClose(%x)", InternetHandle);
|
|
exit(1);
|
|
} else {
|
|
InternetHandle = NULL;
|
|
}
|
|
|
|
printf("Done.\n");
|
|
exit(0);
|
|
}
|
|
|
|
void usage() {
|
|
printf("\n"
|
|
"usage: openurl [-a{l|p}[[ ]{server[:port]}] [-b#] [-c] [-d] [-h[ ]{headers}]\n"
|
|
" [-l#] [-n] [-p] [-q] [-r] [-v] [-x] [-y] [url]*\n"
|
|
"\n"
|
|
"where: -al = local internet access\n"
|
|
" -ap = CERN proxy internet access\n"
|
|
" -b = buffer size\n"
|
|
" -c = enable status callbacks\n"
|
|
" -d = don't dump data\n"
|
|
" -e = use existing connection\n"
|
|
" -h = headers\n"
|
|
" -l = read length\n"
|
|
" -n = don't use cache\n"
|
|
" -p = PASSIVE mode (FTP transfers)\n"
|
|
" -q = use InternetQueryDataAvailable\n"
|
|
" -r = raw data. Default is HTML for FTP and gopher directories\n"
|
|
" -v = Verbose mode\n"
|
|
" -x = use context value when calling InternetOpenUrl()\n"
|
|
" -y = Async mode\n"
|
|
"\n"
|
|
" server = gateway server or proxy server name\n"
|
|
" :port = (optional) CERN proxy port\n"
|
|
" url = one or more URLs to open\n"
|
|
"\n"
|
|
"Default internet access is pre-configured (i.e. use settings in registry)\n"
|
|
);
|
|
exit(1);
|
|
}
|
|
|
|
void _CRTAPI1 my_cleanup() {
|
|
if (InternetHandle != NULL) {
|
|
if (Verbose) {
|
|
printf("closing Internet handle %x\n", InternetHandle);
|
|
}
|
|
if (!InternetCloseHandle(InternetHandle)) {
|
|
print_error("my_cleanup", "InternetCloseHandle(%x)", InternetHandle);
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
my_callback(
|
|
HINTERNET hInternet,
|
|
DWORD Context,
|
|
DWORD Status,
|
|
LPVOID Info,
|
|
DWORD Length
|
|
)
|
|
{
|
|
char* type$;
|
|
DWORD handleType;
|
|
DWORD size;
|
|
|
|
size = sizeof(handleType);
|
|
if (!InternetQueryOption(hInternet,
|
|
INTERNET_OPTION_HANDLE_TYPE,
|
|
(LPVOID)&handleType,
|
|
&size)) {
|
|
print_error("my_callback", "InternetQueryOption(HANDLE_TYPE)");
|
|
} else {
|
|
switch (handleType) {
|
|
case INTERNET_HANDLE_TYPE_INTERNET:
|
|
type$ = "Internet";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_CONNECT_FTP:
|
|
type$ = "FTP Connect";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_CONNECT_GOPHER:
|
|
type$ = "Gopher Connect";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_CONNECT_HTTP:
|
|
type$ = "HTTP Connect";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_FTP_FIND:
|
|
type$ = "FTP Find";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_FTP_FIND_HTML:
|
|
type$ = "FTP Find HTML";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_FTP_FILE:
|
|
type$ = "FTP File";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_FTP_FILE_HTML:
|
|
type$ = "FTP File HTML";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_GOPHER_FIND:
|
|
type$ = "Gopher Find";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML:
|
|
type$ = "Gopher Find HTML";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_GOPHER_FILE:
|
|
type$ = "Gopher File";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML:
|
|
type$ = "Gopher File HTML";
|
|
type$ = "Internet";
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_HTTP_REQUEST:
|
|
type$ = "HTTP Request";
|
|
break;
|
|
|
|
default:
|
|
type$ = "???";
|
|
}
|
|
printf("callback: handle %x = %s\n", hInternet, type$);
|
|
}
|
|
|
|
switch (Status) {
|
|
case INTERNET_STATUS_RESOLVING_NAME:
|
|
type$ = "RESOLVING NAME";
|
|
break;
|
|
|
|
case INTERNET_STATUS_NAME_RESOLVED:
|
|
type$ = "NAME RESOLVED";
|
|
break;
|
|
|
|
case INTERNET_STATUS_CONNECTING_TO_SERVER:
|
|
type$ = "CONNECTING TO SERVER";
|
|
break;
|
|
|
|
case INTERNET_STATUS_CONNECTED_TO_SERVER:
|
|
type$ = "CONNECTED TO SERVER";
|
|
break;
|
|
|
|
case INTERNET_STATUS_SENDING_REQUEST:
|
|
type$ = "SENDING REQUEST";
|
|
break;
|
|
|
|
case INTERNET_STATUS_REQUEST_SENT:
|
|
type$ = "REQUEST SENT";
|
|
break;
|
|
|
|
case INTERNET_STATUS_RECEIVING_RESPONSE:
|
|
type$ = "RECEIVING RESPONSE";
|
|
break;
|
|
|
|
case INTERNET_STATUS_RESPONSE_RECEIVED:
|
|
type$ = "RESPONSE RECEIVED";
|
|
break;
|
|
|
|
case INTERNET_STATUS_CLOSING_CONNECTION:
|
|
type$ = "CLOSING CONNECTION";
|
|
break;
|
|
|
|
case INTERNET_STATUS_CONNECTION_CLOSED:
|
|
type$ = "CONNECTION CLOSED";
|
|
break;
|
|
|
|
case INTERNET_STATUS_HANDLE_CREATED:
|
|
type$ = "HANDLE CREATED";
|
|
hCancel = *(LPHINTERNET)Info;
|
|
break;
|
|
|
|
case INTERNET_STATUS_HANDLE_CLOSING:
|
|
type$ = "HANDLE CLOSING";
|
|
break;
|
|
|
|
case INTERNET_STATUS_REQUEST_COMPLETE:
|
|
type$ = "REQUEST COMPLETE";
|
|
AsyncResult = ((LPINTERNET_ASYNC_RESULT)Info)->dwResult;
|
|
AsyncError = ((LPINTERNET_ASYNC_RESULT)Info)->dwError;
|
|
break;
|
|
|
|
default:
|
|
type$ = "???";
|
|
break;
|
|
}
|
|
if (Verbose) {
|
|
printf("callback: handle %x [context %x [%s]] %s ",
|
|
hInternet,
|
|
Context,
|
|
(Context == URL_CONTEXT) ? "UrlContext" : "???",
|
|
type$
|
|
);
|
|
if (Info) {
|
|
if ((Status == INTERNET_STATUS_HANDLE_CREATED)
|
|
|| (Status == INTERNET_STATUS_HANDLE_CLOSING)) {
|
|
printf("%x", *(LPHINTERNET)Info);
|
|
} else if (Length == sizeof(DWORD)) {
|
|
printf("%d", *(LPDWORD)Info);
|
|
} else if (Status != INTERNET_STATUS_REQUEST_COMPLETE) {
|
|
printf(Info);
|
|
}
|
|
}
|
|
putchar('\n');
|
|
}
|
|
if (Status == INTERNET_STATUS_REQUEST_COMPLETE) {
|
|
if (AsyncMode) {
|
|
SetEvent(AsyncEvent);
|
|
} else {
|
|
printf("error: INTERNET_STATUS_REQUEST_COMPLETE received when not async\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void default_url_test(LPSTR headers, DWORD flags, DWORD context) {
|
|
open_urls(default_urls, NUMBER_OF_DEFAULT_URLS, headers, flags, context);
|
|
}
|
|
|
|
void open_urls(LPSTR* purls, int nurls, LPSTR headers, DWORD flags, DWORD context) {
|
|
|
|
HINTERNET handle;
|
|
|
|
if (headers) {
|
|
|
|
LPSTR h;
|
|
|
|
for (h = headers; *h; ++h) {
|
|
if (*h == '\\' && *(h + 1) == 'n') {
|
|
*h++ = '\r';
|
|
*h = '\n';
|
|
}
|
|
}
|
|
}
|
|
while (nurls--) {
|
|
if (Verbose) {
|
|
printf("\nopening URL \"%s\"\n\n", *purls);
|
|
}
|
|
handle = InternetOpenUrl(InternetHandle,
|
|
*purls,
|
|
headers,
|
|
headers ? -1 : 0,
|
|
flags,
|
|
context
|
|
);
|
|
if ((handle == NULL) && AsyncMode) {
|
|
|
|
DWORD err;
|
|
|
|
err = GetLastError();
|
|
if (err == ERROR_IO_PENDING) {
|
|
if (Verbose) {
|
|
printf("waiting for async InternetOpenUrl()...\n");
|
|
}
|
|
WaitForSingleObject(AsyncEvent, INFINITE);
|
|
handle = (HINTERNET)AsyncResult;
|
|
SetLastError(AsyncError);
|
|
}
|
|
} else if (AsyncMode && Verbose) {
|
|
printf("async InternetOpenUrl() returns sync result\n");
|
|
}
|
|
|
|
if (handle == NULL) {
|
|
print_error("open_urls", "InternetOpenUrl(%s)", *purls);
|
|
} else {
|
|
if (Verbose) {
|
|
printf("InternetOpenUrl() returns handle %x\n", handle);
|
|
}
|
|
get_request_flags(handle);
|
|
get_url_data(handle);
|
|
}
|
|
|
|
++purls;
|
|
}
|
|
}
|
|
|
|
void get_url_data(HINTERNET handle) {
|
|
|
|
DWORD handleType;
|
|
DWORD handleTypeLen;
|
|
|
|
handleTypeLen = sizeof(handleType);
|
|
if (InternetQueryOption(handle,
|
|
INTERNET_OPTION_HANDLE_TYPE,
|
|
(LPVOID)&handleType,
|
|
&handleTypeLen
|
|
)) {
|
|
switch (handleType) {
|
|
case INTERNET_HANDLE_TYPE_INTERNET:
|
|
printf("error: get_url_data: HANDLE_TYPE_INTERNET?\n");
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_CONNECT_FTP:
|
|
printf("error: get_url_data: INTERNET_HANDLE_TYPE_CONNECT_FTP?\n");
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_CONNECT_GOPHER:
|
|
printf("error: get_url_data: INTERNET_HANDLE_TYPE_CONNECT_GOPHER?\n");
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_CONNECT_HTTP:
|
|
printf("error: get_url_data: INTERNET_HANDLE_TYPE_CONNECT_HTTP?\n");
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_FTP_FIND:
|
|
ftp_find(handle);
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_GOPHER_FIND:
|
|
gopher_find(handle);
|
|
break;
|
|
|
|
case INTERNET_HANDLE_TYPE_FTP_FIND_HTML:
|
|
case INTERNET_HANDLE_TYPE_FTP_FILE:
|
|
case INTERNET_HANDLE_TYPE_FTP_FILE_HTML:
|
|
case INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML:
|
|
case INTERNET_HANDLE_TYPE_GOPHER_FILE:
|
|
case INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML:
|
|
case INTERNET_HANDLE_TYPE_HTTP_REQUEST:
|
|
read_data(handle);
|
|
break;
|
|
|
|
default:
|
|
printf("error: get_url_data: handleType == %d?\n", handleType);
|
|
break;
|
|
}
|
|
if (Verbose) {
|
|
printf("closing Internet handle %x\n", handle);
|
|
}
|
|
if (!InternetCloseHandle(handle)) {
|
|
print_error("get_url_data", "InternetCloseHandle(%x)", handle);
|
|
}
|
|
} else {
|
|
print_error("get_url_data", "InternetQueryOption()");
|
|
}
|
|
}
|
|
|
|
void ftp_find(HINTERNET handle) {
|
|
|
|
WIN32_FIND_DATA data;
|
|
BOOL ok;
|
|
|
|
do {
|
|
|
|
SYSTEMTIME systemTime;
|
|
|
|
ok = InternetFindNextFile(handle, (LPVOID)&data);
|
|
if (!ok) {
|
|
if (AsyncMode) {
|
|
if (GetLastError() == ERROR_IO_PENDING) {
|
|
if (Verbose) {
|
|
printf("waiting for async InternetFindNextFile()...\n");
|
|
}
|
|
WaitForSingleObject(AsyncEvent, INFINITE);
|
|
ok = (BOOL)AsyncResult;
|
|
SetLastError(AsyncError);
|
|
}
|
|
}
|
|
}
|
|
if (ok && !NoDump) {
|
|
if (!FileTimeToSystemTime(&data.ftLastWriteTime, &systemTime)) {
|
|
print_error("ftp_find", "FileTimeToSystemTime()");
|
|
}
|
|
|
|
printf("%2d-%02d-%04d %2d:%02d:%02d %15d bytes %-s%-s%-s %s\n",
|
|
systemTime.wMonth,
|
|
systemTime.wDay,
|
|
systemTime.wYear,
|
|
systemTime.wHour,
|
|
systemTime.wMinute,
|
|
systemTime.wSecond,
|
|
data.nFileSizeLow,
|
|
(data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)
|
|
? "Normal " : "",
|
|
(data.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
|
? "ReadOnly " : "",
|
|
(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
? "Directory " : "",
|
|
data.cFileName
|
|
);
|
|
}
|
|
} while (ok);
|
|
|
|
if (GetLastError() != ERROR_NO_MORE_FILES) {
|
|
print_error("ftp_find", "InternetFindNextFile()");
|
|
}
|
|
}
|
|
|
|
void gopher_find(HINTERNET handle) {
|
|
|
|
GOPHER_FIND_DATA data;
|
|
BOOL ok;
|
|
int i;
|
|
|
|
i = 0;
|
|
do {
|
|
ok = InternetFindNextFile(handle, (LPVOID)&data);
|
|
if (!ok) {
|
|
if (AsyncMode) {
|
|
if (GetLastError() == ERROR_IO_PENDING) {
|
|
if (Verbose) {
|
|
printf("waiting for async InternetFindNextFile()...\n");
|
|
}
|
|
WaitForSingleObject(AsyncEvent, INFINITE);
|
|
ok = (BOOL)AsyncResult;
|
|
SetLastError(AsyncError);
|
|
}
|
|
}
|
|
}
|
|
if (ok && !NoDump) {
|
|
|
|
LPGOPHER_FIND_DATA p;
|
|
SYSTEMTIME systemTime;
|
|
char timeBuf[9];
|
|
char sizeBuf[32];
|
|
|
|
p = (LPGOPHER_FIND_DATA)&data;
|
|
if ((p->LastModificationTime.dwLowDateTime != 0)
|
|
&& (p->LastModificationTime.dwHighDateTime != 0)) {
|
|
FileTimeToSystemTime(&p->LastModificationTime, &systemTime);
|
|
sprintf(timeBuf,
|
|
"%02d-%02d-%02d",
|
|
systemTime.wMonth,
|
|
systemTime.wDay,
|
|
systemTime.wYear % 100
|
|
);
|
|
sprintf(sizeBuf, "%d", p->SizeLow);
|
|
} else {
|
|
timeBuf[0] = '\0';
|
|
sizeBuf[0] = '\0';
|
|
}
|
|
printf("%5d %c %7s %10s %8s %s\n",
|
|
i,
|
|
(p->GopherType & GOPHER_TYPE_GOPHER_PLUS) ? '+' : ' ',
|
|
(p->GopherType & GOPHER_TYPE_TEXT_FILE) ? "Text"
|
|
: (p->GopherType & GOPHER_TYPE_DIRECTORY) ? "Dir"
|
|
: (p->GopherType & GOPHER_TYPE_CSO) ? "Phone"
|
|
: (p->GopherType & GOPHER_TYPE_ERROR) ? "Error"
|
|
: (p->GopherType & GOPHER_TYPE_MAC_BINHEX) ? "MAC"
|
|
: (p->GopherType & GOPHER_TYPE_DOS_ARCHIVE) ? "Archive"
|
|
: (p->GopherType & GOPHER_TYPE_UNIX_UUENCODED) ? "UNIX"
|
|
: (p->GopherType & GOPHER_TYPE_INDEX_SERVER) ? "Index"
|
|
: (p->GopherType & GOPHER_TYPE_TELNET) ? "Telnet"
|
|
: (p->GopherType & GOPHER_TYPE_BINARY) ? "Binary"
|
|
: (p->GopherType & GOPHER_TYPE_REDUNDANT) ? "Backup"
|
|
: (p->GopherType & GOPHER_TYPE_TN3270) ? "TN3270"
|
|
: (p->GopherType & GOPHER_TYPE_GIF) ? "GIF"
|
|
: (p->GopherType & GOPHER_TYPE_IMAGE) ? "Image"
|
|
: (p->GopherType & GOPHER_TYPE_BITMAP) ? "Bitmap"
|
|
: (p->GopherType & GOPHER_TYPE_MOVIE) ? "Movie"
|
|
: (p->GopherType & GOPHER_TYPE_SOUND) ? "Sound"
|
|
: (p->GopherType & GOPHER_TYPE_HTML) ? "HTML"
|
|
: (p->GopherType & GOPHER_TYPE_PDF) ? "PDF"
|
|
: (p->GopherType & GOPHER_TYPE_CALENDAR) ? "Cal"
|
|
: (p->GopherType & GOPHER_TYPE_INLINE) ? "Inline"
|
|
: (p->GopherType & GOPHER_TYPE_UNKNOWN) ? "Unknown"
|
|
: "\a????",
|
|
sizeBuf,
|
|
timeBuf,
|
|
p->DisplayString
|
|
);
|
|
++i;
|
|
}
|
|
} while (ok);
|
|
|
|
if (GetLastError() != ERROR_NO_MORE_FILES) {
|
|
print_error("gopher_find", "InternetFindNextFile()");
|
|
}
|
|
}
|
|
|
|
void read_data(HINTERNET handle) {
|
|
|
|
char* buf;
|
|
DWORD nread;
|
|
BOOL ok;
|
|
int mode;
|
|
|
|
buf = (char*)malloc(BufferLength);
|
|
if (!buf) {
|
|
printf("error: failed to allocate %d bytes for buffer\n", BufferLength);
|
|
return;
|
|
}
|
|
|
|
mode = _setmode(1, _O_BINARY);
|
|
|
|
do {
|
|
|
|
DWORD avail;
|
|
int i;
|
|
|
|
if (UseQueryData) {
|
|
ok = InternetQueryDataAvailable(handle, &avail, 0, 0);
|
|
if (!ok) {
|
|
if (GetLastError() == ERROR_IO_PENDING) {
|
|
if (Verbose) {
|
|
printf("waiting for async InternetQueryDataAvailable()...\n");
|
|
}
|
|
WaitForSingleObject(AsyncEvent, INFINITE);
|
|
ok = (BOOL)AsyncResult;
|
|
SetLastError(AsyncError);
|
|
}
|
|
}
|
|
if (!ok) {
|
|
print_error("read_file", "InternetQueryDataAvailable()");
|
|
break;
|
|
}
|
|
|
|
if (Verbose) {
|
|
printf("InternetQueryDataAvailable() returns %d bytes\n", avail);
|
|
}
|
|
} else {
|
|
avail = BufferLength;
|
|
}
|
|
|
|
avail = min(avail, ReadLength);
|
|
|
|
for (i = 0; i < 2; ++i) {
|
|
memset(buf, '@', avail);
|
|
ok = InternetReadFile(handle, buf, avail, &nread);
|
|
if (!ok) {
|
|
if (AsyncMode) {
|
|
if (GetLastError() == ERROR_IO_PENDING) {
|
|
if (Verbose) {
|
|
printf("waiting for async InternetFindNextFile()...\n");
|
|
}
|
|
WaitForSingleObject(AsyncEvent, INFINITE);
|
|
ok = (BOOL)AsyncResult;
|
|
SetLastError(AsyncError);
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
|
if (i == 1) {
|
|
printf("error: failed to read %d bytes in 2 attempts\n",
|
|
nread);
|
|
goto quit;
|
|
}
|
|
|
|
//
|
|
// second attempt with all buffer
|
|
//
|
|
|
|
avail = BufferLength;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (ok && !NoDump) {
|
|
if (!nread) {
|
|
printf("=== end of file ===\n");
|
|
} else {
|
|
_write(1, buf, nread);
|
|
}
|
|
} else if (ok && NoDump && Verbose) {
|
|
printf("InternetReadFile() returns %d bytes\n", nread);
|
|
}
|
|
} while (ok && nread);
|
|
|
|
if (GetLastError() != ERROR_SUCCESS) {
|
|
print_error("read_file", "InternetReadFile()");
|
|
}
|
|
|
|
quit:
|
|
|
|
free(buf);
|
|
|
|
_setmode(1, mode);
|
|
}
|
|
|
|
void get_request_flags(HINTERNET hInternet) {
|
|
|
|
DWORD dwFlags;
|
|
DWORD len = sizeof(dwFlags);
|
|
|
|
if (InternetQueryOption(hInternet,
|
|
INTERNET_OPTION_REQUEST_FLAGS,
|
|
&dwFlags,
|
|
&len)) {
|
|
|
|
char buf[256];
|
|
char * p = buf;
|
|
|
|
p += sprintf(p, "REQUEST_FLAGS = %08x\n", dwFlags);
|
|
p += sprintf(p, "\tRetrieved from: %s\n",
|
|
(dwFlags & INTERNET_REQFLAG_FROM_CACHE) ? "Cache" : "Network");
|
|
p += sprintf(p, "\tNo Headers: %s\n",
|
|
(dwFlags & INTERNET_REQFLAG_NO_HEADERS) ? "TRUE" : "FALSE");
|
|
p += sprintf(p, "\tVia Proxy: %s\n",
|
|
(dwFlags & INTERNET_REQFLAG_VIA_PROXY) ? "YES" : "NO");
|
|
printf(buf);
|
|
} else {
|
|
print_error("get_request_flags()", "InternetQueryOption()");
|
|
}
|
|
}
|