/* * Copyright (c) 2004 Nokia. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Nokia nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include //atoi #include #include #if defined(HAVE_CONFIG_H) #include #endif #include "Http.h" #if defined(HAVE_LIBCURL) #include "HttpCurl.h" #endif #if defined(HAVE_LIBSOUP) #include "HttpLibsoup.h" #endif #if !defined(HAVE_LIBCURL) && !defined(HAVE_LIBSOUP) #error Need curl or libsoup. #endif class CombinerFactory : public HttpFactory { private: friend HttpFactory& getHttpFactory(); public: ~CombinerFactory(); bool canProvide(const gchar * url) const; HttpRequest* createRequest(HttpRequestListener* listener, OSB::URLCredentialStorage* credentials, const gchar * url, const gchar* cookies, HttpRequest::Method type); HttpRequest* createSynchronizedRequest(HttpRequestListener* listener, OSB::URLCredentialStorage* credentials, const gchar * url, const gchar* cookies, HttpRequest::Method type); void setProxy(const gchar * proto, const gchar * url); private: CombinerFactory(); private: HttpFactory* factoryForURL(const gchar * url) const; GList * factories; }; CombinerFactory::CombinerFactory() :factories(0) { #if defined(HAVE_LIBSOUP) factories = g_list_append(factories, new LibsoupFactory()); #endif #if defined(HAVE_LIBCURL) factories = g_list_append(factories, new CurlFactory()); #endif } extern "C" { static void factoriesDeleter(gpointer data, gpointer user_data) { HttpFactory* factory = static_cast(data); delete factory; } } CombinerFactory::~CombinerFactory() { g_list_foreach(factories, factoriesDeleter, this); g_list_free(factories); } extern"C"{ static gboolean findFactoryFunc(gconstpointer fact, gconstpointer data) { const HttpFactory * factory = static_cast(fact); const gchar * url = static_cast(data); return factory->canProvide(url)? 0 : -1; } } HttpFactory* CombinerFactory::factoryForURL(const gchar * url) const { GList * item = g_list_find_custom(factories, url, findFactoryFunc); if (item) { return static_cast(item->data); } return 0; } bool CombinerFactory::canProvide(const gchar * url) const { return factoryForURL(url) != 0; } HttpRequest* CombinerFactory::createRequest(HttpRequestListener* listener, OSB::URLCredentialStorage* credentials, const gchar * url, const gchar* cookies, HttpRequest::Method type) { HttpFactory *f = factoryForURL(url); if (f) return f->createRequest(listener, credentials, url, cookies, type); return 0; } HttpRequest* CombinerFactory::createSynchronizedRequest(HttpRequestListener* listener, OSB::URLCredentialStorage* credentials, const gchar * url, const gchar* cookies, HttpRequest::Method type) { HttpFactory *f = factoryForURL(url); if (f) return f->createSynchronizedRequest(listener, credentials, url, cookies, type); return 0; } void CombinerFactory::setProxy(const gchar * proto, const gchar * proxyURL) { HttpFactory *f = factoryForURL(proto); if (f) { f->setProxy(proto, proxyURL); } } HttpFactory& getHttpFactory() { static CombinerFactory factory; return factory; } HttpRequestListener* HttpFactory::dummyListener() { static HttpRequestListener single; return &single; } /** HttpRequest */ HttpRequest::HttpRequest(HttpRequestListener* aListener, const gchar * aurl, const gchar * acookies, Method atype) :m_listener(aListener) ,m_url(g_strdup(aurl)) ,m_cookies(g_strdup(acookies)) ,m_authRealm(0) ,m_authScheme(0) ,m_authIsProxy(false) ,m_agent(0) ,m_referrer(0) ,m_reload(false) ,m_type(atype) { m_listener->attached(this); } HttpRequest::~HttpRequest() { g_free(m_url); g_free(m_cookies); g_free(m_authRealm); g_free(m_authScheme); g_free(m_agent); g_free(m_referrer); m_listener->detached(this); m_listener = 0; } void HttpRequest::setType(Method type) { m_type = m_type; } void HttpRequest::setPostData(const gchar * contentType, GByteArray * buf) { } HttpHeaderLocation::HttpHeaderLocation(const gchar * value) :HttpHeader(Location, "Location", value) { } HttpHeaderRefresh::HttpHeaderRefresh(const gchar * value) :HttpHeader(Refresh, "Http-Refresh", value) { } HttpHeaderContentType::HttpHeaderContentType(const gchar * value) :HttpHeader(ContentType, "Content-Type", value) ,m_contentType(0) ,m_encoding(0) { gchar **chunks = g_strsplit(value, ";", 2); assert(chunks); int i = 0; while(chunks[i]) { gchar* charset = strstr(chunks[i], "charset="); if (charset) { // assume "CONTENT-TYPE; charset=CHARSET-NAME" or "charset=CHARSET-NAME" if (!m_encoding) { m_encoding = g_strstrip(g_strdup(charset+8)); g_free(chunks[i]); } } else { // assume "CONTENT-TYPE" or "CONTENT-TYPE; CHARSET-NAME" if (!m_contentType) m_contentType = chunks[i]; else if (!m_encoding) m_encoding = chunks[i]; } ++i; } g_free(chunks); } HttpHeaderContentType::~HttpHeaderContentType() { if (m_contentType) g_free(m_contentType); if (m_encoding) g_free(m_encoding); } HttpHeaderContentLength::HttpHeaderContentLength(const gchar * value) :HttpHeader(ContentLength, "Content-Length", value) ,m_length(0) { assert(value); gchar* endptr = 0; m_length = strtol(value, &endptr, 10); if (!(*value != '\0' && endptr && *endptr=='\0')) m_length = -1; } HttpHeaderSetCookie::HttpHeaderSetCookie(const gchar * value) : HttpHeader(SetCookie, "Set-Cookie", value) { }