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(
""");
114 return (scheme.startsWith(QLatin1String(
"http"))
115 || scheme == QLatin1String(
"socks"));
128 QCoreApplication app( argc, argv );
134 fprintf(stderr,
"Usage: kio_http protocol domain-socket1 domain-socket2\n");
139 slave.dispatchLoop();
147 return QString::fromLatin1(value.constData(), value.size());
153 if (originURL == QLatin1String(
"true"))
156 KUrl url ( originURL );
166 QStringList la = a.split(QLatin1Char(
'.'), QString::SkipEmptyParts);
167 QStringList lb = b.split(QLatin1Char(
'.'), QString::SkipEmptyParts);
169 if (qMin(la.count(), lb.count()) < 2) {
173 while(la.count() > 2)
175 while(lb.count() > 2)
187 const QStringList headers = _header.split(QRegExp(QLatin1String(
"[\r\n]")));
189 for(QStringList::ConstIterator it = headers.begin(); it != headers.end(); ++it)
193 if (!(*it).contains(QLatin1Char(
':')) ||
194 (*it).startsWith(QLatin1String(
"host"), Qt::CaseInsensitive) ||
195 (*it).startsWith(QLatin1String(
"proxy-authorization"), Qt::CaseInsensitive) ||
196 (*it).startsWith(QLatin1String(
"via"), Qt::CaseInsensitive))
199 sanitizedHeaders += (*it);
200 sanitizedHeaders += QLatin1String(
"\r\n");
202 sanitizedHeaders.chop(2);
204 return sanitizedHeaders;
210 if (config->
readEntry(
"no-spoof-check",
false)) {
214 if (request.
url.
user().isEmpty()) {
219 if (config->
readEntry(QLatin1String(
"cached-www-auth"),
false)) {
250 if (responseCode >= 100 && responseCode < 200) {
253 switch (responseCode) {
259 Q_ASSERT(method != HTTP_HEAD);
269 return method != HTTP_HEAD;
274 return p ==
"https" || p ==
"webdavs";
279 return u.isValid() && u.
hasHost();
293 device =
new QBuffer;
295 if (!device->open(QIODevice::ReadWrite))
309 if (type == QLatin1String(
"dateTime.tz") ) {
311 }
else if (type == QLatin1String(
"dateTime.rfc1123")) {
332 kDebug(7113) <<
"item:" <<
name <<
", mimeType:" << mimeType;
334 if (mimeType.isEmpty() && type != S_IFDIR) {
335 KMimeType::Ptr mime = KMimeType::findByUrl(
name, 0,
false,
true);
336 if (mime && !mime->isDefault()) {
337 kDebug(7113) <<
"Setting" << mime->name() <<
"as guessed mime type for" <<
name;
348 if (!methodStringOverride.isEmpty())
349 return (methodStringOverride).toLatin1();
382 case DAV_UNSUBSCRIBE:
383 return "UNSUBSCRIBE";
403 if (!dt.
time().second()) {
404 ret.append(QLatin1String(
":00"));
406 ret.append(QLatin1String(
" GMT"));
412 return (responseCode == 401) || (responseCode == 407);
415 #define NO_SIZE ((KIO::filesize_t) -1)
418 #define STRTOLL strtoll
420 #define STRTOLL strtol
428 const QByteArray &app )
436 , m_protocol(protocol)
439 , m_socketProxyAuth(0)
441 , m_isLoadingErrorPage(false)
443 , m_iEOFRetryCount(0)
447 connect(
socket(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
467 TCPSlaveBase::reparseConfiguration();
495 setMetaData(QLatin1String(
"request-id"),
m_request.
id);
510 const bool noAuth =
config()->readEntry(
"no-auth",
false);
521 kDebug(7113) <<
"ssl_was_in_use =" << metaData(QLatin1String(
"ssl_was_in_use"));
529 KUrl refUrl(metaData(QLatin1String(
"referrer")));
530 if (refUrl.isValid()) {
533 if (protocol.startsWith(QLatin1String(
"webdav"))) {
534 protocol.replace(0, 6, QLatin1String(
"http"));
538 if (protocol.startsWith(QLatin1String(
"http"))) {
544 if (
config()->readEntry(
"SendLanguageSettings",
true)) {
556 QString resumeOffset = metaData(QLatin1String(
"resume"));
557 if (!resumeOffset.isEmpty()) {
563 QString resumeEndOffset = metaData(QLatin1String(
"resume_until"));
564 if (!resumeEndOffset.isEmpty()) {
572 m_request.
id = metaData(QLatin1String(
"request-id"));
618 if (host.indexOf(QLatin1Char(
':')) == -1) {
621 int pos = host.indexOf(QLatin1Char(
'%'));
647 if (u.host().isEmpty()) {
652 if (u.
path().isEmpty()) {
654 newUrl.
setPath(QLatin1String(
"/"));
677 if (dataInternal || !status) {
736 setMetaData(QLatin1String(
"content-type"),
m_mimeType);
754 QString statSide = metaData(QLatin1String(
"statSide"));
755 if (statSide != QLatin1String(
"source"))
802 QString query = metaData(QLatin1String(
"davSearchQuery"));
803 if ( !query.isEmpty() )
805 QByteArray request =
"<?xml version=\"1.0\"?>\r\n";
806 request.append(
"<D:searchrequest xmlns:D=\"DAV:\">\r\n" );
807 request.append( query.toUtf8() );
808 request.append(
"</D:searchrequest>\r\n" );
814 request =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
815 "<D:propfind xmlns:D=\"DAV:\">";
818 if ( hasMetaData(QLatin1String(
"davRequestResponse")) )
819 request += metaData(QLatin1String(
"davRequestResponse")).toUtf8();
822 request +=
"<D:prop>"
824 "<D:getcontentlength/>"
827 "<D:getcontentlanguage/>"
828 "<D:getcontenttype/>"
829 "<D:getlastmodified/>"
836 request +=
"</D:propfind>";
850 infoMessage(QLatin1String(
""));
860 QDomDocument multiResponse;
863 bool hasResponse =
false;
867 for ( QDomNode n = multiResponse.documentElement().firstChild();
868 !n.isNull(); n = n.nextSibling()) {
869 QDomElement thisResponse = n.toElement();
870 if (thisResponse.isNull())
875 QDomElement href = thisResponse.namedItem(QLatin1String(
"href")).toElement();
876 if ( !href.isNull() ) {
879 QString urlStr = QUrl::fromPercentEncoding(href.text().toUtf8());
880 #if 0 // qt4/kde4 say: it's all utf8...
881 int encoding = remoteEncoding()->encodingMib();
885 KUrl thisURL ( urlStr, encoding );
887 KUrl thisURL( urlStr );
890 if ( thisURL.isValid() ) {
895 name = QLatin1Char(
'.');
900 QDomNodeList propstats = thisResponse.elementsByTagName(QLatin1String(
"propstat"));
913 listEntry( entry,
false );
915 kDebug(7113) <<
"Error: no URL contained in response to PROPFIND on" << url;
919 if ( stat || !hasResponse ) {
924 listEntry( entry,
true );
951 const int firstSpace = response.indexOf( QLatin1Char(
' ') );
952 const int secondSpace = response.indexOf( QLatin1Char(
' '), firstSpace + 1 );
953 return response.mid( firstSpace + 1, secondSpace - firstSpace - 1 ).toInt();
959 bool foundExecutable =
false;
960 bool isDirectory =
false;
962 uint supportedLockCount = 0;
964 for (
int i = 0; i < propstats.count(); i++)
966 QDomElement propstat = propstats.item(i).toElement();
968 QDomElement status = propstat.namedItem(QLatin1String(
"status")).toElement();
969 if ( status.isNull() )
972 kDebug(7113) <<
"Error, no status code in this propstat";
980 kDebug(7113) <<
"Got status code" << code <<
"(this may mean that some properties are unavailable)";
984 QDomElement prop = propstat.namedItem( QLatin1String(
"prop") ).toElement();
987 kDebug(7113) <<
"Error: no prop segment in this propstat.";
991 if ( hasMetaData( QLatin1String(
"davRequestResponse") ) )
994 doc.appendChild(prop);
998 for ( QDomNode n = prop.firstChild(); !n.isNull(); n = n.nextSibling() )
1000 QDomElement
property = n.toElement();
1001 if (property.isNull())
1004 if ( property.namespaceURI() != QLatin1String(
"DAV:") )
1010 if ( property.tagName() == QLatin1String(
"creationdate") )
1015 else if ( property.tagName() == QLatin1String(
"getcontentlength") )
1020 else if ( property.tagName() == QLatin1String(
"displayname") )
1023 setMetaData( QLatin1String(
"davDisplayName"), property.text() );
1025 else if ( property.tagName() == QLatin1String(
"source") )
1028 QDomElement source =
property.namedItem( QLatin1String(
"link") ).toElement()
1029 .namedItem( QLatin1String(
"dst") ).toElement();
1030 if ( !source.isNull() )
1031 setMetaData( QLatin1String(
"davSource"), source.text() );
1033 else if ( property.tagName() == QLatin1String(
"getcontentlanguage") )
1036 setMetaData( QLatin1String(
"davContentLanguage"), property.text() );
1038 else if ( property.tagName() == QLatin1String(
"getcontenttype") )
1043 if ( property.text() == QLatin1String(
"httpd/unix-directory") )
1049 mimeType =
property.text();
1052 else if ( property.tagName() == QLatin1String(
"executable") )
1055 if ( property.text() == QLatin1String(
"T") )
1056 foundExecutable =
true;
1059 else if ( property.tagName() == QLatin1String(
"getlastmodified") )
1064 else if ( property.tagName() == QLatin1String(
"getetag") )
1067 setMetaData( QLatin1String(
"davEntityTag"), property.text() );
1069 else if ( property.tagName() == QLatin1String(
"supportedlock") )
1072 for ( QDomNode n2 = property.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
1074 QDomElement lockEntry = n2.toElement();
1075 if ( lockEntry.tagName() == QLatin1String(
"lockentry") )
1077 QDomElement lockScope = lockEntry.namedItem( QLatin1String(
"lockscope") ).toElement();
1078 QDomElement lockType = lockEntry.namedItem( QLatin1String(
"locktype") ).toElement();
1079 if ( !lockScope.isNull() && !lockType.isNull() )
1082 supportedLockCount++;
1083 const QString lockCountStr = QString::number(supportedLockCount);
1084 const QString scope = lockScope.firstChild().toElement().tagName();
1085 const QString type = lockType.firstChild().toElement().tagName();
1087 setMetaData( QLatin1String(
"davSupportedLockScope") + lockCountStr, scope );
1088 setMetaData( QLatin1String(
"davSupportedLockType") + lockCountStr, type );
1093 else if ( property.tagName() == QLatin1String(
"lockdiscovery") )
1096 davParseActiveLocks( property.elementsByTagName( QLatin1String(
"activelock") ), lockCount );
1098 else if ( property.tagName() == QLatin1String(
"resourcetype") )
1101 if ( !property.namedItem( QLatin1String(
"collection") ).toElement().isNull() )
1109 kDebug(7113) <<
"Found unknown webdav property:" <<
property.tagName();
1114 setMetaData( QLatin1String(
"davLockCount"), QString::number(lockCount) );
1115 setMetaData( QLatin1String(
"davSupportedLockCount"), QString::number(supportedLockCount) );
1119 if ( foundExecutable || isDirectory )
1129 if ( !isDirectory && !mimeType.isEmpty() )
1138 for (
int i = 0; i < activeLocks.count(); i++ )
1140 const QDomElement activeLock = activeLocks.item(i).toElement();
1144 const QDomElement lockScope = activeLock.namedItem( QLatin1String(
"lockscope") ).toElement();
1145 const QDomElement lockType = activeLock.namedItem( QLatin1String(
"locktype") ).toElement();
1146 const QDomElement lockDepth = activeLock.namedItem( QLatin1String(
"depth") ).toElement();
1148 const QDomElement lockOwner = activeLock.namedItem( QLatin1String(
"owner") ).toElement();
1149 const QDomElement lockTimeout = activeLock.namedItem( QLatin1String(
"timeout") ).toElement();
1150 const QDomElement lockToken = activeLock.namedItem( QLatin1String(
"locktoken") ).toElement();
1152 if ( !lockScope.isNull() && !lockType.isNull() && !lockDepth.isNull() )
1156 const QString lockCountStr = QString::number(lockCount);
1157 const QString scope = lockScope.firstChild().toElement().tagName();
1158 const QString type = lockType.firstChild().toElement().tagName();
1159 const QString depth = lockDepth.text();
1161 setMetaData( QLatin1String(
"davLockScope") + lockCountStr, scope );
1162 setMetaData( QLatin1String(
"davLockType") + lockCountStr, type );
1163 setMetaData( QLatin1String(
"davLockDepth") + lockCountStr, depth );
1165 if ( !lockOwner.isNull() )
1166 setMetaData( QLatin1String(
"davLockOwner") + lockCountStr, lockOwner.text() );
1168 if ( !lockTimeout.isNull() )
1169 setMetaData( QLatin1String(
"davLockTimeout") + lockCountStr, lockTimeout.text() );
1171 if ( !lockToken.isNull() )
1173 QDomElement tokenVal = lockScope.namedItem( QLatin1String(
"href") ).toElement();
1174 if ( !tokenVal.isNull() )
1175 setMetaData( QLatin1String(
"davLockToken") + lockCountStr, tokenVal.text() );
1183 if ( hasMetaData( QLatin1String(
"davLockCount") ) )
1185 QString response = QLatin1String(
"If:");
1186 int numLocks = metaData( QLatin1String(
"davLockCount") ).toInt();
1187 bool bracketsOpen =
false;
1188 for (
int i = 0; i < numLocks; i++ )
1190 const QString countStr = QString::number(i);
1191 if ( hasMetaData( QLatin1String(
"davLockToken") + countStr ) )
1193 if ( hasMetaData( QLatin1String(
"davLockURL") + countStr ) )
1197 response += QLatin1Char(
')');
1198 bracketsOpen =
false;
1200 response += QLatin1String(
" <") + metaData( QLatin1String(
"davLockURL") + countStr ) + QLatin1Char(
'>');
1203 if ( !bracketsOpen )
1205 response += QLatin1String(
" (");
1206 bracketsOpen =
true;
1210 response += QLatin1Char(
' ');
1213 if ( hasMetaData( QLatin1String(
"davLockNot") + countStr ) )
1214 response += QLatin1String(
"Not ");
1216 response += QLatin1Char(
'<') + metaData( QLatin1String(
"davLockToken") + countStr ) + QLatin1Char(
'>');
1221 response += QLatin1Char(
')');
1223 response += QLatin1String(
"\r\n");
1243 kDebug(7113) <<
" false";
1266 if (ok && verNo > 0 && verNo < 3)
1269 kDebug(7113) <<
"Server supports DAV version" << verNo;
1320 const QString tmp (metaData(QLatin1String(
"cache")));
1342 const QByteArray request (
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1343 "<D:propfind xmlns:D=\"DAV:\"><D:prop>"
1345 "<D:getcontentlength/>"
1348 "</D:prop></D:propfind>");
1384 kDebug(7113) << src <<
"->" << dest;
1391 KUrl newDest = dest;
1392 if (newDest.
protocol() == QLatin1String(
"webdavs"))
1394 else if (newDest.
protocol() == QLatin1String(
"webdav"))
1414 kDebug(7113) << src <<
"->" << dest;
1421 KUrl newDest = dest;
1422 if (newDest.
protocol() == QLatin1String(
"webdavs"))
1424 else if (newDest.
protocol() == QLatin1String(
"webdav"))
1518 QDomDocument lockReq;
1520 QDomElement lockInfo = lockReq.createElementNS( QLatin1String(
"DAV:"), QLatin1String(
"lockinfo") );
1521 lockReq.appendChild( lockInfo );
1523 QDomElement lockScope = lockReq.createElement( QLatin1String(
"lockscope") );
1524 lockInfo.appendChild( lockScope );
1526 lockScope.appendChild( lockReq.createElement( scope ) );
1528 QDomElement lockType = lockReq.createElement( QLatin1String(
"locktype") );
1529 lockInfo.appendChild( lockType );
1531 lockType.appendChild( lockReq.createElement( type ) );
1533 if ( !owner.isNull() ) {
1534 QDomElement ownerElement = lockReq.createElement( QLatin1String(
"owner") );
1535 lockReq.appendChild( ownerElement );
1537 QDomElement ownerHref = lockReq.createElement( QLatin1String(
"href") );
1538 ownerElement.appendChild( ownerHref );
1540 ownerHref.appendChild( lockReq.createTextNode( owner ) );
1550 QDomDocument multiResponse;
1553 QDomElement prop = multiResponse.documentElement().namedItem( QLatin1String(
"prop") ).toElement();
1555 QDomElement lockdiscovery = prop.namedItem( QLatin1String(
"lockdiscovery") ).toElement();
1558 davParseActiveLocks( lockdiscovery.elementsByTagName( QLatin1String(
"activelock") ), lockCount );
1560 setMetaData( QLatin1String(
"davLockCount"), QString::number( lockCount ) );
1590 bool callError =
false;
1600 if ( !url.isNull() )
1607 QString ow =
i18n(
"Otherwise, the request would have succeeded." );
1611 action =
i18nc(
"request type",
"retrieve property values" );
1614 action =
i18nc(
"request type",
"set property values" );
1617 action =
i18nc(
"request type",
"create the requested folder" );
1620 action =
i18nc(
"request type",
"copy the specified file or folder" );
1623 action =
i18nc(
"request type",
"move the specified file or folder" );
1626 action =
i18nc(
"request type",
"search in the specified folder" );
1629 action =
i18nc(
"request type",
"lock the specified file or folder" );
1632 action =
i18nc(
"request type",
"unlock the specified file or folder" );
1635 action =
i18nc(
"request type",
"delete the specified file or folder" );
1638 action =
i18nc(
"request type",
"query the server's capabilities" );
1641 action =
i18nc(
"request type",
"retrieve the contents of the specified file or folder" );
1644 action =
i18nc(
"request type",
"run a report in the specified folder" );
1655 errorString =
i18nc(
"%1: code, %2: request type",
"An unexpected error (%1) occurred "
1656 "while attempting to %2.", code, action);
1663 errorString =
i18n(
"The server does not support the WebDAV protocol.");
1677 QDomDocument multiResponse;
1681 QDomElement multistatus = multiResponse.documentElement().namedItem( QLatin1String(
"multistatus") ).toElement();
1683 QDomNodeList responses = multistatus.elementsByTagName( QLatin1String(
"response") );
1685 for (
int i = 0; i < responses.count(); i++)
1690 QDomElement response = responses.item(i).toElement();
1691 QDomElement code = response.namedItem( QLatin1String(
"status") ).toElement();
1693 if ( !code.isNull() )
1696 QDomElement href = response.namedItem( QLatin1String(
"href") ).toElement();
1697 if ( !href.isNull() )
1698 errUrl = href.text();
1699 errors <<
davError( errCode, errUrl );
1704 errorString =
i18nc(
"%1: request type, %2: url",
1705 "An error occurred while attempting to %1, %2. A "
1706 "summary of the reasons is below.", action, url );
1708 errorString += QLatin1String(
"<ul>");
1711 errorString += QLatin1String(
"<li>") + error + QLatin1String(
"</li>");
1713 errorString += QLatin1String(
"</ul>");
1719 errorString =
i18nc(
"%1: request type",
"Access was denied while attempting to %1.", action );
1732 errorString =
i18n(
"A resource cannot be created at the destination "
1733 "until one or more intermediate collections (folders) "
1734 "have been created.");
1740 errorString =
i18n(
"The server was unable to maintain the liveness of "
1741 "the properties listed in the propertybehavior XML "
1742 "element or you attempted to overwrite a file while "
1743 "requesting that files are not overwritten. %1",
1748 errorString =
i18n(
"The requested lock could not be granted. %1", ow );
1754 errorString =
i18n(
"The server does not support the request type of the body.");
1759 errorString =
i18nc(
"%1: request type",
"Unable to %1 because the resource is locked.", action );
1763 errorString =
i18n(
"This action was prevented by another error.");
1769 errorString =
i18nc(
"%1: request type",
"Unable to %1 because the destination server refuses "
1770 "to accept the file or folder.", action );
1776 errorString =
i18n(
"The destination resource does not have sufficient space "
1777 "to record the state of the resource after the execution "
1788 error( errorCode, errorString );
1796 Q_ASSERT(errorString);
1799 errorString->clear();
1811 Q_ASSERT(errorString);
1815 errorString->clear();
1817 switch (responseCode) {
1826 && (responseCode < 200 || responseCode > 400)
1827 && responseCode != 404) {
1829 *errorString =
i18n(
"The resource cannot be deleted." );
1838 Q_ASSERT(errorString);
1844 switch (responseCode) {
1851 *errorString =
i18nc(
"%1: request type",
"Access was denied while attempting to %1.", action );
1857 *errorString =
i18n(
"A resource cannot be created at the destination "
1858 "until one or more intermediate collections (folders) "
1859 "have been created.");
1865 *errorString =
i18nc(
"%1: request type",
"Unable to %1 because the resource is locked.", action );
1871 *errorString =
i18nc(
"%1: request type",
"Unable to %1 because the destination server refuses "
1872 "to accept the file or folder.", action );
1878 *errorString =
i18n(
"The destination resource does not have sufficient space "
1879 "to record the state of the resource after the execution "
1888 && (responseCode < 200 || responseCode > 400)
1889 && responseCode != 404) {
1891 *errorString =
i18nc(
"%1: response code, %2: request type",
1892 "An unexpected error (%1) occurred while attempting to %2.",
1893 responseCode, action);
1920 infoMessage(QLatin1String(
""));
1923 error( errorCode, errorString );
1936 kWarning(7113) <<
"called twice during one request, something is probably wrong.";
1939 SlaveBase::errorPage();
1949 Solid::Networking::Status status = Solid::Networking::status();
1951 kDebug(7113) <<
"networkstatus:" << status;
1954 return status == Solid::Networking::Unconnected;
1959 QDataStream stream(data);
1971 for (
unsigned i = 0; i < n; ++i) {
1973 stream >> url >> mIncomingMetaData;
1986 QString tmp = metaData(QLatin1String(
"cache"));
2001 while (it.hasNext()) {
2013 while (it.hasNext()) {
2030 setMetaData(QLatin1String(
"request-id"), QString::number(requestId++));
2031 sendAndKeepMetaData();
2050 const char* buf =
static_cast<const char*
>(_buf);
2051 while (sent < nbytes)
2053 int n = TCPSlaveBase::write(buf + sent, nbytes - sent);
2078 for (
size_t i = 0; i < size; i++) {
2089 size_t bytesRead = 0;
2092 bytesRead = qMin((
int)size, bufSize);
2094 for (
size_t i = 0; i < bytesRead; i++) {
2095 buf[i] =
m_unreadBuf.constData()[bufSize - i - 1];
2106 if (bytesRead < size) {
2107 int rawRead = TCPSlaveBase::read(buf + bytesRead, size - bytesRead);
2112 bytesRead += rawRead;
2123 Q_ASSERT(numNewlines >=1 && numNewlines <= 2);
2126 while (pos < end && !
m_isEOF) {
2127 int step = qMin((
int)
sizeof(mybuf), end - pos);
2136 for (
size_t i = 0; i < bufferFill ; ++i, ++pos) {
2139 buf[pos] = mybuf[i];
2144 if (buf[pos] ==
'\n') {
2145 bool found = numNewlines == 1;
2148 found = ((pos >= 1 && buf[pos - 1] ==
'\n') ||
2149 (pos >= 2 && buf[pos - 2] ==
'\n' && buf[pos - 1] ==
'\r'));
2153 unread(&mybuf[i], bufferFill - i);
2166 if (previous.host() != now.host() || previous.port() != now.port()) {
2169 if (previous.
user().isEmpty() && previous.
pass().isEmpty()) {
2185 if (url != QLatin1String(
"DIRECT")) {
2204 disconnect(
socket(), SIGNAL(connected()),
2209 int connectError = 0;
2219 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2224 if (proxyUrl == QLatin1String(
"DIRECT")) {
2225 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2227 if (connectError == 0) {
2235 const KUrl url(proxyUrl);
2239 errorString = url.
url();
2240 badProxyUrls << url;
2244 QNetworkProxy::ProxyType proxyType = QNetworkProxy::NoProxy;
2245 if (proxyScheme == QLatin1String(
"socks")) {
2246 proxyType = QNetworkProxy::Socks5Proxy;
2248 proxyType = QNetworkProxy::HttpProxy;
2251 kDebug(7113) <<
"Connecting to proxy: address=" << proxyUrl <<
"type=" << proxyType;
2253 if (proxyType == QNetworkProxy::NoProxy) {
2254 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2255 connectError =
connectToHost(url.host(), url.port(), &errorString);
2256 if (connectError == 0) {
2258 kDebug(7113) <<
"Connected to proxy: host=" << url.host() <<
"port=" << url.port();
2264 kDebug(7113) <<
"Failed to connect to proxy:" << proxyUrl;
2265 badProxyUrls << url;
2268 QNetworkProxy proxy(proxyType, url.host(), url.port(), url.
user(), url.
pass());
2269 QNetworkProxy::setApplicationProxy(proxy);
2271 if (connectError == 0) {
2272 kDebug(7113) <<
"Tunneling thru proxy: host=" << url.host() <<
"port=" << url.port();
2278 kDebug(7113) <<
"Failed to connect to proxy:" << proxyUrl;
2279 badProxyUrls << url;
2280 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2285 if (!badProxyUrls.isEmpty()) {
2290 if (connectError != 0) {
2291 error(connectError, errorString);
2321 bool openForReading =
false;
2325 if (!openForReading && (isCacheOnly || offline)) {
2327 *cacheHasPage =
false;
2330 }
else if (offline) {
2337 if (openForReading) {
2339 *cacheHasPage =
true;
2344 *cacheHasPage =
false;
2357 if (protocol.startsWith(QLatin1String(
"webdav"))) {
2358 protocol.replace(0, qstrlen(
"webdav"), QLatin1String(
"http"));
2415 kDebug(7113) <<
"Couldn't connect, oopsie!";
2427 bool hasBodyData =
false;
2428 bool hasDavData =
false;
2440 bool cacheHasPage =
false;
2442 kDebug(7113) <<
"cacheHasPage =" << cacheHasPage;
2443 return cacheHasPage;
2445 if (!cacheHasPage) {
2462 davHeader = QLatin1String(
"Depth: ");
2463 if ( hasMetaData( QLatin1String(
"davDepth") ) )
2465 kDebug(7113) <<
"Reading DAV depth from metadata:" << metaData( QLatin1String(
"davDepth") );
2466 davHeader += metaData( QLatin1String(
"davDepth") );
2471 davHeader += QLatin1String(
"infinity");
2475 davHeader += QLatin1String(
"\r\n");
2487 davHeader += QLatin1String(
"\r\nDepth: infinity\r\nOverwrite: ");
2489 davHeader += QLatin1String(
"\r\n");
2492 davHeader = QLatin1String(
"Timeout: ");
2495 if ( hasMetaData( QLatin1String(
"davTimeout") ) )
2496 timeout = metaData( QLatin1String(
"davTimeout") ).toUInt();
2498 davHeader += QLatin1String(
"Infinite");
2500 davHeader += QLatin1String(
"Seconds-") + QString::number(timeout);
2502 davHeader += QLatin1String(
"\r\n");
2506 davHeader = QLatin1String(
"Lock-token: ") + metaData(QLatin1String(
"davLockToken")) + QLatin1String(
"\r\n");
2513 case DAV_UNSUBSCRIBE:
2527 header += QLatin1Char(
':') + QString::number(
m_request.
url.port());
2529 header += QLatin1String(
"\r\n");
2536 header += QLatin1String(
"Proxy-Connection: ");
2538 header += QLatin1String(
"Connection: ");
2541 header += QLatin1String(
"keep-alive\r\n");
2543 header += QLatin1String(
"close\r\n");
2548 header += QLatin1String(
"User-Agent: ");
2550 header += QLatin1String(
"\r\n");
2555 header += QLatin1String(
"Referer: ");
2557 header += QLatin1String(
"\r\n");
2562 header += QLatin1String(
"Range: bytes=");
2564 header += QLatin1Char(
'-');
2566 header += QLatin1String(
"\r\n");
2572 header += QLatin1String(
"Range: bytes=");
2574 header += QLatin1String(
"-\r\n");
2581 header += QLatin1String(
"Pragma: no-cache\r\n");
2582 header += QLatin1String(
"Cache-control: no-cache\r\n");
2586 kDebug(7113) <<
"needs validation, performing conditional get.";
2593 header += QLatin1String(
"If-Modified-Since: ") + httpDate + QLatin1String(
"\r\n");
2594 setMetaData(QLatin1String(
"modified"), httpDate);
2598 header += QLatin1String(
"Accept: ");
2599 const QString acceptHeader = metaData(QLatin1String(
"accept"));
2600 if (!acceptHeader.isEmpty())
2601 header += acceptHeader;
2604 header += QLatin1String(
"\r\n");
2607 header += QLatin1String(
"Accept-Encoding: gzip, deflate, x-gzip, x-deflate\r\n");
2610 header += QLatin1String(
"Accept-Charset: ") +
m_request.
charsets + QLatin1String(
"\r\n");
2613 header += QLatin1String(
"Accept-Language: ") +
m_request.
languages + QLatin1String(
"\r\n");
2616 const QString cookieMode = metaData(QLatin1String(
"cookies")).toLower();
2618 if (cookieMode == QLatin1String(
"none"))
2622 else if (cookieMode == QLatin1String(
"manual"))
2625 cookieStr = metaData(QLatin1String(
"setcookies"));
2634 if (!cookieStr.isEmpty())
2635 header += cookieStr + QLatin1String(
"\r\n");
2637 const QString customHeader = metaData( QLatin1String(
"customHTTPHeader") );
2638 if (!customHeader.isEmpty())
2641 header += QLatin1String(
"\r\n");
2644 const QString contentType = metaData(QLatin1String(
"content-type"));
2645 if (!contentType.isEmpty())
2647 if (!contentType.startsWith(QLatin1String(
"content-type"), Qt::CaseInsensitive))
2648 header += QLatin1String(
"Content-Type: ");
2649 header += contentType;
2650 header += QLatin1String(
"\r\n");
2655 header += QLatin1String(
"DNT: 1\r\n");
2668 davHeader += metaData(QLatin1String(
"davHeader"));
2672 davHeader += QLatin1String(
"Content-Type: text/xml; charset=utf-8\r\n");
2675 header += davHeader;
2679 kDebug(7103) <<
"============ Sending Header:";
2680 Q_FOREACH (
const QString &s, header.split(QLatin1String(
"\r\n"), QString::SkipEmptyParts)) {
2686 if (!hasBodyData && !hasDavData)
2687 header += QLatin1String(
"\r\n");
2696 const QByteArray headerBytes = header.toLatin1();
2697 ssize_t written =
write(headerBytes.constData(), headerBytes.length());
2698 bool sendOk = (written == (ssize_t) headerBytes.length());
2702 <<
" -- intended to write" << headerBytes.length()
2703 <<
"bytes but wrote" << (int)written <<
".";
2713 kDebug(7113) <<
"sendOk == false. Connection broken !"
2714 <<
" -- intended to write" << headerBytes.length()
2715 <<
"bytes but wrote" << (int)written <<
".";
2720 kDebug(7113) <<
"sent it!";
2723 if (hasBodyData || hasDavData)
2726 infoMessage(
i18n(
"%1 contacted. Waiting for reply...",
m_request.
url.host()));
2739 if (forwardImmediately)
2752 if (header.startsWith(QLatin1String(
"content-type:"), Qt::CaseInsensitive)) {
2753 int pos = header.indexOf(QLatin1String(
"charset="), Qt::CaseInsensitive);
2755 const QString charset = header.mid(pos + 8).toLower();
2757 setMetaData(QLatin1String(
"charset"), charset);
2759 }
else if (header.startsWith(QLatin1String(
"content-language:"), Qt::CaseInsensitive)) {
2760 const QString language = header.mid(17).trimmed().toLower();
2761 setMetaData(QLatin1String(
"content-language"), language);
2762 }
else if (header.startsWith(QLatin1String(
"content-disposition:"), Qt::CaseInsensitive)) {
2789 if (
m_mimeType == QLatin1String(
"application/x-targz"))
2790 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2791 else if (
m_mimeType == QLatin1String(
"image/x-png"))
2795 else if (
m_mimeType == QLatin1String(
"audio/microsoft-wave"))
2797 else if (
m_mimeType == QLatin1String(
"image/x-ms-bmp"))
2801 else if (
m_mimeType == QLatin1String(
"application/pkix-cert") ||
2802 m_mimeType == QLatin1String(
"application/binary-certificate")) {
2803 m_mimeType = QLatin1String(
"application/x-x509-ca-cert");
2807 else if (
m_mimeType == QLatin1String(
"application/x-gzip")) {
2810 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2812 m_mimeType = QLatin1String(
"application/x-gzpostscript");
2817 else if(
m_mimeType == QLatin1String(
"application/x-xz")) {
2820 m_mimeType = QLatin1String(
"application/x-xz-compressed-tar");
2825 else if ((
m_mimeType == QLatin1String(
"text/plain")) || (
m_mimeType == QLatin1String(
"application/octet-stream"))) {
2827 if (ext == QLatin1String(
"BZ2"))
2828 m_mimeType = QLatin1String(
"application/x-bzip");
2829 else if (ext == QLatin1String(
"PEM"))
2830 m_mimeType = QLatin1String(
"application/x-x509-ca-cert");
2831 else if (ext == QLatin1String(
"SWF"))
2832 m_mimeType = QLatin1String(
"application/x-shockwave-flash");
2833 else if (ext == QLatin1String(
"PLS"))
2835 else if (ext == QLatin1String(
"WMV"))
2836 m_mimeType = QLatin1String(
"video/x-ms-wmv");
2837 else if (ext == QLatin1String(
"WEBM"))
2839 else if (ext == QLatin1String(
"DEB"))
2840 m_mimeType = QLatin1String(
"application/x-deb");
2854 if (
m_mimeType == QLatin1String(
"application/x-tar")) {
2856 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2857 }
else if (
m_mimeType == QLatin1String(
"application/postscript")) {
2861 m_mimeType = QLatin1String(
"application/x-gzpostscript");
2866 m_mimeType != QLatin1String(
"application/x-compressed-tar") &&
2867 m_mimeType != QLatin1String(
"application/x-tgz") &&
2868 m_mimeType != QLatin1String(
"application/x-targz") &&
2869 m_mimeType != QLatin1String(
"application/x-gzip"))) {
2873 m_mimeType = QLatin1String(
"application/x-gzip");
2885 m_mimeType = QLatin1String(
"application/x-bzip");
2892 static bool consume(
const char input[],
int *pos,
int end,
const char *term)
2896 if (idx + (
int)strlen(term) >= end) {
2900 if (strncasecmp(&input[idx], term, strlen(term)) == 0) {
2901 *pos = idx + strlen(term);
2925 bool upgradeRequired =
false;
2929 bool noHeadersFound =
false;
2934 static const int maxHeaderSize = 128 * 1024;
2936 char buffer[maxHeaderSize];
2938 bool bCanResume =
false;
2941 kDebug(7113) <<
"No connection.";
2951 kDebug(7113) <<
"Got socket error:" <<
socket()->errorString();
2960 if (!foundDelimiter && bufPos < maxHeaderSize) {
2961 kDebug(7113) <<
"EOF while waiting for header start.";
2978 kDebug(7113) <<
"Connection broken !";
2982 if (!foundDelimiter) {
2987 kDebug(7103) <<
"============ Received Status Response:";
2988 kDebug(7103) << QByteArray(buffer, bufPos).trimmed();
2993 if (idx != bufPos && buffer[idx] ==
'<') {
2994 kDebug(7103) <<
"No valid HTTP header found! Document starts with XML/HTML tag";
3000 noHeadersFound =
true;
3007 if (
consume(buffer, &idx, bufPos,
"ICY ")) {
3010 }
else if (
consume(buffer, &idx, bufPos,
"HTTP/")) {
3011 if (
consume(buffer, &idx, bufPos,
"1.0")) {
3014 }
else if (
consume(buffer, &idx, bufPos,
"1.1")) {
3019 if (httpRev ==
HTTP_None && bufPos != 0) {
3022 kDebug(7113) <<
"DO NOT WANT." << bufPos;
3030 noHeadersFound =
true;
3041 if (idx != bufPos) {
3057 messageBox(WarningYesNo,
3058 i18nc(
"@info Security check on url being accessed",
3059 "<p>You are about to log in to the site \"%1\" "
3060 "with the username \"%2\", but the website "
3061 "does not require authentication. "
3062 "This may be an attempt to trick you.</p>"
3063 "<p>Is \"%1\" the site you want to visit?</p>",
3065 i18nc(
"@title:window",
"Confirm Website Access"));
3070 setMetaData(QLatin1String(
"{internal~currenthost}LastSpoofedUserName"),
m_request.
url.
user());
3092 upgradeRequired =
true;
3114 setMetaData(QLatin1String(
"permanent-redirect"), QLatin1String(
"true"));
3119 setMetaData(QLatin1String(
"redirect-to-get"), QLatin1String(
"true"));
3125 setMetaData(QLatin1String(
"redirect-to-get"), QLatin1String(
"true"));
3129 setMetaData(QLatin1String(
"permanent-redirect"), QLatin1String(
"true"));
3155 infoMessage(
i18n(
"Server processing request, please wait..." ) );
3164 bool authRequiresAnotherRoundtrip =
false;
3167 if (!noHeadersFound) {
3172 kDebug(7113) <<
"wasAuthError=" << wasAuthError <<
"isAuthError=" << isAuthError
3173 <<
"sameAuthError=" << sameAuthError;
3185 kDebug(7113) <<
" -- full response:" << endl << QByteArray(buffer, bufPos).trimmed();
3188 Q_ASSERT(foundDelimiter);
3195 tokenizer.
tokenize(idx,
sizeof(buffer));
3200 if (tIt.
hasNext() && tIt.
next().toLower().startsWith(
"none")) {
3204 tIt = tokenizer.iterator(
"keep-alive");
3206 QByteArray ka = tIt.
next().trimmed().toLower();
3207 if (ka.startsWith(
"timeout=")) {
3208 int ka_timeout = ka.mid(qstrlen(
"timeout=")).trimmed().toInt();
3220 tIt = tokenizer.iterator(
"content-length");
3225 tIt = tokenizer.iterator(
"content-location");
3227 setMetaData(QLatin1String(
"content-location"),
toQString(tIt.
next().trimmed()));
3233 tIt = tokenizer.iterator(
"content-type");
3239 if (
m_mimeType.startsWith(QLatin1Char(
'"'))) {
3251 Q_FOREACH (
const QByteArray &statement, l) {
3252 const int index = statement.indexOf(
'=');
3254 mediaAttribute =
toQString(statement.mid(0, index));
3256 mediaAttribute =
toQString(statement.mid(0, index));
3257 mediaValue =
toQString(statement.mid(index+1));
3259 mediaAttribute = mediaAttribute.trimmed();
3260 mediaValue = mediaValue.trimmed();
3262 bool quoted =
false;
3263 if (mediaValue.startsWith(QLatin1Char(
'"'))) {
3265 mediaValue.remove(0, 1);
3268 if (mediaValue.endsWith(QLatin1Char(
'"'))) {
3272 kDebug (7113) <<
"Encoding-type:" << mediaAttribute <<
"=" << mediaValue;
3274 if (mediaAttribute == QLatin1String(
"charset")) {
3275 mediaValue = mediaValue.toLower();
3277 setMetaData(QLatin1String(
"charset"), mediaValue);
3279 setMetaData(QLatin1String(
"media-") + mediaAttribute, mediaValue);
3281 setMetaData(QLatin1String(
"media-") + mediaAttribute + QLatin1String(
"-kio-quoted"),
3282 QLatin1String(
"true"));
3289 tIt = tokenizer.iterator(
"content-encoding");
3307 tIt = tokenizer.iterator(
"content-disposition");
3311 tIt = tokenizer.iterator(
"content-language");
3314 if (!language.isEmpty()) {
3315 setMetaData(QLatin1String(
"content-language"), language);
3319 tIt = tokenizer.iterator(
"proxy-connection");
3321 QByteArray pc = tIt.
next().toLower();
3322 if (pc.startsWith(
"close")) {
3324 }
else if (pc.startsWith(
"keep-alive")) {
3329 tIt = tokenizer.iterator(
"link");
3333 if (link.count() == 2) {
3334 QString rel = link[1].trimmed();
3335 if (rel.startsWith(QLatin1String(
"rel=\""))) {
3336 rel = rel.mid(5, rel.length() - 6);
3337 if (rel.toLower() == QLatin1String(
"pageservices")) {
3339 QString url = link[0].remove(QRegExp(QLatin1String(
"[<>]"))).trimmed();
3340 setMetaData(QLatin1String(
"PageServices"), url);
3346 tIt = tokenizer.iterator(
"p3p");
3352 .split(QLatin1Char(
'='), QString::SkipEmptyParts);
3353 if (policy.count() == 2) {
3354 if (policy[0].toLower() == QLatin1String(
"policyref")) {
3355 policyrefs << policy[1].remove(QRegExp(QLatin1String(
"[\")\']"))).trimmed();
3356 }
else if (policy[0].toLower() == QLatin1String(
"cp")) {
3360 const QString s = policy[1].remove(QRegExp(QLatin1String(
"[\")\']")));
3361 const QStringList cps = s.split(QLatin1Char(
' '), QString::SkipEmptyParts);
3366 if (!policyrefs.isEmpty()) {
3367 setMetaData(QLatin1String(
"PrivacyPolicy"), policyrefs.join(QLatin1String(
"\n")));
3369 if (!compact.isEmpty()) {
3370 setMetaData(QLatin1String(
"PrivacyCompactPolicy"), compact.join(QLatin1String(
"\n")));
3377 tIt = tokenizer.iterator(
"connection");
3379 QByteArray connection = tIt.
next().toLower();
3381 if (connection.startsWith(
"close")) {
3383 }
else if (connection.startsWith(
"keep-alive")) {
3387 if (connection.startsWith(
"upgrade")) {
3390 upgradeRequired =
true;
3391 }
else if (upgradeRequired) {
3397 tIt = tokenizer.iterator(
"transfer-encoding");
3406 tIt = tokenizer.iterator(
"content-md5");
3413 tIt = tokenizer.iterator(
"dav");
3423 tIt = tokenizer.iterator(
"upgrade");
3427 upgradeOffers = offered.split(QRegExp(QLatin1String(
"[ \n,\r\t]")), QString::SkipEmptyParts);
3429 Q_FOREACH (
const QString &opt, upgradeOffers) {
3430 if (opt == QLatin1String(
"TLS/1.0")) {
3431 if (!
startSsl() && upgradeRequired) {
3435 }
else if (opt == QLatin1String(
"HTTP/1.1")) {
3437 }
else if (upgradeRequired) {
3445 QByteArray cookieStr;
3446 tIt = tokenizer.iterator(
"set-cookie");
3448 cookieStr +=
"Set-Cookie: ";
3449 cookieStr += tIt.
next();
3452 if (!cookieStr.isEmpty()) {
3457 cookieStr =
"Cross-Domain\n" + cookieStr;
3462 setMetaData(QLatin1String(
"setcookies"), QString::fromUtf8(cookieStr));
3470 kDebug(7113) <<
"cont; returning to mark try_again";
3476 kDebug(7113) <<
"Ignoring keep-alive: otherwise unable to determine response body length.";
3491 authRequiresAnotherRoundtrip =
false;
3496 tIt = tokenizer.iterator(
"location");
3498 locationStr = QString::fromUtf8(tIt.
next().trimmed());
3501 if (!locationStr.isEmpty())
3528 if(u.
protocol() == QLatin1String(
"http")){
3530 }
else if(u.
protocol() == QLatin1String(
"https")){
3570 kDebug(7113) <<
"Reading resource from cache even though the cache plan is not "
3571 "UseCached; the server is probably sending wrong expiry information.";
3581 int nextLinePos = 0;
3582 int prevLinePos = 0;
3583 bool haveMore =
true;
3585 haveMore =
nextLine(buffer, &nextLinePos, bufPos);
3586 int prevLineEnd = nextLinePos;
3587 while (buffer[prevLineEnd - 1] ==
'\r' || buffer[prevLineEnd - 1] ==
'\n') {
3592 prevLineEnd - prevLinePos));
3593 prevLinePos = nextLinePos;
3620 return !authRequiresAnotherRoundtrip;
3628 while (i != parameters.constEnd()) {
3629 setMetaData(QLatin1String(
"content-disposition-") + i.key(), i.value());
3630 kDebug(7113) <<
"Content-Disposition:" << i.key() <<
"=" << i.value();
3637 QString encoding = _encoding.trimmed().toLower();
3639 if (encoding == QLatin1String(
"identity")) {
3641 }
else if (encoding == QLatin1String(
"8bit")) {
3644 }
else if (encoding == QLatin1String(
"chunked")) {
3649 }
else if ((encoding == QLatin1String(
"x-gzip")) || (encoding == QLatin1String(
"gzip"))) {
3650 encs.append(QLatin1String(
"gzip"));
3651 }
else if ((encoding == QLatin1String(
"x-bzip2")) || (encoding == QLatin1String(
"bzip2"))) {
3652 encs.append(QLatin1String(
"bzip2"));
3653 }
else if ((encoding == QLatin1String(
"x-deflate")) || (encoding == QLatin1String(
"deflate"))) {
3654 encs.append(QLatin1String(
"deflate"));
3656 kDebug(7113) <<
"Unknown encoding encountered. "
3657 <<
"Please write code. Encoding =" << encoding;
3675 const qint64 currentDate = QDateTime::currentMSecsSinceEpoch()/1000;
3691 tIt = tokenizer.iterator(
"date");
3698 tIt = tokenizer.iterator(
"age");
3700 ageHeader = tIt.
next().toLongLong();
3704 if (dateHeader != -1) {
3706 }
else if (ageHeader) {
3713 bool hasCacheDirective =
false;
3718 tIt = tokenizer.iterator(
"cache-control");
3720 QByteArray cacheStr = tIt.
next().toLower();
3721 if (cacheStr.startsWith(
"no-cache") || cacheStr.startsWith(
"no-store")) {
3724 hasCacheDirective =
true;
3725 }
else if (cacheStr.startsWith(
"max-age=")) {
3726 QByteArray ba = cacheStr.mid(qstrlen(
"max-age=")).trimmed();
3728 maxAgeHeader = ba.toLongLong(&ok);
3730 hasCacheDirective =
true;
3735 qint64 expiresHeader = -1;
3736 tIt = tokenizer.iterator(
"expires");
3739 kDebug(7113) <<
"parsed expire date from 'expires' header:" << tIt.
current();
3744 }
else if (expiresHeader != -1) {
3753 expAge = qMin(expAge,
qint64(3600 * 24));
3766 tIt = tokenizer.iterator(
"etag");
3771 kDebug(7103) <<
"304 Not Modified but new entity tag - I don't think this is legal HTTP.";
3776 tIt = tokenizer.iterator(
"warning");
3784 tIt = tokenizer.iterator(
"pragma");
3786 if (tIt.
next().toLower().startsWith(
"no-cache")) {
3788 hasCacheDirective =
true;
3793 tIt = tokenizer.iterator(
"refresh");
3796 setMetaData(QLatin1String(
"http-refresh"),
toQString(tIt.
next().trimmed()));
3800 if (
m_mimeType.startsWith(QLatin1String(
"text/")) && (
m_mimeType != QLatin1String(
"text/css")) &&
3801 (
m_mimeType != QLatin1String(
"text/x-javascript")) && !hasCacheDirective) {
3812 kDebug(7113) <<
"Cache needs validation";
3814 kDebug(7113) <<
"...was revalidated by response code but not by updated expire times. "
3815 "We're going to set the expire date to 60 seconds in the future...";
3821 kDebug(7113) <<
"this proxy or server apparently sends bogus expiry information.";
3838 kDebug(7113) <<
"This webserver is confused about the cacheability of the data it sends.";
3852 if (!cachingAllowed) {
3853 setMetaData(QLatin1String(
"no-cache"), QLatin1String(
"true"));
3854 setMetaData(QLatin1String(
"expire-date"), QLatin1String(
"1"));
3858 setMetaData(QLatin1String(
"expire-date"), tmp);
3861 setMetaData(QLatin1String(
"cache-creation-date"), tmp);
3869 QByteArray cLength (
"Content-Length: ");
3870 cLength += QByteArray::number(
m_POSTbuf->size());
3871 cLength +=
"\r\n\r\n";
3873 kDebug(7113) <<
"sending cached data (size=" <<
m_POSTbuf->size() <<
")";
3876 bool sendOk = (
write(cLength.data(), cLength.size()) == (ssize_t) cLength.size());
3878 kDebug( 7113 ) <<
"Connection broken when sending "
3890 sendOk = (
write(buffer.data(), buffer.size()) == (ssize_t) buffer.size());
3892 kDebug(7113) <<
"Connection broken when sending message body: ("
3923 QByteArray cLength (
"Content-Length: ");
3925 cLength +=
"\r\n\r\n";
3927 kDebug(7113) << cLength.trimmed();
3930 bool sendOk = (
write(cLength.data(), cLength.size()) == (ssize_t) cLength.size());
3940 kDebug(7113) <<
"Connection broken while sending POST content size to" <<
m_request.
url.host();
3959 const int bytesRead = readData(buffer);
3962 if (bytesRead == 0) {
3968 if (bytesRead < 0) {
3982 if (
write(buffer.data(), bytesRead) == static_cast<ssize_t>(bytesRead)) {
3983 bytesSent += bytesRead;
3984 processedSize(bytesSent);
3988 kDebug(7113) <<
"Connection broken while sending POST content to" <<
m_request.
url.host();
3998 kDebug(7113) <<
"keepAlive =" << keepAlive;
4014 QDataStream stream( &data, QIODevice::WriteOnly );
4036 setTimeoutSpecialCommand(-1);
4073 QDataStream stream(data);
4081 stream >> url >> size;
4090 stream >> url >> no_cache >> expireDate;
4096 QFile::remove(filename);
4117 stream >> url >> scope >> type >> owner;
4118 davLock( url, scope, type, owner );
4133 stream >> url >> method >> size;
4134 davGeneric( url, (KIO::HTTP_METHOD) method, size );
4163 if (foundCrLf && bufPos == 2) {
4170 kDebug(7113) <<
"Failed to read chunk header.";
4173 Q_ASSERT(bufPos > 2);
4176 if (nextChunkSize < 0)
4178 kDebug(7113) <<
"Negative chunk size";
4195 int trashBufPos = 2;
4198 if (trashBufPos > 3) {
4200 for (
int i = 0; i < 3; i++) {
4201 trash[i] = trash[trashBufPos - 3 + i];
4208 kDebug(7113) <<
"Failed to read chunk trailer.";
4220 return bytesReceived;
4238 if (bytesReceived <= 0)
4242 return bytesReceived;
4249 kDebug(7113) <<
"Unbounded datastream on a Keep-alive connection!";
4289 kDebug(7113) <<
"Determining mime-type from content...";
4303 if( mime && !mime->isDefault() )
4384 if ( !dataInternal ) {
4395 kDebug(7113) <<
"reading data from cache...";
4407 if (!dataInternal) {
4414 if (!dataInternal) {
4442 QObject::connect(&chain, SIGNAL(
output(QByteArray)),
4452 if ( enc == QLatin1String(
"gzip") )
4454 else if ( enc == QLatin1String(
"deflate") )
4482 if ( enc == QLatin1String(
"gzip") )
4484 else if ( enc == QLatin1String(
"deflate") )
4503 if (bytesReceived == -1)
4513 kDebug(7113) <<
"bytesReceived==-1 sz=" << (int)sz
4514 <<
" Connection broken !";
4521 if (bytesReceived > 0)
4532 sz += bytesReceived;
4534 processedSize( sz );
4558 kWarning(7113) <<
"MD5 checksum MISMATCH! Expected:"
4567 if (!dataInternal && sz <= 1)
4580 data( QByteArray() );
4608 SlaveBase::error( _err, _text );
4616 QDBusInterface kcookiejar( QLatin1String(
"org.kde.kded"), QLatin1String(
"/modules/kcookiejar"), QLatin1String(
"org.kde.KCookieServer") );
4617 (void)kcookiejar.call( QDBus::NoBlock, QLatin1String(
"addCookies"), url,
4618 cookieHeader, windowId );
4624 QDBusInterface kcookiejar( QLatin1String(
"org.kde.kded"), QLatin1String(
"/modules/kcookiejar"), QLatin1String(
"org.kde.KCookieServer") );
4625 QDBusReply<QString> reply = kcookiejar.call( QLatin1String(
"findCookies"), url, windowId );
4627 if ( !reply.isValid() )
4629 kWarning(7113) <<
"Can't communicate with kded_kcookiejar!";
4658 qint64 currentDate = QDateTime::currentMSecsSinceEpoch()/1000;
4671 struct BinaryCacheFileHeader
4683 static const int size = 36;
4695 BinaryCacheFileHeader
header;
4704 QDataStream stream(&ret, QIODevice::WriteOnly);
4705 stream << quint8(
'A');
4706 stream << quint8(
'\n');
4707 stream << quint8(0);
4708 stream << quint8(0);
4710 stream << fileUseCount;
4711 stream << servedDate;
4712 stream << lastModifiedDate;
4713 stream << expireDate;
4715 stream << bytesCached;
4716 Q_ASSERT(ret.size() == BinaryCacheFileHeader::size);
4724 return byte == value;
4733 if (d.size() != BinaryCacheFileHeader::size) {
4736 QDataStream stream(d);
4737 stream.setVersion(QDataStream::Qt_4_5);
4748 stream >> fileUseCount;
4749 stream >> servedDate;
4750 stream >> lastModifiedDate;
4751 stream >> expireDate;
4752 stream >> bytesCached;
4777 static const char linefeed =
'\n';
4779 dev->write(&linefeed, 1);
4786 Q_ASSERT(file->openMode() & QIODevice::WriteOnly);
4788 file->seek(BinaryCacheFileHeader::size);
4802 if (line->isEmpty() || !line->endsWith(
'\n')) {
4814 Q_ASSERT(file->openMode() == QIODevice::ReadOnly);
4818 if (
storableUrl(desiredUrl).toEncoded() != readBuf) {
4819 kDebug(7103) <<
"You have witnessed a very improbable hash collision!";
4833 Q_ASSERT(file->openMode() == QIODevice::ReadOnly);
4839 qint64 oldPos = file->pos();
4840 file->seek(BinaryCacheFileHeader::size);
4843 Q_ASSERT(file->pos() == oldPos);
4852 if (ok && !readBuf.isEmpty()) {
4863 QCryptographicHash hash(QCryptographicHash::Sha1);
4865 return toQString(hash.result().toHex());
4871 if (!filePath.endsWith(QLatin1Char(
'/'))) {
4872 filePath.append(QLatin1Char(
'/'));
4885 kDebug(7113) <<
"File unexpectedly open; old file is" << file->fileName()
4886 <<
"new name is" << filename;
4887 Q_ASSERT(file->fileName() == filename);
4890 file =
new QFile(filename);
4891 if (file->open(QIODevice::ReadOnly)) {
4892 QByteArray
header = file->read(BinaryCacheFileHeader::size);
4894 kDebug(7103) <<
"Cache file header is invalid.";
4904 if (!file->isOpen()) {
4922 Q_ASSERT(!qobject_cast<QTemporaryFile *>(file));
4923 Q_ASSERT((file->openMode() & QIODevice::WriteOnly) == 0);
4924 Q_ASSERT(file->fileName() == filename);
4925 kDebug(7113) <<
"deleting expired cache entry and recreating.";
4933 file->open(QIODevice::WriteOnly);
4939 if ((file->openMode() & QIODevice::WriteOnly) == 0) {
4940 kDebug(7113) <<
"Could not open file for writing:" << file->fileName()
4941 <<
"due to error" << file->error();
4952 QDataStream stream(&ret, QIODevice::WriteOnly);
4953 stream.setVersion(QDataStream::Qt_4_5);
4955 stream.skipRawData(BinaryCacheFileHeader::size);
4960 int basenameStart = fileName.lastIndexOf(QLatin1Char(
'/')) + 1;
4962 stream.writeRawData(baseName.constData(), baseName.size());
4964 Q_ASSERT(ret.size() == BinaryCacheFileHeader::size +
sizeof(quint32) +
s_hashedUrlNibbles);
4980 QByteArray ccCommand;
4983 if (file->openMode() & QIODevice::WriteOnly) {
4989 tempFile->write(header);
4993 QString oldName = tempFile->fileName();
4995 int basenameStart = newName.lastIndexOf(QLatin1Char(
'/')) + 1;
4998 kDebug(7113) <<
"Renaming temporary file" << oldName <<
"to" << newName;
5001 tempFile->setAutoRemove(
false);
5005 if (!QFile::rename(oldName, newName)) {
5008 kDebug(7113) <<
"Renaming temporary file failed, deleting it instead.";
5009 QFile::remove(oldName);
5016 }
else if (file->openMode() == QIODevice::ReadOnly) {
5017 Q_ASSERT(!tempFile);
5023 if (!ccCommand.isEmpty()) {
5034 if (attempts == 2) {
5048 kDebug(7113) <<
"Could not connect to cache cleaner, not updating stats of this cache file.";
5058 if (ret.isEmpty()) {
5075 kDebug(7113) <<
"Caching disabled because content size is too big.";
5105 m_POSTbuf->write (data.constData(), data.size());
5131 const int bytesRead = readData(buffer);
5133 if (bytesRead < 0) {
5138 if (bytesRead == 0) {
5142 m_POSTbuf->write(buffer.constData(), buffer.size());
5170 if (useCachedAuth && checkCachedAuthentication(authinfo)) {
5171 const QByteArray cachedChallenge =
config()->readEntry(
"www-auth-challenge", QByteArray());
5172 if (!cachedChallenge.isEmpty()) {
5175 kDebug(7113) <<
"creating www authentcation header from cached info";
5193 if (checkCachedAuthentication(authinfo)) {
5194 const QByteArray cachedChallenge =
config()->readEntry(
"proxy-auth-challenge", QByteArray());
5195 if (!cachedChallenge.isEmpty()) {
5198 kDebug(7113) <<
"creating proxy authentcation header from cached info";
5208 ret +=
"Authorization: ";
5213 ret +=
"Proxy-Authorization: ";
5223 case QNetworkProxy::DefaultProxy:
5225 case QNetworkProxy::Socks5Proxy:
5226 return QLatin1String(
"socks");
5227 case QNetworkProxy::NoProxy:
5229 case QNetworkProxy::HttpProxy:
5230 case QNetworkProxy::HttpCachingProxy:
5231 case QNetworkProxy::FtpCachingProxy:
5236 return QLatin1String(
"http");
5241 kDebug(7113) <<
"realm:" << authenticator->realm() <<
"user:" << authenticator->user();
5252 info.
username = authenticator->user();
5255 const bool haveCachedCredentials = checkCachedAuthentication(info);
5260 if (!haveCachedCredentials || retryAuth) {
5263 connect(
socket(), SIGNAL(connected()),
5266 info.
prompt =
i18n(
"You need to supply a username and a password for "
5267 "the proxy server listed below before you are allowed "
5268 "to access any sites.");
5273 const QString errMsg ((retryAuth ?
i18n(
"Proxy Authentication Failed.") :
QString()));
5275 if (!openPasswordDialog(info, errMsg)) {
5276 kDebug(7113) <<
"looks like the user canceled proxy authentication.";
5283 authenticator->setUser(info.
username);
5284 authenticator->setPassword(info.
password);
5285 authenticator->setOption(QLatin1String(
"keepalive"), info.
keepPassword);
5300 kDebug(7113) <<
"Saving authenticator";
5301 disconnect(
socket(), SIGNAL(connected()),
5313 cacheAuthentication(a);
5322 bool alreadyCached =
false;
5327 alreadyCached =
config()->readEntry(
"cached-www-auth",
false);
5331 alreadyCached =
config()->readEntry(
"cached-proxy-auth",
false);
5338 if (auth && (!auth->
realm().isEmpty() || !alreadyCached)) {
5341 setMetaData(QLatin1String(
"{internal~currenthost}cached-www-auth"), QLatin1String(
"true"));
5343 setMetaData(QLatin1String(
"{internal~currenthost}www-auth-realm"), authinfo.
realmValue);
5345 setMetaData(QLatin1String(
"{internal~currenthost}www-auth-challenge"), authinfo.
digestInfo);
5347 setMetaData(QLatin1String(
"{internal~allhosts}cached-proxy-auth"), QLatin1String(
"true"));
5349 setMetaData(QLatin1String(
"{internal~allhosts}proxy-auth-realm"), authinfo.
realmValue);
5351 setMetaData(QLatin1String(
"{internal~allhosts}proxy-auth-challenge"), authinfo.
digestInfo);
5357 cacheAuthentication(authinfo);
5373 authTokens = tokenizer->iterator(
"www-authenticate").all();
5376 authinfo.
prompt =
i18n(
"You need to supply a username and a "
5377 "password to access this site.");
5383 Q_ASSERT(QNetworkProxy::applicationProxy().type() == QNetworkProxy::NoProxy);
5385 authTokens = tokenizer->iterator(
"proxy-authenticate").all();
5388 authinfo.
prompt =
i18n(
"You need to supply a username and a password for "
5389 "the proxy server listed below before you are allowed "
5390 "to access any sites." );
5394 bool authRequiresAnotherRoundtrip =
false;
5399 if (!authTokens.isEmpty()) {
5401 authRequiresAnotherRoundtrip =
true;
5405 if ((*auth)->wasFinalStage()) {
5407 i18n(
"Authentication Failed.") :
5408 i18n(
"Proxy Authentication Failed."));
5416 QMutableListIterator<QByteArray> it (authTokens);
5417 const QByteArray authScheme ((*auth)->scheme().trimmed());
5418 while (it.hasNext()) {
5419 if (qstrnicmp(authScheme.constData(), it.next().constData(), authScheme.length()) != 0) {
5426 try_next_auth_scheme:
5429 const QByteArray authScheme ((*auth)->scheme().trimmed());
5430 if (qstrnicmp(authScheme.constData(), bestOffer.constData(), authScheme.length()) != 0) {
5442 kDebug(7113) <<
"Trying authentication scheme:" << (*auth)->scheme();
5448 bool generateAuthHeader =
true;
5449 if ((*auth)->needCredentials()) {
5460 if (authinfo.
realmValue.isEmpty() && !(*auth)->supportsPathMatching())
5461 authinfo.
realmValue = QLatin1String((*auth)->scheme());
5466 const KUrl reqUrl = authinfo.
url;
5467 if (!errorMsg.isEmpty() || !checkCachedAuthentication(authinfo)) {
5469 authinfo.
url = reqUrl;
5474 if (!openPasswordDialog(authinfo, errorMsg)) {
5475 generateAuthHeader =
false;
5476 authRequiresAnotherRoundtrip =
false;
5480 kDebug(7113) <<
"looks like the user canceled the authentication dialog";
5490 if (generateAuthHeader) {
5491 (*auth)->generateResponse(username, password);
5492 (*auth)->setCachePasswordEnabled(authinfo.
keepPassword);
5494 kDebug(7113) <<
"isError=" << (*auth)->isError()
5495 <<
"needCredentials=" << (*auth)->needCredentials()
5496 <<
"forceKeepAlive=" << (*auth)->forceKeepAlive()
5497 <<
"forceDisconnect=" << (*auth)->forceDisconnect();
5499 if ((*auth)->isError()) {
5500 authTokens.removeOne(bestOffer);
5501 if (!authTokens.isEmpty()) {
5502 goto try_next_auth_scheme;
5505 authRequiresAnotherRoundtrip =
false;
5508 }
else if ((*auth)->forceKeepAlive()) {
5511 }
else if ((*auth)->forceDisconnect()) {
5518 authRequiresAnotherRoundtrip =
false;
5525 return authRequiresAnotherRoundtrip;
#define DEFAULT_RESPONSE_TIMEOUT
#define DEFAULT_KEEP_ALIVE_TIMEOUT
void cachePostData(const QByteArray &)
Caches the POST data in a temporary buffer.
static KAbstractHttpAuthentication * newAuth(const QByteArray &offer, KConfigGroup *config=0)
Returns authentication object instance appropriate for offer.
QString i18n(const char *text)
quint16 defaultPort() const
void adjustPath(AdjustPathOption trailing)
bool m_davHostUnsupported
void davStatList(const KUrl &url, bool stat=true)
void cacheParseResponseHeader(const HeaderTokenizer &tokenizer)
KAutostart::StartPhase readEntry(const KConfigGroup &group, const char *key, const KAutostart::StartPhase &aDefault)
void fixupResponseMimetype()
fix common mimetype errors by webservers.
QString findCookies(const QString &url)
Look for cookies in the cookiejar.
QByteArray methodString() const
int readLimited()
Read maximum m_iSize bytes.
virtual void mkdir(const KUrl &url, int _permissions)
bool sendErrorPageNotification()
Call SlaveBase::errorPage() and remember that we've called it.
void parseContentDisposition(const QString &disposition)
bool cacheFileOpenWrite()
void slotInput(const QByteArray &d)
void saveAuthenticationData()
Saves HTTP authentication data.
static int httpDelError(const HTTPProtocol::HTTPRequest &request, QString *errorString)
static QString decode_string(const QString &str)
static bool nextLine(const char input[], int *pos, int end)
#define DEFAULT_HTTP_PORT
virtual void copy(const KUrl &src, const KUrl &dest, int _permissions, KIO::JobFlags flags)
bool m_isChunked
Chunked transfer encoding.
void setCacheabilityMetadata(bool cachingAllowed)
void insert(uint field, const QString &value)
long m_maxCacheSize
Maximum cache size in Kb.
bool readResponseHeader()
This function will read in the return header from the server.
bool sendQuery()
This function is responsible for opening up the connection to the remote HTTP server and sending the ...
QByteArray sentMethodString
void httpCloseConnection()
Close connection.
bool m_isRedirection
Indicates current request is a redirection.
bool readDelimitedText(char *buf, int *idx, int end, int numNewlines)
QString m_strCacheDir
Location of the cache.
const char * name(StandardAction id)
QLocalSocket m_cacheCleanerConnection
Connection to the cache cleaner process.
static KDateTime fromString(const QString &string, TimeFormat format=ISODate, bool *negZero=0)
The request for the current connection.
void setRef(const QString &fragment)
QByteArray cacheFileReadPayload(int maxLength)
static bool supportedProxyScheme(const QString &scheme)
void setEncodedPathAndQuery(const QString &_txt)
QString toString(const QString &format) const
static bool isEncryptedHttpVariety(const QByteArray &p)
static bool isHttpProxy(const KUrl &u)
KIO::filesize_t m_iPostDataSize
virtual void closeConnection()
Forced close of connection.
QString cacheFilePathFromUrl(const KUrl &url) const
#define DEFAULT_MAX_CACHE_SIZE
bool maybeSetRequestUrl(const KUrl &)
QByteArray m_receiveBuf
Receive buffer.
bool connectToHost(const QString &protocol, const QString &host, quint16 port)
static bool canHaveResponseBody(int responseCode, KIO::HTTP_METHOD method)
virtual void get(const KUrl &url)
#define DEFAULT_CACHE_EXPIRE
QString methodStringOverride
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
void davSetRequest(const QByteArray &requestXML)
Performs a WebDAV stat or list.
static KUrl storableUrl(const KUrl &url)
static void updateUDSEntryMimeType(UDSEntry *entry)
int kdemain(int argc, char **argv)
bool isOffline()
Check network status.
void setQuery(const QString &query)
KIO::filesize_t m_iBytesLeft
of bytes left to receive in this message.
QString i18nc(const char *ctxt, const char *text)
KSharedConfigPtr config()
void error(int errid, const QString &text)
#define DEFAULT_MIME_TYPE
void setPath(const QString &path)
virtual void put(const KUrl &url, int _mode, KIO::JobFlags flags)
unsigned int responseCode
static QString formatHttpDate(qint64 date)
static bool isCompatibleNextUrl(const KUrl &previous, const KUrl &now)
static QIODevice * createPostBufferDeviceFor(KIO::filesize_t size)
void setUser(const QString &user)
virtual void listDir(const KUrl &url)
void setTime_t(qint64 seconds)
bool sendHttpError()
Generate and send error message based on response code.
bool deserialize(const QByteArray &)
virtual void fillKioAuthInfo(KIO::AuthInfo *ai) const =0
KIO compatible data to find cached credentials.
QByteArray m_webDavDataBuf
QStringList m_responseHeaders
All headers.
int readUnlimited()
Read as much as possible.
void setProtocol(const QString &proto)
static QString sanitizeCustomHTTPHeader(const QString &_header)
QStringList m_contentEncodings
bool m_isLoadingErrorPage
static const int s_hashedUrlBits
static bool readLineChecked(QIODevice *dev, QByteArray *line)
int codeFromResponse(const QString &response)
Returns the error code from a "HTTP/1.1 code Code Name" string.
static QString filePath(const QString &baseName)
QString authenticationHeader()
create HTTP authentications response(s), if any
bool httpShouldCloseConnection()
Check whether to keep or close the connection.
#define DEFAULT_PARTIAL_CHARSET_HEADER
long long numberValue(uint field, long long defaultValue=0) const
QList< HTTPRequest > m_requestQueue
void multiGet(const QByteArray &data)
bool isUtf8(const char *str)
void output(QList< Action > actions, QHash< QString, QString > domain)
bool m_isBusy
Busy handling request queue.
static const int s_hashedUrlBytes
virtual void mimetype(const KUrl &url)
QAuthenticator * m_socketProxyAuth
bool satisfyRequestFromCache(bool *cacheHasPage)
Return true if the request is already "done", false otherwise.
virtual void setHost(const QString &host, quint16 port, const QString &user, const QString &pass)
QDateTime dateTime() const
void updateCredentials(const HTTPRequest &request)
KAbstractHttpAuthentication * m_wwwAuth
KIO::filesize_t endoffset
bool doNotWWWAuthenticate
static bool compareByte(QDataStream *stream, quint8 value)
void post(const KUrl &url, qint64 size=-1)
static QByteArray bestOffer(const QList< QByteArray > &offers)
Choose the best authentication mechanism from the offered ones.
void setPass(const QString &pass)
void fixupResponseContentEncoding()
fix common content-encoding errors by webservers.
bool parseHeaderFromCache()
enum HTTPProtocol::HTTPRequest::@1 cookieMode
QString stringValue(uint field) const
void davLock(const KUrl &url, const QString &scope, const QString &type, const QString &owner)
void setSocketOption(QAbstractSocket::SocketOption options, const QVariant &value)
static bool isValidProxy(const KUrl &u)
void resetResponseParsing()
Resets variables related to parsing a response.
void davGeneric(const KUrl &url, KIO::HTTP_METHOD method, qint64 size=-1)
#define DEFAULT_MAX_CACHE_AGE
static void skipSpace(const char input[], int *pos, int end)
CopyJob * link(const KUrl &src, const KUrl &destDir, JobFlags flags=DefaultFlags)
QByteArray headerFragment() const
insert this into the next request header after "Authorization: " or "Proxy-Authorization: " ...
void davUnlock(const KUrl &url)
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
int readChunked()
Read a chunk.
HTTPProtocol(const QByteArray &protocol, const QByteArray &pool, const QByteArray &app)
void disconnectFromHost()
void cacheFileWriteTextHeader()
void slotData(const QByteArray &)
virtual void generateResponse(const QString &user, const QString &password)=0
what to do in response to challenge
QByteArray current() const
bool proceedUntilResponseHeader()
Ensure we are connected, send our query, and get the response header.
KIO::CacheControl parseCacheControl(const QString &cacheControl)
static QString protocolForProxyType(QNetworkProxy::ProxyType type)
#define DEFAULT_HTTPS_PORT
static int httpPutError(const HTTPProtocol::HTTPRequest &request, QString *errorString)
static qint64 parseDateTime(const QString &input, const QString &type)
static const int s_hashedUrlNibbles
virtual void reparseConfiguration()
virtual void setChallenge(const QByteArray &c, const KUrl &resource, const QByteArray &httpMethod)
initiate authentication with challenge string (from HTTP header)
static int httpGenericError(const HTTPProtocol::HTTPRequest &request, QString *errorString)
bool retrieveAllData()
Returns true on successful retrieval of all content data.
QIODevice * socket() const
KIO::filesize_t m_iContentLeft
of content bytes left
void forwardHttpResponseHeader(bool forwardImmediately=true)
void resetSessionSettings()
Resets any per session settings.
void httpClose(bool keepAlive)
Close transfer.
QByteArray serialize() const
virtual void slave_status()
#define DEFAULT_LANGUAGE_HEADER
QString encodedPathAndQuery(AdjustPathOption trailing=LeaveTrailingSlash, const EncodedPathAndQueryOptions &options=PermitEmptyPath) const
bool handleAuthenticationHeader(const HeaderTokenizer *tokenizer)
Handles HTTP authentication.
void clearPostDataBuffer()
Clears the POST data buffer.
static QMap< QString, QString > contentDispositionParser(const QString &disposition)
bool readBody(bool dataInternal=false)
This function is our "receive" function.
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
unsigned int prevResponseCode
#define DEFAULT_ACCEPT_HEADER
static QString locateLocal(const char *type, const QString &filename, const KComponentData &cData=KGlobal::mainComponent())
void resetConnectionSettings()
Resets any per connection settings.
bool cacheFileReadTextHeader2()
load the rest of the text fields
bool cacheFileReadTextHeader1(const KUrl &desiredUrl)
check URL to guard against hash collisions, and load the etag for validation
static const int s_MaxInMemPostBufSize
virtual void rename(const KUrl &src, const KUrl &dest, KIO::JobFlags flags)
bool allowTransferCompression
static qint64 toTime_t(const QString &value, KDateTime::TimeFormat format)
void proxyAuthenticationForSocket(const QNetworkProxy &, QAuthenticator *)
bool httpOpenConnection()
Open connection.
QStringList m_davCapabilities
void davParseActiveLocks(const QDomNodeList &activeLocks, uint &lockCount)
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
void addFilter(HTTPFilterBase *filter)
static QString toQString(const QByteArray &value)
void saveProxyAuthenticationForSocket()
ssize_t write(const void *buf, size_t nbytes)
A thin wrapper around TCPSlaveBase::write() that will retry writing as long as no error occurs...
void unread(char *buf, size_t size)
QString formatRequestUri() const
virtual void stat(const KUrl &url)
static QString htmlEscape(const QString &plain)
virtual void del(const KUrl &url, bool _isfile)
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
QString davProcessLocks()
Extracts locks from metadata Returns the appropriate If: header.
virtual void special(const QByteArray &data)
Special commands supported by this slave : 1 - HTTP POST 2 - Cache has been updated 3 - SSL Certifica...
static QByteArray makeCacheCleanerCommand(const HTTPProtocol::CacheTag &cacheTag, CacheCleanerCommandCode cmd)
static QString filenameFromUrl(const KUrl &url)
QByteArray m_mimeTypeBuffer
CachePlan plan(int maxCacheAge) const
static void writeLine(QIODevice *dev, const QByteArray &line)
void davParsePropstats(const QDomNodeList &propstats, KIO::UDSEntry &entry)
size_t readBuffered(char *buf, size_t size, bool unlimited=true)
QString convertSize(KIO::filesize_t size)
#define DEFAULT_CACHE_CONTROL
static bool isPotentialSpoofingAttack(const HTTPProtocol::HTTPRequest &request, const KConfigGroup *config)
void addEncoding(const QString &, QStringList &)
Add an encoding on to the appropriate stack this is nececesary because transfer encodings and content...
void addCookies(const QString &url, const QByteArray &cookieHeader)
Send a cookie to the cookiejar.
static bool isCrossDomainRequest(const QString &fqdn, const QString &originURL)
static bool consume(const char input[], int *pos, int end, const char *term)
void sendCacheCleanerCommand(const QByteArray &command)
KIO::filesize_t m_iSize
Expected size of message.
T readEntry(const QString &key, const T &aDefault) const
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
static bool isAuthenticationRequired(int responseCode)
CopyJob * trash(const KUrl &src, JobFlags flags=DefaultFlags)
void initFrom(const HTTPRequest &request)
QString realm() const
Returns the realm sent by the server.
void cacheFileWritePayload(const QByteArray &d)
KAbstractHttpAuthentication * m_proxyAuth
bool m_dataInternal
Data is for internal consumption.
bool waitForResponse(int t)
void proceedUntilResponseContent(bool dataInternal=false)
Do everything proceedUntilResponseHeader does, and also get the response body.
QString number(KIO::filesize_t size)
QStringList m_transferEncodings
bool doNotProxyAuthenticate
int m_maxCacheAge
Maximum age of a cache entry in seconds.
void slotFilterError(const QString &text)
QString davError(int code=-1, const QString &url=QString())