/* $Id: glibwww-init.cc,v 1.1.1.1 2003/07/04 22:30:06 atterer Exp $ -*- C++ -*- This code was taken from glibwww2 , main author: James Henstdridge , distributable under GPL, v2 or later. */ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ #undef PACKAGE #undef _ extern "C" { #include #include #include #include #include #include #include #include #include } /* clean up the cpp namespace -- libwww is particularly dirty */ #undef PACKAGE #undef VERSION #undef _ #include #include #ifndef FTP_PORT #define FTP_PORT 21 #endif #ifndef HTTP_PORT #define HTTP_PORT 80 #endif /*#include "WWWMIME.h"*/ static void HTMIMEInit (void); /*static*/ void glibwww_parse_proxy_env (void); static int HTProxyFilter (HTRequest *request, void *param, int status); static int HTRedirectFilter (HTRequest *request, HTResponse *response, void *param, int status); static int HTCredentialsFilter (HTRequest *request, void *param, int status); static int HTAuthFilter (HTRequest *request, HTResponse *response, void *param, int status); static int HTAuthInfoFilter (HTRequest *request, HTResponse *response, void *param, int status); static gboolean exitfunc = FALSE; void glibwww_init(const gchar *appName, const gchar *appVersion) { if (!HTLib_isInitialized()) HTLibInit(appName, appVersion); /*HTAlertInit(); HTAlert_setInteractive(NO);*/ HTTransport_add("tcp", HT_TP_SINGLE,HTReader_new,HTWriter_new); HTTransport_add("buffered_tcp",HT_TP_SINGLE,HTReader_new,HTBufferWriter_new); HTTransport_add("local", HT_TP_SINGLE,HTReader_new,HTWriter_new); HTProtocol_add("ftp", "tcp", FTP_PORT, NO, HTLoadFTP, NULL); HTProtocol_add("http", "buffered_tcp", HTTP_PORT, NO, HTLoadHTTP, NULL); HTProtocol_add("file", "local", 0, NO, HTLoadFile, NULL); HTNet_setMaxSocket(6); HTNet_addBefore(HTCredentialsFilter, "http://*", NULL, HT_FILTER_LATE); HTNet_addBefore(HTProxyFilter, NULL, NULL, HT_FILTER_LATE); HTNet_addAfter(HTAuthFilter, "http://*", NULL, HT_NO_ACCESS, HT_FILTER_MIDDLE); HTNet_addAfter(HTAuthFilter, "http://*", NULL, HT_REAUTH, HT_FILTER_MIDDLE); HTNet_addAfter(HTRedirectFilter, "http://*", NULL, HT_PERM_REDIRECT, HT_FILTER_MIDDLE); HTNet_addAfter(HTRedirectFilter, "http://*", NULL, HT_FOUND, HT_FILTER_MIDDLE); HTNet_addAfter(HTRedirectFilter, "http://*", NULL, HT_SEE_OTHER, HT_FILTER_MIDDLE); HTNet_addAfter(HTRedirectFilter, "http://*", NULL, HT_TEMP_REDIRECT, HT_FILTER_MIDDLE); HTNet_addAfter(HTAuthInfoFilter, "http://*", NULL, HT_ALL, HT_FILTER_MIDDLE); HTAA_newModule ("basic", HTBasic_generate, HTBasic_parse, NULL, HTBasic_delete); //[RA]glibwww_parse_proxy_env(); /* set proxy from our config files ... */ /* glibwww_add_proxy("http", ...); */ /* glibwww_add_proxy("ftp", ...); */ HTMIME_setSaveStream (HTSaveLocally); HTFormat_addConversion("message/rfc822", "*/*", HTMIMEConvert, 1.0, 0.0, 0.0); HTFormat_addConversion("message/x-rfc822-foot", "*/*", HTMIMEFooter, 1.0, 0.0, 0.0); HTFormat_addConversion("message/x-rfc822-head", "*/*", HTMIMEHeader, 1.0, 0.0, 0.0); HTFormat_addConversion("message/x-rfc822-cont", "*/*", HTMIMEContinue, 1.0, 0.0, 0.0); HTFormat_addConversion("message/x-rfc822-upgrade", "*/*", HTMIMEUpgrade, 1.0, 0.0, 0.0); HTFormat_addConversion("message/x-rfc822-partial", "*/*", HTMIMEPartial, 1.0, 0.0, 0.0); HTFormat_addConversion("text/x-http", "*/*", HTTPStatus_new, 1.0, 0.0, 0.0); HTFormat_addCoding("*", HTIdentityCoding, HTIdentityCoding, 0.3); HTFormat_addTransferCoding("deflate", NULL, HTZLib_inflate, 1.0); HTFormat_addTransferCoding("chunked", HTChunkedEncoder,HTChunkedDecoder,1.0); HTMIMEInit(); HTFileInit(); HTHost_setEventTimeout(30000); HTFTP_setTransferMode(FTP_BINARY_TRANSFER_MODE); glibwww_register_callbacks(); if (!exitfunc) g_atexit(glibwww_cleanup); exitfunc = TRUE; /*WWWTRACE = SHOW_MEM_TRACE;*/ } void glibwww_cleanup(void) { if (HTLib_isInitialized()) { HTFormat_deleteAll(); //HTLibTerminate(); Causes segfaults -- RA } } struct ProxyEntry { gchar *protocol; gchar *proxy; }; static GList *proxies = NULL; static GList *noproxy = NULL; void glibwww_add_proxy(const gchar *protocol, const gchar *proxy) { GList *tmp; struct ProxyEntry *ent; for (tmp = proxies; tmp; tmp = tmp->next) { ent = static_cast(tmp->data); if (!g_ascii_strcasecmp(protocol, ent->protocol)) { // g_free(ent->proxy); // ent->proxy = g_strdup(proxy); // RA: allow proxy==null to delete existing entry g_free(ent->proxy); if (proxy) { ent->proxy = g_strdup(proxy); } else { g_free(ent->protocol); proxies = g_list_remove(proxies, ent); g_free(ent); } return; } } // RA: allow proxy==null to delete existing entry if (proxy == 0) return; ent = g_new(struct ProxyEntry, 1); ent->protocol = g_strdup(protocol); ent->proxy = g_strdup(proxy); proxies = g_list_prepend(proxies, ent); } void glibwww_add_noproxy(const gchar *host) { noproxy = g_list_prepend(noproxy, g_strdup(host)); } static const gchar * glibwww_get_proxy(const gchar *url) { gchar *protocol; GList *tmp; if (!url || !proxies) return NULL; if (noproxy) { char *host = HTParse(url, "", PARSE_HOST); char *ptr = strchr(host, ':'); if (ptr != NULL) *ptr = ':'; for (tmp = noproxy; tmp; tmp = tmp->next) { char *nophost = static_cast(tmp->data); char *np = nophost + strlen(nophost); char *hp = host + strlen(host); while (np>=nophost && hp>=host && (*np--==*hp--)) ; if (np==nophost-1 && (hp==host-1 || *hp=='.')) return NULL; } free(host); } protocol = HTParse(url, "", PARSE_ACCESS); for (tmp = proxies; tmp; tmp = tmp->next) { struct ProxyEntry *ent = static_cast(tmp->data); if (!g_ascii_strcasecmp(ent->protocol, protocol)) { HT_FREE(protocol); return ent->proxy; } } HT_FREE(protocol); return NULL; } /*[RA]static*/ void glibwww_parse_proxy_env(void) { static const char *protocollist[] = { "http", "ftp", "news", "wais", "gopher", NULL }; const char **prot = protocollist; char *nop; for (prot = protocollist; *prot != NULL; prot++) { gchar *var = g_strconcat(*prot, "_proxy", NULL); gchar *proxy = getenv(var); if (proxy && proxy[0]) glibwww_add_proxy(*prot, proxy); else { gchar *up = var; while ((*up = TOUPPER(*up))) up++; if ((proxy = getenv(var)) != NULL && proxy[0]) glibwww_add_proxy(*prot, proxy); } g_free(var); } nop = getenv("no_proxy"); if (nop && nop[0]) { char *str = g_strdup(nop); char *ptr = str; char *name; while ((name = HTNextField(&ptr)) != NULL) glibwww_add_noproxy(name); g_free(str); } } /* mime initialisation */ static void HTMIMEInit(void) { struct { char *string; HTParserCallback *pHandler; } fixedHandlers[] = { {"accept", &HTMIME_accept}, {"accept-charset", &HTMIME_acceptCharset}, {"accept-encoding", &HTMIME_acceptEncoding}, {"accept-language", &HTMIME_acceptLanguage}, {"accept-ranges", &HTMIME_acceptRanges}, {"authorization", NULL}, {"cache-control", &HTMIME_cacheControl}, {"connection", &HTMIME_connection}, {"content-encoding", &HTMIME_contentEncoding}, {"content-length", &HTMIME_contentLength}, {"content-range", &HTMIME_contentRange}, {"content-transfer-encoding", &HTMIME_contentTransferEncoding}, {"content-type", &HTMIME_contentType}, {"digest-MessageDigest", &HTMIME_messageDigest}, {"keep-alive", &HTMIME_keepAlive}, {"link", &HTMIME_link}, {"location", &HTMIME_location}, {"max-forwards", &HTMIME_maxForwards}, {"mime-version", NULL}, {"pragma", &HTMIME_pragma}, {"protocol", &HTMIME_protocol}, {"protocol-info", &HTMIME_protocolInfo}, {"protocol-request", &HTMIME_protocolRequest}, {"proxy-authenticate", &HTMIME_authenticate}, {"proxy-authorization", &HTMIME_proxyAuthorization}, {"public", &HTMIME_public}, {"range", &HTMIME_range}, {"referer", &HTMIME_referer}, {"retry-after", &HTMIME_retryAfter}, {"server", &HTMIME_server}, {"trailer", &HTMIME_trailer}, {"transfer-encoding", &HTMIME_transferEncoding}, {"upgrade", &HTMIME_upgrade}, {"user-agent", &HTMIME_userAgent}, {"vary", &HTMIME_vary}, {"via", &HTMIME_via}, {"warning", &HTMIME_warning}, {"www-authenticate", &HTMIME_authenticate}, {"authentication-info", &HTMIME_authenticationInfo}, {"proxy-authentication-info", &HTMIME_proxyAuthenticationInfo} }; size_t i; for (i = 0; i < sizeof(fixedHandlers)/sizeof(fixedHandlers[0]); i++) HTHeader_addParser(fixedHandlers[i].string, NO, fixedHandlers[i].pHandler); } /* the following filters are from HTFilter.c: */ static int HTProxyFilter(HTRequest *request, void */*param*/, int /*status*/) { HTParentAnchor *anchor = HTRequest_anchor(request); char *addr = HTAnchor_physical(anchor); const char *physical = NULL; if ((physical = glibwww_get_proxy(addr))) { HTRequest_setFullURI(request, YES); HTRequest_setProxy(request, physical); } else { HTRequest_setFullURI(request, NO); HTRequest_deleteProxy(request); } return HT_OK; } static int HTRedirectFilter(HTRequest *request, HTResponse *response, void */*param*/, int /*status*/) { HTMethod method = HTRequest_method(request); HTAnchor *new_anchor = HTResponse_redirection(response); if (!new_anchor) return HT_OK; if (!HTMethod_isSafe(method)) return HT_OK; HTRequest_deleteCredentialsAll(request); if (HTRequest_doRetry(request)) { HTRequest_setAnchor(request, new_anchor); HTLoad(request, NO); } else { HTRequest_addError(request, ERR_FATAL, NO, HTERR_MAX_REDIRECT, NULL, 0, "HTRedirectFilter"); return HT_OK; } return HT_ERROR; } static int HTCredentialsFilter(HTRequest *request, void *param, int status) { if (HTAA_beforeFilter(request, param, status) == HT_OK) return HT_OK; else { HTRequest_addError(request, ERR_FATAL, NO, HTERR_UNAUTHORIZED, NULL, 0, "HTCredentialsFilter"); return HT_ERROR; } } static int HTAuthFilter(HTRequest *request, HTResponse *response, void *param, int status) { if (HTAA_afterFilter(request, response, param, status) == HT_OK) { HTLoad(request, NO); return HT_ERROR; } return HT_OK; } static int HTAuthInfoFilter(HTRequest *request, HTResponse *response, void *param, int status) { if (!HTResponse_challenge(response)) return HT_OK; else if (HTAA_updateFilter(request, response, param, status) == HT_OK) return HT_OK; else return HT_ERROR; }