/* * $Header: /home/gene/library/website/docsrc/httpxtran/src/RCS/xhttp.c,v 395.1 2008/04/20 17:25:51 gene Exp $ * * Copyright (c) 2005 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, struct XHTTP_Proxy *proxy) { static TCHAR agent[] = TEXT (__FILE__); DWORD access_type; static TCHAR *proxy_bypass = NULL; static DWORD flags = 0; HINTERNET hnd; Trace ("S_InternetOpen"); access_type = proxy->hostname ? INTERNET_OPEN_TYPE_PRECONFIG : INTERNET_OPEN_TYPE_PROXY; hnd = InternetOpen (agent, access_type, proxy->hostname, proxy_bypass, flags); if (hnd != NULL) { if (proxy != NULL && proxy->login != NULL) { InternetSetOption (hnd, INTERNET_OPTION_PROXY_USERNAME, proxy->login, strlen (proxy->login)); } if (proxy != NULL && proxy->password != NULL) { InternetSetOption (hnd, INTERNET_OPTION_PROXY_PASSWORD, proxy->password, strlen (proxy->password)); } } else { DEBUG_PrintLastError (__FILE__, __LINE__, "InternetOpen"); assert (hnd == NULL); } return hnd; } /* */ static HINTERNET S_InternetConnect (HINTERNET inet, URL_COMPONENTS *urco, struct XHTTP_Proxy *proxy) { 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, char *post) { 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, post ? TEXT ("POST") : TEXT ("GET"), 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_ReadPayload (HINTERNET hnd, size_t *count) { char *p = NULL; size_t sz = 10 * 1024; DWORD dw; Trace ("S_ReadPayload"); *count = 0; p = (char *) xmalloc (sz); if (p != NULL) { Trace ("S_ReadPayload"); do { if (InternetReadFile (hnd, &p[*count], sz - *count, &dw)) { *count += dw; if (*count >= sz) { sz += 10 * 1024; p = (char *) xrealloc (p, sz); } } else { DEBUG_PrintLastError (__FILE__, __LINE__, "InternetReadFile"); dw = 0; } } while (p != 0 && dw > 0); Trace ("S_ReadPayload"); if (p == NULL) { LOG_OutOfMemory (__FILE__, __LINE__); } } else { LOG_OutOfMemory (__FILE__, __LINE__); } Trace ("S_ReadPayload"); return p; } /* */ int XHTTP_Transact (char url[], char headers[], char post[], size_t count, struct XHTTP_Proxy *proxy, struct XHTTP_TransactReply *reply) { 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; DWORD dw; Trace ("XHTTP_Transact"); assert (reply != NULL); bzero (reply, sizeof *reply); if (S_CrackUrl (url, &urco) == 0) { inet = S_InternetOpen (&urco, proxy); if (inet != NULL) { conn = S_InternetConnect (inet, &urco, proxy); if (conn != NULL) { x = S_HttpOpenRequest (conn, &urco, post); if (x != NULL) { do if (HttpSendRequest (x, headers, -1L, post, post ? count : 0)) { dw = ERROR_SUCCESS; } else { dw = InternetErrorDlg (GetDesktopWindow (), x, GetLastError (), flags, NULL); } while (dw == ERROR_INTERNET_FORCE_RETRY); if (dw == ERROR_SUCCESS) { reply->payload = S_ReadPayload (x, &reply->payload_len); reply->status = 200; /* should obtain from headers */ rc = 0; } else { rc = 218; } 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; } Trace ("XHTTP_Transact"); return rc; } /* --- end of file --- */