29 #define QT_NO_CAST_FROM_ASCII
43 #include <QtXml/qdom.h>
44 #include <QtCore/QFile>
45 #include <QtCore/QRegExp>
46 #include <QtCore/QDate>
47 #include <QtCore/QBuffer>
48 #include <QtCore/QIODevice>
49 #include <QtDBus/QtDBus>
50 #include <QtNetwork/QAuthenticator>
51 #include <QtNetwork/QNetworkProxy>
52 #include <QtNetwork/QTcpSocket>
74 #include <solid/networking.h>
94 rich.reserve(
int(plain.length() * 1.1));
95 for (
int i = 0; i < plain.length(); ++i) {
96 if (plain.at(i) == QLatin1Char(
'<'))
97 rich += QLatin1String(
"<");
98 else if (plain.at(i) == QLatin1Char(
'>'))
99 rich += QLatin1String(
">");
100 else if (plain.at(i) == QLatin1Char(
'&'))
101 rich += QLatin1String(
"&");
102 else if (plain.at(i) == QLatin1Char(
'"'))
103 rich += QLatin1String(
""");
113 return (scheme.startsWith(QLatin1String(
"http"), Qt::CaseInsensitive)
114 || scheme == QLatin1String(
"socks"));
127 QCoreApplication app( argc, argv );
133 fprintf(stderr,
"Usage: kio_http protocol domain-socket1 domain-socket2\n");
146 return QString::fromLatin1(value.constData(), value.size());
152 if (originURL == QLatin1String(
"true"))
155 KUrl url ( originURL );
165 QStringList la = a.split(QLatin1Char(
'.'), QString::SkipEmptyParts);
166 QStringList lb = b.split(QLatin1Char(
'.'), QString::SkipEmptyParts);
168 if (qMin(la.count(), lb.count()) < 2) {
172 while(la.count() > 2)
174 while(lb.count() > 2)
186 const QStringList headers = _header.split(QRegExp(QLatin1String(
"[\r\n]")));
188 for(QStringList::ConstIterator it = headers.begin(); it != headers.end(); ++it)
192 if (!(*it).contains(QLatin1Char(
':')) ||
193 (*it).startsWith(QLatin1String(
"host"), Qt::CaseInsensitive) ||
194 (*it).startsWith(QLatin1String(
"proxy-authorization"), Qt::CaseInsensitive) ||
195 (*it).startsWith(QLatin1String(
"via"), Qt::CaseInsensitive))
198 sanitizedHeaders += (*it);
199 sanitizedHeaders += QLatin1String(
"\r\n");
201 sanitizedHeaders.chop(2);
203 return sanitizedHeaders;
209 if (config->
readEntry(
"no-spoof-check",
false)) {
213 if (request.
url.
user().isEmpty()) {
219 if (request.
url.
user() == QLatin1String(
"undefined") && request.
url.
pass() == QLatin1String(
"undefined")) {
224 if (config->
readEntry(QLatin1String(
"cached-www-auth"),
false)) {
255 if (responseCode >= 100 && responseCode < 200) {
258 switch (responseCode) {
264 Q_ASSERT(method != HTTP_HEAD);
274 return method != HTTP_HEAD;
279 return p ==
"https" || p ==
"webdavs";
284 return u.isValid() && u.
hasHost();
298 device =
new QBuffer;
300 if (!device->open(QIODevice::ReadWrite))
308 if (!methodStringOverride.isEmpty())
309 return (methodStringOverride + QLatin1Char(
' ')).toLatin1();
342 case DAV_UNSUBSCRIBE:
343 return "UNSUBSCRIBE ";
363 if (!dt.
time().second()) {
364 ret.append(QLatin1String(
":00"));
366 ret.append(QLatin1String(
" GMT"));
372 return (responseCode == 401) || (responseCode == 407);
375 #define NO_SIZE ((KIO::filesize_t) -1)
378 #define STRTOLL strtoll
380 #define STRTOLL strtol
388 const QByteArray &app )
396 , m_protocol(protocol)
399 , m_socketProxyAuth(0)
401 , m_isLoadingErrorPage(false)
406 connect(
socket(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
479 kDebug(7113) <<
"ssl_was_in_use =" <<
metaData(QLatin1String(
"ssl_was_in_use"));
488 if (refUrl.isValid()) {
491 if (protocol.startsWith(QLatin1String(
"webdav"))) {
492 protocol.replace(0, 6, QLatin1String(
"http"));
496 if (protocol.startsWith(QLatin1String(
"http"))) {
515 if (!resumeOffset.isEmpty()) {
522 if (!resumeEndOffset.isEmpty()) {
573 if (host.indexOf(QLatin1Char(
':')) == -1) {
576 int pos = host.indexOf(QLatin1Char(
'%'));
602 if (u.host().isEmpty()) {
607 if (u.
path().isEmpty()) {
609 newUrl.
setPath(QLatin1String(
"/"));
632 if (dataInternal || !status) {
710 if (statSide != QLatin1String(
"source"))
758 if ( !query.isEmpty() )
760 QByteArray request =
"<?xml version=\"1.0\"?>\r\n";
761 request.append(
"<D:searchrequest xmlns:D=\"DAV:\">\r\n" );
762 request.append( query.toUtf8() );
763 request.append(
"</D:searchrequest>\r\n" );
769 request =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
770 "<D:propfind xmlns:D=\"DAV:\">";
773 if (
hasMetaData(QLatin1String(
"davRequestResponse")) )
774 request +=
metaData(QLatin1String(
"davRequestResponse")).toUtf8();
777 request +=
"<D:prop>"
779 "<D:getcontentlength/>"
782 "<D:getcontentlanguage/>"
783 "<D:getcontenttype/>"
784 "<D:getlastmodified/>"
791 request +=
"</D:propfind>";
815 QDomDocument multiResponse;
818 bool hasResponse =
false;
822 for ( QDomNode n = multiResponse.documentElement().firstChild();
823 !n.isNull(); n = n.nextSibling()) {
824 QDomElement thisResponse = n.toElement();
825 if (thisResponse.isNull())
830 QDomElement href = thisResponse.namedItem(QLatin1String(
"href")).toElement();
831 if ( !href.isNull() ) {
834 QString urlStr = QUrl::fromPercentEncoding(href.text().toUtf8());
835 #if 0 // qt4/kde4 say: it's all utf8...
840 KUrl thisURL ( urlStr, encoding );
842 KUrl thisURL( urlStr );
845 if ( thisURL.isValid() ) {
850 name = QLatin1Char(
'.');
855 QDomNodeList propstats = thisResponse.elementsByTagName(QLatin1String(
"propstat"));
866 if (mime && !mime->isDefault() && accuracy == 100) {
867 kDebug(7113) <<
"Setting" << mime->name() <<
"as guessed mime type for" << thisURL.
fileName();
881 kDebug(7113) <<
"Error: no URL contained in response to PROPFIND on" << url;
885 if ( stat || !hasResponse ) {
917 const int firstSpace = response.indexOf( QLatin1Char(
' ') );
918 const int secondSpace = response.indexOf( QLatin1Char(
' '), firstSpace + 1 );
919 return response.mid( firstSpace + 1, secondSpace - firstSpace - 1 ).toInt();
925 bool foundExecutable =
false;
926 bool isDirectory =
false;
928 uint supportedLockCount = 0;
930 for (
int i = 0; i < propstats.count(); i++)
932 QDomElement propstat = propstats.item(i).toElement();
934 QDomElement status = propstat.namedItem(QLatin1String(
"status")).toElement();
935 if ( status.isNull() )
938 kDebug(7113) <<
"Error, no status code in this propstat";
946 kDebug(7113) <<
"Got status code" << code <<
"(this may mean that some properties are unavailable)";
950 QDomElement prop = propstat.namedItem( QLatin1String(
"prop") ).toElement();
953 kDebug(7113) <<
"Error: no prop segment in this propstat.";
957 if (
hasMetaData( QLatin1String(
"davRequestResponse") ) )
960 doc.appendChild(prop);
964 for ( QDomNode n = prop.firstChild(); !n.isNull(); n = n.nextSibling() )
966 QDomElement
property = n.toElement();
967 if (property.isNull())
970 if ( property.namespaceURI() != QLatin1String(
"DAV:") )
976 if ( property.tagName() == QLatin1String(
"creationdate") )
981 else if ( property.tagName() == QLatin1String(
"getcontentlength") )
986 else if ( property.tagName() == QLatin1String(
"displayname") )
989 setMetaData( QLatin1String(
"davDisplayName"), property.text() );
991 else if ( property.tagName() == QLatin1String(
"source") )
994 QDomElement source =
property.namedItem( QLatin1String(
"link") ).toElement()
995 .namedItem( QLatin1String(
"dst") ).toElement();
996 if ( !source.isNull() )
997 setMetaData( QLatin1String(
"davSource"), source.text() );
999 else if ( property.tagName() == QLatin1String(
"getcontentlanguage") )
1002 setMetaData( QLatin1String(
"davContentLanguage"), property.text() );
1004 else if ( property.tagName() == QLatin1String(
"getcontenttype") )
1009 if ( property.text() == QLatin1String(
"httpd/unix-directory") )
1015 mimeType =
property.text();
1018 else if ( property.tagName() == QLatin1String(
"executable") )
1021 if ( property.text() == QLatin1String(
"T") )
1022 foundExecutable =
true;
1025 else if ( property.tagName() == QLatin1String(
"getlastmodified") )
1030 else if ( property.tagName() == QLatin1String(
"getetag") )
1033 setMetaData( QLatin1String(
"davEntityTag"), property.text() );
1035 else if ( property.tagName() == QLatin1String(
"supportedlock") )
1038 for ( QDomNode n2 = property.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
1040 QDomElement lockEntry = n2.toElement();
1041 if ( lockEntry.tagName() == QLatin1String(
"lockentry") )
1043 QDomElement lockScope = lockEntry.namedItem( QLatin1String(
"lockscope") ).toElement();
1044 QDomElement lockType = lockEntry.namedItem( QLatin1String(
"locktype") ).toElement();
1045 if ( !lockScope.isNull() && !lockType.isNull() )
1048 supportedLockCount++;
1049 const QString lockCountStr = QString::number(supportedLockCount);
1050 const QString scope = lockScope.firstChild().toElement().tagName();
1051 const QString type = lockType.firstChild().toElement().tagName();
1053 setMetaData( QLatin1String(
"davSupportedLockScope") + lockCountStr, scope );
1054 setMetaData( QLatin1String(
"davSupportedLockType") + lockCountStr, type );
1059 else if ( property.tagName() == QLatin1String(
"lockdiscovery") )
1062 davParseActiveLocks( property.elementsByTagName( QLatin1String(
"activelock") ), lockCount );
1064 else if ( property.tagName() == QLatin1String(
"resourcetype") )
1067 if ( !property.namedItem( QLatin1String(
"collection") ).toElement().isNull() )
1075 kDebug(7113) <<
"Found unknown webdav property:" <<
property.tagName();
1080 setMetaData( QLatin1String(
"davLockCount"), QString::number(lockCount) );
1081 setMetaData( QLatin1String(
"davSupportedLockCount"), QString::number(supportedLockCount) );
1085 if ( foundExecutable || isDirectory )
1095 if ( !isDirectory && !mimeType.isEmpty() )
1104 for (
int i = 0; i < activeLocks.count(); i++ )
1106 const QDomElement activeLock = activeLocks.item(i).toElement();
1110 const QDomElement lockScope = activeLock.namedItem( QLatin1String(
"lockscope") ).toElement();
1111 const QDomElement lockType = activeLock.namedItem( QLatin1String(
"locktype") ).toElement();
1112 const QDomElement lockDepth = activeLock.namedItem( QLatin1String(
"depth") ).toElement();
1114 const QDomElement lockOwner = activeLock.namedItem( QLatin1String(
"owner") ).toElement();
1115 const QDomElement lockTimeout = activeLock.namedItem( QLatin1String(
"timeout") ).toElement();
1116 const QDomElement lockToken = activeLock.namedItem( QLatin1String(
"locktoken") ).toElement();
1118 if ( !lockScope.isNull() && !lockType.isNull() && !lockDepth.isNull() )
1122 const QString lockCountStr = QString::number(lockCount);
1123 const QString scope = lockScope.firstChild().toElement().tagName();
1124 const QString type = lockType.firstChild().toElement().tagName();
1125 const QString depth = lockDepth.text();
1127 setMetaData( QLatin1String(
"davLockScope") + lockCountStr, scope );
1128 setMetaData( QLatin1String(
"davLockType") + lockCountStr, type );
1129 setMetaData( QLatin1String(
"davLockDepth") + lockCountStr, depth );
1131 if ( !lockOwner.isNull() )
1132 setMetaData( QLatin1String(
"davLockOwner") + lockCountStr, lockOwner.text() );
1134 if ( !lockTimeout.isNull() )
1135 setMetaData( QLatin1String(
"davLockTimeout") + lockCountStr, lockTimeout.text() );
1137 if ( !lockToken.isNull() )
1139 QDomElement tokenVal = lockScope.namedItem( QLatin1String(
"href") ).toElement();
1140 if ( !tokenVal.isNull() )
1141 setMetaData( QLatin1String(
"davLockToken") + lockCountStr, tokenVal.text() );
1149 if ( type == QLatin1String(
"dateTime.tz") )
1153 else if ( type == QLatin1String(
"dateTime.rfc1123") )
1168 if (
hasMetaData( QLatin1String(
"davLockCount") ) )
1170 QString response = QLatin1String(
"If:");
1171 int numLocks =
metaData( QLatin1String(
"davLockCount") ).toInt();
1172 bool bracketsOpen =
false;
1173 for (
int i = 0; i < numLocks; i++ )
1175 const QString countStr = QString::number(i);
1176 if (
hasMetaData( QLatin1String(
"davLockToken") + countStr ) )
1178 if (
hasMetaData( QLatin1String(
"davLockURL") + countStr ) )
1182 response += QLatin1Char(
')');
1183 bracketsOpen =
false;
1185 response += QLatin1String(
" <") +
metaData( QLatin1String(
"davLockURL") + countStr ) + QLatin1Char(
'>');
1188 if ( !bracketsOpen )
1190 response += QLatin1String(
" (");
1191 bracketsOpen =
true;
1195 response += QLatin1Char(
' ');
1198 if (
hasMetaData( QLatin1String(
"davLockNot") + countStr ) )
1199 response += QLatin1String(
"Not ");
1201 response += QLatin1Char(
'<') +
metaData( QLatin1String(
"davLockToken") + countStr ) + QLatin1Char(
'>');
1206 response += QLatin1Char(
')');
1208 response += QLatin1String(
"\r\n");
1228 kDebug(7113) <<
" false";
1251 if (ok && verNo > 0 && verNo < 3)
1254 kDebug(7113) <<
"Server supports DAV version" << verNo;
1331 const QByteArray request (
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1332 "<D:propfind xmlns:D=\"DAV:\"><D:prop>"
1334 "<D:getcontentlength/>"
1337 "</D:prop></D:propfind>");
1373 kDebug(7113) << src <<
"->" << dest;
1380 KUrl newDest = dest;
1381 if (newDest.
protocol() == QLatin1String(
"webdavs"))
1383 else if (newDest.
protocol() == QLatin1String(
"webdav"))
1403 kDebug(7113) << src <<
"->" << dest;
1410 KUrl newDest = dest;
1411 if (newDest.
protocol() == QLatin1String(
"webdavs"))
1413 else if (newDest.
protocol() == QLatin1String(
"webdav"))
1507 QDomDocument lockReq;
1509 QDomElement lockInfo = lockReq.createElementNS( QLatin1String(
"DAV:"), QLatin1String(
"lockinfo") );
1510 lockReq.appendChild( lockInfo );
1512 QDomElement lockScope = lockReq.createElement( QLatin1String(
"lockscope") );
1513 lockInfo.appendChild( lockScope );
1515 lockScope.appendChild( lockReq.createElement( scope ) );
1517 QDomElement lockType = lockReq.createElement( QLatin1String(
"locktype") );
1518 lockInfo.appendChild( lockType );
1520 lockType.appendChild( lockReq.createElement( type ) );
1522 if ( !owner.isNull() ) {
1523 QDomElement ownerElement = lockReq.createElement( QLatin1String(
"owner") );
1524 lockReq.appendChild( ownerElement );
1526 QDomElement ownerHref = lockReq.createElement( QLatin1String(
"href") );
1527 ownerElement.appendChild( ownerHref );
1529 ownerHref.appendChild( lockReq.createTextNode( owner ) );
1539 QDomDocument multiResponse;
1542 QDomElement prop = multiResponse.documentElement().namedItem( QLatin1String(
"prop") ).toElement();
1544 QDomElement lockdiscovery = prop.namedItem( QLatin1String(
"lockdiscovery") ).toElement();
1547 davParseActiveLocks( lockdiscovery.elementsByTagName( QLatin1String(
"activelock") ), lockCount );
1549 setMetaData( QLatin1String(
"davLockCount"), QString::number( lockCount ) );
1579 bool callError =
false;
1589 if ( !url.isNull() )
1596 QString ow =
i18n(
"Otherwise, the request would have succeeded." );
1600 action =
i18nc(
"request type",
"retrieve property values" );
1603 action =
i18nc(
"request type",
"set property values" );
1606 action =
i18nc(
"request type",
"create the requested folder" );
1609 action =
i18nc(
"request type",
"copy the specified file or folder" );
1612 action =
i18nc(
"request type",
"move the specified file or folder" );
1615 action =
i18nc(
"request type",
"search in the specified folder" );
1618 action =
i18nc(
"request type",
"lock the specified file or folder" );
1621 action =
i18nc(
"request type",
"unlock the specified file or folder" );
1624 action =
i18nc(
"request type",
"delete the specified file or folder" );
1627 action =
i18nc(
"request type",
"query the server's capabilities" );
1630 action =
i18nc(
"request type",
"retrieve the contents of the specified file or folder" );
1633 action =
i18nc(
"request type",
"run a report in the specified folder" );
1644 errorString =
i18nc(
"%1: code, %2: request type",
"An unexpected error (%1) occurred "
1645 "while attempting to %2.", code, action);
1652 errorString =
i18n(
"The server does not support the WebDAV protocol.");
1666 QDomDocument multiResponse;
1670 QDomElement multistatus = multiResponse.documentElement().namedItem( QLatin1String(
"multistatus") ).toElement();
1672 QDomNodeList responses = multistatus.elementsByTagName( QLatin1String(
"response") );
1674 for (
int i = 0; i < responses.count(); i++)
1679 QDomElement response = responses.item(i).toElement();
1680 QDomElement code = response.namedItem( QLatin1String(
"status") ).toElement();
1682 if ( !code.isNull() )
1685 QDomElement href = response.namedItem( QLatin1String(
"href") ).toElement();
1686 if ( !href.isNull() )
1687 errUrl = href.text();
1688 errors <<
davError( errCode, errUrl );
1693 errorString =
i18nc(
"%1: request type, %2: url",
1694 "An error occurred while attempting to %1, %2. A "
1695 "summary of the reasons is below.", action, url );
1697 errorString += QLatin1String(
"<ul>");
1700 errorString += QLatin1String(
"<li>") + error + QLatin1String(
"</li>");
1702 errorString += QLatin1String(
"</ul>");
1708 errorString =
i18nc(
"%1: request type",
"Access was denied while attempting to %1.", action );
1721 errorString =
i18n(
"A resource cannot be created at the destination "
1722 "until one or more intermediate collections (folders) "
1723 "have been created.");
1729 errorString =
i18n(
"The server was unable to maintain the liveness of "
1730 "the properties listed in the propertybehavior XML "
1731 "element or you attempted to overwrite a file while "
1732 "requesting that files are not overwritten. %1",
1737 errorString =
i18n(
"The requested lock could not be granted. %1", ow );
1743 errorString =
i18n(
"The server does not support the request type of the body.");
1748 errorString =
i18nc(
"%1: request type",
"Unable to %1 because the resource is locked.", action );
1752 errorString =
i18n(
"This action was prevented by another error.");
1758 errorString =
i18nc(
"%1: request type",
"Unable to %1 because the destination server refuses "
1759 "to accept the file or folder.", action );
1765 errorString =
i18n(
"The destination resource does not have sufficient space "
1766 "to record the state of the resource after the execution "
1777 error( errorCode, errorString );
1785 Q_ASSERT(errorString);
1788 errorString->clear();
1800 Q_ASSERT(errorString);
1804 errorString->clear();
1806 switch (responseCode) {
1815 && (responseCode < 200 || responseCode > 400)
1816 && responseCode != 404) {
1818 *errorString =
i18n(
"The resource cannot be deleted." );
1827 Q_ASSERT(errorString);
1833 switch (responseCode) {
1840 *errorString =
i18nc(
"%1: request type",
"Access was denied while attempting to %1.", action );
1846 *errorString =
i18n(
"A resource cannot be created at the destination "
1847 "until one or more intermediate collections (folders) "
1848 "have been created.");
1854 *errorString =
i18nc(
"%1: request type",
"Unable to %1 because the resource is locked.", action );
1860 *errorString =
i18nc(
"%1: request type",
"Unable to %1 because the destination server refuses "
1861 "to accept the file or folder.", action );
1867 *errorString =
i18n(
"The destination resource does not have sufficient space "
1868 "to record the state of the resource after the execution "
1877 && (responseCode < 200 || responseCode > 400)
1878 && responseCode != 404) {
1880 *errorString =
i18nc(
"%1: response code, %2: request type",
1881 "An unexpected error (%1) occurred while attempting to %2.",
1882 responseCode, action);
1912 error( errorCode, errorString );
1925 kWarning(7113) <<
"called twice during one request, something is probably wrong.";
1938 Solid::Networking::Status status = Solid::Networking::status();
1940 kDebug(7113) <<
"networkstatus:" << status;
1943 return status == Solid::Networking::Unconnected;
1948 QDataStream stream(data);
1960 for (
unsigned i = 0; i < n; ++i) {
1990 while (it.hasNext()) {
2002 while (it.hasNext()) {
2019 setMetaData(QLatin1String(
"request-id"), QString::number(requestId++));
2039 const char* buf =
static_cast<const char*
>(_buf);
2040 while (sent < nbytes)
2067 for (
size_t i = 0; i < size; i++) {
2078 size_t bytesRead = 0;
2081 bytesRead = qMin((
int)size, bufSize);
2083 for (
size_t i = 0; i < bytesRead; i++) {
2084 buf[i] =
m_unreadBuf.constData()[bufSize - i - 1];
2095 if (bytesRead < size) {
2101 bytesRead += rawRead;
2112 Q_ASSERT(numNewlines >=1 && numNewlines <= 2);
2115 while (pos < end && !
m_isEOF) {
2116 int step = qMin((
int)
sizeof(mybuf), end - pos);
2125 for (
size_t i = 0; i < bufferFill ; ++i, ++pos) {
2128 buf[pos] = mybuf[i];
2133 if (buf[pos] ==
'\n') {
2134 bool found = numNewlines == 1;
2137 found = ((pos >= 1 && buf[pos - 1] ==
'\n') ||
2138 (pos >= 2 && buf[pos - 2] ==
'\n' && buf[pos - 1] ==
'\r'));
2142 unread(&mybuf[i], bufferFill - i);
2155 if (previous.host() != now.host() || previous.port() != now.port()) {
2158 if (previous.
user().isEmpty() && previous.
pass().isEmpty()) {
2174 if (url != QLatin1String(
"DIRECT")) {
2198 int connectError = 0;
2212 const KUrl url (proxyUrl);
2217 errorString = url.
url();
2221 const bool isDirectConnect = (proxyUrl == QLatin1String(
"DIRECT"));
2222 QNetworkProxy::ProxyType proxyType = QNetworkProxy::NoProxy;
2223 if (url.
protocol() == QLatin1String(
"socks")) {
2224 proxyType = QNetworkProxy::Socks5Proxy;
2225 }
else if (!isDirectConnect &&
isAutoSsl()) {
2226 proxyType = QNetworkProxy::HttpProxy;
2229 kDebug(7113) <<
"Connecting to proxy: address=" << proxyUrl <<
"type=" << proxyType;
2231 if (proxyType == QNetworkProxy::NoProxy) {
2234 if (isDirectConnect) {
2238 connectError =
connectToHost(url.host(), url.port(), &errorString);
2239 if (connectError == 0) {
2241 kDebug(7113) <<
"Connected to proxy: host=" << url.host() <<
"port=" << url.port();
2245 kDebug(7113) <<
"Failed to connect to proxy:" << proxyUrl;
2246 badProxyUrls << url;
2249 if (connectError == 0) {
2253 QNetworkProxy proxy (proxyType, url.host(), url.port(), url.
user(), url.
pass());
2254 QNetworkProxy::setApplicationProxy(proxy);
2256 if (connectError == 0) {
2257 kDebug(7113) <<
"Tunneling thru proxy: host=" << url.host() <<
"port=" << url.port();
2262 kDebug(7113) <<
"Failed to connect to proxy:" << proxyUrl;
2263 badProxyUrls << url;
2264 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2269 if (!badProxyUrls.isEmpty()) {
2274 if (connectError != 0) {
2275 error (connectError, errorString);
2305 bool openForReading =
false;
2309 if (!openForReading && (isCacheOnly || offline)) {
2311 *cacheHasPage =
false;
2314 }
else if (offline) {
2321 if (openForReading) {
2323 *cacheHasPage =
true;
2328 *cacheHasPage =
false;
2341 if (protocol.startsWith(QLatin1String(
"webdav"))) {
2342 protocol.replace(0, qstrlen(
"webdav"), QLatin1String(
"http"));
2399 kDebug(7113) <<
"Couldn't connect, oopsie!";
2411 bool hasBodyData =
false;
2412 bool hasDavData =
false;
2422 bool cacheHasPage =
false;
2424 kDebug(7113) <<
"cacheHasPage =" << cacheHasPage;
2425 return cacheHasPage;
2427 if (!cacheHasPage) {
2444 davHeader = QLatin1String(
"Depth: ");
2447 kDebug(7113) <<
"Reading DAV depth from metadata:" <<
metaData( QLatin1String(
"davDepth") );
2448 davHeader +=
metaData( QLatin1String(
"davDepth") );
2453 davHeader += QLatin1String(
"infinity");
2457 davHeader += QLatin1String(
"\r\n");
2469 davHeader += QLatin1String(
"\r\nDepth: infinity\r\nOverwrite: ");
2471 davHeader += QLatin1String(
"\r\n");
2474 davHeader = QLatin1String(
"Timeout: ");
2478 timeout =
metaData( QLatin1String(
"davTimeout") ).toUInt();
2480 davHeader += QLatin1String(
"Infinite");
2482 davHeader += QLatin1String(
"Seconds-") + QString::number(timeout);
2484 davHeader += QLatin1String(
"\r\n");
2488 davHeader = QLatin1String(
"Lock-token: ") +
metaData(QLatin1String(
"davLockToken")) + QLatin1String(
"\r\n");
2495 case DAV_UNSUBSCRIBE:
2509 header += QLatin1Char(
':') + QString::number(
m_request.
url.port());
2511 header += QLatin1String(
"\r\n");
2518 header += QLatin1String(
"Proxy-Connection: ");
2520 header += QLatin1String(
"Connection: ");
2523 header += QLatin1String(
"keep-alive\r\n");
2525 header += QLatin1String(
"close\r\n");
2530 header += QLatin1String(
"User-Agent: ");
2532 header += QLatin1String(
"\r\n");
2537 header += QLatin1String(
"Referer: ");
2539 header += QLatin1String(
"\r\n");
2544 header += QLatin1String(
"Range: bytes=");
2546 header += QLatin1Char(
'-');
2548 header += QLatin1String(
"\r\n");
2554 header += QLatin1String(
"Range: bytes=");
2556 header += QLatin1String(
"-\r\n");
2563 header += QLatin1String(
"Pragma: no-cache\r\n");
2564 header += QLatin1String(
"Cache-control: no-cache\r\n");
2568 kDebug(7113) <<
"needs validation, performing conditional get.";
2575 header += QLatin1String(
"If-Modified-Since: ") + httpDate + QLatin1String(
"\r\n");
2580 header += QLatin1String(
"Accept: ");
2582 if (!acceptHeader.isEmpty())
2583 header += acceptHeader;
2586 header += QLatin1String(
"\r\n");
2589 header += QLatin1String(
"Accept-Encoding: gzip, deflate, x-gzip, x-deflate\r\n");
2592 header += QLatin1String(
"Accept-Charset: ") +
m_request.
charsets + QLatin1String(
"\r\n");
2595 header += QLatin1String(
"Accept-Language: ") +
m_request.
languages + QLatin1String(
"\r\n");
2598 const QString cookieMode =
metaData(QLatin1String(
"cookies")).toLower();
2600 if (cookieMode == QLatin1String(
"none"))
2604 else if (cookieMode == QLatin1String(
"manual"))
2607 cookieStr =
metaData(QLatin1String(
"setcookies"));
2616 if (!cookieStr.isEmpty())
2617 header += cookieStr + QLatin1String(
"\r\n");
2619 const QString customHeader =
metaData( QLatin1String(
"customHTTPHeader") );
2620 if (!customHeader.isEmpty())
2623 header += QLatin1String(
"\r\n");
2627 if (!contentType.isEmpty())
2629 if (!contentType.startsWith(QLatin1String(
"content-type"), Qt::CaseInsensitive))
2630 header += QLatin1String(
"Content-Type: ");
2631 header += contentType;
2632 header += QLatin1String(
"\r\n");
2637 header += QLatin1String(
"DNT: 1\r\n");
2650 davHeader +=
metaData(QLatin1String(
"davHeader"));
2654 davHeader += QLatin1String(
"Content-Type: text/xml; charset=utf-8\r\n");
2657 header += davHeader;
2661 kDebug(7103) <<
"============ Sending Header:";
2662 Q_FOREACH (
const QString &s, header.split(QLatin1String(
"\r\n"), QString::SkipEmptyParts)) {
2668 if (!hasBodyData && !hasDavData)
2669 header += QLatin1String(
"\r\n");
2678 ssize_t
written =
write(header.toLatin1(), header.length());
2679 bool sendOk = (written == (ssize_t) header.length());
2683 <<
" -- intended to write" << header.length()
2684 <<
"bytes but wrote" << (int)written <<
".";
2694 kDebug(7113) <<
"sendOk == false. Connection broken !"
2695 <<
" -- intended to write" << header.length()
2696 <<
"bytes but wrote" << (int)written <<
".";
2701 kDebug(7113) <<
"sent it!";
2704 if (hasBodyData || hasDavData)
2720 if (forwardImmediately)
2733 if (header.startsWith(QLatin1String(
"content-type:")), Qt::CaseInsensitive) {
2734 int pos = header.indexOf(QLatin1String(
"charset="), Qt::CaseInsensitive);
2736 const QString charset = header.mid(pos + 8).toLower();
2740 }
else if (header.startsWith(QLatin1String(
"content-language:")), Qt::CaseInsensitive) {
2741 const QString language = header.mid(17).trimmed().toLower();
2742 setMetaData(QLatin1String(
"content-language"), language);
2743 }
else if (header.startsWith(QLatin1String(
"content-disposition:")), Qt::CaseInsensitive) {
2770 if (
m_mimeType == QLatin1String(
"application/x-targz"))
2771 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2772 else if (
m_mimeType == QLatin1String(
"image/x-png"))
2776 else if (
m_mimeType == QLatin1String(
"audio/microsoft-wave"))
2778 else if (
m_mimeType == QLatin1String(
"image/x-ms-bmp"))
2782 else if (
m_mimeType == QLatin1String(
"application/pkix-cert") ||
2783 m_mimeType == QLatin1String(
"application/binary-certificate")) {
2784 m_mimeType = QLatin1String(
"application/x-x509-ca-cert");
2788 else if (
m_mimeType == QLatin1String(
"application/x-gzip")) {
2791 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2793 m_mimeType = QLatin1String(
"application/x-gzpostscript");
2798 else if(
m_mimeType == QLatin1String(
"application/x-xz")) {
2801 m_mimeType = QLatin1String(
"application/x-xz-compressed-tar");
2806 else if ((
m_mimeType == QLatin1String(
"text/plain")) || (
m_mimeType == QLatin1String(
"application/octet-stream"))) {
2808 if (ext == QLatin1String(
"BZ2"))
2809 m_mimeType = QLatin1String(
"application/x-bzip");
2810 else if (ext == QLatin1String(
"PEM"))
2811 m_mimeType = QLatin1String(
"application/x-x509-ca-cert");
2812 else if (ext == QLatin1String(
"SWF"))
2813 m_mimeType = QLatin1String(
"application/x-shockwave-flash");
2814 else if (ext == QLatin1String(
"PLS"))
2816 else if (ext == QLatin1String(
"WMV"))
2817 m_mimeType = QLatin1String(
"video/x-ms-wmv");
2818 else if (ext == QLatin1String(
"WEBM"))
2820 else if (ext == QLatin1String(
"DEB"))
2821 m_mimeType = QLatin1String(
"application/x-deb");
2835 if (
m_mimeType == QLatin1String(
"application/x-tar")) {
2837 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2838 }
else if (
m_mimeType == QLatin1String(
"application/postscript")) {
2842 m_mimeType = QLatin1String(
"application/x-gzpostscript");
2847 m_mimeType != QLatin1String(
"application/x-compressed-tar") &&
2848 m_mimeType != QLatin1String(
"application/x-tgz") &&
2849 m_mimeType != QLatin1String(
"application/x-targz") &&
2850 m_mimeType != QLatin1String(
"application/x-gzip"))) {
2854 m_mimeType = QLatin1String(
"application/x-gzip");
2866 m_mimeType = QLatin1String(
"application/x-bzip");
2873 static bool consume(
const char input[],
int *pos,
int end,
const char *term)
2877 if (idx + (
int)strlen(term) >= end) {
2881 if (strncasecmp(&input[idx], term, strlen(term)) == 0) {
2882 *pos = idx + strlen(term);
2906 bool upgradeRequired =
false;
2910 bool noHeadersFound =
false;
2915 static const int maxHeaderSize = 128 * 1024;
2917 char buffer[maxHeaderSize];
2919 bool bCanResume =
false;
2922 kDebug(7113) <<
"No connection.";
2932 kDebug(7113) <<
"Got socket error:" <<
socket()->errorString();
2941 if (!foundDelimiter && bufPos < maxHeaderSize) {
2942 kDebug(7113) <<
"EOF while waiting for header start.";
2959 kDebug(7113) <<
"Connection broken !";
2963 if (!foundDelimiter) {
2968 kDebug(7103) <<
"============ Received Status Response:";
2969 kDebug(7103) << QByteArray(buffer, bufPos).trimmed();
2974 if (idx != bufPos && buffer[idx] ==
'<') {
2975 kDebug(7103) <<
"No valid HTTP header found! Document starts with XML/HTML tag";
2981 noHeadersFound =
true;
2988 if (
consume(buffer, &idx, bufPos,
"ICY ")) {
2991 }
else if (
consume(buffer, &idx, bufPos,
"HTTP/")) {
2992 if (
consume(buffer, &idx, bufPos,
"1.0")) {
2995 }
else if (
consume(buffer, &idx, bufPos,
"1.1")) {
3000 if (httpRev ==
HTTP_None && bufPos != 0) {
3003 kDebug(7113) <<
"DO NOT WANT." << bufPos;
3011 noHeadersFound =
true;
3022 if (idx != bufPos) {
3038 i18nc(
"@warning: Security check on url "
3039 "being accessed",
"You are about to "
3040 "log in to the site \"%1\" with the "
3041 "username \"%2\", but the website "
3042 "does not require authentication. "
3043 "This may be an attempt to trick you."
3044 "<p>Is \"%1\" the site you want to visit?",
3046 i18nc(
"@title:window",
"Confirm Website Access"));
3075 upgradeRequired =
true;
3089 setMetaData(QLatin1String(
"permanent-redirect"), QLatin1String(
"true"));
3131 bool authRequiresAnotherRoundtrip =
false;
3134 if (!noHeadersFound) {
3139 kDebug(7113) <<
"wasAuthError=" << wasAuthError <<
"isAuthError=" << isAuthError
3140 <<
"sameAuthError=" << sameAuthError;
3152 kDebug(7113) <<
" -- full response:" << endl << QByteArray(buffer, bufPos).trimmed();
3155 Q_ASSERT(foundDelimiter);
3162 tokenizer.
tokenize(idx,
sizeof(buffer));
3167 if (tIt.
hasNext() && tIt.
next().toLower().startsWith(
"none")) {
3171 tIt = tokenizer.iterator(
"keep-alive");
3173 QByteArray ka = tIt.
next().trimmed().toLower();
3174 if (ka.startsWith(
"timeout=")) {
3175 int ka_timeout = ka.mid(qstrlen(
"timeout=")).trimmed().toInt();
3187 tIt = tokenizer.iterator(
"content-length");
3192 tIt = tokenizer.iterator(
"content-location");
3200 tIt = tokenizer.iterator(
"content-type");
3202 QList<QByteArray> l = tIt.
next().split(
';');
3206 if (
m_mimeType.startsWith(QLatin1Char(
'"'))) {
3218 Q_FOREACH (
const QByteArray &statement, l) {
3219 const int index = statement.indexOf(
'=');
3221 mediaAttribute =
toQString(statement.mid(0, index));
3223 mediaAttribute =
toQString(statement.mid(0, index));
3224 mediaValue =
toQString(statement.mid(index+1));
3226 mediaAttribute = mediaAttribute.trimmed();
3227 mediaValue = mediaValue.trimmed();
3229 bool quoted =
false;
3230 if (mediaValue.startsWith(QLatin1Char(
'"'))) {
3232 mediaValue.remove(0, 1);
3235 if (mediaValue.endsWith(QLatin1Char(
'"'))) {
3239 kDebug (7113) <<
"Encoding-type:" << mediaAttribute <<
"=" << mediaValue;
3241 if (mediaAttribute == QLatin1String(
"charset")) {
3242 mediaValue = mediaValue.toLower();
3244 setMetaData(QLatin1String(
"charset"), mediaValue);
3246 setMetaData(QLatin1String(
"media-") + mediaAttribute, mediaValue);
3248 setMetaData(QLatin1String(
"media-") + mediaAttribute + QLatin1String(
"-kio-quoted"),
3249 QLatin1String(
"true"));
3256 tIt = tokenizer.iterator(
"content-encoding");
3274 tIt = tokenizer.iterator(
"content-disposition");
3278 tIt = tokenizer.iterator(
"content-language");
3281 if (!language.isEmpty()) {
3282 setMetaData(QLatin1String(
"content-language"), language);
3286 tIt = tokenizer.iterator(
"proxy-connection");
3288 QByteArray pc = tIt.
next().toLower();
3289 if (pc.startsWith(
"close")) {
3291 }
else if (pc.startsWith(
"keep-alive")) {
3296 tIt = tokenizer.iterator(
"link");
3300 if (link.count() == 2) {
3301 QString rel = link[1].trimmed();
3302 if (rel.startsWith(QLatin1String(
"rel=\""))) {
3303 rel = rel.mid(5, rel.length() - 6);
3304 if (rel.toLower() == QLatin1String(
"pageservices")) {
3306 QString url = link[0].remove(QRegExp(QLatin1String(
"[<>]"))).trimmed();
3313 tIt = tokenizer.iterator(
"p3p");
3319 .split(QLatin1Char(
'='), QString::SkipEmptyParts);
3320 if (policy.count() == 2) {
3321 if (policy[0].toLower() == QLatin1String(
"policyref")) {
3322 policyrefs << policy[1].remove(QRegExp(QLatin1String(
"[\")\']"))).trimmed();
3323 }
else if (policy[0].toLower() == QLatin1String(
"cp")) {
3327 const QString s = policy[1].remove(QRegExp(QLatin1String(
"[\")\']")));
3328 const QStringList cps = s.split(QLatin1Char(
' '), QString::SkipEmptyParts);
3333 if (!policyrefs.isEmpty()) {
3334 setMetaData(QLatin1String(
"PrivacyPolicy"), policyrefs.join(QLatin1String(
"\n")));
3336 if (!compact.isEmpty()) {
3337 setMetaData(QLatin1String(
"PrivacyCompactPolicy"), compact.join(QLatin1String(
"\n")));
3344 tIt = tokenizer.iterator(
"connection");
3346 QByteArray connection = tIt.
next().toLower();
3348 if (connection.startsWith(
"close")) {
3350 }
else if (connection.startsWith(
"keep-alive")) {
3354 if (connection.startsWith(
"upgrade")) {
3357 upgradeRequired =
true;
3358 }
else if (upgradeRequired) {
3364 tIt = tokenizer.iterator(
"transfer-encoding");
3373 tIt = tokenizer.iterator(
"content-md5");
3380 tIt = tokenizer.iterator(
"dav");
3390 tIt = tokenizer.iterator(
"upgrade");
3394 upgradeOffers = offered.split(QRegExp(QLatin1String(
"[ \n,\r\t]")), QString::SkipEmptyParts);
3396 Q_FOREACH (
const QString &opt, upgradeOffers) {
3397 if (opt == QLatin1String(
"TLS/1.0")) {
3398 if (!
startSsl() && upgradeRequired) {
3402 }
else if (opt == QLatin1String(
"HTTP/1.1")) {
3404 }
else if (upgradeRequired) {
3412 QByteArray cookieStr;
3413 tIt = tokenizer.iterator(
"set-cookie");
3415 cookieStr +=
"Set-Cookie: ";
3416 cookieStr += tIt.
next();
3419 if (!cookieStr.isEmpty()) {
3424 cookieStr =
"Cross-Domain\n" + cookieStr;
3429 setMetaData(QLatin1String(
"setcookies"), QString::fromUtf8(cookieStr));
3437 kDebug(7113) <<
"cont; returning to mark try_again";
3443 kDebug(7113) <<
"Ignoring keep-alive: otherwise unable to determine response body length.";
3458 authRequiresAnotherRoundtrip =
false;
3463 tIt = tokenizer.iterator(
"location");
3465 locationStr = QString::fromUtf8(tIt.
next().trimmed());
3468 if (!locationStr.isEmpty())
3495 if(u.
protocol() == QLatin1String(
"http")){
3497 }
else if(u.
protocol() == QLatin1String(
"https")){
3537 kDebug(7113) <<
"Reading resource from cache even though the cache plan is not "
3538 "UseCached; the server is probably sending wrong expiry information.";
3548 int nextLinePos = 0;
3549 int prevLinePos = 0;
3550 bool haveMore =
true;
3552 haveMore =
nextLine(buffer, &nextLinePos, bufPos);
3553 int prevLineEnd = nextLinePos;
3554 while (buffer[prevLineEnd - 1] ==
'\r' || buffer[prevLineEnd - 1] ==
'\n') {
3559 prevLineEnd - prevLinePos));
3560 prevLinePos = nextLinePos;
3587 return !authRequiresAnotherRoundtrip;
3595 while (i != parameters.constEnd()) {
3596 setMetaData(QLatin1String(
"content-disposition-") + i.key(), i.value());
3597 kDebug(7113) <<
"Content-Disposition:" << i.key() <<
"=" << i.value();
3604 QString encoding = _encoding.trimmed().toLower();
3606 if (encoding == QLatin1String(
"identity")) {
3608 }
else if (encoding == QLatin1String(
"8bit")) {
3611 }
else if (encoding == QLatin1String(
"chunked")) {
3616 }
else if ((encoding == QLatin1String(
"x-gzip")) || (encoding == QLatin1String(
"gzip"))) {
3617 encs.append(QLatin1String(
"gzip"));
3618 }
else if ((encoding == QLatin1String(
"x-bzip2")) || (encoding == QLatin1String(
"bzip2"))) {
3619 encs.append(QLatin1String(
"bzip2"));
3620 }
else if ((encoding == QLatin1String(
"x-deflate")) || (encoding == QLatin1String(
"deflate"))) {
3621 encs.append(QLatin1String(
"deflate"));
3623 kDebug(7113) <<
"Unknown encoding encountered. "
3624 <<
"Please write code. Encoding =" << encoding;
3643 const qint64 currentDate = time(0);
3660 tIt = tokenizer.iterator(
"date");
3667 tIt = tokenizer.iterator(
"age");
3669 ageHeader = tIt.
next().toLongLong();
3673 if (dateHeader != -1) {
3675 }
else if (ageHeader) {
3682 bool hasCacheDirective =
false;
3687 tIt = tokenizer.iterator(
"cache-control");
3689 QByteArray cacheStr = tIt.
next().toLower();
3690 if (cacheStr.startsWith(
"no-cache") || cacheStr.startsWith(
"no-store")) {
3693 hasCacheDirective =
true;
3694 }
else if (cacheStr.startsWith(
"max-age=")) {
3695 QByteArray ba = cacheStr.mid(qstrlen(
"max-age=")).trimmed();
3697 maxAgeHeader = ba.toLongLong(&ok);
3699 hasCacheDirective =
true;
3704 qint64 expiresHeader = -1;
3705 tIt = tokenizer.iterator(
"expires");
3708 kDebug(7113) <<
"parsed expire date from 'expires' header:" << tIt.
current();
3713 }
else if (expiresHeader != -1) {
3722 expAge = qMin(expAge,
qint64(3600 * 24));
3735 tIt = tokenizer.iterator(
"etag");
3740 kDebug(7103) <<
"304 Not Modified but new entity tag - I don't think this is legal HTTP.";
3745 tIt = tokenizer.iterator(
"warning");
3753 tIt = tokenizer.iterator(
"pragma");
3755 if (tIt.
next().toLower().startsWith(
"no-cache")) {
3757 hasCacheDirective =
true;
3762 tIt = tokenizer.iterator(
"refresh");
3769 if (
m_mimeType.startsWith(QLatin1String(
"text/")) && (
m_mimeType != QLatin1String(
"text/css")) &&
3770 (
m_mimeType != QLatin1String(
"text/x-javascript")) && !hasCacheDirective) {
3781 kDebug(7113) <<
"Cache needs validation";
3783 kDebug(7113) <<
"...was revalidated by response code but not by updated expire times. "
3784 "We're going to set the expire date to 60 seconds in the future...";
3790 kDebug(7113) <<
"this proxy or server apparently sends bogus expiry information.";
3807 kDebug(7113) <<
"This webserver is confused about the cacheability of the data it sends.";
3821 if (!cachingAllowed) {
3822 setMetaData(QLatin1String(
"no-cache"), QLatin1String(
"true"));
3823 setMetaData(QLatin1String(
"expire-date"), QLatin1String(
"1"));
3830 setMetaData(QLatin1String(
"cache-creation-date"), tmp);
3838 QByteArray cLength (
"Content-Length: ");
3839 cLength += QByteArray::number(
m_POSTbuf->size());
3840 cLength +=
"\r\n\r\n";
3842 kDebug(7113) <<
"sending cached data (size=" <<
m_POSTbuf->size() <<
")";
3845 bool sendOk = (
write(cLength.data(), cLength.size()) == (ssize_t) cLength.size());
3847 kDebug( 7113 ) <<
"Connection broken when sending "
3859 sendOk = (
write(buffer.data(), buffer.size()) == (ssize_t) buffer.size());
3861 kDebug(7113) <<
"Connection broken when sending message body: ("
3892 QByteArray cLength (
"Content-Length: ");
3894 cLength +=
"\r\n\r\n";
3896 kDebug(7113) << cLength.trimmed();
3899 bool sendOk = (
write(cLength.data(), cLength.size()) == (ssize_t) cLength.size());
3909 kDebug(7113) <<
"Connection broken while sending POST content size to" <<
m_request.
url.host();
3928 const int bytesRead =
readData(buffer);
3931 if (bytesRead == 0) {
3937 if (bytesRead < 0) {
3951 if (
write(buffer.data(), bytesRead) == static_cast<ssize_t>(bytesRead)) {
3952 bytesSent += bytesRead;
3957 kDebug(7113) <<
"Connection broken while sending POST content to" <<
m_request.
url.host();
3967 kDebug(7113) <<
"keepAlive =" << keepAlive;
3983 QDataStream stream( &data, QIODevice::WriteOnly );
4042 QDataStream stream(data);
4050 stream >> url >> size;
4059 stream >> url >> no_cache >> expireDate;
4065 QFile::remove(filename);
4086 stream >> url >> scope >> type >> owner;
4087 davLock( url, scope, type, owner );
4102 stream >> url >> method >> size;
4103 davGeneric( url, (KIO::HTTP_METHOD) method, size );
4132 if (foundCrLf && bufPos == 2) {
4139 kDebug(7113) <<
"Failed to read chunk header.";
4142 Q_ASSERT(bufPos > 2);
4145 if (nextChunkSize < 0)
4147 kDebug(7113) <<
"Negative chunk size";
4164 int trashBufPos = 2;
4167 if (trashBufPos > 3) {
4169 for (
int i = 0; i < 3; i++) {
4170 trash[i] = trash[trashBufPos - 3 + i];
4177 kDebug(7113) <<
"Failed to read chunk trailer.";
4189 return bytesReceived;
4207 if (bytesReceived <= 0)
4211 return bytesReceived;
4218 kDebug(7113) <<
"Unbounded datastream on a Keep-alive connection!";
4258 kDebug(7113) <<
"Determining mime-type from content...";
4272 if( mime && !mime->isDefault() )
4353 if ( !dataInternal ) {
4364 kDebug(7113) <<
"reading data from cache...";
4376 if (!dataInternal) {
4383 if (!dataInternal) {
4411 QObject::connect(&chain, SIGNAL(
output(QByteArray)),
4421 if ( enc == QLatin1String(
"gzip") )
4423 else if ( enc == QLatin1String(
"deflate") )
4451 if ( enc == QLatin1String(
"gzip") )
4453 else if ( enc == QLatin1String(
"deflate") )
4472 if (bytesReceived == -1)
4482 kDebug(7113) <<
"bytesReceived==-1 sz=" << (int)sz
4483 <<
" Connection broken !";
4490 if (bytesReceived > 0)
4501 sz += bytesReceived;
4527 kWarning(7113) <<
"MD5 checksum MISMATCH! Expected:"
4536 if (!dataInternal && sz <= 1)
4549 data( QByteArray() );
4585 QDBusInterface kcookiejar( QLatin1String(
"org.kde.kded"), QLatin1String(
"/modules/kcookiejar"), QLatin1String(
"org.kde.KCookieServer") );
4586 (void)kcookiejar.call( QDBus::NoBlock, QLatin1String(
"addCookies"), url,
4587 cookieHeader, windowId );
4593 QDBusInterface kcookiejar( QLatin1String(
"org.kde.kded"), QLatin1String(
"/modules/kcookiejar"), QLatin1String(
"org.kde.KCookieServer") );
4594 QDBusReply<QString> reply = kcookiejar.call( QLatin1String(
"findCookies"), url, windowId );
4596 if ( !reply.isValid() )
4598 kWarning(7113) <<
"Can't communicate with kded_kcookiejar!";
4627 time_t currentDate = time(0);
4640 struct BinaryCacheFileHeader
4652 static const int size = 36;
4664 BinaryCacheFileHeader
header;
4673 QDataStream stream(&ret, QIODevice::WriteOnly);
4674 stream << quint8(
'A');
4675 stream << quint8(
'\n');
4676 stream << quint8(0);
4677 stream << quint8(0);
4679 stream << fileUseCount;
4682 stream <<
qint64(servedDate);
4683 stream << qint64(lastModifiedDate);
4684 stream << qint64(expireDate);
4686 stream << bytesCached;
4687 Q_ASSERT(ret.size() == BinaryCacheFileHeader::size);
4696 return byte == value;
4699 static bool readTime(QDataStream *stream, time_t *time)
4703 *time =
static_cast<time_t
>(intTime);
4706 return check == intTime;
4715 if (d.size() != BinaryCacheFileHeader::size) {
4718 QDataStream stream(d);
4719 stream.setVersion(QDataStream::Qt_4_5);
4730 stream >> fileUseCount;
4733 ok = ok &&
readTime(&stream, &servedDate);
4734 ok = ok &&
readTime(&stream, &lastModifiedDate);
4735 ok = ok &&
readTime(&stream, &expireDate);
4740 stream >> bytesCached;
4765 static const char linefeed =
'\n';
4767 dev->write(&linefeed, 1);
4774 Q_ASSERT(file->openMode() & QIODevice::WriteOnly);
4776 file->seek(BinaryCacheFileHeader::size);
4790 if (line->isEmpty() || !line->endsWith(
'\n')) {
4802 Q_ASSERT(file->openMode() == QIODevice::ReadOnly);
4806 if (
storableUrl(desiredUrl).toEncoded() != readBuf) {
4807 kDebug(7103) <<
"You have witnessed a very improbable hash collision!";
4821 Q_ASSERT(file->openMode() == QIODevice::ReadOnly);
4827 qint64 oldPos = file->pos();
4828 file->seek(BinaryCacheFileHeader::size);
4831 Q_ASSERT(file->pos() == oldPos);
4840 if (ok && !readBuf.isEmpty()) {
4851 QCryptographicHash hash(QCryptographicHash::Sha1);
4853 return toQString(hash.result().toHex());
4859 if (!filePath.endsWith(QLatin1Char(
'/'))) {
4860 filePath.append(QLatin1Char(
'/'));
4873 kDebug(7113) <<
"File unexpectedly open; old file is" << file->fileName()
4874 <<
"new name is" << filename;
4875 Q_ASSERT(file->fileName() == filename);
4878 file =
new QFile(filename);
4879 if (file->open(QIODevice::ReadOnly)) {
4880 QByteArray
header = file->read(BinaryCacheFileHeader::size);
4882 kDebug(7103) <<
"Cache file header is invalid.";
4892 if (!file->isOpen()) {
4910 Q_ASSERT(!qobject_cast<QTemporaryFile *>(file));
4911 Q_ASSERT((file->openMode() & QIODevice::WriteOnly) == 0);
4912 Q_ASSERT(file->fileName() == filename);
4913 kDebug(7113) <<
"deleting expired cache entry and recreating.";
4921 file->open(QIODevice::WriteOnly);
4927 if ((file->openMode() & QIODevice::WriteOnly) == 0) {
4928 kDebug(7113) <<
"Could not open file for writing:" << file->fileName()
4929 <<
"due to error" << file->error();
4940 QDataStream stream(&ret, QIODevice::WriteOnly);
4941 stream.setVersion(QDataStream::Qt_4_5);
4943 stream.skipRawData(BinaryCacheFileHeader::size);
4948 int basenameStart = fileName.lastIndexOf(QLatin1Char(
'/')) + 1;
4950 stream.writeRawData(baseName.constData(), baseName.size());
4952 Q_ASSERT(ret.size() == BinaryCacheFileHeader::size +
sizeof(quint32) +
s_hashedUrlNibbles);
4968 QByteArray ccCommand;
4971 if (file->openMode() & QIODevice::WriteOnly) {
4977 tempFile->write(header);
4981 QString oldName = tempFile->fileName();
4983 int basenameStart = newName.lastIndexOf(QLatin1Char(
'/')) + 1;
4986 kDebug(7113) <<
"Renaming temporary file" << oldName <<
"to" << newName;
4989 tempFile->setAutoRemove(
false);
4993 if (!QFile::rename(oldName, newName)) {
4996 kDebug(7113) <<
"Renaming temporary file failed, deleting it instead.";
4997 QFile::remove(oldName);
5004 }
else if (file->openMode() == QIODevice::ReadOnly) {
5005 Q_ASSERT(!tempFile);
5011 if (!ccCommand.isEmpty()) {
5022 if (attempts == 2) {
5036 kDebug(7113) <<
"Could not connect to cache cleaner, not updating stats of this cache file.";
5046 if (ret.isEmpty()) {
5063 kDebug(7113) <<
"Caching disabled because content size is too big.";
5093 m_POSTbuf->write (data.constData(), data.size());
5119 const int bytesRead =
readData(buffer);
5121 if (bytesRead < 0) {
5126 if (bytesRead == 0) {
5130 m_POSTbuf->write(buffer.constData(), buffer.size());
5159 const QByteArray cachedChallenge =
config()->
readEntry(
"www-auth-challenge", QByteArray());
5160 if (!cachedChallenge.isEmpty()) {
5163 kDebug(7113) <<
"creating www authentcation header from cached info";
5182 const QByteArray cachedChallenge =
config()->
readEntry(
"proxy-auth-challenge", QByteArray());
5183 if (!cachedChallenge.isEmpty()) {
5186 kDebug(7113) <<
"creating proxy authentcation header from cached info";
5196 ret +=
"Authorization: ";
5201 ret +=
"Proxy-Authorization: ";
5211 case QNetworkProxy::DefaultProxy:
5213 case QNetworkProxy::Socks5Proxy:
5214 return QLatin1String(
"socks");
5215 case QNetworkProxy::NoProxy:
5217 case QNetworkProxy::HttpProxy:
5218 case QNetworkProxy::HttpCachingProxy:
5219 case QNetworkProxy::FtpCachingProxy:
5224 return QLatin1String(
"http");
5229 kDebug(7113) <<
"realm:" << authenticator->realm() <<
"user:" << authenticator->user();
5240 info.
username = authenticator->user();
5248 if (!haveCachedCredentials || retryAuth) {
5254 info.
prompt =
i18n(
"You need to supply a username and a password for "
5255 "the proxy server listed below before you are allowed "
5256 "to access any sites.");
5261 const QString errMsg ((retryAuth ?
i18n(
"Proxy Authentication Failed.") :
QString()));
5264 kDebug(7113) <<
"looks like the user canceled proxy authentication.";
5271 authenticator->setUser(info.
username);
5272 authenticator->setPassword(info.
password);
5273 authenticator->setOption(QLatin1String(
"keepalive"), info.
keepPassword);
5288 kDebug(7113) <<
"Saving authenticator";
5310 bool alreadyCached =
false;
5326 if (auth && (!auth->
realm().isEmpty() || !alreadyCached)) {
5329 setMetaData(QLatin1String(
"{internal~currenthost}cached-www-auth"), QLatin1String(
"true"));
5335 setMetaData(QLatin1String(
"{internal~allhosts}cached-proxy-auth"), QLatin1String(
"true"));
5356 QList<QByteArray> authTokens;
5361 authTokens = tokenizer->iterator(
"www-authenticate").all();
5364 authinfo.
prompt =
i18n(
"You need to supply a username and a "
5365 "password to access this site.");
5371 Q_ASSERT(QNetworkProxy::applicationProxy().type() == QNetworkProxy::NoProxy);
5373 authTokens = tokenizer->iterator(
"proxy-authenticate").all();
5376 authinfo.
prompt =
i18n(
"You need to supply a username and a password for "
5377 "the proxy server listed below before you are allowed "
5378 "to access any sites." );
5382 bool authRequiresAnotherRoundtrip =
false;
5387 if (!authTokens.isEmpty()) {
5389 authRequiresAnotherRoundtrip =
true;
5393 if ((*auth)->wasFinalStage()) {
5395 i18n(
"Authentication Failed.") :
5396 i18n(
"Proxy Authentication Failed."));
5404 QMutableListIterator<QByteArray> it (authTokens);
5405 const QByteArray authScheme ((*auth)->scheme().trimmed());
5406 while (it.hasNext()) {
5407 if (qstrnicmp(authScheme.constData(), it.next().constData(), authScheme.length()) != 0) {
5414 try_next_auth_scheme:
5417 const QByteArray authScheme ((*auth)->scheme().trimmed());
5418 if (qstrnicmp(authScheme.constData(), bestOffer.constData(), authScheme.length()) != 0) {
5430 kDebug(7113) <<
"Trying authentication scheme:" << (*auth)->scheme();
5436 bool generateAuthHeader =
true;
5437 if ((*auth)->needCredentials()) {
5448 if (authinfo.
realmValue.isEmpty() && !(*auth)->supportsPathMatching())
5449 authinfo.
realmValue = QLatin1String((*auth)->scheme());
5454 const KUrl reqUrl = authinfo.
url;
5457 authinfo.
url = reqUrl;
5463 generateAuthHeader =
false;
5464 authRequiresAnotherRoundtrip =
false;
5468 kDebug(7113) <<
"looks like the user canceled the authentication dialog";
5478 if (generateAuthHeader) {
5479 (*auth)->generateResponse(username, password);
5480 (*auth)->setCachePasswordEnabled(authinfo.
keepPassword);
5482 kDebug(7113) <<
"isError=" << (*auth)->isError()
5483 <<
"needCredentials=" << (*auth)->needCredentials()
5484 <<
"forceKeepAlive=" << (*auth)->forceKeepAlive()
5485 <<
"forceDisconnect=" << (*auth)->forceDisconnect();
5487 if ((*auth)->isError()) {
5488 authTokens.removeOne(bestOffer);
5489 if (!authTokens.isEmpty()) {
5490 goto try_next_auth_scheme;
5493 authRequiresAnotherRoundtrip =
false;
5496 }
else if ((*auth)->forceKeepAlive()) {
5499 }
else if ((*auth)->forceDisconnect()) {
5506 authRequiresAnotherRoundtrip =
false;
5513 return authRequiresAnotherRoundtrip;