32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <netinet/tcp.h>
46 #include <tqdatetime.h>
47 #include <tqstringlist.h>
54 #include <tdelocale.h>
55 #include <tdeconfig.h>
60 #include <kinstance.h>
61 #include <kresolver.h>
62 #include <kmimemagic.h>
63 #include <dcopclient.h>
64 #include <kdatastream.h>
65 #include <tdeapplication.h>
66 #include <kstandarddirs.h>
67 #include <kstringhandler.h>
68 #include <kremoteencoding.h>
70 #include "tdeio/ioslave_defaults.h"
71 #include "tdeio/http_slave_defaults.h"
73 #include "httpfilter.h"
78 #include <gssapi/gssapi.h>
84 #if defined(GSS_RFC_COMPLIANT_OIDS) && (GSS_RFC_COMPLIANT_OIDS == 0)
85 #include <gssapi/gssapi_generic.h>
86 #define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
91 #include <misc/tdentlm/tdentlm.h>
93 using namespace TDEIO;
96 TDE_EXPORT
int kdemain(
int argc,
char **argv);
99 int kdemain(
int argc,
char **argv )
101 TDELocale::setMainCatalogue(
"tdelibs");
102 TDEInstance instance(
"tdeio_http" );
103 ( void ) TDEGlobal::locale();
107 fprintf(stderr,
"Usage: tdeio_http protocol domain-socket1 domain-socket2\n");
111 HTTPProtocol slave(argv[1], argv[2], argv[3]);
112 slave.dispatchLoop();
118 static char * trimLead (
char *orig_string)
120 while (*orig_string ==
' ')
125 static bool isCrossDomainRequest(
const TQString& fqdn,
const TQString& originURL )
127 if (originURL ==
"true")
130 KURL url ( originURL );
133 TQString a = url.host();
141 TQStringList l1 = TQStringList::split(
'.', a);
142 TQStringList l2 = TQStringList::split(
'.', b);
144 while(l1.count() > l2.count())
147 while(l2.count() > l1.count())
150 while(l2.count() >= 2)
165 static TQString sanitizeCustomHTTPHeader(
const TQString& _header)
167 TQString sanitizedHeaders;
168 TQStringList headers = TQStringList::split(TQRegExp(
"[\r\n]"), _header);
170 for(TQStringList::Iterator it = headers.begin(); it != headers.end(); ++it)
172 TQString header = (*it).lower();
175 if (header.find(
':') == -1 ||
176 header.startsWith(
"host") ||
177 header.startsWith(
"via"))
180 sanitizedHeaders += (*it);
181 sanitizedHeaders +=
"\r\n";
184 return sanitizedHeaders.stripWhiteSpace();
187 static TQString htmlEscape(
const TQString &plain)
190 rich.reserve(uint(plain.length() * 1.1));
191 for (uint i = 0; i < plain.length(); ++i) {
192 if (plain.at(i) ==
'<') {
194 }
else if (plain.at(i) ==
'>') {
196 }
else if (plain.at(i) ==
'&') {
198 }
else if (plain.at(i) ==
'"') {
209 #define NO_SIZE ((TDEIO::filesize_t) -1)
212 #define STRTOLL strtoll
214 #define STRTOLL strtol
220 HTTPProtocol::HTTPProtocol(
const TQCString &protocol,
const TQCString &pool,
221 const TQCString &app )
222 :TCPSlaveBase( 0, protocol , pool, app,
223 (protocol ==
"https" || protocol ==
"webdavs") )
225 m_requestQueue.setAutoDelete(
true);
228 m_bFirstRequest =
false;
229 m_bProxyAuthValid =
false;
234 m_protocol = protocol;
236 m_maxCacheAge = DEFAULT_MAX_CACHE_AGE;
237 m_maxCacheSize = DEFAULT_MAX_CACHE_SIZE / 2;
238 m_remoteConnTimeout = DEFAULT_CONNECT_TIMEOUT;
239 m_remoteRespTimeout = DEFAULT_RESPONSE_TIMEOUT;
240 m_proxyConnTimeout = DEFAULT_PROXY_CONNECT_TIMEOUT;
244 setMultipleAuthCaching(
true );
245 reparseConfiguration();
248 HTTPProtocol::~HTTPProtocol()
253 void HTTPProtocol::reparseConfiguration()
255 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::reparseConfiguration" << endl;
257 m_strProxyRealm = TQString::null;
258 m_strProxyAuthorization = TQString::null;
259 ProxyAuthentication = AUTH_None;
262 if (m_protocol ==
"https" || m_protocol ==
"webdavs")
263 m_iDefaultPort = DEFAULT_HTTPS_PORT;
264 else if (m_protocol ==
"ftp")
265 m_iDefaultPort = DEFAULT_FTP_PORT;
267 m_iDefaultPort = DEFAULT_HTTP_PORT;
270 void HTTPProtocol::resetConnectionSettings()
276 m_lineCountUnget = 0;
277 m_iProxyAuthCount = 0;
281 void HTTPProtocol::resetResponseSettings()
284 m_redirectLocation = KURL();
288 m_responseHeader.clear();
289 m_qContentEncodings.clear();
290 m_qTransferEncodings.clear();
291 m_sContentMD5 = TQString::null;
292 m_strMimeType = TQString::null;
294 setMetaData(
"request-id", m_request.id);
297 void HTTPProtocol::resetSessionSettings()
301 KURL proxy ( config()->readEntry(
"UseProxy") );
303 if ( m_strProxyRealm.isEmpty() || !proxy.isValid() ||
304 m_proxyURL.host() != proxy.host() ||
305 (!proxy.user().isNull() && proxy.user() != m_proxyURL.user()) ||
306 (!proxy.pass().isNull() && proxy.pass() != m_proxyURL.pass()) )
308 m_bProxyAuthValid =
false;
310 m_bUseProxy = m_proxyURL.isValid();
312 kdDebug(7113) <<
"(" << m_pid <<
") Using proxy: " << m_bUseProxy <<
313 " URL: " << m_proxyURL.prettyURL() <<
314 " Realm: " << m_strProxyRealm << endl;
317 m_bPersistentProxyConnection = config()->readBoolEntry(
"PersistentProxyConnection",
false);
318 kdDebug(7113) <<
"(" << m_pid <<
") Enable Persistent Proxy Connection: "
319 << m_bPersistentProxyConnection << endl;
321 m_request.bUseCookiejar = config()->readBoolEntry(
"Cookies");
322 m_request.bUseCache = config()->readBoolEntry(
"UseCache",
true);
323 m_request.bErrorPage = config()->readBoolEntry(
"errorPage",
true);
324 m_request.bNoAuth = config()->readBoolEntry(
"no-auth");
325 m_strCacheDir = config()->readPathEntry(
"CacheDir");
326 m_maxCacheAge = config()->readNumEntry(
"MaxCacheAge", DEFAULT_MAX_CACHE_AGE);
327 m_request.window = config()->readEntry(
"window-id");
329 kdDebug(7113) <<
"(" << m_pid <<
") Window Id = " << m_request.window << endl;
330 kdDebug(7113) <<
"(" << m_pid <<
") ssl_was_in_use = "
331 << metaData (
"ssl_was_in_use") << endl;
333 m_request.referrer = TQString::null;
334 if ( config()->readBoolEntry(
"SendReferrer",
true) &&
335 (m_protocol ==
"https" || m_protocol ==
"webdavs" ||
336 metaData (
"ssl_was_in_use") !=
"TRUE" ) )
338 KURL referrerURL ( metaData(
"referrer") );
339 if (referrerURL.isValid())
342 TQString protocol = referrerURL.protocol();
343 if (protocol.startsWith(
"webdav"))
345 protocol.replace(0, 6,
"http");
346 referrerURL.setProtocol(protocol);
349 if (protocol.startsWith(
"http"))
351 referrerURL.setRef(TQString::null);
352 referrerURL.setUser(TQString::null);
353 referrerURL.setPass(TQString::null);
354 m_request.referrer = referrerURL.url();
359 if ( config()->readBoolEntry(
"SendLanguageSettings",
true) )
361 m_request.charsets = config()->readEntry(
"Charsets",
"iso-8859-1" );
363 if ( !m_request.charsets.isEmpty() )
364 m_request.charsets += DEFAULT_PARTIAL_CHARSET_HEADER;
366 m_request.languages = config()->readEntry(
"Languages", DEFAULT_LANGUAGE_HEADER );
370 m_request.charsets = TQString::null;
371 m_request.languages = TQString::null;
375 TQString resumeOffset = metaData(
"resume");
376 if ( !resumeOffset.isEmpty() )
377 m_request.offset = resumeOffset.toInt();
379 m_request.offset = 0;
381 m_request.disablePassDlg = config()->readBoolEntry(
"DisablePassDlg",
false);
382 m_request.allowCompressedPage = config()->readBoolEntry(
"AllowCompressedPage",
true);
383 m_request.id = metaData(
"request-id");
386 if ( config()->readBoolEntry(
"SendUserAgent",
true) )
387 m_request.userAgent = metaData(
"UserAgent");
389 m_request.userAgent = TQString::null;
394 if ( m_request.bUseCache )
398 if ( m_bIsSSL && m_bUseProxy && m_proxyURL.protocol() !=
"https" &&
399 m_proxyURL.protocol() !=
"webdavs")
401 m_bNeedTunnel =
true;
402 setRealHost( m_request.hostname );
403 kdDebug(7113) <<
"(" << m_pid <<
") SSL tunnel: Setting real hostname to: "
404 << m_request.hostname << endl;
408 m_bNeedTunnel =
false;
409 setRealHost( TQString::null);
413 m_prevResponseCode = 0;
415 m_strRealm = TQString::null;
416 m_strAuthorization = TQString::null;
417 Authentication = AUTH_None;
420 m_proxyConnTimeout = proxyConnectTimeout();
421 m_remoteConnTimeout = connectTimeout();
422 m_remoteRespTimeout = responseTimeout();
428 setMetaData(
"referrer", m_request.referrer);
434 m_keepAliveTimeout = 0;
435 m_bUnauthorized =
false;
445 m_bFirstRequest =
false;
448 void HTTPProtocol::setHost(
const TQString& host,
int port,
449 const TQString& user,
const TQString& pass )
452 if ( m_request.hostname != host )
453 m_davHostOk = m_davHostUnsupported =
false;
456 if (host.find(
':') == -1)
458 m_request.hostname = host;
459 m_request.encoded_hostname = KIDNA::toAscii(host);
463 m_request.hostname = host;
464 int pos = host.find(
'%');
466 m_request.encoded_hostname =
'[' + host +
']';
469 m_request.encoded_hostname =
'[' + host.left(pos) +
']';
471 m_request.port = (port == 0) ? m_iDefaultPort : port;
472 m_request.user = user;
473 m_request.passwd = pass;
475 m_bIsTunneled =
false;
477 kdDebug(7113) <<
"(" << m_pid <<
") Hostname is now: " << m_request.hostname <<
478 " (" << m_request.encoded_hostname <<
")" <<endl;
481 bool HTTPProtocol::checkRequestURL(
const KURL& u )
483 kdDebug (7113) <<
"(" << m_pid <<
") HTTPProtocol::checkRequestURL: " << u.prettyURL() << endl;
487 if (m_request.hostname.isEmpty())
489 error( TDEIO::ERR_UNKNOWN_HOST, i18n(
"No host specified."));
493 if (u.path().isEmpty())
502 if ( m_protocol != u.protocol().latin1() )
504 short unsigned int oldDefaultPort = m_iDefaultPort;
505 m_protocol = u.protocol().latin1();
506 reparseConfiguration();
507 if ( m_iDefaultPort != oldDefaultPort &&
508 m_request.port == oldDefaultPort )
509 m_request.port = m_iDefaultPort;
512 resetSessionSettings();
516 void HTTPProtocol::retrieveContent(
bool dataInternal )
518 kdDebug (7113) <<
"(" << m_pid <<
") HTTPProtocol::retrieveContent " << endl;
519 if ( !retrieveHeader(
false ) )
526 if ( !readBody( dataInternal ) && m_bError )
530 httpClose(m_bKeepAlive);
536 if ((m_responseCode == 204) &&
537 ((m_request.method == HTTP_GET) || (m_request.method == HTTP_POST)))
538 error(ERR_NO_CONTENT,
"");
544 bool HTTPProtocol::retrieveHeader(
bool close_connection )
546 kdDebug (7113) <<
"(" << m_pid <<
") HTTPProtocol::retrieveHeader " << endl;
552 resetResponseSettings();
560 kdDebug(7113) <<
"(" << m_pid <<
") Re-establishing SSL tunnel..." << endl;
561 httpCloseConnection();
568 kdDebug(7113) <<
"(" << m_pid <<
") Previous Response: "
569 << m_prevResponseCode << endl;
570 kdDebug(7113) <<
"(" << m_pid <<
") Current Response: "
571 << m_responseCode << endl;
573 if (isSSLTunnelEnabled() && m_bIsSSL && !m_bUnauthorized && !m_bError)
576 if ( m_responseCode < 400 )
578 kdDebug(7113) <<
"(" << m_pid <<
") Unset tunneling flag!" << endl;
579 setEnableSSLTunnel(
false );
580 m_bIsTunneled =
true;
582 m_responseCode = m_prevResponseCode;
587 if ( !m_request.bErrorPage )
589 kdDebug(7113) <<
"(" << m_pid <<
") Sending an error message!" << endl;
590 error( ERR_UNKNOWN_PROXY_HOST, m_proxyURL.host() );
594 kdDebug(7113) <<
"(" << m_pid <<
") Sending an error page!" << endl;
598 if (m_responseCode < 400 && (m_prevResponseCode == 401 ||
599 m_prevResponseCode == 407))
606 if (!m_bufPOST.isEmpty())
609 kdDebug(7113) <<
"(" << m_pid <<
") HTTP::retreiveHeader: Cleared POST "
613 if ( close_connection )
615 httpClose(m_bKeepAlive);
622 void HTTPProtocol::stat(
const KURL& url)
624 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::stat " << url.prettyURL()
627 if ( !checkRequestURL( url ) )
630 if ( m_protocol !=
"webdav" && m_protocol !=
"webdavs" )
632 TQString statSide = metaData(TQString::fromLatin1(
"statSide"));
633 if ( statSide !=
"source" )
636 error( ERR_DOES_NOT_EXIST, url.prettyURL() );
643 atom.m_uds = TDEIO::UDS_NAME;
644 atom.m_str = url.fileName();
645 entry.append( atom );
647 atom.m_uds = TDEIO::UDS_FILE_TYPE;
648 atom.m_long = S_IFREG;
649 entry.append( atom );
651 atom.m_uds = TDEIO::UDS_ACCESS;
652 atom.m_long = S_IRUSR | S_IRGRP | S_IROTH;
653 entry.append( atom );
663 void HTTPProtocol::listDir(
const KURL& url )
665 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::listDir " << url.prettyURL()
668 if ( !checkRequestURL( url ) )
671 if (!url.protocol().startsWith(
"webdav")) {
672 error(ERR_UNSUPPORTED_ACTION, url.prettyURL());
676 davStatList( url,
false );
679 void HTTPProtocol::davSetRequest(
const TQCString& requestXML )
682 m_bufPOST = requestXML;
684 if (m_bufPOST.size())
685 m_bufPOST.truncate( m_bufPOST.size() - 1 );
688 void HTTPProtocol::davStatList(
const KURL& url,
bool stat )
698 TQString query = metaData(
"davSearchQuery");
699 if ( !query.isEmpty() )
701 TQCString request =
"<?xml version=\"1.0\"?>\r\n";
702 request.append(
"<D:searchrequest xmlns:D=\"DAV:\">\r\n" );
703 request.append( query.utf8() );
704 request.append(
"</D:searchrequest>\r\n" );
706 davSetRequest( request );
710 request =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
711 "<D:propfind xmlns:D=\"DAV:\">";
714 if ( hasMetaData(
"davRequestResponse" ) )
715 request += metaData(
"davRequestResponse" ).utf8();
718 request +=
"<D:prop>"
720 "<D:getcontentlength/>"
723 "<D:getcontentlanguage/>"
724 "<D:getcontenttype/>"
726 "<D:getlastmodified/>"
733 request +=
"</D:propfind>";
735 davSetRequest( request );
739 m_request.method = query.isEmpty() ? DAV_PROPFIND : DAV_SEARCH;
740 m_request.query = TQString::null;
741 m_request.cache = CC_Reload;
742 m_request.doProxy = m_bUseProxy;
743 m_request.davData.depth = stat ? 0 : 1;
745 m_request.url.adjustPath(+1);
747 retrieveContent(
true );
755 TQDomDocument multiResponse;
756 multiResponse.setContent( m_bufWebDavData,
true );
758 bool hasResponse =
false;
760 for ( TQDomNode n = multiResponse.documentElement().firstChild();
761 !n.isNull(); n = n.nextSibling())
763 TQDomElement thisResponse = n.toElement();
764 if (thisResponse.isNull())
769 TQDomElement href = thisResponse.namedItem(
"href" ).toElement();
770 if ( !href.isNull() )
774 TQString urlStr = href.text();
776 int encoding = remoteEncoding()->encodingMib();
777 if ((encoding == 106) && (!KStringHandler::isUtf8(KURL::decode_string(urlStr, 4).latin1())))
780 TQUrl::decode(urlStr);
784 KURL thisURL ( urlStr, encoding );
786 atom.m_uds = TDEIO::UDS_NAME;
788 if ( thisURL.isValid() ) {
790 if ( !stat && thisURL.path(+1).length() == url.path(+1).length() )
793 atom.m_str = thisURL.fileName();
796 atom.m_str = href.text();
799 entry.append( atom );
801 TQDomNodeList propstats = thisResponse.elementsByTagName(
"propstat" );
803 davParsePropstats( propstats, entry );
814 listEntry( entry,
false );
819 kdDebug(7113) <<
"Error: no URL contained in response to PROPFIND on "
820 << url.prettyURL() << endl;
824 if ( stat || !hasResponse )
826 error( ERR_DOES_NOT_EXIST, url.prettyURL() );
830 listEntry( entry,
true );
835 void HTTPProtocol::davGeneric(
const KURL& url, TDEIO::HTTP_METHOD method )
837 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::davGeneric " << url.prettyURL()
840 if ( !checkRequestURL( url ) )
848 m_request.method = method;
849 m_request.query = TQString::null;
850 m_request.cache = CC_Reload;
851 m_request.doProxy = m_bUseProxy;
853 retrieveContent(
false );
856 int HTTPProtocol::codeFromResponse(
const TQString& response )
858 int firstSpace = response.find(
' ' );
859 int secondSpace = response.find(
' ', firstSpace + 1 );
860 return response.mid( firstSpace + 1, secondSpace - firstSpace - 1 ).toInt();
863 void HTTPProtocol::davParsePropstats(
const TQDomNodeList& propstats, UDSEntry& entry )
867 bool foundExecutable =
false;
868 bool isDirectory =
false;
870 uint supportedLockCount = 0;
872 for ( uint i = 0; i < propstats.count(); i++)
874 TQDomElement propstat = propstats.item(i).toElement();
876 TQDomElement status = propstat.namedItem(
"status" ).toElement();
877 if ( status.isNull() )
880 kdDebug(7113) <<
"Error, no status code in this propstat" << endl;
884 int code = codeFromResponse( status.text() );
888 kdDebug(7113) <<
"Warning: status code " << code <<
" (this may mean that some properties are unavailable" << endl;
892 TQDomElement prop = propstat.namedItem(
"prop" ).toElement();
895 kdDebug(7113) <<
"Error: no prop segment in this propstat." << endl;
899 if ( hasMetaData(
"davRequestResponse" ) )
901 atom.m_uds = TDEIO::UDS_XML_PROPERTIES;
903 doc.appendChild(prop);
904 atom.m_str = doc.toString();
905 entry.append( atom );
908 for ( TQDomNode n = prop.firstChild(); !n.isNull(); n = n.nextSibling() )
910 TQDomElement
property = n.toElement();
911 if (property.isNull())
914 if ( property.namespaceURI() !=
"DAV:" )
920 if ( property.tagName() ==
"creationdate" )
923 atom.m_uds = TDEIO::UDS_CREATION_TIME;
924 atom.m_long = parseDateTime( property.text(), property.attribute(
"dt") );
925 entry.append( atom );
927 else if ( property.tagName() ==
"getcontentlength" )
930 atom.m_uds = TDEIO::UDS_SIZE;
931 atom.m_long =
property.text().toULong();
932 entry.append( atom );
934 else if ( property.tagName() ==
"displayname" )
937 setMetaData(
"davDisplayName", property.text() );
939 else if ( property.tagName() ==
"source" )
942 TQDomElement source =
property.namedItem(
"link" ).toElement()
943 .namedItem(
"dst" ).toElement();
944 if ( !source.isNull() )
945 setMetaData(
"davSource", source.text() );
947 else if ( property.tagName() ==
"getcontentlanguage" )
950 setMetaData(
"davContentLanguage", property.text() );
952 else if ( property.tagName() ==
"getcontenttype" )
957 if ( property.text() ==
"httpd/unix-directory" )
963 mimeType =
property.text();
966 else if ( property.tagName() ==
"executable" )
969 if ( property.text() ==
"T" )
970 foundExecutable =
true;
973 else if ( property.tagName() ==
"getlastmodified" )
976 atom.m_uds = TDEIO::UDS_MODIFICATION_TIME;
977 atom.m_long = parseDateTime( property.text(), property.attribute(
"dt") );
978 entry.append( atom );
981 else if ( property.tagName() ==
"getetag" )
984 setMetaData(
"davEntityTag", property.text() );
986 else if ( property.tagName() ==
"supportedlock" )
989 for ( TQDomNode n2 = property.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
991 TQDomElement lockEntry = n2.toElement();
992 if ( lockEntry.tagName() ==
"lockentry" )
994 TQDomElement lockScope = lockEntry.namedItem(
"lockscope" ).toElement();
995 TQDomElement lockType = lockEntry.namedItem(
"locktype" ).toElement();
996 if ( !lockScope.isNull() && !lockType.isNull() )
999 supportedLockCount++;
1000 TQString scope = lockScope.firstChild().toElement().tagName();
1001 TQString type = lockType.firstChild().toElement().tagName();
1003 setMetaData( TQString(
"davSupportedLockScope%1").arg(supportedLockCount), scope );
1004 setMetaData( TQString(
"davSupportedLockType%1").arg(supportedLockCount), type );
1009 else if ( property.tagName() ==
"lockdiscovery" )
1012 davParseActiveLocks( property.elementsByTagName(
"activelock" ), lockCount );
1014 else if ( property.tagName() ==
"resourcetype" )
1017 if ( !property.namedItem(
"collection" ).toElement().isNull() )
1025 kdDebug(7113) <<
"Found unknown webdav property: " <<
property.tagName() << endl;
1030 setMetaData(
"davLockCount", TQString(
"%1").arg(lockCount) );
1031 setMetaData(
"davSupportedLockCount", TQString(
"%1").arg(supportedLockCount) );
1033 atom.m_uds = TDEIO::UDS_FILE_TYPE;
1034 atom.m_long = isDirectory ? S_IFDIR : S_IFREG;
1035 entry.append( atom );
1037 if ( foundExecutable || isDirectory )
1040 atom.m_uds = TDEIO::UDS_ACCESS;
1046 atom.m_uds = TDEIO::UDS_ACCESS;
1051 if ( !isDirectory && !mimeType.isEmpty() )
1053 atom.m_uds = TDEIO::UDS_MIME_TYPE;
1054 atom.m_str = mimeType;
1055 entry.append( atom );
1059 void HTTPProtocol::davParseActiveLocks(
const TQDomNodeList& activeLocks,
1062 for ( uint i = 0; i < activeLocks.count(); i++ )
1064 TQDomElement activeLock = activeLocks.item(i).toElement();
1068 TQDomElement lockScope = activeLock.namedItem(
"lockscope" ).toElement();
1069 TQDomElement lockType = activeLock.namedItem(
"locktype" ).toElement();
1070 TQDomElement lockDepth = activeLock.namedItem(
"depth" ).toElement();
1072 TQDomElement lockOwner = activeLock.namedItem(
"owner" ).toElement();
1073 TQDomElement lockTimeout = activeLock.namedItem(
"timeout" ).toElement();
1074 TQDomElement lockToken = activeLock.namedItem(
"locktoken" ).toElement();
1076 if ( !lockScope.isNull() && !lockType.isNull() && !lockDepth.isNull() )
1080 TQString scope = lockScope.firstChild().toElement().tagName();
1081 TQString type = lockType.firstChild().toElement().tagName();
1082 TQString depth = lockDepth.text();
1084 setMetaData( TQString(
"davLockScope%1").arg( lockCount ), scope );
1085 setMetaData( TQString(
"davLockType%1").arg( lockCount ), type );
1086 setMetaData( TQString(
"davLockDepth%1").arg( lockCount ), depth );
1088 if ( !lockOwner.isNull() )
1089 setMetaData( TQString(
"davLockOwner%1").arg( lockCount ), lockOwner.text() );
1091 if ( !lockTimeout.isNull() )
1092 setMetaData( TQString(
"davLockTimeout%1").arg( lockCount ), lockTimeout.text() );
1094 if ( !lockToken.isNull() )
1096 TQDomElement tokenVal = lockScope.namedItem(
"href" ).toElement();
1097 if ( !tokenVal.isNull() )
1098 setMetaData( TQString(
"davLockToken%1").arg( lockCount ), tokenVal.text() );
1104 long HTTPProtocol::parseDateTime(
const TQString& input,
const TQString& type )
1106 if ( type ==
"dateTime.tz" )
1108 return KRFCDate::parseDateISO8601( input );
1110 else if ( type ==
"dateTime.rfc1123" )
1112 return KRFCDate::parseDate( input );
1116 time_t time = KRFCDate::parseDate( input );
1120 return KRFCDate::parseDateISO8601( input );
1123 TQString HTTPProtocol::davProcessLocks()
1125 if ( hasMetaData(
"davLockCount" ) )
1127 TQString response(
"If:");
1129 numLocks = metaData(
"davLockCount" ).toInt();
1130 bool bracketsOpen =
false;
1131 for (
int i = 0; i < numLocks; i++ )
1133 if ( hasMetaData( TQString(
"davLockToken%1").arg(i) ) )
1135 if ( hasMetaData( TQString(
"davLockURL%1").arg(i) ) )
1140 bracketsOpen =
false;
1142 response +=
" <" + metaData( TQString(
"davLockURL%1").arg(i) ) +
">";
1145 if ( !bracketsOpen )
1148 bracketsOpen =
true;
1155 if ( hasMetaData( TQString(
"davLockNot%1").arg(i) ) )
1158 response +=
"<" + metaData( TQString(
"davLockToken%1").arg(i) ) +
">";
1169 return TQString::null;
1172 bool HTTPProtocol::davHostOk()
1180 kdDebug(7113) <<
"(" << m_pid <<
") " << k_funcinfo <<
" true" << endl;
1183 else if ( m_davHostUnsupported )
1185 kdDebug(7113) <<
"(" << m_pid <<
") " << k_funcinfo <<
" false" << endl;
1190 m_request.method = HTTP_OPTIONS;
1193 m_request.path =
"*";
1194 m_request.query = TQString::null;
1195 m_request.cache = CC_Reload;
1196 m_request.doProxy = m_bUseProxy;
1199 m_davCapabilities.clear();
1201 retrieveHeader(
false);
1203 if (m_davCapabilities.count())
1205 for (uint i = 0; i < m_davCapabilities.count(); i++)
1208 uint verNo = m_davCapabilities[i].toUInt(&ok);
1209 if (ok && verNo > 0 && verNo < 3)
1212 kdDebug(7113) <<
"Server supports DAV version " << verNo <<
"." << endl;
1220 m_davHostUnsupported =
true;
1227 void HTTPProtocol::davFinished()
1230 httpClose(m_bKeepAlive);
1234 void HTTPProtocol::mkdir(
const KURL& url,
int )
1236 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::mkdir " << url.prettyURL()
1239 if ( !checkRequestURL( url ) )
1242 m_request.method = DAV_MKCOL;
1243 m_request.path = url.path();
1244 m_request.query = TQString::null;
1245 m_request.cache = CC_Reload;
1246 m_request.doProxy = m_bUseProxy;
1248 retrieveHeader(
false );
1250 if ( m_responseCode == 201 )
1256 void HTTPProtocol::get(
const KURL& url )
1258 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::get " << url.prettyURL()
1261 if ( !checkRequestURL( url ) )
1264 m_request.method = HTTP_GET;
1265 m_request.path = url.path();
1266 m_request.query = url.query();
1268 TQString tmp = metaData(
"cache");
1270 m_request.cache = parseCacheControl(tmp);
1272 m_request.cache = DEFAULT_CACHE_CONTROL;
1274 m_request.passwd = url.pass();
1275 m_request.user = url.user();
1276 m_request.doProxy = m_bUseProxy;
1281 void HTTPProtocol::put(
const KURL &url,
int,
bool overwrite,
bool)
1283 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::put " << url.prettyURL()
1286 if ( !checkRequestURL( url ) )
1290 if (!overwrite && m_protocol.left(6) ==
"webdav") {
1296 request =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1297 "<D:propfind xmlns:D=\"DAV:\"><D:prop>"
1299 "<D:getcontentlength/>"
1302 "</D:prop></D:propfind>";
1304 davSetRequest( request );
1307 m_request.method = DAV_PROPFIND;
1308 m_request.query = TQString::null;
1309 m_request.cache = CC_Reload;
1310 m_request.doProxy = m_bUseProxy;
1311 m_request.davData.depth = 0;
1313 retrieveContent(
true);
1315 if (m_responseCode == 207) {
1316 error(ERR_FILE_ALREADY_EXIST, TQString::null);
1323 m_request.method = HTTP_PUT;
1324 m_request.path = url.path();
1325 m_request.query = TQString::null;
1326 m_request.cache = CC_Reload;
1327 m_request.doProxy = m_bUseProxy;
1329 retrieveHeader(
false );
1331 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::put error = " << m_bError << endl;
1335 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::put responseCode = " << m_responseCode << endl;
1339 if ( (m_responseCode >= 200) && (m_responseCode < 300) )
1345 void HTTPProtocol::copy(
const KURL& src,
const KURL& dest,
int,
bool overwrite )
1347 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::copy " << src.prettyURL()
1348 <<
" -> " << dest.prettyURL() << endl;
1350 if ( !checkRequestURL( dest ) || !checkRequestURL( src ) )
1354 KURL newDest = dest;
1355 if (newDest.protocol() ==
"webdavs")
1356 newDest.setProtocol(
"https");
1358 newDest.setProtocol(
"http");
1360 m_request.method = DAV_COPY;
1361 m_request.path = src.path();
1362 m_request.davData.desturl = newDest.url();
1363 m_request.davData.overwrite = overwrite;
1364 m_request.query = TQString::null;
1365 m_request.cache = CC_Reload;
1366 m_request.doProxy = m_bUseProxy;
1368 retrieveHeader(
false );
1371 if ( m_responseCode == 201 || m_responseCode == 204 )
1377 void HTTPProtocol::rename(
const KURL& src,
const KURL& dest,
bool overwrite )
1379 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::rename " << src.prettyURL()
1380 <<
" -> " << dest.prettyURL() << endl;
1382 if ( !checkRequestURL( dest ) || !checkRequestURL( src ) )
1386 KURL newDest = dest;
1387 if (newDest.protocol() ==
"webdavs")
1388 newDest.setProtocol(
"https");
1390 newDest.setProtocol(
"http");
1392 m_request.method = DAV_MOVE;
1393 m_request.path = src.path();
1394 m_request.davData.desturl = newDest.url();
1395 m_request.davData.overwrite = overwrite;
1396 m_request.query = TQString::null;
1397 m_request.cache = CC_Reload;
1398 m_request.doProxy = m_bUseProxy;
1400 retrieveHeader(
false );
1402 if ( m_responseCode == 301 )
1408 if (m_redirectLocation.protocol() ==
"https")
1409 m_redirectLocation.setProtocol(
"webdavs");
1411 m_redirectLocation.setProtocol(
"webdav");
1413 if ( !checkRequestURL( m_redirectLocation ) )
1416 m_request.method = DAV_MOVE;
1417 m_request.path = m_redirectLocation.path();
1418 m_request.davData.desturl = newDest.url();
1419 m_request.davData.overwrite = overwrite;
1420 m_request.query = TQString::null;
1421 m_request.cache = CC_Reload;
1422 m_request.doProxy = m_bUseProxy;
1424 retrieveHeader(
false );
1427 if ( m_responseCode == 201 )
1433 void HTTPProtocol::del(
const KURL& url,
bool )
1435 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::del " << url.prettyURL()
1438 if ( !checkRequestURL( url ) )
1441 m_request.method = HTTP_DELETE;
1442 m_request.path = url.path();
1443 m_request.query = TQString::null;
1444 m_request.cache = CC_Reload;
1445 m_request.doProxy = m_bUseProxy;
1447 retrieveHeader(
false );
1451 if ( m_responseCode == 200 || m_responseCode == 204 )
1457 void HTTPProtocol::post(
const KURL& url )
1459 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::post "
1460 << url.prettyURL() << endl;
1462 if ( !checkRequestURL( url ) )
1465 m_request.method = HTTP_POST;
1466 m_request.path = url.path();
1467 m_request.query = url.query();
1468 m_request.cache = CC_Reload;
1469 m_request.doProxy = m_bUseProxy;
1474 void HTTPProtocol::davLock(
const KURL& url,
const TQString& scope,
1475 const TQString& type,
const TQString& owner )
1477 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::davLock "
1478 << url.prettyURL() << endl;
1480 if ( !checkRequestURL( url ) )
1483 m_request.method = DAV_LOCK;
1484 m_request.path = url.path();
1485 m_request.query = TQString::null;
1486 m_request.cache = CC_Reload;
1487 m_request.doProxy = m_bUseProxy;
1490 TQDomDocument lockReq;
1492 TQDomElement lockInfo = lockReq.createElementNS(
"DAV:",
"lockinfo" );
1493 lockReq.appendChild( lockInfo );
1495 TQDomElement lockScope = lockReq.createElement(
"lockscope" );
1496 lockInfo.appendChild( lockScope );
1498 lockScope.appendChild( lockReq.createElement( scope ) );
1500 TQDomElement lockType = lockReq.createElement(
"locktype" );
1501 lockInfo.appendChild( lockType );
1503 lockType.appendChild( lockReq.createElement( type ) );
1505 if ( !owner.isNull() ) {
1506 TQDomElement ownerElement = lockReq.createElement(
"owner" );
1507 lockReq.appendChild( ownerElement );
1509 TQDomElement ownerHref = lockReq.createElement(
"href" );
1510 ownerElement.appendChild( ownerHref );
1512 ownerHref.appendChild( lockReq.createTextNode( owner ) );
1516 m_bufPOST = lockReq.toCString();
1518 retrieveContent(
true );
1520 if ( m_responseCode == 200 ) {
1522 TQDomDocument multiResponse;
1523 multiResponse.setContent( m_bufWebDavData,
true );
1525 TQDomElement prop = multiResponse.documentElement().namedItem(
"prop" ).toElement();
1527 TQDomElement lockdiscovery = prop.namedItem(
"lockdiscovery" ).toElement();
1530 davParseActiveLocks( lockdiscovery.elementsByTagName(
"activelock" ), lockCount );
1532 setMetaData(
"davLockCount", TQString(
"%1").arg( lockCount ) );
1540 void HTTPProtocol::davUnlock(
const KURL& url )
1542 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::davUnlock "
1543 << url.prettyURL() << endl;
1545 if ( !checkRequestURL( url ) )
1548 m_request.method = DAV_UNLOCK;
1549 m_request.path = url.path();
1550 m_request.query = TQString::null;
1551 m_request.cache = CC_Reload;
1552 m_request.doProxy = m_bUseProxy;
1554 retrieveContent(
true );
1556 if ( m_responseCode == 200 )
1562 TQString HTTPProtocol::davError(
int code , TQString url )
1564 bool callError =
false;
1566 code = m_responseCode;
1575 if ( !url.isNull() )
1576 url = m_request.url.prettyURL();
1578 TQString action, errorString;
1579 TDEIO::Error kError;
1582 TQString ow = i18n(
"Otherwise, the request would have succeeded." );
1584 switch ( m_request.method ) {
1586 action = i18n(
"retrieve property values" );
1589 action = i18n(
"set property values" );
1592 action = i18n(
"create the requested folder" );
1595 action = i18n(
"copy the specified file or folder" );
1598 action = i18n(
"move the specified file or folder" );
1601 action = i18n(
"search in the specified folder" );
1604 action = i18n(
"lock the specified file or folder" );
1607 action = i18n(
"unlock the specified file or folder" );
1610 action = i18n(
"delete the specified file or folder" );
1613 action = i18n(
"query the server's capabilities" );
1616 action = i18n(
"retrieve the contents of the specified file or folder" );
1627 kError = ERR_INTERNAL;
1628 errorString = i18n(
"An unexpected error (%1) occurred while attempting to %2.")
1629 .arg( code ).arg( action );
1635 kError = ERR_UNSUPPORTED_PROTOCOL;
1636 errorString = i18n(
"The server does not support the WebDAV protocol.");
1646 if ( !readBody(
true ) && m_bError )
1647 return TQString::null;
1649 TQStringList errors;
1650 TQDomDocument multiResponse;
1652 multiResponse.setContent( m_bufWebDavData,
true );
1654 TQDomElement multistatus = multiResponse.documentElement().namedItem(
"multistatus" ).toElement();
1656 TQDomNodeList responses = multistatus.elementsByTagName(
"response" );
1658 for (uint i = 0; i < responses.count(); i++)
1663 TQDomElement response = responses.item(i).toElement();
1664 TQDomElement code = response.namedItem(
"status" ).toElement();
1666 if ( !code.isNull() )
1668 errCode = codeFromResponse( code.text() );
1669 TQDomElement href = response.namedItem(
"href" ).toElement();
1670 if ( !href.isNull() )
1671 errUrl = href.text();
1672 errors << davError( errCode, errUrl );
1677 errorString = i18n(
"An error occurred while attempting to %1, %2. A "
1678 "summary of the reasons is below.<ul>").arg( action ).arg( url );
1680 for ( TQStringList::Iterator it = errors.begin(); it != errors.end(); ++it )
1681 errorString +=
"<li>" + *it +
"</li>";
1683 errorString +=
"</ul>";
1688 kError = ERR_ACCESS_DENIED;
1689 errorString = i18n(
"Access was denied while attempting to %1.").arg( action );
1693 if ( m_request.method == DAV_MKCOL )
1695 kError = ERR_DIR_ALREADY_EXIST;
1696 errorString = i18n(
"The specified folder already exists.");
1701 kError = ERR_ACCESS_DENIED;
1702 errorString = i18n(
"A resource cannot be created at the destination "
1703 "until one or more intermediate collections (folders) "
1704 "have been created.");
1708 if ( m_request.method == DAV_COPY || m_request.method == DAV_MOVE )
1710 kError = ERR_ACCESS_DENIED;
1711 errorString = i18n(
"The server was unable to maintain the liveness of "
1712 "the properties listed in the propertybehavior XML "
1713 "element or you attempted to overwrite a file while "
1714 "requesting that files are not overwritten. %1")
1718 else if ( m_request.method == DAV_LOCK )
1720 kError = ERR_ACCESS_DENIED;
1721 errorString = i18n(
"The requested lock could not be granted. %1").arg( ow );
1726 kError = ERR_ACCESS_DENIED;
1727 errorString = i18n(
"The server does not support the request type of the body.");
1731 kError = ERR_ACCESS_DENIED;
1732 errorString = i18n(
"Unable to %1 because the resource is locked.").arg( action );
1736 errorString = i18n(
"This action was prevented by another error.");
1740 if ( m_request.method == DAV_COPY || m_request.method == DAV_MOVE )
1742 kError = ERR_WRITE_ACCESS_DENIED;
1743 errorString = i18n(
"Unable to %1 because the destination server refuses "
1744 "to accept the file or folder.").arg( action );
1749 kError = ERR_DISK_FULL;
1750 errorString = i18n(
"The destination resource does not have sufficient space "
1751 "to record the state of the resource after the execution "
1760 error( ERR_SLAVE_DEFINED, errorString );
1765 void HTTPProtocol::httpError()
1767 TQString action, errorString;
1768 TDEIO::Error kError;
1770 switch ( m_request.method ) {
1772 action = i18n(
"upload %1" ).arg(m_request.url.prettyURL());
1780 kError = ERR_INTERNAL;
1781 errorString = i18n(
"An unexpected error (%1) occurred while attempting to %2.")
1782 .arg( m_responseCode ).arg( action );
1784 switch ( m_responseCode )
1791 kError = ERR_ACCESS_DENIED;
1792 errorString = i18n(
"Access was denied while attempting to %1.").arg( action );
1796 kError = ERR_ACCESS_DENIED;
1797 errorString = i18n(
"A resource cannot be created at the destination "
1798 "until one or more intermediate collections (folders) "
1799 "have been created.");
1803 kError = ERR_ACCESS_DENIED;
1804 errorString = i18n(
"Unable to %1 because the resource is locked.").arg( action );
1808 kError = ERR_WRITE_ACCESS_DENIED;
1809 errorString = i18n(
"Unable to %1 because the destination server refuses "
1810 "to accept the file or folder.").arg( action );
1814 kError = ERR_DISK_FULL;
1815 errorString = i18n(
"The destination resource does not have sufficient space "
1816 "to record the state of the resource after the execution "
1824 error( ERR_SLAVE_DEFINED, errorString );
1827 bool HTTPProtocol::isOffline(
const KURL &url)
1829 const int NetWorkStatusUnknown = 1;
1830 const int NetWorkStatusOnline = 8;
1831 TQCString replyType;
1835 TQDataStream stream(params, IO_WriteOnly);
1837 if ( url.host() == TQString::fromLatin1(
"localhost") || url.host() == TQString::fromLatin1(
"127.0.0.1") || url.host() == TQString::fromLatin1(
"::") ) {
1840 if ( dcopClient()->call(
"kded",
"networkstatus",
"status()",
1841 params, replyType, reply ) && (replyType ==
"int") )
1844 TQDataStream stream2( reply, IO_ReadOnly );
1846 kdDebug(7113) <<
"(" << m_pid <<
") networkstatus status = " << result << endl;
1847 return (result != NetWorkStatusUnknown) && (result != NetWorkStatusOnline);
1849 kdDebug(7113) <<
"(" << m_pid <<
") networkstatus <unreachable>" << endl;
1853 void HTTPProtocol::multiGet(
const TQByteArray &data)
1855 TQDataStream stream(data, IO_ReadOnly);
1859 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtcool::multiGet n = " << n << endl;
1861 HTTPRequest saveRequest;
1863 saveRequest = m_request;
1866 for(
unsigned i = 0; i < n; i++)
1869 stream >> url >> mIncomingMetaData;
1871 if ( !checkRequestURL( url ) )
1874 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::multi_get " << url.prettyURL() << endl;
1876 m_request.method = HTTP_GET;
1877 m_request.path = url.path();
1878 m_request.query = url.query();
1879 TQString tmp = metaData(
"cache");
1881 m_request.cache = parseCacheControl(tmp);
1883 m_request.cache = DEFAULT_CACHE_CONTROL;
1885 m_request.passwd = url.pass();
1886 m_request.user = url.user();
1887 m_request.doProxy = m_bUseProxy;
1889 HTTPRequest *newRequest =
new HTTPRequest(m_request);
1890 m_requestQueue.append(newRequest);
1894 m_request = saveRequest;
1899 while(!m_requestQueue.isEmpty())
1901 HTTPRequest *request = m_requestQueue.take(0);
1902 m_request = *request;
1910 ssize_t HTTPProtocol::write (
const void *_buf,
size_t nbytes)
1913 const char* buf =
static_cast<const char*
>(_buf);
1914 while ( nbytes > 0 )
1916 int n = TCPSlaveBase::write(buf, nbytes);
1924 if (n < 0 && ((errno == EINTR) || (errno == EAGAIN)))
1938 void HTTPProtocol::setRewindMarker()
1943 void HTTPProtocol::rewind()
1945 m_linePtrUnget = m_rewindBuf,
1946 m_lineCountUnget = m_rewindCount;
1951 char *HTTPProtocol::gets (
char *s,
int size)
1955 char mybuf[2]={0,0};
1963 if (m_rewindCount <
sizeof(m_rewindBuf))
1964 m_rewindBuf[m_rewindCount++] = *mybuf;
1969 if ((*mybuf ==
'\n') || !*mybuf)
1980 ssize_t HTTPProtocol::read (
void *b,
size_t nbytes)
1984 if (m_lineCountUnget > 0)
1986 ret = ( nbytes < m_lineCountUnget ? nbytes : m_lineCountUnget );
1987 m_lineCountUnget -= ret;
1988 memcpy(b, m_linePtrUnget, ret);
1989 m_linePtrUnget += ret;
1994 if (m_lineCount > 0)
1996 ret = ( nbytes < m_lineCount ? nbytes : m_lineCount );
1998 memcpy(b, m_linePtr, ret);
2005 ret = read(m_lineBuf, 1024);
2006 m_linePtr = m_lineBuf;
2018 ret = TCPSlaveBase::read( b, nbytes);
2022 }
while ((ret == -1) && (errno == EAGAIN || errno == EINTR));
2027 void HTTPProtocol::httpCheckConnection()
2029 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::httpCheckConnection: " <<
2030 " Socket status: " << m_iSock <<
2031 " Keep Alive: " << m_bKeepAlive <<
2032 " First: " << m_bFirstRequest << endl;
2034 if ( !m_bFirstRequest && (m_iSock != -1) )
2036 bool closeDown =
false;
2037 if ( !isConnectionValid())
2039 kdDebug(7113) <<
"(" << m_pid <<
") Connection lost!" << endl;
2042 else if ( m_request.method != HTTP_GET )
2046 else if ( !m_state.doProxy && !m_request.doProxy )
2048 if (m_state.hostname != m_request.hostname ||
2049 m_state.port != m_request.port ||
2050 m_state.user != m_request.user ||
2051 m_state.passwd != m_request.passwd)
2057 if ( !(m_request.doProxy && m_state.doProxy) )
2062 httpCloseConnection();
2066 m_state.hostname = m_request.hostname;
2067 m_state.encoded_hostname = m_request.encoded_hostname;
2068 m_state.port = m_request.port;
2069 m_state.user = m_request.user;
2070 m_state.passwd = m_request.passwd;
2071 m_state.doProxy = m_request.doProxy;
2074 bool HTTPProtocol::httpOpenConnection()
2079 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::httpOpenConnection" << endl;
2081 setBlockConnection(
true );
2083 KSocks::self()->disableSocks();
2085 if ( m_state.doProxy )
2087 TQString proxy_host = m_proxyURL.host();
2088 int proxy_port = m_proxyURL.port();
2090 kdDebug(7113) <<
"(" << m_pid <<
") Connecting to proxy server: "
2091 << proxy_host <<
", port: " << proxy_port << endl;
2093 infoMessage( i18n(
"Connecting to %1...").arg(m_state.hostname) );
2095 setConnectTimeout( m_proxyConnTimeout );
2097 if ( !connectToHost(proxy_host, proxy_port,
false) )
2099 if (userAborted()) {
2100 error(ERR_NO_CONTENT,
"");
2104 switch ( connectResult() )
2106 case IO_LookupError:
2107 errMsg = proxy_host;
2108 errCode = ERR_UNKNOWN_PROXY_HOST;
2110 case IO_TimeOutError:
2111 errMsg = i18n(
"Proxy %1 at port %2").arg(proxy_host).arg(proxy_port);
2112 errCode = ERR_SERVER_TIMEOUT;
2115 errMsg = i18n(
"Proxy %1 at port %2").arg(proxy_host).arg(proxy_port);
2116 errCode = ERR_COULD_NOT_CONNECT;
2118 error( errCode, errMsg );
2125 setConnectTimeout(m_remoteConnTimeout);
2127 if ( !connectToHost(m_state.hostname, m_state.port,
false ) )
2129 if (userAborted()) {
2130 error(ERR_NO_CONTENT,
"");
2134 switch ( connectResult() )
2136 case IO_LookupError:
2137 errMsg = m_state.hostname;
2138 errCode = ERR_UNKNOWN_HOST;
2140 case IO_TimeOutError:
2141 errMsg = i18n(
"Connection was to %1 at port %2").arg(m_state.hostname).arg(m_state.port);
2142 errCode = ERR_SERVER_TIMEOUT;
2145 errCode = ERR_COULD_NOT_CONNECT;
2146 if (m_state.port != m_iDefaultPort)
2147 errMsg = i18n(
"%1 (port %2)").arg(m_state.hostname).arg(m_state.port);
2149 errMsg = m_state.hostname;
2151 error( errCode, errMsg );
2158 (void) setsockopt( m_iSock, IPPROTO_TCP, TCP_NODELAY, (
char*)&on,
sizeof(on) );
2160 m_bFirstRequest =
true;
2189 bool HTTPProtocol::httpOpen()
2191 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::httpOpen" << endl;
2196 if ( (m_protocol ==
"https" || m_protocol ==
"webdavs") && !m_bIsSSL )
2198 error( ERR_UNSUPPORTED_PROTOCOL, m_protocol );
2202 m_request.fcache = 0;
2203 m_request.bCachedRead =
false;
2204 m_request.bCachedWrite =
false;
2205 m_request.bMustRevalidate =
false;
2206 m_request.expireDate = 0;
2207 m_request.creationDate = 0;
2209 if (m_request.bUseCache)
2211 m_request.fcache = checkCacheEntry( );
2213 bool bCacheOnly = (m_request.cache == TDEIO::CC_CacheOnly);
2214 bool bOffline = isOffline(m_request.doProxy ? m_proxyURL : m_request.url);
2215 if (bOffline && (m_request.cache != TDEIO::CC_Reload))
2216 m_request.cache = TDEIO::CC_CacheOnly;
2218 if (m_request.cache == CC_Reload && m_request.fcache)
2220 if (m_request.fcache)
2221 fclose(m_request.fcache);
2222 m_request.fcache = 0;
2224 if ((m_request.cache == TDEIO::CC_CacheOnly) || (m_request.cache == TDEIO::CC_Cache))
2225 m_request.bMustRevalidate =
false;
2227 m_request.bCachedWrite =
true;
2229 if (m_request.fcache && !m_request.bMustRevalidate)
2232 m_request.bCachedRead =
true;
2235 else if (!m_request.fcache)
2237 m_request.bMustRevalidate =
false;
2244 if (bCacheOnly && bOffline)
2246 error( ERR_OFFLINE_MODE, m_request.url.prettyURL() );
2251 error( ERR_DOES_NOT_EXIST, m_request.url.prettyURL() );
2256 error( ERR_OFFLINE_MODE, m_request.url.prettyURL() );
2264 bool moreData =
false;
2265 bool davData =
false;
2268 resetConnectionSettings ();
2271 httpCheckConnection();
2273 if ( !m_bIsTunneled && m_bNeedTunnel )
2275 setEnableSSLTunnel(
true );
2278 header = TQString(
"CONNECT %1:%2 HTTP/1.0"
2279 "\r\n").arg( m_request.encoded_hostname).arg(m_request.port);
2282 if (!m_request.userAgent.isEmpty())
2283 header +=
"User-Agent: " + m_request.userAgent +
"\r\n";
2286 header +=
"Host: " + m_state.encoded_hostname;
2288 if (m_state.port != m_iDefaultPort)
2289 header += TQString(
":%1").arg(m_state.port);
2292 header += proxyAuthenticationHeader();
2297 switch (m_request.method)
2305 m_request.bCachedWrite =
false;
2310 m_request.bCachedWrite =
false;
2317 m_request.bCachedWrite =
false;
2320 header =
"OPTIONS ";
2321 m_request.bCachedWrite =
false;
2324 header =
"PROPFIND ";
2326 davHeader =
"Depth: ";
2327 if ( hasMetaData(
"davDepth" ) )
2329 kdDebug(7113) <<
"Reading DAV depth from metadata: " << metaData(
"davDepth" ) << endl;
2330 davHeader += metaData(
"davDepth" );
2334 if ( m_request.davData.depth == 2 )
2335 davHeader +=
"infinity";
2337 davHeader += TQString(
"%1").arg( m_request.davData.depth );
2339 davHeader +=
"\r\n";
2340 m_request.bCachedWrite =
false;
2343 header =
"PROPPATCH ";
2345 m_request.bCachedWrite =
false;
2349 m_request.bCachedWrite =
false;
2353 header = ( m_request.method == DAV_COPY ) ?
"COPY " :
"MOVE ";
2354 davHeader =
"Destination: " + m_request.davData.desturl;
2357 davHeader +=
"\r\nDepth: infinity\r\nOverwrite: ";
2358 davHeader += m_request.davData.overwrite ?
"T" :
"F";
2359 davHeader +=
"\r\n";
2360 m_request.bCachedWrite =
false;
2364 davHeader =
"Timeout: ";
2367 if ( hasMetaData(
"davTimeout" ) )
2368 timeout = metaData(
"davTimeout" ).toUInt();
2370 davHeader +=
"Infinite";
2372 davHeader += TQString(
"Seconds-%1").arg(timeout);
2374 davHeader +=
"\r\n";
2375 m_request.bCachedWrite =
false;
2380 davHeader =
"Lock-token: " + metaData(
"davLockToken") +
"\r\n";
2381 m_request.bCachedWrite =
false;
2386 m_request.bCachedWrite =
false;
2389 header =
"SUBSCRIBE ";
2390 m_request.bCachedWrite =
false;
2392 case DAV_UNSUBSCRIBE:
2393 header =
"UNSUBSCRIBE ";
2394 m_request.bCachedWrite =
false;
2398 m_request.bCachedWrite =
false;
2401 error (ERR_UNSUPPORTED_ACTION, TQString::null);
2407 if (m_state.doProxy && !m_bIsTunneled)
2411 if (m_protocol ==
"webdav")
2412 u.setProtocol(
"http" );
2413 else if (m_protocol ==
"webdavs" )
2414 u.setProtocol(
"https" );
2416 u.setProtocol( m_protocol );
2422 if (m_protocol !=
"http" && m_protocol !=
"https" &&
2423 !m_state.user.isEmpty())
2424 u.setUser (m_state.user);
2426 u.setHost( m_state.hostname );
2427 if (m_state.port != m_iDefaultPort)
2428 u.setPort( m_state.port );
2429 u.setEncodedPathAndQuery( m_request.url.encodedPathAndQuery(0,
true) );
2434 header += m_request.url.encodedPathAndQuery(0,
true);
2437 header +=
" HTTP/1.1\r\n";
2439 if (!m_request.userAgent.isEmpty())
2441 header +=
"User-Agent: ";
2442 header += m_request.userAgent;
2446 if (!m_request.referrer.isEmpty())
2448 header +=
"Referer: ";
2449 header += m_request.referrer;
2453 if ( m_request.offset > 0 )
2455 header += TQString(
"Range: bytes=%1-\r\n").arg(TDEIO::number(m_request.offset));
2456 kdDebug(7103) <<
"tdeio_http : Range = " << TDEIO::number(m_request.offset) << endl;
2459 if ( m_request.cache == CC_Reload )
2462 header +=
"Pragma: no-cache\r\n";
2463 header +=
"Cache-control: no-cache\r\n";
2466 if (m_request.bMustRevalidate)
2469 if (!m_request.etag.isEmpty())
2470 header +=
"If-None-Match: "+m_request.etag+
"\r\n";
2471 if (!m_request.lastModified.isEmpty())
2472 header +=
"If-Modified-Since: "+m_request.lastModified+
"\r\n";
2475 header +=
"Accept: ";
2476 TQString acceptHeader = metaData(
"accept");
2477 if (!acceptHeader.isEmpty())
2478 header += acceptHeader;
2480 header += DEFAULT_ACCEPT_HEADER;
2484 if (m_request.allowCompressedPage)
2485 header +=
"Accept-Encoding: x-gzip, x-deflate, gzip, deflate\r\n";
2488 if (!m_request.charsets.isEmpty())
2489 header +=
"Accept-Charset: " + m_request.charsets +
"\r\n";
2491 if (!m_request.languages.isEmpty())
2492 header +=
"Accept-Language: " + m_request.languages +
"\r\n";
2496 header +=
"Host: " + m_state.encoded_hostname;
2498 if (m_state.port != m_iDefaultPort)
2499 header += TQString(
":%1").arg(m_state.port);
2503 TQString cookieMode = metaData(
"cookies").lower();
2504 if (cookieMode ==
"none")
2506 m_request.cookieMode = HTTPRequest::CookiesNone;
2508 else if (cookieMode ==
"manual")
2510 m_request.cookieMode = HTTPRequest::CookiesManual;
2511 cookieStr = metaData(
"setcookies");
2515 m_request.cookieMode = HTTPRequest::CookiesAuto;
2516 if (m_request.bUseCookiejar)
2517 cookieStr = findCookies( m_request.url.url());
2520 if (!cookieStr.isEmpty())
2521 header += cookieStr +
"\r\n";
2523 TQString customHeader = metaData(
"customHTTPHeader" );
2524 if (!customHeader.isEmpty())
2526 header += sanitizeCustomHTTPHeader(customHeader);
2530 if (m_request.method == HTTP_POST)
2532 header += metaData(
"content-type");
2539 if ( !m_request.bNoAuth && m_responseCode != 401 && m_responseCode != 407 && Authentication != AUTH_Negotiate )
2541 kdDebug(7113) <<
"(" << m_pid <<
") Calling checkCachedAuthentication " << endl;
2543 info.url = m_request.url;
2544 info.verifyPath =
true;
2545 if ( !m_request.user.isEmpty() )
2546 info.username = m_request.user;
2547 if ( checkCachedAuthentication( info ) && !info.digestInfo.isEmpty() )
2549 Authentication = info.digestInfo.startsWith(
"Basic") ? AUTH_Basic : info.digestInfo.startsWith(
"NTLM") ? AUTH_NTLM : info.digestInfo.startsWith(
"Negotiate") ? AUTH_Negotiate : AUTH_Digest ;
2550 m_state.user = info.username;
2551 m_state.passwd = info.password;
2552 m_strRealm = info.realmValue;
2553 if ( Authentication != AUTH_NTLM && Authentication != AUTH_Negotiate )
2554 m_strAuthorization = info.digestInfo;
2559 kdDebug(7113) <<
"(" << m_pid <<
") Not calling checkCachedAuthentication " << endl;
2562 switch ( Authentication )
2565 header += createBasicAuth();
2568 header += createDigestAuth();
2570 #ifdef HAVE_LIBGSSAPI
2571 case AUTH_Negotiate:
2572 header += createNegotiateAuth();
2576 header += createNTLMAuth();
2584 if ( Authentication != AUTH_None )
2586 kdDebug(7113) <<
"(" << m_pid <<
") Using Authentication: " << endl;
2587 kdDebug(7113) <<
"(" << m_pid <<
") HOST= " << m_state.hostname << endl;
2588 kdDebug(7113) <<
"(" << m_pid <<
") PORT= " << m_state.port << endl;
2589 kdDebug(7113) <<
"(" << m_pid <<
") USER= " << m_state.user << endl;
2590 kdDebug(7113) <<
"(" << m_pid <<
") PASSWORD= [protected]" << endl;
2591 kdDebug(7113) <<
"(" << m_pid <<
") REALM= " << m_strRealm << endl;
2592 kdDebug(7113) <<
"(" << m_pid <<
") EXTRA= " << m_strAuthorization << endl;
2596 if ( m_state.doProxy && !m_bIsTunneled )
2597 header += proxyAuthenticationHeader();
2603 if (!m_bUseProxy || m_bPersistentProxyConnection || m_bIsTunneled)
2604 header +=
"Connection: Keep-Alive\r\n";
2606 header +=
"Connection: close\r\n";
2608 if ( m_protocol ==
"webdav" || m_protocol ==
"webdavs" )
2610 header += davProcessLocks();
2613 TQString davExtraHeader = metaData(
"davHeader");
2614 if ( !davExtraHeader.isEmpty() )
2615 davHeader += davExtraHeader;
2619 davHeader +=
"Content-Type: text/xml; charset=utf-8\r\n";
2622 if ( !davHeader.isNull() )
2623 header += davHeader;
2627 kdDebug(7103) <<
"(" << m_pid <<
") ============ Sending Header:" << endl;
2629 TQStringList headerOutput = TQStringList::split(
"\r\n", header);
2630 TQStringList::Iterator it = headerOutput.begin();
2632 for (; it != headerOutput.end(); it++)
2633 kdDebug(7103) <<
"(" << m_pid <<
") " << (*it) << endl;
2635 if ( !moreData && !davData)
2643 if (!httpOpenConnection())
2648 bool sendOk = (write(header.latin1(), header.length()) == (ssize_t) header.length());
2651 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::httpOpen: "
2652 "Connection broken! (" << m_state.hostname <<
")" << endl;
2658 httpCloseConnection();
2664 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::httpOpen: sendOk==false."
2665 " Connnection broken !" << endl;
2666 error( ERR_CONNECTION_BROKEN, m_state.hostname );
2673 if ( moreData || davData )
2676 infoMessage(i18n(
"%1 contacted. Waiting for reply...").arg(m_request.hostname));
2681 void HTTPProtocol::forwardHttpResponseHeader()
2684 if ( config()->readBoolEntry(
"PropagateHttpHeader",
false) )
2686 setMetaData(
"HTTP-Headers", m_responseHeader.join(
"\n"));
2689 m_responseHeader.clear();
2698 bool HTTPProtocol::readHeader()
2701 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::readHeader" << endl;
2704 if (m_request.bCachedRead)
2706 m_responseHeader <<
"HTTP-CACHE";
2709 if (!fgets(buffer, 4096, m_request.fcache) )
2712 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::readHeader: "
2713 <<
"Could not access cache to obtain mimetype!" << endl;
2714 error( ERR_CONNECTION_BROKEN, m_state.hostname );
2718 m_strMimeType = TQString(TQString::fromUtf8( buffer)).stripWhiteSpace();
2720 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::readHeader: cached "
2721 <<
"data mimetype: " << m_strMimeType << endl;
2723 if (!fgets(buffer, 4096, m_request.fcache) )
2726 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::readHeader: "
2727 <<
"Could not access cached data! " << endl;
2728 error( ERR_CONNECTION_BROKEN, m_state.hostname );
2732 m_request.strCharset = TQString(TQString::fromUtf8( buffer)).stripWhiteSpace().lower();
2733 setMetaData(
"charset", m_request.strCharset);
2734 if (!m_request.lastModified.isEmpty())
2735 setMetaData(
"modified", m_request.lastModified);
2737 tmp.setNum(m_request.expireDate);
2738 setMetaData(
"expire-date", tmp);
2739 tmp.setNum(m_request.creationDate);
2740 setMetaData(
"cache-creation-date", tmp);
2741 mimeType(m_strMimeType);
2742 forwardHttpResponseHeader();
2746 TQCString locationStr;
2747 TQCString cookieStr;
2749 TQString dispositionType;
2750 TQString dispositionFilename;
2752 TQString mediaValue;
2753 TQString mediaAttribute;
2755 TQStringList upgradeOffers;
2757 bool upgradeRequired =
false;
2761 bool canUpgrade =
false;
2764 m_request.etag = TQString::null;
2765 m_request.lastModified = TQString::null;
2766 m_request.strCharset = TQString::null;
2768 time_t dateHeader = 0;
2769 time_t expireDate = 0;
2772 int maxHeaderSize = 64*1024;
2778 bool cacheValidated =
false;
2779 bool mayCache =
true;
2780 bool hasCacheDirective =
false;
2781 bool bCanResume =
false;
2785 kdDebug(7113) <<
"HTTPProtocol::readHeader: No connection." << endl;
2789 if (!waitForResponse(m_remoteRespTimeout))
2792 error( ERR_SERVER_TIMEOUT , m_state.hostname );
2798 gets(buffer,
sizeof(buffer)-1);
2800 if (m_bEOF || *buffer ==
'\0')
2802 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::readHeader: "
2803 <<
"EOF while waiting for header start." << endl;
2806 httpCloseConnection();
2810 if (m_request.method == HTTP_HEAD)
2816 kdDebug(7113) <<
"(" << m_pid <<
") HTTPPreadHeader: HEAD -> returned "
2817 <<
"mimetype: " << DEFAULT_MIME_TYPE << endl;
2818 mimeType(TQString::fromLatin1(DEFAULT_MIME_TYPE));
2822 kdDebug(7113) <<
"HTTPProtocol::readHeader: Connection broken !" << endl;
2823 error( ERR_CONNECTION_BROKEN, m_state.hostname );
2827 kdDebug(7103) <<
"(" << m_pid <<
") ============ Received Response:"<< endl;
2829 bool noHeader =
true;
2830 HTTP_REV httpRev = HTTP_None;
2836 len = strlen(buffer);
2838 while(len && (buffer[len-1] ==
'\n' || buffer[len-1] ==
'\r'))
2844 kdDebug(7103) <<
"(" << m_pid <<
") --empty--" << endl;
2856 kdDebug(7103) <<
"(" << m_pid <<
") \"" << buffer <<
"\"" << endl;
2860 while( *buf ==
' ' )
2868 kdDebug(7103) <<
"tdeio_http: No valid HTTP header found! Document starts with XML/HTML tag" << endl;
2871 m_strMimeType =
"text/html";
2879 m_responseHeader << TQString::fromLatin1(buf);
2881 if ((strncasecmp(buf,
"HTTP/", 5) == 0) ||
2882 (strncasecmp(buf,
"ICY ", 4) == 0))
2884 if (strncasecmp(buf,
"ICY ", 4) == 0)
2887 httpRev = SHOUTCAST;
2888 m_bKeepAlive =
false;
2890 else if (strncmp((buf + 5),
"1.0",3) == 0)
2898 m_bKeepAlive =
false;
2900 else if (strncmp((buf + 5),
"1.1",3) == 0)
2906 httpRev = HTTP_Unknown;
2910 m_prevResponseCode = m_responseCode;
2912 const char* rptr = buf;
2913 while ( *rptr && *rptr >
' ' )
2915 m_responseCode = atoi(rptr);
2918 if (m_responseCode >= 500 && m_responseCode <= 599)
2920 if (m_request.method == HTTP_HEAD)
2926 if (m_request.bErrorPage)
2930 error(ERR_INTERNAL_SERVER, m_request.url.prettyURL());
2934 m_request.bCachedWrite =
false;
2938 else if (m_responseCode == 401 || m_responseCode == 407)
2942 if ( m_prevResponseCode != m_responseCode &&
2943 (m_prevResponseCode == 401 || m_prevResponseCode == 407) )
2944 saveAuthorization();
2946 m_bUnauthorized =
true;
2947 m_request.bCachedWrite =
false;
2951 else if (m_responseCode == 416)
2953 m_request.offset = 0;
2954 httpCloseConnection();
2958 else if (m_responseCode == 426)
2960 upgradeRequired =
true;
2963 else if (m_responseCode >= 400 && m_responseCode <= 499)
2966 if (m_request.bErrorPage)
2970 error(ERR_DOES_NOT_EXIST, m_request.url.prettyURL());
2973 m_request.bCachedWrite =
false;
2976 else if (m_responseCode == 307)
2979 m_request.bCachedWrite =
false;
2982 else if (m_responseCode == 304)
2986 cacheValidated =
true;
2988 else if (m_responseCode >= 301 && m_responseCode<= 303)
2991 if (m_responseCode == 301)
2992 setMetaData(
"permanent-redirect",
"true");
2996 if (m_request.method != HTTP_HEAD && m_request.method != HTTP_GET)
3001 if (m_request.method == HTTP_POST)
3002 m_bufPOST.resize(0);
3013 m_request.method = HTTP_GET;
3015 m_request.bCachedWrite =
false;
3018 else if ( m_responseCode == 207 )
3022 else if ( m_responseCode == 204 )
3032 else if ( m_responseCode == 206 )
3034 if ( m_request.offset )
3037 else if (m_responseCode == 102)
3044 infoMessage( i18n(
"Server processing request, please wait..." ) );
3047 else if (m_responseCode == 100)
3055 else if (strncasecmp(buf,
"Accept-Ranges:", 14) == 0) {
3056 if (strncasecmp(trimLead(buf + 14),
"none", 4) == 0)
3060 else if (strncasecmp(buf,
"Keep-Alive:", 11) == 0) {
3061 TQStringList options = TQStringList::split(
',',
3062 TQString::fromLatin1(trimLead(buf+11)));
3063 for(TQStringList::ConstIterator it = options.begin();
3064 it != options.end();
3067 TQString option = (*it).stripWhiteSpace().lower();
3068 if (option.startsWith(
"timeout="))
3070 m_keepAliveTimeout = option.mid(8).toInt();
3076 else if (strncasecmp(buf,
"Cache-Control:", 14) == 0) {
3077 TQStringList cacheControls = TQStringList::split(
',',
3078 TQString::fromLatin1(trimLead(buf+14)));
3079 for(TQStringList::ConstIterator it = cacheControls.begin();
3080 it != cacheControls.end();
3083 TQString cacheControl = (*it).stripWhiteSpace();
3084 if (strncasecmp(cacheControl.latin1(),
"no-cache", 8) == 0)
3086 m_request.bCachedWrite =
false;
3089 else if (strncasecmp(cacheControl.latin1(),
"no-store", 8) == 0)
3091 m_request.bCachedWrite =
false;
3094 else if (strncasecmp(cacheControl.latin1(),
"max-age=", 8) == 0)
3096 TQString age = cacheControl.mid(8).stripWhiteSpace();
3098 maxAge = STRTOLL(age.latin1(), 0, 10);
3101 hasCacheDirective =
true;
3105 else if (strncasecmp(buf,
"Content-length:", 15) == 0) {
3106 char* len = trimLead(buf + 15);
3108 m_iSize = STRTOLL(len, 0, 10);
3111 else if (strncasecmp(buf,
"Content-location:", 17) == 0) {
3112 setMetaData (
"content-location",
3113 TQString::fromLatin1(trimLead(buf+17)).stripWhiteSpace());
3117 else if (strncasecmp(buf,
"Content-type:", 13) == 0) {
3118 char *start = trimLead(buf + 13);
3122 while ( *pos && *pos !=
';' ) pos++;
3125 m_strMimeType = TQString::fromLatin1(start, pos-start).stripWhiteSpace().lower();
3126 kdDebug(7113) <<
"(" << m_pid <<
") Content-type: " << m_strMimeType << endl;
3133 while ( *pos && *pos !=
'=' ) pos++;
3136 while ( *end && *end !=
';' ) end++;
3140 mediaAttribute = TQString::fromLatin1(start, pos-start).stripWhiteSpace().lower();
3141 mediaValue = TQString::fromLatin1(pos+1, end-pos-1).stripWhiteSpace();
3143 if (mediaValue.length() &&
3144 (mediaValue[0] ==
'"') &&
3145 (mediaValue[mediaValue.length()-1] ==
'"'))
3146 mediaValue = mediaValue.mid(1, mediaValue.length()-2);
3148 kdDebug (7113) <<
"(" << m_pid <<
") Media-Parameter Attribute: "
3149 << mediaAttribute << endl;
3150 kdDebug (7113) <<
"(" << m_pid <<
") Media-Parameter Value: "
3151 << mediaValue << endl;
3153 if ( mediaAttribute ==
"charset")
3155 mediaValue = mediaValue.lower();
3156 m_request.strCharset = mediaValue;
3160 setMetaData(
"media-"+mediaAttribute, mediaValue);
3167 else if (strncasecmp(buf,
"Date:", 5) == 0) {
3168 dateHeader = KRFCDate::parseDate(trimLead(buf+5));
3172 else if (strncasecmp(buf,
"ETag:", 5) == 0) {
3173 m_request.etag = trimLead(buf+5);
3177 else if (strncasecmp(buf,
"Expires:", 8) == 0) {
3178 expireDate = KRFCDate::parseDate(trimLead(buf+8));
3184 else if (strncasecmp(buf,
"Last-Modified:", 14) == 0) {
3185 m_request.lastModified = (TQString::fromLatin1(trimLead(buf+14))).stripWhiteSpace();
3189 else if (strncasecmp(buf,
"Warning:", 8) == 0) {
3192 infoMessage(trimLead(buf + 8));
3196 else if (strncasecmp(buf,
"Pragma:", 7) == 0) {
3197 TQCString pragma = TQCString(trimLead(buf+7)).stripWhiteSpace().lower();
3198 if (pragma ==
"no-cache")
3200 m_request.bCachedWrite =
false;
3202 hasCacheDirective =
true;
3207 else if (strncasecmp(buf,
"Refresh:", 8) == 0) {
3209 setMetaData(
"http-refresh", TQString::fromLatin1(trimLead(buf+8)).stripWhiteSpace() );
3213 else if (strncasecmp(buf,
"Location:", 9) == 0) {
3215 if ( m_responseCode > 299 && m_responseCode < 400 )
3216 locationStr = TQCString(trimLead(buf+9)).stripWhiteSpace();
3220 else if (strncasecmp(buf,
"Set-Cookie", 10) == 0) {
3226 else if (strncasecmp(buf,
"WWW-Authenticate:", 17) == 0) {
3227 configAuth(trimLead(buf + 17),
false);
3231 else if (strncasecmp(buf,
"Proxy-Authenticate:", 19) == 0) {
3232 configAuth(trimLead(buf + 19),
true);
3235 else if (strncasecmp(buf,
"Upgrade:", 8) == 0) {
3237 TQString offered = &(buf[8]);
3238 upgradeOffers = TQStringList::split(TQRegExp(
"[ \n,\r\t]"), offered);
3242 else if (strncasecmp(buf,
"Content-Encoding:", 17) == 0) {
3256 addEncoding(trimLead(buf + 17), m_qContentEncodings);
3259 else if(strncasecmp(buf,
"Content-Disposition:", 20) == 0) {
3260 char* dispositionBuf = trimLead(buf + 20);
3261 while ( *dispositionBuf )
3263 if ( strncasecmp( dispositionBuf,
"filename", 8 ) == 0 )
3265 dispositionBuf += 8;
3267 while ( *dispositionBuf ==
' ' || *dispositionBuf ==
'=' )
3270 char* bufStart = dispositionBuf;
3272 while ( *dispositionBuf && *dispositionBuf !=
';' )
3275 if ( dispositionBuf > bufStart )
3278 while ( *bufStart ==
'"' )
3282 while ( *(dispositionBuf-1) ==
' ' || *(dispositionBuf-1) ==
'"')
3285 if ( dispositionBuf > bufStart )
3286 dispositionFilename = TQString::fromLatin1( bufStart, dispositionBuf-bufStart );
3293 char *bufStart = dispositionBuf;
3295 while ( *dispositionBuf && *dispositionBuf !=
';' )
3298 if ( dispositionBuf > bufStart )
3299 dispositionType = TQString::fromLatin1( bufStart, dispositionBuf-bufStart ).stripWhiteSpace();
3301 while ( *dispositionBuf ==
';' || *dispositionBuf ==
' ' )
3308 if ( !dispositionFilename.isEmpty() )
3310 int pos = dispositionFilename.findRev(
'/' );
3313 dispositionFilename = dispositionFilename.mid(pos+1);
3315 kdDebug(7113) <<
"(" << m_pid <<
") Content-Disposition: filename="
3316 << dispositionFilename<< endl;
3319 else if(strncasecmp(buf,
"Content-Language:", 17) == 0) {
3320 TQString language = TQString::fromLatin1(trimLead(buf+17)).stripWhiteSpace();
3321 if (!language.isEmpty())
3322 setMetaData(
"content-language", language);
3324 else if (strncasecmp(buf,
"Proxy-Connection:", 17) == 0)
3326 if (strncasecmp(trimLead(buf + 17),
"Close", 5) == 0)
3327 m_bKeepAlive =
false;
3328 else if (strncasecmp(trimLead(buf + 17),
"Keep-Alive", 10)==0)
3329 m_bKeepAlive =
true;
3331 else if (strncasecmp(buf,
"Link:", 5) == 0) {
3333 TQStringList link = TQStringList::split(
";", TQString(buf)
3334 .replace(TQRegExp(
"^Link:[ ]*"),
3336 if (link.count() == 2) {
3337 TQString rel = link[1].stripWhiteSpace();
3338 if (rel.startsWith(
"rel=\"")) {
3339 rel = rel.mid(5, rel.length() - 6);
3340 if (rel.lower() ==
"pageservices") {
3341 TQString url = TQString(link[0].replace(TQRegExp(
"[<>]"),
"")).stripWhiteSpace();
3342 setMetaData(
"PageServices", url);
3347 else if (strncasecmp(buf,
"P3P:", 4) == 0) {
3348 TQString p3pstr = buf;
3349 p3pstr = p3pstr.mid(4).simplifyWhiteSpace();
3350 TQStringList policyrefs, compact;
3351 TQStringList policyfields = TQStringList::split(TQRegExp(
",[ ]*"), p3pstr);
3352 for (TQStringList::Iterator it = policyfields.begin();
3353 it != policyfields.end();
3355 TQStringList policy = TQStringList::split(
"=", *it);
3357 if (policy.count() == 2) {
3358 if (policy[0].lower() ==
"policyref") {
3359 policyrefs << TQString(policy[1].replace(TQRegExp(
"[\"\']"),
""))
3361 }
else if (policy[0].lower() ==
"cp") {
3365 TQStringList cps = TQStringList::split(
" ",
3366 TQString(policy[1].replace(TQRegExp(
"[\"\']"),
""))
3367 .simplifyWhiteSpace());
3369 for (TQStringList::Iterator j = cps.begin(); j != cps.end(); ++j)
3375 if (!policyrefs.isEmpty())
3376 setMetaData(
"PrivacyPolicy", policyrefs.join(
"\n"));
3378 if (!compact.isEmpty())
3379 setMetaData(
"PrivacyCompactPolicy", compact.join(
"\n"));
3382 else if (strncasecmp(buf,
"Connection:", 11) == 0)
3384 if (strncasecmp(trimLead(buf + 11),
"Close", 5) == 0)
3385 m_bKeepAlive =
false;
3386 else if (strncasecmp(trimLead(buf + 11),
"Keep-Alive", 10)==0)
3387 m_bKeepAlive =
true;
3388 else if (strncasecmp(trimLead(buf + 11),
"Upgrade", 7)==0)
3390 if (m_responseCode == 101) {
3392 upgradeRequired =
true;
3393 }
else if (upgradeRequired) {
3402 else if ( httpRev == HTTP_11) {
3404 if (strncasecmp(buf,
"Transfer-Encoding:", 18) == 0) {
3408 addEncoding(trimLead(buf + 18), m_qTransferEncodings);
3412 else if (strncasecmp(buf,
"Content-MD5:", 12) == 0) {
3413 m_sContentMD5 = TQString::fromLatin1(trimLead(buf + 12));
3418 else if (strncasecmp(buf,
"DAV:", 4) == 0) {
3419 if (m_davCapabilities.isEmpty()) {
3420 m_davCapabilities << TQString::fromLatin1(trimLead(buf + 4));
3423 m_davCapabilities << TQString::fromLatin1(trimLead(buf + 4));
3428 else if ((httpRev == HTTP_None) && (strlen(buf) != 0))
3434 m_prevResponseCode = m_responseCode;
3436 m_responseCode = 200;
3437 httpRev = HTTP_Unknown;
3438 m_bKeepAlive =
false;
3444 memset(buffer, 0,
sizeof(buffer));
3446 }
while (!m_bEOF && (len || noHeader) && (headerSize < maxHeaderSize) && (gets(buffer,
sizeof(buffer)-1)));
3449 TQStringList::Iterator opt = upgradeOffers.begin();
3450 for( ; opt != upgradeOffers.end(); ++opt) {
3451 if (*opt ==
"TLS/1.0") {
3452 if(upgradeRequired) {
3453 if (!startTLS() && !usingTLS()) {
3454 error(ERR_UPGRADE_REQUIRED, *opt);
3458 }
else if (*opt ==
"HTTP/1.1") {
3462 if (upgradeRequired) {
3463 error(ERR_UPGRADE_REQUIRED, *opt);
3469 setMetaData(
"charset", m_request.strCharset);
3472 if ( (m_responseCode == 401 && Authentication == AUTH_None) ||
3473 (m_responseCode == 407 && ProxyAuthentication == AUTH_None) )
3475 m_bUnauthorized =
false;
3476 if (m_request.bErrorPage)
3480 error( ERR_UNSUPPORTED_ACTION,
"Unknown Authorization method!" );
3486 if (expireDate && (expireDate <= dateHeader))
3492 else if (maxAge > 0)
3495 maxAge -= currentAge;
3498 expireDate = time(0) + maxAge;
3503 time_t lastModifiedDate = 0;
3504 if (!m_request.lastModified.isEmpty())
3505 lastModifiedDate = KRFCDate::parseDate(m_request.lastModified);
3507 if (lastModifiedDate)
3509 long diff =
static_cast<long>(difftime(dateHeader, lastModifiedDate));
3511 expireDate = time(0) + 1;
3513 expireDate = time(0) + (diff / 10);
3517 expireDate = time(0) + DEFAULT_CACHE_EXPIRE;
3522 if (!cookieStr.isEmpty())
3524 if ((m_request.cookieMode == HTTPRequest::CookiesAuto) && m_request.bUseCookiejar)
3527 TQString domain = config()->readEntry(
"cross-domain");
3528 if (!domain.isEmpty() && isCrossDomainRequest(m_request.url.host(), domain))
3529 cookieStr =
"Cross-Domain\n" + cookieStr;
3530 addCookies( m_request.url.url(), cookieStr );
3532 else if (m_request.cookieMode == HTTPRequest::CookiesManual)
3535 setMetaData(
"setcookies", cookieStr);
3539 if (m_request.bMustRevalidate)
3541 m_request.bMustRevalidate =
false;
3546 fclose(m_request.fcache);
3547 m_request.fcache = 0;
3548 updateExpireDate( expireDate,
true );
3549 m_request.fcache = checkCacheEntry( );
3551 if (m_request.fcache)
3553 m_request.bCachedRead =
true;
3564 fclose(m_request.fcache);
3565 m_request.fcache = 0;
3577 if (!m_bChunked && (m_iSize == NO_SIZE))
3578 m_bKeepAlive =
false;
3580 if ( m_responseCode == 204 )
3586 if ( m_bUnauthorized )
3588 if ( (m_responseCode == 401) ||
3589 (m_bUseProxy && (m_responseCode == 407))
3592 if ( getAuthorization() )
3595 if ( Authentication == AUTH_NTLM && m_strAuthorization.length() > 4 )
3597 m_bKeepAlive =
true;
3600 else if (ProxyAuthentication == AUTH_NTLM && m_strProxyAuthorization.length() > 4)
3605 httpCloseConnection();
3614 m_bUnauthorized =
false;
3618 if (!locationStr.isEmpty())
3620 KURL u(m_request.url, locationStr);
3623 error(ERR_MALFORMED_URL, u.prettyURL());
3626 if ((u.protocol() !=
"http") && (u.protocol() !=
"https") &&
3627 (u.protocol() !=
"ftp") && (u.protocol() !=
"webdav") &&
3628 (u.protocol() !=
"webdavs"))
3631 error(ERR_ACCESS_DENIED, u.prettyURL());
3639 if (m_request.url.hasRef() && !u.hasRef() &&
3640 (m_request.url.host() == u.host()) &&
3641 (m_request.url.protocol() == u.protocol()))
3642 u.setRef(m_request.url.ref());
3645 m_redirectLocation = u;
3647 if (!m_request.id.isEmpty())
3652 kdDebug(7113) <<
"(" << m_pid <<
") request.url: " << m_request.url.prettyURL()
3653 << endl <<
"LocationStr: " << locationStr.data() << endl;
3655 kdDebug(7113) <<
"(" << m_pid <<
") Requesting redirection to: " << u.prettyURL()
3659 if (m_protocol ==
"webdav" || m_protocol ==
"webdavs")
3660 u.setProtocol(m_protocol);
3663 m_request.bCachedWrite =
false;
3668 if ( bCanResume && m_request.offset )
3671 m_request.offset = 0;
3674 if (m_strMimeType.startsWith(
"text/") &&
3675 (m_strMimeType !=
"text/css") &&
3676 (m_strMimeType !=
"text/x-javascript") &&
3682 if ( m_bIsSSL || (Authentication != AUTH_None) )
3684 m_request.bCachedWrite =
false;
3694 if (m_qContentEncodings.last() ==
"gzip")
3696 if (m_strMimeType ==
"application/x-tar")
3698 m_qContentEncodings.remove(m_qContentEncodings.fromLast());
3699 m_strMimeType = TQString::fromLatin1(
"application/x-tgz");
3701 else if (m_strMimeType ==
"application/postscript")
3705 m_qContentEncodings.remove(m_qContentEncodings.fromLast());
3706 m_strMimeType = TQString::fromLatin1(
"application/x-gzpostscript");
3708 else if ( m_request.allowCompressedPage &&
3709 m_strMimeType !=
"application/x-tgz" &&
3710 m_strMimeType !=
"application/x-targz" &&
3711 m_strMimeType !=
"application/x-gzip" &&
3712 m_request.url.path().right(6) ==
".ps.gz" )
3714 m_qContentEncodings.remove(m_qContentEncodings.fromLast());
3715 m_strMimeType = TQString::fromLatin1(
"application/x-gzpostscript");
3717 else if ( (m_request.allowCompressedPage &&
3718 m_strMimeType ==
"text/html")
3720 (m_request.allowCompressedPage &&
3721 m_strMimeType !=
"application/x-tgz" &&
3722 m_strMimeType !=
"application/x-targz" &&
3723 m_strMimeType !=
"application/x-gzip" &&
3724 m_request.url.path().right(3) !=
".gz")
3731 m_qContentEncodings.remove(m_qContentEncodings.fromLast());
3732 m_strMimeType = TQString::fromLatin1(
"application/x-gzip");
3742 if (m_qContentEncodings.last() ==
"bzip2")
3744 m_qContentEncodings.remove(m_qContentEncodings.fromLast());
3745 m_strMimeType = TQString::fromLatin1(
"application/x-bzip2");
3749 if (m_strMimeType ==
"application/x-targz")
3750 m_strMimeType = TQString::fromLatin1(
"application/x-tgz");
3751 else if (m_strMimeType ==
"application/zip")
3752 m_strMimeType = TQString::fromLatin1(
"application/x-zip");
3753 else if (m_strMimeType ==
"image/x-png")
3754 m_strMimeType = TQString::fromLatin1(
"image/png");
3755 else if (m_strMimeType ==
"image/bmp")
3756 m_strMimeType = TQString::fromLatin1(
"image/x-bmp");
3757 else if (m_strMimeType ==
"audio/mpeg" || m_strMimeType ==
"audio/x-mpeg" || m_strMimeType ==
"audio/mp3")
3758 m_strMimeType = TQString::fromLatin1(
"audio/x-mp3");
3759 else if (m_strMimeType ==
"audio/microsoft-wave")
3760 m_strMimeType = TQString::fromLatin1(
"audio/x-wav");
3761 else if (m_strMimeType ==
"audio/midi")
3762 m_strMimeType = TQString::fromLatin1(
"audio/x-midi");
3763 else if (m_strMimeType ==
"image/x-xpixmap")
3764 m_strMimeType = TQString::fromLatin1(
"image/x-xpm");
3765 else if (m_strMimeType ==
"application/rtf")
3766 m_strMimeType = TQString::fromLatin1(
"text/rtf");
3769 else if (m_strMimeType ==
"application/pkix-cert" ||
3770 m_strMimeType ==
"application/binary-certificate")
3772 m_strMimeType = TQString::fromLatin1(
"application/x-x509-ca-cert");
3776 else if (m_strMimeType ==
"application/x-gzip")
3778 if ((m_request.url.path().right(7) ==
".tar.gz") ||
3779 (m_request.url.path().right(4) ==
".tar"))
3780 m_strMimeType = TQString::fromLatin1(
"application/x-tgz");
3781 if ((m_request.url.path().right(6) ==
".ps.gz"))
3782 m_strMimeType = TQString::fromLatin1(
"application/x-gzpostscript");
3786 else if ((m_strMimeType ==
"text/plain") || (m_strMimeType ==
"application/octet-stream"))
3788 TQString ext = m_request.url.path().right(4).upper();
3790 m_strMimeType = TQString::fromLatin1(
"application/x-bzip2");
3791 else if (ext ==
".PEM")
3792 m_strMimeType = TQString::fromLatin1(
"application/x-x509-ca-cert");
3793 else if (ext ==
".SWF")
3794 m_strMimeType = TQString::fromLatin1(
"application/x-shockwave-flash");
3795 else if (ext ==
".PLS")
3796 m_strMimeType = TQString::fromLatin1(
"audio/x-scpls");
3797 else if (ext ==
".WMV")
3798 m_strMimeType = TQString::fromLatin1(
"video/x-ms-wmv");
3805 if (!m_qContentEncodings.isEmpty())
3812 if( !dispositionType.isEmpty() )
3814 kdDebug(7113) <<
"(" << m_pid <<
") Setting Content-Disposition type to: "
3815 << dispositionType << endl;
3816 setMetaData(
"content-disposition-type", dispositionType);
3818 if( !dispositionFilename.isEmpty() )
3820 kdDebug(7113) <<
"(" << m_pid <<
") Setting Content-Disposition filename to: "
3821 << dispositionFilename << endl;
3823 setMetaData(
"content-disposition", dispositionFilename);
3824 setMetaData(
"content-disposition-filename", dispositionFilename);
3827 if (!m_request.lastModified.isEmpty())
3828 setMetaData(
"modified", m_request.lastModified);
3832 setMetaData(
"no-cache",
"true");
3833 setMetaData(
"expire-date",
"1");
3838 tmp.setNum(expireDate);
3839 setMetaData(
"expire-date", tmp);
3840 tmp.setNum(time(0));
3841 setMetaData(
"cache-creation-date", tmp);
3846 if (locationStr.isEmpty() && (!m_strMimeType.isEmpty() ||
3847 m_request.method == HTTP_HEAD))
3849 kdDebug(7113) <<
"(" << m_pid <<
") Emitting mimetype " << m_strMimeType << endl;
3850 mimeType( m_strMimeType );
3855 forwardHttpResponseHeader();
3857 if (m_request.method == HTTP_HEAD)
3861 if (m_request.bUseCache)
3863 ::unlink( TQFile::encodeName(m_request.cef));
3864 if ( m_request.bCachedWrite && !m_strMimeType.isEmpty() )
3867 createCacheEntry(m_strMimeType, expireDate);
3868 if (!m_request.fcache)
3870 m_request.bCachedWrite =
false;
3871 kdDebug(7113) <<
"(" << m_pid <<
") Error creating cache entry for " << m_request.url.prettyURL()<<
"!\n";
3873 m_request.expireDate = expireDate;
3874 m_maxCacheSize = config()->readNumEntry(
"MaxCacheSize", DEFAULT_MAX_CACHE_SIZE) / 2;
3878 if (m_request.bCachedWrite && !m_strMimeType.isEmpty())
3879 kdDebug(7113) <<
"(" << m_pid <<
") Cache, adding \"" << m_request.url.prettyURL() <<
"\"" << endl;
3880 else if (m_request.bCachedWrite && m_strMimeType.isEmpty())
3881 kdDebug(7113) <<
"(" << m_pid <<
") Cache, pending \"" << m_request.url.prettyURL() <<
"\"" << endl;
3883 kdDebug(7113) <<
"(" << m_pid <<
") Cache, not adding \"" << m_request.url.prettyURL() <<
"\"" << endl;
3888 void HTTPProtocol::addEncoding(TQString encoding, TQStringList &encs)
3890 encoding = encoding.stripWhiteSpace().lower();
3892 if (encoding ==
"identity") {
3894 }
else if (encoding ==
"8bit") {
3897 }
else if (encoding ==
"chunked") {
3902 }
else if ((encoding ==
"x-gzip") || (encoding ==
"gzip")) {
3903 encs.append(TQString::fromLatin1(
"gzip"));
3904 }
else if ((encoding ==
"x-bzip2") || (encoding ==
"bzip2")) {
3905 encs.append(TQString::fromLatin1(
"bzip2"));
3906 }
else if ((encoding ==
"x-deflate") || (encoding ==
"deflate")) {
3907 encs.append(TQString::fromLatin1(
"deflate"));
3909 kdDebug(7113) <<
"(" << m_pid <<
") Unknown encoding encountered. "
3910 <<
"Please write code. Encoding = \"" << encoding
3915 bool HTTPProtocol::sendBody()
3920 infoMessage( i18n(
"Requesting data to send" ) );
3925 if ( !m_bufPOST.isNull() )
3927 kdDebug(7113) <<
"(" << m_pid <<
") POST'ing saved data..." << endl;
3930 length = m_bufPOST.size();
3934 kdDebug(7113) <<
"(" << m_pid <<
") POST'ing live data..." << endl;
3939 m_bufPOST.resize(0);
3943 result = readData( buffer );
3947 old_size = m_bufPOST.size();
3948 m_bufPOST.resize( old_size+result );
3949 memcpy( m_bufPOST.data()+ old_size, buffer.data(), buffer.size() );
3952 }
while ( result > 0 );
3957 error( ERR_ABORTED, m_request.hostname );
3961 infoMessage( i18n(
"Sending data to %1" ).arg( m_request.hostname ) );
3963 TQString size = TQString (
"Content-Length: %1\r\n\r\n").arg(length);
3964 kdDebug( 7113 ) <<
"(" << m_pid <<
")" << size << endl;
3967 bool sendOk = (write(size.latin1(), size.length()) == (ssize_t) size.length());
3970 kdDebug( 7113 ) <<
"(" << m_pid <<
") Connection broken when sending "
3971 <<
"content length: (" << m_state.hostname <<
")" << endl;
3972 error( ERR_CONNECTION_BROKEN, m_state.hostname );
3978 sendOk = (write(m_bufPOST.data(), m_bufPOST.size()) == (ssize_t) m_bufPOST.size());
3981 kdDebug(7113) <<
"(" << m_pid <<
") Connection broken when sending message body: ("
3982 << m_state.hostname <<
")" << endl;
3983 error( ERR_CONNECTION_BROKEN, m_state.hostname );
3990 void HTTPProtocol::httpClose(
bool keepAlive )
3992 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::httpClose" << endl;
3994 if (m_request.fcache)
3996 fclose(m_request.fcache);
3997 m_request.fcache = 0;
3998 if (m_request.bCachedWrite)
4000 TQString filename = m_request.cef +
".new";
4001 ::unlink( TQFile::encodeName(filename) );
4009 if (keepAlive && (!m_bUseProxy ||
4010 m_bPersistentProxyConnection || m_bIsTunneled))
4012 if (!m_keepAliveTimeout)
4013 m_keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
4014 else if (m_keepAliveTimeout > 2*DEFAULT_KEEP_ALIVE_TIMEOUT)
4015 m_keepAliveTimeout = 2*DEFAULT_KEEP_ALIVE_TIMEOUT;
4017 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::httpClose: keep alive (" << m_keepAliveTimeout <<
")" << endl;
4019 TQDataStream stream( data, IO_WriteOnly );
4021 setTimeoutSpecialCommand(m_keepAliveTimeout, data);
4025 httpCloseConnection();
4028 void HTTPProtocol::closeConnection()
4030 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::closeConnection" << endl;
4031 httpCloseConnection ();
4034 void HTTPProtocol::httpCloseConnection ()
4036 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::httpCloseConnection" << endl;
4037 m_bIsTunneled =
false;
4038 m_bKeepAlive =
false;
4040 setTimeoutSpecialCommand(-1);
4043 void HTTPProtocol::slave_status()
4045 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::slave_status" << endl;
4047 if ( m_iSock != -1 && !isConnectionValid() )
4048 httpCloseConnection();
4050 slaveStatus( m_state.hostname, (m_iSock != -1) );
4053 void HTTPProtocol::mimetype(
const KURL& url )
4055 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::mimetype: "
4056 << url.prettyURL() << endl;
4058 if ( !checkRequestURL( url ) )
4061 m_request.method = HTTP_HEAD;
4062 m_request.path = url.path();
4063 m_request.query = url.query();
4064 m_request.cache = CC_Cache;
4065 m_request.doProxy = m_bUseProxy;
4069 kdDebug(7113) <<
"(" << m_pid <<
") http: mimetype = " << m_strMimeType
4073 void HTTPProtocol::special(
const TQByteArray &data )
4075 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::special" << endl;
4078 TQDataStream stream(data, IO_ReadOnly);
4094 stream >> url >> no_cache >> expireDate;
4095 cacheUpdate( url, no_cache, expireDate );
4101 TQString scope, type, owner;
4102 stream >> url >> scope >> type >> owner;
4103 davLock( url, scope, type, owner );
4117 stream >> url >> method;
4118 davGeneric( url, (TDEIO::HTTP_METHOD) method );
4123 httpCloseConnection();
4136 int HTTPProtocol::readChunked()
4138 if ((m_iBytesLeft == 0) || (m_iBytesLeft == NO_SIZE))
4142 m_bufReceive.resize(4096);
4144 if (!gets(m_bufReceive.data(), m_bufReceive.size()-1))
4146 kdDebug(7113) <<
"(" << m_pid <<
") gets() failure on Chunk header" << endl;
4151 if (m_bufReceive[0] ==
'\0')
4153 if (!gets(m_bufReceive.data(), m_bufReceive.size()-1))
4155 kdDebug(7113) <<
"(" << m_pid <<
") gets() failure on Chunk header" << endl;
4165 kdDebug(7113) <<
"(" << m_pid <<
") EOF on Chunk header" << endl;
4170 long long trunkSize = STRTOLL(m_bufReceive.data(), 0, 16);
4173 kdDebug(7113) <<
"(" << m_pid <<
") Negative chunk size" << endl;
4176 m_iBytesLeft = trunkSize;
4180 if (m_iBytesLeft == 0)
4186 if (!gets(m_bufReceive.data(), m_bufReceive.size()-1))
4188 kdDebug(7113) <<
"(" << m_pid <<
") gets() failure on Chunk trailer" << endl;
4193 while (strlen(m_bufReceive.data()) != 0);
4199 int bytesReceived = readLimited();
4201 m_iBytesLeft = NO_SIZE;
4204 return bytesReceived;
4207 int HTTPProtocol::readLimited()
4212 m_bufReceive.resize(4096);
4217 if (m_iBytesLeft > m_bufReceive.size())
4218 bytesToReceive = m_bufReceive.size();
4220 bytesToReceive = m_iBytesLeft;
4222 bytesReceived = read(m_bufReceive.data(), bytesToReceive);
4224 if (bytesReceived <= 0)
4227 m_iBytesLeft -= bytesReceived;
4228 return bytesReceived;
4231 int HTTPProtocol::readUnlimited()
4235 kdDebug(7113) <<
"(" << m_pid <<
") Unbounded datastream on a Keep "
4236 <<
"alive connection!" << endl;
4237 m_bKeepAlive =
false;
4240 m_bufReceive.resize(4096);
4242 int result = read(m_bufReceive.data(), m_bufReceive.size());
4251 void HTTPProtocol::slotData(
const TQByteArray &_d)
4259 if (m_iContentLeft != NO_SIZE)
4261 if (m_iContentLeft >= _d.size())
4262 m_iContentLeft -= _d.size();
4264 m_iContentLeft = NO_SIZE;
4268 if ( !m_dataInternal )
4273 if ( m_strMimeType.isEmpty() && !m_bRedirect &&
4274 !( m_responseCode >= 300 && m_responseCode <=399) )
4276 kdDebug(7113) <<
"(" << m_pid <<
") Determining mime-type from content..." << endl;
4277 int old_size = m_mimeTypeBuffer.size();
4278 m_mimeTypeBuffer.resize( old_size + d.size() );
4279 memcpy( m_mimeTypeBuffer.data() + old_size, d.data(), d.size() );
4280 if ( (m_iBytesLeft != NO_SIZE) && (m_iBytesLeft > 0)
4281 && (m_mimeTypeBuffer.size() < 1024) )
4283 m_cpMimeBuffer =
true;
4287 kdDebug(7113) <<
"(" << m_pid <<
") Mimetype buffer size: " << m_mimeTypeBuffer.size()
4290 KMimeMagicResult *result;
4291 result = KMimeMagic::self()->findBufferFileType( m_mimeTypeBuffer,
4292 m_request.url.fileName() );
4295 m_strMimeType = result->mimeType();
4296 kdDebug(7113) <<
"(" << m_pid <<
") Mimetype from content: "
4297 << m_strMimeType << endl;
4300 if ( m_strMimeType.isEmpty() )
4302 m_strMimeType = TQString::fromLatin1( DEFAULT_MIME_TYPE );
4303 kdDebug(7113) <<
"(" << m_pid <<
") Using default mimetype: "
4304 << m_strMimeType << endl;
4307 if ( m_request.bCachedWrite )
4309 createCacheEntry( m_strMimeType, m_request.expireDate );
4310 if (!m_request.fcache)
4311 m_request.bCachedWrite =
false;
4314 if ( m_cpMimeBuffer )
4320 d.resize(m_mimeTypeBuffer.size());
4321 memcpy( d.data(), m_mimeTypeBuffer.data(),
4324 mimeType(m_strMimeType);
4325 m_mimeTypeBuffer.resize(0);
4329 if (m_request.bCachedWrite && m_request.fcache)
4330 writeCacheEntry(d.data(), d.size());
4334 uint old_size = m_bufWebDavData.size();
4335 m_bufWebDavData.resize (old_size + d.size());
4336 memcpy (m_bufWebDavData.data() + old_size, d.data(), d.size());
4349 bool HTTPProtocol::readBody(
bool dataInternal )
4351 if (m_responseCode == 204)
4360 m_dataInternal = dataInternal;
4362 m_bufWebDavData.resize (0);
4366 bool useMD5 = !m_sContentMD5.isEmpty();
4369 TDEIO::filesize_t sz = m_request.offset;
4377 if ( !dataInternal ) {
4378 if ( (m_iSize > 0) && (m_iSize != NO_SIZE)) {
4380 infoMessage( i18n(
"Retrieving %1 from %2...").arg(TDEIO::convertSize(m_iSize))
4381 .arg( m_request.hostname ) );
4389 infoMessage( i18n(
"Retrieving from %1..." ).arg( m_request.hostname ) );
4391 if (m_request.bCachedRead)
4393 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::readBody: read data from cache!" << endl;
4394 m_request.bCachedWrite =
false;
4396 char buffer[ MAX_IPC_SIZE ];
4398 m_iContentLeft = NO_SIZE;
4401 while (!feof(m_request.fcache) && !ferror(m_request.fcache))
4403 int nbytes = fread( buffer, 1, MAX_IPC_SIZE, m_request.fcache);
4407 m_bufReceive.setRawData( buffer, nbytes);
4408 slotData( m_bufReceive );
4409 m_bufReceive.resetRawData( buffer, nbytes );
4414 m_bufReceive.resize( 0 );
4416 if ( !dataInternal )
4418 processedSize( sz );
4419 data( TQByteArray() );
4426 if (m_iSize != NO_SIZE)
4427 m_iBytesLeft = m_iSize - sz;
4429 m_iBytesLeft = NO_SIZE;
4431 m_iContentLeft = m_iBytesLeft;
4434 m_iBytesLeft = NO_SIZE;
4436 kdDebug(7113) <<
"(" << m_pid <<
") HTTPProtocol::readBody: retrieve data. "
4437 << TDEIO::number(m_iBytesLeft) <<
" left." << endl;
4440 m_cpMimeBuffer =
false;
4441 m_mimeTypeBuffer.resize(0);
4442 struct timeval last_tv;
4443 gettimeofday( &last_tv, 0L );
4445 HTTPFilterChain chain;
4447 TQObject::connect(&chain, TQ_SIGNAL(output(
const TQByteArray &)),
4448 this, TQ_SLOT(slotData(
const TQByteArray &)));
4449 TQObject::connect(&chain, TQ_SIGNAL(error(
int,
const TQString &)),
4450 this, TQ_SLOT(error(
int,
const TQString &)));
4453 while (!m_qTransferEncodings.isEmpty())
4455 TQString enc = m_qTransferEncodings.last();
4456 m_qTransferEncodings.remove(m_qTransferEncodings.fromLast());
4457 if ( enc ==
"gzip" )
4458 chain.addFilter(
new HTTPFilterGZip);
4459 else if ( enc ==
"deflate" )
4460 chain.addFilter(
new HTTPFilterDeflate);
4469 HTTPFilterMD5 *md5Filter = 0;
4472 md5Filter =
new HTTPFilterMD5;
4473 chain.addFilter(md5Filter);
4484 while (!m_qContentEncodings.isEmpty())
4486 TQString enc = m_qContentEncodings.last();
4487 m_qContentEncodings.remove(m_qContentEncodings.fromLast());
4488 if ( enc ==
"gzip" )
4489 chain.addFilter(
new HTTPFilterGZip);
4490 else if ( enc ==
"deflate" )
4491 chain.addFilter(
new HTTPFilterDeflate);
4499 bytesReceived = readChunked();
4500 else if (m_iSize != NO_SIZE)
4501 bytesReceived = readLimited();
4503 bytesReceived = readUnlimited();
4509 if (bytesReceived == -1)
4511 if (m_iContentLeft == 0)
4519 kdDebug(7113) <<
"(" << m_pid <<
") readBody: bytesReceived==-1 sz=" << (int)sz
4520 <<
" Connnection broken !" << endl;
4521 error(ERR_CONNECTION_BROKEN, m_state.hostname);
4527 if (bytesReceived > 0)
4531 m_bufReceive.truncate( bytesReceived );
4533 chain.slotInput(m_bufReceive);
4538 sz += bytesReceived;
4540 processedSize( sz );
4542 m_bufReceive.resize(0);
4544 if (m_iBytesLeft && m_bEOD && !m_bChunked)
4551 if (m_iBytesLeft == 0)
4553 kdDebug(7113) <<
"("<<m_pid<<
") EOD received! Left = "<< TDEIO::number(m_iBytesLeft) << endl;
4557 chain.slotInput(TQByteArray());
4561 TQString calculatedMD5 = md5Filter->md5();
4563 if ( m_sContentMD5 == calculatedMD5 )
4564 kdDebug(7113) <<
"(" << m_pid <<
") MD5 checksum MATCHED!!" << endl;
4566 kdDebug(7113) <<
"(" << m_pid <<
") MD5 checksum MISMATCH! Expected: "
4567 << calculatedMD5 <<
", Got: " << m_sContentMD5 << endl;
4571 if (m_iBytesLeft == 0)
4573 if (m_request.bCachedWrite && m_request.fcache)
4575 else if (m_request.bCachedWrite)
4576 kdDebug(7113) <<
"(" << m_pid <<
") no cache file!\n";
4580 kdDebug(7113) <<
"(" << m_pid <<
") still "<< TDEIO::number(m_iBytesLeft)
4581 <<
" bytes left! can't close cache entry!\n";
4588 if (m_responseCode >= 500 && m_responseCode <= 599)
4589 error(ERR_INTERNAL_SERVER, m_state.hostname);
4590 else if (m_responseCode >= 400 && m_responseCode <= 499)
4591 error(ERR_DOES_NOT_EXIST, m_state.hostname);
4595 data( TQByteArray() );
4601 void HTTPProtocol::error(
int _err,
const TQString &_text )
4605 if (!m_request.id.isEmpty())
4607 forwardHttpResponseHeader();
4612 if (!m_bufPOST.isEmpty())
4614 m_bufPOST.resize(0);
4615 kdDebug(7113) <<
"(" << m_pid <<
") HTTP::retreiveHeader: Cleared POST "
4616 "buffer..." << endl;
4619 SlaveBase::error( _err, _text );
4624 void HTTPProtocol::addCookies(
const TQString &url,
const TQCString &cookieHeader )
4626 long windowId = m_request.window.toLong();
4628 TQDataStream stream(params, IO_WriteOnly);
4629 stream << url << cookieHeader << windowId;
4631 kdDebug(7113) <<
"(" << m_pid <<
") " << cookieHeader << endl;
4632 kdDebug(7113) <<
"(" << m_pid <<
") " <<
"Window ID: "
4633 << windowId <<
", for host = " << url << endl;
4635 if ( !dcopClient()->send(
"kded",
"kcookiejar",
"addCookies(TQString,TQCString,long int)", params ) )
4637 kdWarning(7113) <<
"(" << m_pid <<
") Can't communicate with kded_kcookiejar!" << endl;
4641 TQString HTTPProtocol::findCookies(
const TQString &url)
4643 TQCString replyType;
4648 long windowId = m_request.window.toLong();
4649 result = TQString::null;
4650 TQDataStream stream(params, IO_WriteOnly);
4651 stream << url << windowId;
4653 if ( !dcopClient()->call(
"kded",
"kcookiejar",
"findCookies(TQString,long int)",
4654 params, replyType, reply ) )
4656 kdWarning(7113) <<
"(" << m_pid <<
") Can't communicate with kded_kcookiejar!" << endl;
4659 if ( replyType ==
"TQString" )
4661 TQDataStream stream2( reply, IO_ReadOnly );
4666 kdError(7113) <<
"(" << m_pid <<
") DCOP function findCookies(...) returns "
4667 << replyType <<
", expected TQString" << endl;
4675 void HTTPProtocol::cacheUpdate(
const KURL& url,
bool no_cache, time_t expireDate)
4677 if ( !checkRequestURL( url ) )
4680 m_request.path = url.path();
4681 m_request.query = url.query();
4682 m_request.cache = CC_Reload;
4683 m_request.doProxy = m_bUseProxy;
4687 m_request.fcache = checkCacheEntry( );
4688 if (m_request.fcache)
4690 fclose(m_request.fcache);
4691 m_request.fcache = 0;
4692 ::unlink( TQFile::encodeName(m_request.cef) );
4697 updateExpireDate( expireDate );
4706 FILE* HTTPProtocol::checkCacheEntry(
bool readWrite)
4708 const TQChar separator =
'_';
4710 TQString CEF = m_request.path;
4712 int p = CEF.find(
'/');
4717 p = CEF.find(
'/', p);
4720 TQString host = m_request.hostname.lower();
4721 CEF = host + CEF +
'_';
4723 TQString dir = m_strCacheDir;
4724 if (dir[dir.length()-1] !=
'/')
4727 int l = host.length();
4728 for(
int i = 0; i < l; i++)
4730 if (host[i].isLetter() && (host[i] !=
'w'))
4736 if (dir[dir.length()-1] ==
'/')
4739 unsigned long hash = 0x00000000;
4740 TQCString u = m_request.url.url().latin1();
4741 for(
int i = u.length(); i--;)
4743 hash = (hash * 12211 +
static_cast<const char>(u.at(i))) % 2147483563;
4746 TQString hashString;
4747 hashString.sprintf(
"%08lx", hash);
4749 CEF = CEF + hashString;
4751 CEF = dir +
"/" + CEF;
4753 m_request.cef = CEF;
4755 const char *mode = (readWrite ?
"r+" :
"r");
4757 FILE *fs = fopen( TQFile::encodeName(CEF), mode);
4765 if (ok && (!fgets(buffer, 400, fs)))
4767 if (ok && (strcmp(buffer, CACHE_REVISION) != 0))
4771 time_t currentDate = time(0);
4774 if (ok && (!fgets(buffer, 400, fs)))
4778 int l = strlen(buffer);
4781 if (m_request.url.url() != buffer)
4788 if (ok && (!fgets(buffer, 400, fs)))
4792 date = (time_t) strtoul(buffer, 0, 10);
4793 m_request.creationDate = date;
4794 if (m_maxCacheAge && (difftime(currentDate, date) > m_maxCacheAge))
4796 m_request.bMustRevalidate =
true;
4797 m_request.expireDate = currentDate;
4802 m_request.cacheExpireDateOffset = ftell(fs);
4803 if (ok && (!fgets(buffer, 400, fs)))
4807 if (m_request.cache == CC_Verify)
4809 date = (time_t) strtoul(buffer, 0, 10);
4811 if (!date || difftime(currentDate, date) >= 0)
4812 m_request.bMustRevalidate =
true;
4813 m_request.expireDate = date;
4815 else if (m_request.cache == CC_Refresh)
4817 m_request.bMustRevalidate =
true;
4818 m_request.expireDate = currentDate;
4823 if (ok && (!fgets(buffer, 400, fs)))
4827 m_request.etag = TQString(buffer).stripWhiteSpace();
4831 if (ok && (!fgets(buffer, 400, fs)))
4835 m_request.lastModified = TQString(buffer).stripWhiteSpace();
4842 unlink( TQFile::encodeName(CEF));
4846 void HTTPProtocol::updateExpireDate(time_t expireDate,
bool updateCreationDate)
4850 FILE *fs = checkCacheEntry(
true);
4855 time_t creationDate;
4857 fseek(fs, 0, SEEK_SET);
4858 if (ok && !fgets(buffer, 400, fs))
4860 if (ok && !fgets(buffer, 400, fs))
4862 long cacheCreationDateOffset = ftell(fs);
4863 if (ok && !fgets(buffer, 400, fs))
4865 creationDate = strtoul(buffer, 0, 10);
4869 if (updateCreationDate)
4871 if (!ok || fseek(fs, cacheCreationDateOffset, SEEK_SET))
4874 date.setNum( time(0) );
4875 date = date.leftJustify(16);
4876 fputs(date.latin1(), fs);
4880 if (expireDate>(30*365*24*60*60))
4884 date.setNum( expireDate );
4893 date.setNum( creationDate + expireDate );
4895 date = date.leftJustify(16);
4896 if (!ok || fseek(fs, m_request.cacheExpireDateOffset, SEEK_SET))
4898 fputs(date.latin1(), fs);
4899 fseek(fs, 0, SEEK_END);
4904 void HTTPProtocol::createCacheEntry(
const TQString &mimetype, time_t expireDate)
4906 TQString dir = m_request.cef;
4907 int p = dir.findRev(
'/');
4908 if (p == -1)
return;
4912 (void) ::mkdir( TQFile::encodeName(dir), 0700 );
4914 TQString filename = m_request.cef +
".new";
4918 m_request.fcache = fopen( TQFile::encodeName(filename),
"w");
4919 if (!m_request.fcache)
4921 kdWarning(7113) <<
"(" << m_pid <<
")createCacheEntry: opening " << filename <<
" failed." << endl;
4925 fputs(CACHE_REVISION, m_request.fcache);
4927 fputs(m_request.url.url().latin1(), m_request.fcache);
4928 fputc(
'\n', m_request.fcache);
4931 m_request.creationDate = time(0);
4932 date.setNum( m_request.creationDate );
4933 date = date.leftJustify(16);
4934 fputs(date.latin1(), m_request.fcache);
4935 fputc(
'\n', m_request.fcache);
4937 date.setNum( expireDate );
4938 date = date.leftJustify(16);
4939 fputs(date.latin1(), m_request.fcache);
4940 fputc(
'\n', m_request.fcache);
4942 if (!m_request.etag.isEmpty())
4943 fputs(m_request.etag.latin1(), m_request.fcache);
4944 fputc(
'\n', m_request.fcache);
4946 if (!m_request.lastModified.isEmpty())
4947 fputs(m_request.lastModified.latin1(), m_request.fcache);
4948 fputc(
'\n', m_request.fcache);
4950 fputs(mimetype.latin1(), m_request.fcache);
4951 fputc(
'\n', m_request.fcache);
4953 if (!m_request.strCharset.isEmpty())
4954 fputs(m_request.strCharset.latin1(), m_request.fcache);
4955 fputc(
'\n', m_request.fcache);
4963 void HTTPProtocol::writeCacheEntry(
const char *buffer,
int nbytes)
4965 if (fwrite( buffer, nbytes, 1, m_request.fcache) != 1)
4967 kdWarning(7113) <<
"(" << m_pid <<
") writeCacheEntry: writing " << nbytes <<
" bytes failed." << endl;
4968 fclose(m_request.fcache);
4969 m_request.fcache = 0;
4970 TQString filename = m_request.cef +
".new";
4971 ::unlink( TQFile::encodeName(filename) );
4974 long file_pos = ftell( m_request.fcache ) / 1024;
4975 if ( file_pos > m_maxCacheSize )
4977 kdDebug(7113) <<
"writeCacheEntry: File size reaches " << file_pos
4978 <<
"Kb, exceeds cache limits. (" << m_maxCacheSize <<
"Kb)" << endl;
4979 fclose(m_request.fcache);
4980 m_request.fcache = 0;
4981 TQString filename = m_request.cef +
".new";
4982 ::unlink( TQFile::encodeName(filename) );
4987 void HTTPProtocol::closeCacheEntry()
4989 TQString filename = m_request.cef +
".new";
4990 int result = fclose( m_request.fcache);
4991 m_request.fcache = 0;
4994 if (::rename( TQFile::encodeName(filename), TQFile::encodeName(m_request.cef)) == 0)
4997 kdWarning(7113) <<
"(" << m_pid <<
") closeCacheEntry: error renaming "
4998 <<
"cache entry. (" << filename <<
" -> " << m_request.cef
5002 kdWarning(7113) <<
"(" << m_pid <<
") closeCacheEntry: error closing cache "
5003 <<
"entry. (" << filename<<
")" << endl;
5006 void HTTPProtocol::cleanCache()
5008 const time_t maxAge = DEFAULT_CLEAN_CACHE_INTERVAL;
5009 bool doClean =
false;
5010 TQString cleanFile = m_strCacheDir;
5011 if (cleanFile[cleanFile.length()-1] !=
'/')
5013 cleanFile +=
"cleaned";
5015 struct stat stat_buf;
5017 int result = ::stat(TQFile::encodeName(cleanFile), &stat_buf);
5020 int fd = creat( TQFile::encodeName(cleanFile), 0600);
5029 time_t age = (time_t) difftime( time(0), stat_buf.st_mtime );
5036 utime(TQFile::encodeName(cleanFile), 0);
5037 TDEApplication::startServiceByDesktopPath(
"http_cache_cleaner.desktop");
5046 void HTTPProtocol::configAuth(
char *p,
bool isForProxy )
5048 HTTP_AUTH f = AUTH_None;
5049 const char *strAuth = p;
5051 if ( strncasecmp( p,
"Basic", 5 ) == 0 )
5057 else if ( strncasecmp (p,
"Digest", 6) == 0 )
5060 memcpy((
void *)p,
"Digest", 6);
5063 else if (strncasecmp( p,
"MBS_PWD_COOKIE", 14 ) == 0)
5070 #ifdef HAVE_LIBGSSAPI
5071 else if ( strncasecmp( p,
"Negotiate", 9 ) == 0 )
5075 if ( !isForProxy && !(m_responseCode == 401 && m_prevResponseCode == 401) )
5078 memcpy((
void *)p,
"Negotiate", 9);
5083 else if ( strncasecmp( p,
"NTLM", 4 ) == 0 )
5086 memcpy((
void *)p,
"NTLM", 4);
5088 m_strRealm =
"NTLM";
5092 kdWarning(7113) <<
"(" << m_pid <<
") Unsupported or invalid authorization "
5093 <<
"type requested" << endl;
5095 kdWarning(7113) <<
"(" << m_pid <<
") Proxy URL: " << m_proxyURL << endl;
5097 kdWarning(7113) <<
"(" << m_pid <<
") URL: " << m_request.url << endl;
5098 kdWarning(7113) <<
"(" << m_pid <<
") Request Authorization: " << p << endl;
5110 if ((f == AUTH_None) ||
5111 ((m_iProxyAuthCount > 0) && (f < ProxyAuthentication)))
5117 if ( m_iProxyAuthCount == 0)
5118 ProxyAuthentication = f;
5119 kdDebug(7113) <<
"(" << m_pid <<
") Rejected proxy auth method: " << f << endl;
5122 m_iProxyAuthCount++;
5123 kdDebug(7113) <<
"(" << m_pid <<
") Accepted proxy auth method: " << f << endl;
5127 if ((f == AUTH_None) ||
5128 ((m_iWWWAuthCount > 0) && (f < Authentication)))
5130 kdDebug(7113) <<
"(" << m_pid <<
") Rejected auth method: " << f << endl;
5134 kdDebug(7113) <<
"(" << m_pid <<
") Accepted auth method: " << f << endl;
5141 while( (*p ==
' ') || (*p ==
',') || (*p ==
'\t') ) { p++; }
5142 if ( strncasecmp( p,
"realm=", 6 ) == 0 )
5145 TQTextCodec* oldCodec=TQTextCodec::codecForCStrings();
5146 if (TDEGlobal::locale()->language().contains(
"ru"))
5147 TQTextCodec::setCodecForCStrings(TQTextCodec::codecForName(
"CP1251"));
5151 while( p[i] && p[i] !=
'"' ) i++;
5153 m_strProxyRealm = TQString::fromAscii( p, i );
5155 m_strRealm = TQString::fromAscii( p, i );
5157 TQTextCodec::setCodecForCStrings(oldCodec);
5166 ProxyAuthentication = f;
5167 m_strProxyAuthorization = TQString::fromLatin1( strAuth );
5172 m_strAuthorization = TQString::fromLatin1( strAuth );
5177 bool HTTPProtocol::retryPrompt()
5180 switch ( m_responseCode )
5183 prompt = i18n(
"Authentication Failed.");
5186 prompt = i18n(
"Proxy Authentication Failed.");
5191 prompt += i18n(
" Do you want to retry?");
5192 return (messageBox(QuestionYesNo, prompt, i18n(
"Authentication")) == 3);
5195 void HTTPProtocol::promptInfo( AuthInfo& info )
5197 if ( m_responseCode == 401 )
5199 info.url = m_request.url;
5200 if ( !m_state.user.isEmpty() )
5201 info.username = m_state.user;
5202 info.readOnly = !m_request.url.user().isEmpty();
5203 info.prompt = i18n(
"You need to supply a username and a "
5204 "password to access this site." );
5205 info.keepPassword =
true;
5206 if ( !m_strRealm.isEmpty() )
5208 info.realmValue = m_strRealm;
5209 info.verifyPath =
false;
5210 info.digestInfo = m_strAuthorization;
5211 info.commentLabel = i18n(
"Site:" );
5212 info.comment = i18n(
"<b>%1</b> at <b>%2</b>").arg( htmlEscape(m_strRealm) ).arg( m_request.hostname );
5215 else if ( m_responseCode == 407 )
5217 info.url = m_proxyURL;
5218 info.username = m_proxyURL.user();
5219 info.prompt = i18n(
"You need to supply a username and a password for "
5220 "the proxy server listed below before you are allowed "
5221 "to access any sites." );
5222 info.keepPassword =
true;
5223 if ( !m_strProxyRealm.isEmpty() )
5225 info.realmValue = m_strProxyRealm;
5226 info.verifyPath =
false;
5227 info.digestInfo = m_strProxyAuthorization;
5228 info.commentLabel = i18n(
"Proxy:" );
5229 info.comment = i18n(
"<b>%1</b> at <b>%2</b>").arg( htmlEscape(m_strProxyRealm) ).arg( m_proxyURL.host() );
5234 bool HTTPProtocol::getAuthorization()
5237 bool result =
false;
5239 kdDebug (7113) <<
"(" << m_pid <<
") HTTPProtocol::getAuthorization: "
5240 <<
"Current Response: " << m_responseCode <<
", "
5241 <<
"Previous Response: " << m_prevResponseCode <<
", "
5242 <<
"Authentication: " << Authentication <<
", "
5243 <<
"ProxyAuthentication: " << ProxyAuthentication << endl;
5245 if (m_request.bNoAuth)
5247 if (m_request.bErrorPage)
5250 error( ERR_COULD_NOT_LOGIN, i18n(
"Authentication needed for %1 but authentication is disabled.").arg(m_request.hostname));
5254 bool repeatFailure = (m_prevResponseCode == m_responseCode);
5261 if ( Authentication == AUTH_Digest || ProxyAuthentication == AUTH_Digest )
5263 bool isStaleNonce =
false;
5264 TQString auth = ( m_responseCode == 401 ) ? m_strAuthorization : m_strProxyAuthorization;
5265 int pos = auth.find(
"stale", 0,
false);
5269 int len = auth.length();
5270 while( pos < len && (auth[pos] ==
' ' || auth[pos] ==
'=') ) pos++;
5271 if ( pos < len && auth.find(
"true", pos,
false) != -1 )
5273 isStaleNonce =
true;
5274 kdDebug(7113) <<
"(" << m_pid <<
") Stale nonce value. "
5275 <<
"Will retry using same info..." << endl;
5282 if ( m_responseCode == 401 )
5284 info.username = m_request.user;
5285 info.password = m_request.passwd;
5286 info.realmValue = m_strRealm;
5287 info.digestInfo = m_strAuthorization;
5289 else if ( m_responseCode == 407 )
5291 info.username = m_proxyURL.user();
5292 info.password = m_proxyURL.pass();
5293 info.realmValue = m_strProxyRealm;
5294 info.digestInfo = m_strProxyAuthorization;
5299 if ( Authentication == AUTH_NTLM || ProxyAuthentication == AUTH_NTLM )
5301 TQString auth = ( m_responseCode == 401 ) ? m_strAuthorization : m_strProxyAuthorization;
5302 kdDebug(7113) <<
"auth: " << auth << endl;
5303 if ( auth.length() > 4 )
5307 kdDebug(7113) <<
"(" << m_pid <<
") NTLM auth second phase, "
5308 <<
"sending response..." << endl;
5309 if ( m_responseCode == 401 )
5311 info.username = m_request.user;
5312 info.password = m_request.passwd;
5313 info.realmValue = m_strRealm;
5314 info.digestInfo = m_strAuthorization;
5316 else if ( m_responseCode == 407 )
5318 info.username = m_proxyURL.user();
5319 info.password = m_proxyURL.pass();
5320 info.realmValue = m_strProxyRealm;
5321 info.digestInfo = m_strProxyAuthorization;
5328 switch ( m_responseCode )
5331 errorMsg = i18n(
"Authentication Failed.");
5334 errorMsg = i18n(
"Proxy Authentication Failed.");
5348 if (m_bProxyAuthValid)
5351 m_bProxyAuthValid =
false;
5352 KURL proxy ( config()->readEntry(
"UseProxy") );
5353 m_proxyURL.setUser(proxy.user());
5354 m_proxyURL.setPass(proxy.pass());
5357 info.verifyPath =
false;
5358 if ( m_responseCode == 407 )
5360 info.url = m_proxyURL;
5361 info.username = m_proxyURL.user();
5362 info.password = m_proxyURL.pass();
5363 info.realmValue = m_strProxyRealm;
5364 info.digestInfo = m_strProxyAuthorization;
5368 info.url = m_request.url;
5369 info.username = m_request.user;
5370 info.password = m_request.passwd;
5371 info.realmValue = m_strRealm;
5372 info.digestInfo = m_strAuthorization;
5377 if ( info.username.isNull() ||
5378 info.password.isNull() )
5379 result = checkCachedAuthentication( info );
5381 if ( Authentication == AUTH_Digest )
5385 if (m_responseCode == 401)
5386 auth = m_strAuthorization;
5388 auth = m_strProxyAuthorization;
5390 int pos = auth.find(
"stale", 0,
false);
5394 int len = auth.length();
5395 while( pos < len && (auth[pos] ==
' ' || auth[pos] ==
'=') ) pos++;
5396 if ( pos < len && auth.find(
"true", pos,
false) != -1 )
5398 info.digestInfo = (m_responseCode == 401) ? m_strAuthorization : m_strProxyAuthorization;
5399 kdDebug(7113) <<
"(" << m_pid <<
") Just a stale nonce value! "
5400 <<
"Retrying using the new nonce sent..." << endl;
5411 if ( !repeatFailure &&
5412 !info.username.isNull() &&
5413 !info.password.isNull() )
5417 if (Authentication == AUTH_Negotiate)
5422 else if ( m_request.disablePassDlg ==
false )
5424 kdDebug( 7113 ) <<
"(" << m_pid <<
") Prompting the user for authorization..." << endl;
5426 result = openPassDlg( info, errorMsg );
5433 switch (m_responseCode)
5436 m_request.user = info.username;
5437 m_request.passwd = info.password;
5438 m_strRealm = info.realmValue;
5439 m_strAuthorization = info.digestInfo;
5442 m_proxyURL.setUser( info.username );
5443 m_proxyURL.setPass( info.password );
5444 m_strProxyRealm = info.realmValue;
5445 m_strProxyAuthorization = info.digestInfo;
5453 if (m_request.bErrorPage)
5456 error( ERR_USER_CANCELED, TQString::null );
5460 void HTTPProtocol::saveAuthorization()
5463 if ( m_prevResponseCode == 407 )
5467 m_bProxyAuthValid =
true;
5468 info.url = m_proxyURL;
5469 info.username = m_proxyURL.user();
5470 info.password = m_proxyURL.pass();
5471 info.realmValue = m_strProxyRealm;
5472 info.digestInfo = m_strProxyAuthorization;
5473 cacheAuthentication( info );
5477 info.url = m_request.url;
5478 info.username = m_request.user;
5479 info.password = m_request.passwd;
5480 info.realmValue = m_strRealm;
5481 info.digestInfo = m_strAuthorization;
5482 cacheAuthentication( info );
5486 #ifdef HAVE_LIBGSSAPI
5487 TQCString HTTPProtocol::gssError(
int major_status,
int minor_status )
5489 OM_uint32 new_status;
5490 OM_uint32 msg_ctx = 0;
5491 gss_buffer_desc major_string;
5492 gss_buffer_desc minor_string;
5499 ret = gss_display_status(&new_status, major_status, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &major_string);
5500 errorstr += (
const char *)major_string.value;
5502 ret = gss_display_status(&new_status, minor_status, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &minor_string);
5503 errorstr += (
const char *)minor_string.value;
5505 }
while (!GSS_ERROR(ret) && msg_ctx != 0);
5510 TQString HTTPProtocol::createNegotiateAuth()
5513 TQCString servicename;
5515 OM_uint32 major_status, minor_status;
5516 OM_uint32 req_flags = 0;
5517 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
5518 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
5522 static gss_OID_desc krb5_oid_desc = {9, (
void *)
"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
5523 static gss_OID_desc spnego_oid_desc = {6, (
void *)
"\x2b\x06\x01\x05\x05\x02"};
5526 gss_OID_set mech_set;
5529 ctx = GSS_C_NO_CONTEXT;
5530 mech_oid = &krb5_oid_desc;
5533 major_status = gss_indicate_mechs(&minor_status, &mech_set);
5534 if (GSS_ERROR(major_status)) {
5535 kdDebug(7113) <<
"(" << m_pid <<
") gss_indicate_mechs failed: " << gssError(major_status, minor_status) << endl;
5537 for (i=0; i<mech_set->count && !found; i++) {
5538 tmp_oid = &mech_set->elements[i];
5539 if (tmp_oid->length == spnego_oid_desc.length &&
5540 !memcmp(tmp_oid->elements, spnego_oid_desc.elements, tmp_oid->length)) {
5541 kdDebug(7113) <<
"(" << m_pid <<
") createNegotiateAuth: found SPNEGO mech" << endl;
5543 mech_oid = &spnego_oid_desc;
5547 gss_release_oid_set(&minor_status, &mech_set);
5551 servicename =
"HTTP@";
5552 servicename += m_state.hostname.ascii();
5554 input_token.value = (
void *)servicename.data();
5555 input_token.length = servicename.length() + 1;
5557 major_status = gss_import_name(&minor_status, &input_token,
5558 GSS_C_NT_HOSTBASED_SERVICE, &server);
5560 input_token.value = NULL;
5561 input_token.length = 0;
5563 if (GSS_ERROR(major_status)) {
5564 kdDebug(7113) <<
"(" << m_pid <<
") gss_import_name failed: " << gssError(major_status, minor_status) << endl;
5566 m_strAuthorization = TQString::null;
5567 return TQString::null;
5570 major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL,
5571 &ctx, server, mech_oid,
5572 req_flags, GSS_C_INDEFINITE,
5573 GSS_C_NO_CHANNEL_BINDINGS,
5574 GSS_C_NO_BUFFER, NULL, &output_token,
5578 if (GSS_ERROR(major_status) || (output_token.length == 0)) {
5579 kdDebug(7113) <<
"(" << m_pid <<
") gss_init_sec_context failed: " << gssError(major_status, minor_status) << endl;
5580 gss_release_name(&minor_status, &server);
5581 if (ctx != GSS_C_NO_CONTEXT) {
5582 gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER);
5583 ctx = GSS_C_NO_CONTEXT;
5586 m_strAuthorization = TQString::null;
5587 return TQString::null;
5590 input.duplicate((
const char *)output_token.value, output_token.length);
5591 auth =
"Authorization: Negotiate ";
5592 auth += KCodecs::base64Encode( input );
5596 gss_release_name(&minor_status, &server);
5597 if (ctx != GSS_C_NO_CONTEXT) {
5598 gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER);
5599 ctx = GSS_C_NO_CONTEXT;
5601 gss_release_buffer(&minor_status, &output_token);
5608 TQCString HTTPProtocol::gssError(
int,
int )
5614 TQString HTTPProtocol::createNegotiateAuth()
5616 return TQString::null;
5620 TQString HTTPProtocol::createNTLMAuth(
bool isForProxy )
5623 TQString auth, user, domain, passwd;
5629 auth =
"Proxy-Connection: Keep-Alive\r\n";
5630 auth +=
"Proxy-Authorization: NTLM ";
5631 user = m_proxyURL.user();
5632 passwd = m_proxyURL.pass();
5633 strauth = m_strProxyAuthorization.latin1();
5634 len = m_strProxyAuthorization.length();
5638 auth =
"Authorization: NTLM ";
5639 user = m_state.user;
5640 passwd = m_state.passwd;
5641 strauth = m_strAuthorization.latin1();
5642 len = m_strAuthorization.length();
5644 if ( user.contains(
'\\') ) {
5645 domain = user.section(
'\\', 0, 0);
5646 user = user.section(
'\\', 1 );
5649 kdDebug(7113) <<
"(" << m_pid <<
") NTLM length: " << len << endl;
5650 if ( user.isEmpty() || passwd.isEmpty() || len < 4 )
5651 return TQString::null;
5656 TQByteArray challenge;
5657 KCodecs::base64Decode( strauth.right( len - 5 ), challenge );
5658 KNTLM::getAuth( buf, challenge, user, passwd, domain,
5659 KNetwork::KResolver::localHostName(),
false,
false );
5663 KNTLM::getNegotiate( buf );
5668 m_strProxyAuthorization =
"NTLM";
5670 m_strAuthorization =
"NTLM";
5672 auth += KCodecs::base64Encode( buf );
5678 TQString HTTPProtocol::createBasicAuth(
bool isForProxy )
5681 TQCString user, passwd;
5684 auth =
"Proxy-Authorization: Basic ";
5685 user = m_proxyURL.user().latin1();
5686 passwd = m_proxyURL.pass().latin1();
5690 auth =
"Authorization: Basic ";
5691 user = m_state.user.latin1();
5692 passwd = m_state.passwd.latin1();
5695 if ( user.isEmpty() )
5697 if ( passwd.isEmpty() )
5702 auth += KCodecs::base64Encode( user );
5708 void HTTPProtocol::calculateResponse( DigestAuthInfo& info, TQCString& Response )
5715 TQCString authStr = info.username;
5717 authStr += info.realm;
5719 authStr += info.password;
5720 md.update( authStr );
5722 if ( info.algorithm.lower() ==
"md5-sess" )
5724 authStr = md.hexDigest();
5726 authStr += info.nonce;
5728 authStr += info.cnonce;
5730 md.update( authStr );
5732 HA1 = md.hexDigest();
5734 kdDebug(7113) <<
"(" << m_pid <<
") calculateResponse(): A1 => " << HA1 << endl;
5737 authStr = info.method;
5739 authStr += m_request.url.encodedPathAndQuery(0,
true).latin1();
5740 if ( info.qop ==
"auth-int" )
5743 authStr += info.entityBody;
5746 md.update( authStr );
5747 HA2 = md.hexDigest();
5749 kdDebug(7113) <<
"(" << m_pid <<
") calculateResponse(): A2 => "
5755 authStr += info.nonce;
5757 if ( !info.qop.isEmpty() )
5761 authStr += info.cnonce;
5763 authStr += info.qop;
5768 md.update( authStr );
5769 Response = md.hexDigest();
5771 kdDebug(7113) <<
"(" << m_pid <<
") calculateResponse(): Response => "
5772 << Response << endl;
5775 TQString HTTPProtocol::createDigestAuth (
bool isForProxy )
5783 DigestAuthInfo info;
5788 auth =
"Proxy-Authorization: Digest ";
5789 info.username = m_proxyURL.user().latin1();
5790 info.password = m_proxyURL.pass().latin1();
5791 p = m_strProxyAuthorization.latin1();
5795 auth =
"Authorization: Digest ";
5796 info.username = m_state.user.latin1();
5797 info.password = m_state.passwd.latin1();
5798 p = m_strAuthorization.latin1();
5801 return TQString::null;
5805 if ( info.username.isEmpty() || info.password.isEmpty() || !p )
5806 return TQString::null;
5810 info.algorithm =
"MD5";
5815 info.cnonce = TDEApplication::randomString(16).latin1();
5818 info.nc =
"00000001";
5821 switch ( m_request.method )
5824 info.method =
"GET";
5827 info.method =
"PUT";
5830 info.method =
"POST";
5833 info.method =
"HEAD";
5836 info.method =
"DELETE";
5839 info.method =
"PROPFIND";
5842 info.method =
"PROPPATCH";
5845 info.method =
"MKCOL";
5848 info.method =
"COPY";
5851 info.method =
"MOVE";
5854 info.method =
"LOCK";
5857 info.method =
"UNLOCK";
5860 info.method =
"SEARCH";
5863 info.method =
"SUBSCRIBE";
5865 case DAV_UNSUBSCRIBE:
5866 info.method =
"UNSUBSCRIBE";
5869 info.method =
"POLL";
5872 error( ERR_UNSUPPORTED_ACTION, i18n(
"Unsupported method: authentication will fail. Please submit a bug report."));
5880 while ( (*p ==
' ') || (*p ==
',') || (*p ==
'\t')) { p++; }
5881 if (strncasecmp(p,
"realm=", 6 )==0)
5884 while ( *p ==
'"' ) p++;
5885 while ( p[i] !=
'"' ) i++;
5886 info.realm = TQCString( p, i+1 );
5888 else if (strncasecmp(p,
"algorith=", 9)==0)
5891 while ( *p ==
'"' ) p++;
5892 while ( ( p[i] !=
'"' ) && ( p[i] !=
',' ) && ( p[i] !=
'\0' ) ) i++;
5893 info.algorithm = TQCString(p, i+1);
5895 else if (strncasecmp(p,
"algorithm=", 10)==0)
5898 while ( *p ==
'"' ) p++;
5899 while ( ( p[i] !=
'"' ) && ( p[i] !=
',' ) && ( p[i] !=
'\0' ) ) i++;
5900 info.algorithm = TQCString(p,i+1);
5902 else if (strncasecmp(p,
"domain=", 7)==0)
5905 while ( *p ==
'"' ) p++;
5906 while ( p[i] !=
'"' ) i++;
5909 TQCString uri = TQCString(p,i+1);
5912 pos = uri.find(
' ', idx );
5915 KURL u (m_request.url, uri.mid(idx, pos-idx));
5917 info.digestURI.append( u.url().latin1() );
5921 KURL u (m_request.url, uri.mid(idx, uri.length()-idx));
5923 info.digestURI.append( u.url().latin1() );
5926 }
while ( pos != -1 );
5928 else if (strncasecmp(p,
"nonce=", 6)==0)
5931 while ( *p ==
'"' ) p++;
5932 while ( p[i] !=
'"' ) i++;
5933 info.nonce = TQCString(p,i+1);
5935 else if (strncasecmp(p,
"opaque=", 7)==0)
5938 while ( *p ==
'"' ) p++;
5939 while ( p[i] !=
'"' ) i++;
5940 opaque = TQCString(p,i+1);
5942 else if (strncasecmp(p,
"qop=", 4)==0)
5945 while ( *p ==
'"' ) p++;
5946 while ( p[i] !=
'"' ) i++;
5947 info.qop = TQCString(p,i+1);
5952 if (info.realm.isEmpty() || info.nonce.isEmpty())
5953 return TQString::null;
5958 if (info.digestURI.isEmpty() && (m_responseCode == 401 || m_responseCode == 407))
5959 info.digestURI.append (m_request.url.url().latin1());
5967 TQString requestPath = m_request.url.directory(
false,
false);
5968 if (requestPath.isEmpty())
5971 int count = info.digestURI.count();
5973 for (
int i = 0; i < count; i++ )
5975 KURL u ( info.digestURI.at(i) );
5977 send &= (m_request.url.protocol().lower() == u.protocol().lower());
5978 send &= (m_request.hostname.lower() == u.host().lower());
5980 if (m_request.port > 0 && u.port() > 0)
5981 send &= (m_request.port == u.port());
5983 TQString digestPath = u.directory (
false,
false);
5984 if (digestPath.isEmpty())
5987 send &= (requestPath.startsWith(digestPath));
5993 kdDebug(7113) <<
"(" << m_pid <<
") createDigestAuth(): passed digest "
5994 "authentication credential test: " << send << endl;
5997 return TQString::null;
6000 kdDebug(7113) <<
"(" << m_pid <<
") RESULT OF PARSING:" << endl;
6001 kdDebug(7113) <<
"(" << m_pid <<
") algorithm: " << info.algorithm << endl;
6002 kdDebug(7113) <<
"(" << m_pid <<
") realm: " << info.realm << endl;
6003 kdDebug(7113) <<
"(" << m_pid <<
") nonce: " << info.nonce << endl;
6004 kdDebug(7113) <<
"(" << m_pid <<
") opaque: " << opaque << endl;
6005 kdDebug(7113) <<
"(" << m_pid <<
") qop: " << info.qop << endl;
6008 calculateResponse( info, Response );
6010 auth +=
"username=\"";
6011 auth += info.username;
6013 auth +=
"\", realm=\"";
6017 auth +=
", nonce=\"";
6020 auth +=
"\", uri=\"";
6021 auth += m_request.url.encodedPathAndQuery(0,
true);
6023 auth +=
"\", algorithm=\"";
6024 auth += info.algorithm;
6027 if ( !info.qop.isEmpty() )
6031 auth +=
"\", cnonce=\"";
6032 auth += info.cnonce;
6037 auth +=
", response=\"";
6039 if ( !opaque.isEmpty() )
6041 auth +=
"\", opaque=\"";
6049 TQString HTTPProtocol::proxyAuthenticationHeader()
6056 if ( m_strProxyRealm.isEmpty() )
6059 info.url = m_proxyURL;
6060 info.username = m_proxyURL.user();
6061 info.password = m_proxyURL.pass();
6062 info.verifyPath =
true;
6067 if ( !info.username.isNull() && !info.password.isNull() )
6069 if( m_strProxyAuthorization.isEmpty() )
6070 ProxyAuthentication = AUTH_None;
6071 else if( m_strProxyAuthorization.startsWith(
"Basic") )
6072 ProxyAuthentication = AUTH_Basic;
6073 else if( m_strProxyAuthorization.startsWith(
"NTLM") )
6074 ProxyAuthentication = AUTH_NTLM;
6076 ProxyAuthentication = AUTH_Digest;
6080 if ( checkCachedAuthentication(info) && !info.digestInfo.isEmpty() )
6082 m_proxyURL.setUser( info.username );
6083 m_proxyURL.setPass( info.password );
6084 m_strProxyRealm = info.realmValue;
6085 m_strProxyAuthorization = info.digestInfo;
6086 if( m_strProxyAuthorization.startsWith(
"Basic") )
6087 ProxyAuthentication = AUTH_Basic;
6088 else if( m_strProxyAuthorization.startsWith(
"NTLM") )
6089 ProxyAuthentication = AUTH_NTLM;
6091 ProxyAuthentication = AUTH_Digest;
6095 ProxyAuthentication = AUTH_None;
6101 if ( ProxyAuthentication != AUTH_None )
6103 kdDebug(7113) <<
"(" << m_pid <<
") Using Proxy Authentication: " << endl;
6104 kdDebug(7113) <<
"(" << m_pid <<
") HOST= " << m_proxyURL.host() << endl;
6105 kdDebug(7113) <<
"(" << m_pid <<
") PORT= " << m_proxyURL.port() << endl;
6106 kdDebug(7113) <<
"(" << m_pid <<
") USER= " << m_proxyURL.user() << endl;
6107 kdDebug(7113) <<
"(" << m_pid <<
") PASSWORD= [protected]" << endl;
6108 kdDebug(7113) <<
"(" << m_pid <<
") REALM= " << m_strProxyRealm << endl;
6109 kdDebug(7113) <<
"(" << m_pid <<
") EXTRA= " << m_strProxyAuthorization << endl;
6112 switch ( ProxyAuthentication )
6115 header += createBasicAuth(
true );
6118 header += createDigestAuth(
true );
6121 if ( m_bFirstRequest ) header += createNTLMAuth(
true );