http.cc

来自「konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版」· CC 代码 · 共 2,361 行 · 第 1/5 页

CC
2,361
字号
/*   Copyright (C) 2000-2003 Waldo Bastian <bastian@kde.org>   Copyright (C) 2000-2002 George Staikos <staikos@kde.org>   Copyright (C) 2000-2002 Dawit Alemayehu <adawit@kde.org>   Copyright (C) 2001,2002 Hamish Rodda <rodda@kde.org>   This library is free software; you can redistribute it and/or   modify it under the terms of the GNU Library General Public   License (LGPL) as published by the Free Software Foundation;   either version 2 of the License, or (at your option) any later   version.   This library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Library General Public License for more details.   You should have received a copy of the GNU Library General Public License   along with this library; see the file COPYING.LIB.  If not, write to   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,   Boston, MA 02110-1301, USA.*/#include <config.h>#include <errno.h>#include <fcntl.h>#include <utime.h>#include <stdlib.h>#include <signal.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>  // Required for AIX#include <netinet/tcp.h>#include <unistd.h> // must be explicitly included for MacOSX/*#include <netdb.h>#include <sys/time.h>#include <sys/wait.h>*/#include <qdom.h>#include <qfile.h>#include <qregexp.h>#include <qdatetime.h>#include <qstringlist.h>#include <kurl.h>#include <kidna.h>#include <ksocks.h>#include <kdebug.h>#include <klocale.h>#include <kconfig.h>#include <kextsock.h>#include <kservice.h>#include <krfcdate.h>#include <kmdcodec.h>#include <kinstance.h>#include <kresolver.h>#include <kmimemagic.h>#include <dcopclient.h>#include <kdatastream.h>#include <kapplication.h>#include <kstandarddirs.h>#include <kstringhandler.h>#include <kremoteencoding.h>#include "kio/ioslave_defaults.h"#include "kio/http_slave_defaults.h"#include "httpfilter.h"#include "http.h"#ifdef HAVE_LIBGSSAPI#ifdef GSSAPI_MIT#include <gssapi/gssapi.h>#else#include <gssapi.h>#endif /* GSSAPI_MIT */// Catch uncompatible crap (BR86019)#if defined(GSS_RFC_COMPLIANT_OIDS) && (GSS_RFC_COMPLIANT_OIDS == 0)#include <gssapi/gssapi_generic.h>#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name#endif#endif /* HAVE_LIBGSSAPI */#ifndef KONQ_EMBEDDED#include <misc/kntlm/kntlm.h>#endifusing namespace KIO;extern "C" {  KDE_EXPORT int http_kdemain(int argc, char **argv);}int http_kdemain( int argc, char **argv ){  KLocale::setMainCatalogue("kdelibs");  KInstance instance( "kio_http" );  ( void ) KGlobal::locale();  if (argc != 4)  {     fprintf(stderr, "Usage: kio_http protocol domain-socket1 domain-socket2\n");     exit(-1);  }  HTTPProtocol slave(argv[1], argv[2], argv[3]);  slave.dispatchLoop();  return 0;}/***********************************  Generic utility functions ********************/static char * trimLead (char *orig_string){  while (*orig_string == ' ')    orig_string++;  return orig_string;}static bool isCrossDomainRequest( const QString& fqdn, const QString& originURL ){  if (originURL == "true") // Backwards compatibility     return true;  KURL url ( originURL );  // Document Origin domain  QString a = url.host();  // Current request domain  QString b = fqdn;  if (a == b)    return false;  QStringList l1 = QStringList::split('.', a);  QStringList l2 = QStringList::split('.', b);  while(l1.count() > l2.count())      l1.pop_front();  while(l2.count() > l1.count())      l2.pop_front();  while(l2.count() >= 2)  {      if (l1 == l2)          return false;      l1.pop_front();      l2.pop_front();  }  return true;}/*  Eliminates any custom header that could potentically alter the request*/static QString sanitizeCustomHTTPHeader(const QString& _header){  QString sanitizedHeaders;  QStringList headers = QStringList::split("\r\n", _header);  for(QStringList::Iterator it = headers.begin(); it != headers.end(); ++it)  {    QString header = (*it).lower();    // Do not allow Request line to be specified and ignore    // the other HTTP headers.    if (header.find(':') == -1 ||        header.startsWith("host") ||        header.startsWith("via"))      continue;    sanitizedHeaders += (*it);    sanitizedHeaders += "\r\n";  }  return sanitizedHeaders.stripWhiteSpace();}#define NO_SIZE		((KIO::filesize_t) -1)#ifdef HAVE_STRTOLL#define STRTOLL	strtoll#else#define STRTOLL	strtol#endif/************************************** HTTPProtocol **********************************************/HTTPProtocol::HTTPProtocol( const QCString &protocol, const QCString &pool,                            const QCString &app )             :TCPSlaveBase( 0, protocol , pool, app,                            (protocol == "https" || protocol == "webdavs") ){  m_requestQueue.setAutoDelete(true);  m_bBusy = false;  m_bFirstRequest = false;  m_bProxyAuthValid = false;  m_iSize = NO_SIZE;  m_lineBufUnget = 0;  m_protocol = protocol;  m_maxCacheAge = DEFAULT_MAX_CACHE_AGE;  m_maxCacheSize = DEFAULT_MAX_CACHE_SIZE / 2;  m_remoteConnTimeout = DEFAULT_CONNECT_TIMEOUT;  m_remoteRespTimeout = DEFAULT_RESPONSE_TIMEOUT;  m_proxyConnTimeout = DEFAULT_PROXY_CONNECT_TIMEOUT;  m_pid = getpid();  setMultipleAuthCaching( true );  reparseConfiguration();}HTTPProtocol::~HTTPProtocol(){  httpClose(false);}void HTTPProtocol::reparseConfiguration(){  kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::reparseConfiguration" << endl;  m_strProxyRealm = QString::null;  m_strProxyAuthorization = QString::null;  ProxyAuthentication = AUTH_None;  m_bUseProxy = false;  if (m_protocol == "https" || m_protocol == "webdavs")    m_iDefaultPort = DEFAULT_HTTPS_PORT;  else if (m_protocol == "ftp")    m_iDefaultPort = DEFAULT_FTP_PORT;  else    m_iDefaultPort = DEFAULT_HTTP_PORT;}void HTTPProtocol::resetConnectionSettings(){  m_bEOF = false;  m_bError = false;  m_lineCount = 0;  m_iWWWAuthCount = 0;  m_lineCountUnget = 0;  m_iProxyAuthCount = 0;}void HTTPProtocol::resetResponseSettings(){  m_bRedirect = false;  m_redirectLocation = KURL();  m_bChunked = false;  m_iSize = NO_SIZE;  m_responseHeader.clear();  m_qContentEncodings.clear();  m_qTransferEncodings.clear();  m_sContentMD5 = QString::null;  m_strMimeType = QString::null;  setMetaData("request-id", m_request.id);}void HTTPProtocol::resetSessionSettings(){  // Do not reset the URL on redirection if the proxy  // URL, username or password has not changed!  KURL proxy ( config()->readEntry("UseProxy") );  if ( m_strProxyRealm.isEmpty() || !proxy.isValid() ||       m_proxyURL.host() != proxy.host() ||       (!proxy.user().isNull() && proxy.user() != m_proxyURL.user()) ||       (!proxy.pass().isNull() && proxy.pass() != m_proxyURL.pass()) )  {    m_bProxyAuthValid = false;    m_proxyURL = proxy;    m_bUseProxy = m_proxyURL.isValid();    kdDebug(7113) << "(" << m_pid << ") Using proxy: " << m_bUseProxy <<                                              " URL: " << m_proxyURL.url() <<                                            " Realm: " << m_strProxyRealm << endl;  }  m_bPersistentProxyConnection = config()->readBoolEntry("PersistentProxyConnection", false);  kdDebug(7113) << "(" << m_pid << ") Enable Persistent Proxy Connection: "                << m_bPersistentProxyConnection << endl;  m_request.bUseCookiejar = config()->readBoolEntry("Cookies");  m_request.bUseCache = config()->readBoolEntry("UseCache", true);  m_request.bErrorPage = config()->readBoolEntry("errorPage", true);  m_request.bNoAuth = config()->readBoolEntry("no-auth");  m_strCacheDir = config()->readPathEntry("CacheDir");  m_maxCacheAge = config()->readNumEntry("MaxCacheAge", DEFAULT_MAX_CACHE_AGE);  m_request.window = config()->readEntry("window-id");  kdDebug(7113) << "(" << m_pid << ") Window Id = " << m_request.window << endl;  kdDebug(7113) << "(" << m_pid << ") ssl_was_in_use = "                << metaData ("ssl_was_in_use") << endl;  m_request.referrer = QString::null;  if ( config()->readBoolEntry("SendReferrer", true) &&       (m_protocol == "https" || m_protocol == "webdavs" ||        metaData ("ssl_was_in_use") != "TRUE" ) )  {     KURL referrerURL ( metaData("referrer") );     if (referrerURL.isValid())     {        // Sanitize        QString protocol = referrerURL.protocol();        if (protocol.startsWith("webdav"))        {           protocol.replace(0, 6, "http");           referrerURL.setProtocol(protocol);        }        if (protocol.startsWith("http"))        {           referrerURL.setRef(QString::null);           referrerURL.setUser(QString::null);           referrerURL.setPass(QString::null);           m_request.referrer = referrerURL.url();        }     }  }  if ( config()->readBoolEntry("SendLanguageSettings", true) )  {      m_request.charsets = config()->readEntry( "Charsets", "iso-8859-1" );      if ( !m_request.charsets.isEmpty() )          m_request.charsets += DEFAULT_PARTIAL_CHARSET_HEADER;      m_request.languages = config()->readEntry( "Languages", DEFAULT_LANGUAGE_HEADER );  }  else  {      m_request.charsets = QString::null;      m_request.languages = QString::null;  }  // Adjust the offset value based on the "resume" meta-data.  QString resumeOffset = metaData("resume");  if ( !resumeOffset.isEmpty() )     m_request.offset = resumeOffset.toInt(); // TODO: Convert to 64 bit  else     m_request.offset = 0;  m_request.disablePassDlg = config()->readBoolEntry("DisablePassDlg", false);  m_request.allowCompressedPage = config()->readBoolEntry("AllowCompressedPage", true);  m_request.id = metaData("request-id");  // Store user agent for this host.  if ( config()->readBoolEntry("SendUserAgent", true) )     m_request.userAgent = metaData("UserAgent");  else     m_request.userAgent = QString::null;  // Deal with cache cleaning.  // TODO: Find a smarter way to deal with cleaning the  // cache ?  if ( m_request.bUseCache )    cleanCache();  // Deal with HTTP tunneling  if ( m_bIsSSL && m_bUseProxy && m_proxyURL.protocol() != "https" &&       m_proxyURL.protocol() != "webdavs")  {    m_bNeedTunnel = true;    setRealHost( m_request.hostname );    kdDebug(7113) << "(" << m_pid << ") SSL tunnel: Setting real hostname to: "                  << m_request.hostname << endl;  }  else  {    m_bNeedTunnel = false;    setRealHost( QString::null);  }  m_responseCode = 0;  m_prevResponseCode = 0;  m_strRealm = QString::null;  m_strAuthorization = QString::null;  Authentication = AUTH_None;  // Obtain the proxy and remote server timeout values  m_proxyConnTimeout = proxyConnectTimeout();  m_remoteConnTimeout = connectTimeout();  m_remoteRespTimeout = responseTimeout();  // Bounce back the actual referrer sent  setMetaData("referrer", m_request.referrer);  // Set the SSL meta-data here...  setSSLMetaData();  // Follow HTTP/1.1 spec and enable keep-alive by default  // unless the remote side tells us otherwise or we determine  // the persistent link has been terminated by the remote end.  m_bKeepAlive = true;  m_keepAliveTimeout = 0;  m_bUnauthorized = false;  // A single request can require multiple exchanges with the remote  // server due to authentication challenges or SSL tunneling.  // m_bFirstRequest is a flag that indicates whether we are  // still processing the first request. This is important because we  // should not force a close of a keep-alive connection in the middle  // of the first request.  // m_bFirstRequest is set to "true" whenever a new connection is  // made in httpOpenConnection()  m_bFirstRequest = false;}void HTTPProtocol::setHost( const QString& host, int port,                            const QString& user, const QString& pass ){#if !defined(QT_NO_DOM)  // Reset the webdav-capable flags for this host  if ( m_request.hostname != host )    m_davHostOk = m_davHostUnsupported = false;#endif  // is it an IPv6 address?  if (host.find(':') == -1)    {      m_request.hostname = host;      m_request.encoded_hostname = KIDNA::toAscii(host);    }  else    {      m_request.hostname = host;      int pos = host.find('%');      if (pos == -1)	m_request.encoded_hostname = '[' + host + ']';      else	// don't send the scope-id in IPv6 addresses to the server	m_request.encoded_hostname = '[' + host.left(pos) + ']';    }  m_request.port = (port == 0) ? m_iDefaultPort : port;  m_request.user = user;  m_request.passwd = pass;  m_bIsTunneled = false;  kdDebug(7113) << "(" << m_pid << ") Hostname is now: " << m_request.hostname <<    " (" << m_request.encoded_hostname << ")" <<endl;}bool HTTPProtocol::checkRequestURL( const KURL& u ){  kdDebug (7113) << "(" << m_pid << ") HTTPProtocol::checkRequestURL:  " << u.url() << endl;  m_request.url = u;  if (m_request.hostname.isEmpty())  {     error( KIO::ERR_UNKNOWN_HOST, i18n("No host specified."));     return false;  }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?