/* * $Header: /home/gene/library/website/docsrc/httpxtran/src/RCS/winet.c,v 395.1 2008/04/20 17:25:51 gene Exp $ * * Copyright (c) 2006 Gene Michael Stover. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL GENE MICHAEL STOVER BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of Gene Michael Stover * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * from Gene Michael Stover. */ #include "this.h" /* * Thie function is not thread-safe. */ static int S_CrackUrl (char url[], URL_COMPONENTS *urco) { int rc = 0; static TCHAR hostname[100], username[100], password[100], path[1024], extra[100]; static DWORD flags = 0; DWORD_PTR context = 0; Trace ("S_CrackUrl"); /* * Initialize the URL_COMPONENTS. It's a length process, but it's * simple. We are mostly pointing its members at the buffers we * declared. */ bzero (urco, sizeof *urco); urco->dwStructSize = sizeof *urco; urco->lpszHostName = hostname; urco->dwHostNameLength = sizeof hostname / sizeof hostname[0]; urco->lpszUserName = username; urco->dwUserNameLength = sizeof username / sizeof username[0]; urco->lpszPassword = password; urco->dwPasswordLength = sizeof password / sizeof password[0]; urco->lpszUrlPath = path; urco->dwUrlPathLength = sizeof path / sizeof path[0]; urco->lpszExtraInfo = extra; urco->dwExtraInfoLength = sizeof extra / sizeof extra[0]; if (InternetCrackUrlA (url, 0, ICU_DECODE, urco)) { /* * Verify that InternetCrackUrl terminated each of the strings * with '\0' characters. We do this to verify that InternetCrackUrl * works the way I think it should. */ assert (hostname[urco->dwHostNameLength] == '\0'); assert (username[urco->dwUserNameLength] == '\0'); assert (password[urco->dwPasswordLength] == '\0'); assert (path[urco->dwUrlPathLength] == '\0'); assert (extra[urco->dwExtraInfoLength] == '\0'); } else { fprintf (stderr, "\n"); DEBUG_PrintLastError (__FILE__, __LINE__, "InternetCrackUrlA"); rc = 1806; } return rc; } /* */ static HINTERNET S_InternetOpen (URL_COMPONENTS *urco) { static TCHAR agent[] = TEXT (__FILE__); static DWORD access_type = INTERNET_OPEN_TYPE_PRECONFIG; static TCHAR *proxy_bypass = NULL; static DWORD flags = 0; HINTERNET hnd; Trace ("S_InternetOpen"); hnd = InternetOpen (agent, access_type, NULL, NULL, flags); if (hnd != NULL) { /* good */ } else { DEBUG_PrintLastError (__FILE__, __LINE__, "InternetOpen"); assert (hnd == NULL); } return hnd; } /* */ static HINTERNET S_InternetConnect (HINTERNET inet, URL_COMPONENTS *urco) { HINTERNET hnd = NULL; static DWORD flags = 0; DWORD_PTR context = 0; Trace ("S_InternetConnect"); hnd = InternetConnect (inet, urco->lpszHostName, urco->nPort, urco->lpszUserName, urco->lpszPassword, INTERNET_SERVICE_HTTP, flags, context); if (hnd != NULL) { /* good */ } else { DEBUG_PrintLastError (__FILE__, __LINE__, "InternetConnect"); assert (hnd == NULL); } return hnd; } /* */ static HINTERNET S_HttpOpenRequest (HINTERNET conn, URL_COMPONENTS *urco) { HINTERNET hnd = NULL; static TCHAR *version = NULL; /* defaults to HTTP 1.1 */ static TCHAR *referer = NULL; /* no referer */ static TCHAR *accept_types[] = { TEXT ("text/html"), TEXT ("application/octet-stream"), NULL }; static DWORD flags = 0; static DWORD_PTR context = 0; Trace ("S_HttpOpenRequest"); hnd = HttpOpenRequest (conn, TEXT ("POST"), urco->lpszUrlPath, version, referer, accept_types, flags, context); if (hnd != NULL) { /* good */ } else { LOG_PrintLastError (__FILE__, __LINE__, "S_HttpOpenRequest", "HttpOpenRequest failed"); assert (hnd == NULL); } return hnd; } /* */ static void S_InternetCloseHandle (HINTERNET hnd) { if (InternetCloseHandle (hnd)) { /* good */ } else { DEBUG_PrintLastError (__FILE__, __LINE__, "InternetOpen"); } } /* */ static char * S_LoadPayload (FILE *src, size_t *count) { char *payload = NULL; size_t len = 0, c2; assert (count != NULL); *count = 0; if (src == NULL) { /* * There is no data to send. This is not an error. */ } else { do { if (*count >= len) { len += 1024; payload = (char *) xrealloc (payload, len); } if (payload != NULL) { c2 = fread (&payload[*count], sizeof payload[0], len - *count, src); *count += c2; } } while (payload != NULL && c2 > 0); if (payload == NULL) { LOG_OutOfMemory (__FILE__, __LINE__); } else if (ferror (src)) { LOG_Fread (sizeof payload[0], __FILE__, __LINE__); } else { assert (feof (src)); /* normal end-of-input */ } } DEBUG_Print (__FILE__, __LINE__, "Payload's length is %u.", (unsigned) *count); return payload; } /* * Read data from X, save to DST. Return 0 on success, * non-zero otherwise. */ static int S_SaveDst (HINTERNET x, FILE *dst) { int rc = 0; TCHAR buffer[1024]; DWORD dw; BOOL irf; Trace ("S_SaveDst"); DEBUG_Print (__FILE__, __LINE__, "sizeof buffer is %u.", (unsigned) (sizeof buffer)); irf = InternetReadFile (x, buffer, sizeof buffer, &dw); DEBUG_Print (__FILE__, __LINE__, "irf is %d. dw is %u. Last error is %ld.", (int) irf, (unsigned) dw, (long) GetLastError ()); while (rc == 0 && irf && dw > 0) { DEBUG_Print (__FILE__, __LINE__, "irf is %d. dw is %u. Last error is %ld.", (int) irf, (unsigned) dw, (long) GetLastError ()); if (fwrite (buffer, dw, 1, dst) == 1) { /* good so far */ } else { LOG_Fwrite (dw, __FILE__, __LINE__); rc = 1631; } irf = InternetReadFile (x, buffer, sizeof buffer, &dw); } Trace ("S_SaveDst"); if (rc == 0) { if (irf && dw == 0) { /* Proper way to exit the loop. Good. */ } else { assert (!irf); LOG_PrintLastError (__FILE__, __LINE__, "S_SaveDst", "Error while reading the server's reply." " InternetReadFile failed"); rc = -35; } } Trace ("S_SaveDst"); return rc; } /* * X is a WinINET request. SRC is the source data; it may be NULL. * DST is the destination for the reply; it must not be NULL. * Send the SRC, read & save the reply. Return 0 on success, non-zero * otherwise. */ static int S_DoRequest (HINTERNET x, FILE *src, FILE *dst) { int rc = 1329; static DWORD flags = FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA; DWORD dw; char *payload; size_t payload_count; Trace ("S_DoRequest"); payload = S_LoadPayload (src, &payload_count); do { if (HttpSendRequest (x, NULL, 0, payload, payload_count)) { dw = ERROR_SUCCESS; } else { dw = InternetErrorDlg (GetDesktopWindow (), x, GetLastError (), flags, NULL); } } while (dw == ERROR_INTERNET_FORCE_RETRY); if (dw == ERROR_SUCCESS) { if (S_SaveDst (x, dst) == 0) { rc = 0; /* good */ } else { DEBUG_Print (__FILE__, __LINE__, "S_SaveDst failed"); rc = 1317; } } else { rc = 218; } if (payload != NULL) { payload = (char *) xfree (payload); } Trace ("S_DoRequest"); return rc; } int WINET_Transact (char url[], FILE *src, FILE *dst) { int rc = 0; HINTERNET inet, conn, x; URL_COMPONENTS urco; static DWORD flags = FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA; if (S_CrackUrl (url, &urco) == 0) { inet = S_InternetOpen (&urco); if (inet != NULL) { conn = S_InternetConnect (inet, &urco); if (conn != NULL) { x = S_HttpOpenRequest (conn, &urco); if (x != NULL) { if (S_DoRequest (x, src, dst) == 0) { rc = 0; /* good */ } else { DEBUG_Print (__FILE__, __LINE__, "S_DoRequest failed"); rc = -1320; } S_InternetCloseHandle (x); } else { DEBUG_Print (__FILE__, __LINE__, "S_HttpOpenRequest failed"); rc = -582; } S_InternetCloseHandle (conn); } else { DEBUG_Print (__FILE__, __LINE__, "S_InternetConnect failed"); rc = 3; } S_InternetCloseHandle (inet); } else { DEBUG_Print (__FILE__, __LINE__, "S_InternetOpen failed"); rc = 3; } } else { fprintf (stderr, "\n%s:%d: S_CrackUrl failed", __FILE__, __LINE__); rc = 1808; } return rc; } /* --- end of file --- */