/* $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;
}