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))
303 if (!methodStringOverride.isEmpty())
304 return (methodStringOverride + QLatin1Char(
' ')).toLatin1();
337 case DAV_UNSUBSCRIBE:
338 return "UNSUBSCRIBE ";
358 if (!dt.
time().second()) {
359 ret.append(QLatin1String(
":00"));
361 ret.append(QLatin1String(
" GMT"));
367 return (responseCode == 401) || (responseCode == 407);
370 #define NO_SIZE ((KIO::filesize_t) -1)
373 #define STRTOLL strtoll
375 #define STRTOLL strtol
383 const QByteArray &app )
391 , m_protocol(protocol)
394 , m_socketProxyAuth(0)
396 , m_isLoadingErrorPage(false)
398 , m_iEOFRetryCount(0)
402 connect(
socket(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
422 TCPSlaveBase::reparseConfiguration();
450 setMetaData(QLatin1String(
"request-id"),
m_request.
id);
465 const bool noAuth =
config()->readEntry(
"no-auth",
false);
475 kDebug(7113) <<
"ssl_was_in_use =" << metaData(QLatin1String(
"ssl_was_in_use"));
483 KUrl refUrl(metaData(QLatin1String(
"referrer")));
484 if (refUrl.isValid()) {
487 if (protocol.startsWith(QLatin1String(
"webdav"))) {
488 protocol.replace(0, 6, QLatin1String(
"http"));
492 if (protocol.startsWith(QLatin1String(
"http"))) {
498 if (
config()->readEntry(
"SendLanguageSettings",
true)) {
510 QString resumeOffset = metaData(QLatin1String(
"resume"));
511 if (!resumeOffset.isEmpty()) {
517 QString resumeEndOffset = metaData(QLatin1String(
"resume_until"));
518 if (!resumeEndOffset.isEmpty()) {
526 m_request.
id = metaData(QLatin1String(
"request-id"));
572 if (host.indexOf(QLatin1Char(
':')) == -1) {
575 int pos = host.indexOf(QLatin1Char(
'%'));
601 if (u.host().isEmpty()) {
606 if (u.
path().isEmpty()) {
608 newUrl.
setPath(QLatin1String(
"/"));
631 if (dataInternal || !status) {
690 setMetaData(QLatin1String(
"content-type"),
m_mimeType);
708 QString statSide = metaData(QLatin1String(
"statSide"));
709 if (statSide != QLatin1String(
"source"))
756 QString query = metaData(QLatin1String(
"davSearchQuery"));
757 if ( !query.isEmpty() )
759 QByteArray request =
"<?xml version=\"1.0\"?>\r\n";
760 request.append(
"<D:searchrequest xmlns:D=\"DAV:\">\r\n" );
761 request.append( query.toUtf8() );
762 request.append(
"</D:searchrequest>\r\n" );
768 request =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
769 "<D:propfind xmlns:D=\"DAV:\">";
772 if ( hasMetaData(QLatin1String(
"davRequestResponse")) )
773 request += metaData(QLatin1String(
"davRequestResponse")).toUtf8();
776 request +=
"<D:prop>"
778 "<D:getcontentlength/>"
781 "<D:getcontentlanguage/>"
782 "<D:getcontenttype/>"
783 "<D:getlastmodified/>"
790 request +=
"</D:propfind>";
804 infoMessage(QLatin1String(
""));
814 QDomDocument multiResponse;
817 bool hasResponse =
false;
821 for ( QDomNode n = multiResponse.documentElement().firstChild();
822 !n.isNull(); n = n.nextSibling()) {
823 QDomElement thisResponse = n.toElement();
824 if (thisResponse.isNull())
829 QDomElement href = thisResponse.namedItem(QLatin1String(
"href")).toElement();
830 if ( !href.isNull() ) {
833 QString urlStr = QUrl::fromPercentEncoding(href.text().toUtf8());
834 #if 0 // qt4/kde4 say: it's all utf8...
835 int encoding = remoteEncoding()->encodingMib();
839 KUrl thisURL ( urlStr, encoding );
841 KUrl thisURL( urlStr );
844 if ( thisURL.isValid() ) {
849 name = QLatin1Char(
'.');
854 QDomNodeList propstats = thisResponse.elementsByTagName(QLatin1String(
"propstat"));
864 KMimeType::Ptr mime = KMimeType::findByUrl(thisURL.
fileName(), 0,
false,
true, &accuracy);
865 if (mime && !mime->isDefault() && accuracy == 100) {
866 kDebug(7113) <<
"Setting" << mime->name() <<
"as guessed mime type for" << thisURL.
fileName();
878 listEntry( entry,
false );
880 kDebug(7113) <<
"Error: no URL contained in response to PROPFIND on" << url;
884 if ( stat || !hasResponse ) {
889 listEntry( entry,
true );
916 const int firstSpace = response.indexOf( QLatin1Char(
' ') );
917 const int secondSpace = response.indexOf( QLatin1Char(
' '), firstSpace + 1 );
918 return response.mid( firstSpace + 1, secondSpace - firstSpace - 1 ).toInt();
924 bool foundExecutable =
false;
925 bool isDirectory =
false;
927 uint supportedLockCount = 0;
929 for (
int i = 0; i < propstats.count(); i++)
931 QDomElement propstat = propstats.item(i).toElement();
933 QDomElement status = propstat.namedItem(QLatin1String(
"status")).toElement();
934 if ( status.isNull() )
937 kDebug(7113) <<
"Error, no status code in this propstat";
945 kDebug(7113) <<
"Got status code" << code <<
"(this may mean that some properties are unavailable)";
949 QDomElement prop = propstat.namedItem( QLatin1String(
"prop") ).toElement();
952 kDebug(7113) <<
"Error: no prop segment in this propstat.";
956 if ( hasMetaData( QLatin1String(
"davRequestResponse") ) )
959 doc.appendChild(prop);
963 for ( QDomNode n = prop.firstChild(); !n.isNull(); n = n.nextSibling() )
965 QDomElement
property = n.toElement();
966 if (property.isNull())
969 if ( property.namespaceURI() != QLatin1String(
"DAV:") )
975 if ( property.tagName() == QLatin1String(
"creationdate") )
980 else if ( property.tagName() == QLatin1String(
"getcontentlength") )
985 else if ( property.tagName() == QLatin1String(
"displayname") )
988 setMetaData( QLatin1String(
"davDisplayName"), property.text() );
990 else if ( property.tagName() == QLatin1String(
"source") )
993 QDomElement source =
property.namedItem( QLatin1String(
"link") ).toElement()
994 .namedItem( QLatin1String(
"dst") ).toElement();
995 if ( !source.isNull() )
996 setMetaData( QLatin1String(
"davSource"), source.text() );
998 else if ( property.tagName() == QLatin1String(
"getcontentlanguage") )
1001 setMetaData( QLatin1String(
"davContentLanguage"), property.text() );
1003 else if ( property.tagName() == QLatin1String(
"getcontenttype") )
1008 if ( property.text() == QLatin1String(
"httpd/unix-directory") )
1014 mimeType =
property.text();
1017 else if ( property.tagName() == QLatin1String(
"executable") )
1020 if ( property.text() == QLatin1String(
"T") )
1021 foundExecutable =
true;
1024 else if ( property.tagName() == QLatin1String(
"getlastmodified") )
1029 else if ( property.tagName() == QLatin1String(
"getetag") )
1032 setMetaData( QLatin1String(
"davEntityTag"), property.text() );
1034 else if ( property.tagName() == QLatin1String(
"supportedlock") )
1037 for ( QDomNode n2 = property.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
1039 QDomElement lockEntry = n2.toElement();
1040 if ( lockEntry.tagName() == QLatin1String(
"lockentry") )
1042 QDomElement lockScope = lockEntry.namedItem( QLatin1String(
"lockscope") ).toElement();
1043 QDomElement lockType = lockEntry.namedItem( QLatin1String(
"locktype") ).toElement();
1044 if ( !lockScope.isNull() && !lockType.isNull() )
1047 supportedLockCount++;
1048 const QString lockCountStr = QString::number(supportedLockCount);
1049 const QString scope = lockScope.firstChild().toElement().tagName();
1050 const QString type = lockType.firstChild().toElement().tagName();
1052 setMetaData( QLatin1String(
"davSupportedLockScope") + lockCountStr, scope );
1053 setMetaData( QLatin1String(
"davSupportedLockType") + lockCountStr, type );
1058 else if ( property.tagName() == QLatin1String(
"lockdiscovery") )
1061 davParseActiveLocks( property.elementsByTagName( QLatin1String(
"activelock") ), lockCount );
1063 else if ( property.tagName() == QLatin1String(
"resourcetype") )
1066 if ( !property.namedItem( QLatin1String(
"collection") ).toElement().isNull() )
1074 kDebug(7113) <<
"Found unknown webdav property:" <<
property.tagName();
1079 setMetaData( QLatin1String(
"davLockCount"), QString::number(lockCount) );
1080 setMetaData( QLatin1String(
"davSupportedLockCount"), QString::number(supportedLockCount) );
1084 if ( foundExecutable || isDirectory )
1094 if ( !isDirectory && !mimeType.isEmpty() )
1103 for (
int i = 0; i < activeLocks.count(); i++ )
1105 const QDomElement activeLock = activeLocks.item(i).toElement();
1109 const QDomElement lockScope = activeLock.namedItem( QLatin1String(
"lockscope") ).toElement();
1110 const QDomElement lockType = activeLock.namedItem( QLatin1String(
"locktype") ).toElement();
1111 const QDomElement lockDepth = activeLock.namedItem( QLatin1String(
"depth") ).toElement();
1113 const QDomElement lockOwner = activeLock.namedItem( QLatin1String(
"owner") ).toElement();
1114 const QDomElement lockTimeout = activeLock.namedItem( QLatin1String(
"timeout") ).toElement();
1115 const QDomElement lockToken = activeLock.namedItem( QLatin1String(
"locktoken") ).toElement();
1117 if ( !lockScope.isNull() && !lockType.isNull() && !lockDepth.isNull() )
1121 const QString lockCountStr = QString::number(lockCount);
1122 const QString scope = lockScope.firstChild().toElement().tagName();
1123 const QString type = lockType.firstChild().toElement().tagName();
1124 const QString depth = lockDepth.text();
1126 setMetaData( QLatin1String(
"davLockScope") + lockCountStr, scope );
1127 setMetaData( QLatin1String(
"davLockType") + lockCountStr, type );
1128 setMetaData( QLatin1String(
"davLockDepth") + lockCountStr, depth );
1130 if ( !lockOwner.isNull() )
1131 setMetaData( QLatin1String(
"davLockOwner") + lockCountStr, lockOwner.text() );
1133 if ( !lockTimeout.isNull() )
1134 setMetaData( QLatin1String(
"davLockTimeout") + lockCountStr, lockTimeout.text() );
1136 if ( !lockToken.isNull() )
1138 QDomElement tokenVal = lockScope.namedItem( QLatin1String(
"href") ).toElement();
1139 if ( !tokenVal.isNull() )
1140 setMetaData( QLatin1String(
"davLockToken") + lockCountStr, tokenVal.text() );
1148 if ( type == QLatin1String(
"dateTime.tz") )
1152 else if ( type == QLatin1String(
"dateTime.rfc1123") )
1167 if ( hasMetaData( QLatin1String(
"davLockCount") ) )
1169 QString response = QLatin1String(
"If:");
1170 int numLocks = metaData( QLatin1String(
"davLockCount") ).toInt();
1171 bool bracketsOpen =
false;
1172 for (
int i = 0; i < numLocks; i++ )
1174 const QString countStr = QString::number(i);
1175 if ( hasMetaData( QLatin1String(
"davLockToken") + countStr ) )
1177 if ( hasMetaData( QLatin1String(
"davLockURL") + countStr ) )
1181 response += QLatin1Char(
')');
1182 bracketsOpen =
false;
1184 response += QLatin1String(
" <") + metaData( QLatin1String(
"davLockURL") + countStr ) + QLatin1Char(
'>');
1187 if ( !bracketsOpen )
1189 response += QLatin1String(
" (");
1190 bracketsOpen =
true;
1194 response += QLatin1Char(
' ');
1197 if ( hasMetaData( QLatin1String(
"davLockNot") + countStr ) )
1198 response += QLatin1String(
"Not ");
1200 response += QLatin1Char(
'<') + metaData( QLatin1String(
"davLockToken") + countStr ) + QLatin1Char(
'>');
1205 response += QLatin1Char(
')');
1207 response += QLatin1String(
"\r\n");
1227 kDebug(7113) <<
" false";
1250 if (ok && verNo > 0 && verNo < 3)
1253 kDebug(7113) <<
"Server supports DAV version" << verNo;
1305 QString tmp(metaData(QLatin1String(
"cache")));
1330 const QByteArray request (
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1331 "<D:propfind xmlns:D=\"DAV:\"><D:prop>"
1333 "<D:getcontentlength/>"
1336 "</D:prop></D:propfind>");
1372 kDebug(7113) << src <<
"->" << dest;
1379 KUrl newDest = dest;
1380 if (newDest.
protocol() == QLatin1String(
"webdavs"))
1382 else if (newDest.
protocol() == QLatin1String(
"webdav"))
1402 kDebug(7113) << src <<
"->" << dest;
1409 KUrl newDest = dest;
1410 if (newDest.
protocol() == QLatin1String(
"webdavs"))
1412 else if (newDest.
protocol() == QLatin1String(
"webdav"))
1506 QDomDocument lockReq;
1508 QDomElement lockInfo = lockReq.createElementNS( QLatin1String(
"DAV:"), QLatin1String(
"lockinfo") );
1509 lockReq.appendChild( lockInfo );
1511 QDomElement lockScope = lockReq.createElement( QLatin1String(
"lockscope") );
1512 lockInfo.appendChild( lockScope );
1514 lockScope.appendChild( lockReq.createElement( scope ) );
1516 QDomElement lockType = lockReq.createElement( QLatin1String(
"locktype") );
1517 lockInfo.appendChild( lockType );
1519 lockType.appendChild( lockReq.createElement( type ) );
1521 if ( !owner.isNull() ) {
1522 QDomElement ownerElement = lockReq.createElement( QLatin1String(
"owner") );
1523 lockReq.appendChild( ownerElement );
1525 QDomElement ownerHref = lockReq.createElement( QLatin1String(
"href") );
1526 ownerElement.appendChild( ownerHref );
1528 ownerHref.appendChild( lockReq.createTextNode( owner ) );
1538 QDomDocument multiResponse;
1541 QDomElement prop = multiResponse.documentElement().namedItem( QLatin1String(
"prop") ).toElement();
1543 QDomElement lockdiscovery = prop.namedItem( QLatin1String(
"lockdiscovery") ).toElement();
1546 davParseActiveLocks( lockdiscovery.elementsByTagName( QLatin1String(
"activelock") ), lockCount );
1548 setMetaData( QLatin1String(
"davLockCount"), QString::number( lockCount ) );
1578 bool callError =
false;
1588 if ( !url.isNull() )
1595 QString ow =
i18n(
"Otherwise, the request would have succeeded." );
1599 action =
i18nc(
"request type",
"retrieve property values" );
1602 action =
i18nc(
"request type",
"set property values" );
1605 action =
i18nc(
"request type",
"create the requested folder" );
1608 action =
i18nc(
"request type",
"copy the specified file or folder" );
1611 action =
i18nc(
"request type",
"move the specified file or folder" );
1614 action =
i18nc(
"request type",
"search in the specified folder" );
1617 action =
i18nc(
"request type",
"lock the specified file or folder" );
1620 action =
i18nc(
"request type",
"unlock the specified file or folder" );
1623 action =
i18nc(
"request type",
"delete the specified file or folder" );
1626 action =
i18nc(
"request type",
"query the server's capabilities" );
1629 action =
i18nc(
"request type",
"retrieve the contents of the specified file or folder" );
1632 action =
i18nc(
"request type",
"run a report in the specified folder" );
1643 errorString =
i18nc(
"%1: code, %2: request type",
"An unexpected error (%1) occurred "
1644 "while attempting to %2.", code, action);
1651 errorString =
i18n(
"The server does not support the WebDAV protocol.");
1665 QDomDocument multiResponse;
1669 QDomElement multistatus = multiResponse.documentElement().namedItem( QLatin1String(
"multistatus") ).toElement();
1671 QDomNodeList responses = multistatus.elementsByTagName( QLatin1String(
"response") );
1673 for (
int i = 0; i < responses.count(); i++)
1678 QDomElement response = responses.item(i).toElement();
1679 QDomElement code = response.namedItem( QLatin1String(
"status") ).toElement();
1681 if ( !code.isNull() )
1684 QDomElement href = response.namedItem( QLatin1String(
"href") ).toElement();
1685 if ( !href.isNull() )
1686 errUrl = href.text();
1687 errors <<
davError( errCode, errUrl );
1692 errorString =
i18nc(
"%1: request type, %2: url",
1693 "An error occurred while attempting to %1, %2. A "
1694 "summary of the reasons is below.", action, url );
1696 errorString += QLatin1String(
"<ul>");
1699 errorString += QLatin1String(
"<li>") + error + QLatin1String(
"</li>");
1701 errorString += QLatin1String(
"</ul>");
1707 errorString =
i18nc(
"%1: request type",
"Access was denied while attempting to %1.", action );
1720 errorString =
i18n(
"A resource cannot be created at the destination "
1721 "until one or more intermediate collections (folders) "
1722 "have been created.");
1728 errorString =
i18n(
"The server was unable to maintain the liveness of "
1729 "the properties listed in the propertybehavior XML "
1730 "element or you attempted to overwrite a file while "
1731 "requesting that files are not overwritten. %1",
1736 errorString =
i18n(
"The requested lock could not be granted. %1", ow );
1742 errorString =
i18n(
"The server does not support the request type of the body.");
1747 errorString =
i18nc(
"%1: request type",
"Unable to %1 because the resource is locked.", action );
1751 errorString =
i18n(
"This action was prevented by another error.");
1757 errorString =
i18nc(
"%1: request type",
"Unable to %1 because the destination server refuses "
1758 "to accept the file or folder.", action );
1764 errorString =
i18n(
"The destination resource does not have sufficient space "
1765 "to record the state of the resource after the execution "
1776 error( errorCode, errorString );
1784 Q_ASSERT(errorString);
1787 errorString->clear();
1799 Q_ASSERT(errorString);
1803 errorString->clear();
1805 switch (responseCode) {
1814 && (responseCode < 200 || responseCode > 400)
1815 && responseCode != 404) {
1817 *errorString =
i18n(
"The resource cannot be deleted." );
1826 Q_ASSERT(errorString);
1832 switch (responseCode) {
1839 *errorString =
i18nc(
"%1: request type",
"Access was denied while attempting to %1.", action );
1845 *errorString =
i18n(
"A resource cannot be created at the destination "
1846 "until one or more intermediate collections (folders) "
1847 "have been created.");
1853 *errorString =
i18nc(
"%1: request type",
"Unable to %1 because the resource is locked.", action );
1859 *errorString =
i18nc(
"%1: request type",
"Unable to %1 because the destination server refuses "
1860 "to accept the file or folder.", action );
1866 *errorString =
i18n(
"The destination resource does not have sufficient space "
1867 "to record the state of the resource after the execution "
1876 && (responseCode < 200 || responseCode > 400)
1877 && responseCode != 404) {
1879 *errorString =
i18nc(
"%1: response code, %2: request type",
1880 "An unexpected error (%1) occurred while attempting to %2.",
1881 responseCode, action);
1908 infoMessage(QLatin1String(
""));
1911 error( errorCode, errorString );
1924 kWarning(7113) <<
"called twice during one request, something is probably wrong.";
1927 SlaveBase::errorPage();
1937 Solid::Networking::Status status = Solid::Networking::status();
1939 kDebug(7113) <<
"networkstatus:" << status;
1942 return status == Solid::Networking::Unconnected;
1947 QDataStream stream(data);
1959 for (
unsigned i = 0; i < n; ++i) {
1961 stream >> url >> mIncomingMetaData;
1974 QString tmp = metaData(QLatin1String(
"cache"));
1989 while (it.hasNext()) {
2001 while (it.hasNext()) {
2018 setMetaData(QLatin1String(
"request-id"), QString::number(requestId++));
2019 sendAndKeepMetaData();
2038 const char* buf =
static_cast<const char*
>(_buf);
2039 while (sent < nbytes)
2041 int n = TCPSlaveBase::write(buf + sent, nbytes - sent);
2066 for (
size_t i = 0; i < size; i++) {
2077 size_t bytesRead = 0;
2080 bytesRead = qMin((
int)size, bufSize);
2082 for (
size_t i = 0; i < bytesRead; i++) {
2083 buf[i] =
m_unreadBuf.constData()[bufSize - i - 1];
2094 if (bytesRead < size) {
2095 int rawRead = TCPSlaveBase::read(buf + bytesRead, size - bytesRead);
2100 bytesRead += rawRead;
2111 Q_ASSERT(numNewlines >=1 && numNewlines <= 2);
2114 while (pos < end && !
m_isEOF) {
2115 int step = qMin((
int)
sizeof(mybuf), end - pos);
2124 for (
size_t i = 0; i < bufferFill ; ++i, ++pos) {
2127 buf[pos] = mybuf[i];
2132 if (buf[pos] ==
'\n') {
2133 bool found = numNewlines == 1;
2136 found = ((pos >= 1 && buf[pos - 1] ==
'\n') ||
2137 (pos >= 2 && buf[pos - 2] ==
'\n' && buf[pos - 1] ==
'\r'));
2141 unread(&mybuf[i], bufferFill - i);
2154 if (previous.host() != now.host() || previous.port() != now.port()) {
2157 if (previous.
user().isEmpty() && previous.
pass().isEmpty()) {
2173 if (url != QLatin1String(
"DIRECT")) {
2192 disconnect(
socket(), SIGNAL(connected()),
2197 int connectError = 0;
2207 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2212 if (proxyUrl == QLatin1String(
"DIRECT")) {
2213 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2215 if (connectError == 0) {
2223 const KUrl url(proxyUrl);
2227 errorString = url.
url();
2228 badProxyUrls << url;
2232 QNetworkProxy::ProxyType proxyType = QNetworkProxy::NoProxy;
2233 if (proxyScheme == QLatin1String(
"socks")) {
2234 proxyType = QNetworkProxy::Socks5Proxy;
2236 proxyType = QNetworkProxy::HttpProxy;
2239 kDebug(7113) <<
"Connecting to proxy: address=" << proxyUrl <<
"type=" << proxyType;
2241 if (proxyType == QNetworkProxy::NoProxy) {
2242 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2243 connectError =
connectToHost(url.host(), url.port(), &errorString);
2244 if (connectError == 0) {
2246 kDebug(7113) <<
"Connected to proxy: host=" << url.host() <<
"port=" << url.port();
2252 kDebug(7113) <<
"Failed to connect to proxy:" << proxyUrl;
2253 badProxyUrls << url;
2256 QNetworkProxy proxy(proxyType, url.host(), url.port(), url.
user(), url.
pass());
2257 QNetworkProxy::setApplicationProxy(proxy);
2259 if (connectError == 0) {
2260 kDebug(7113) <<
"Tunneling thru proxy: host=" << url.host() <<
"port=" << url.port();
2266 kDebug(7113) <<
"Failed to connect to proxy:" << proxyUrl;
2267 badProxyUrls << url;
2268 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2273 if (!badProxyUrls.isEmpty()) {
2278 if (connectError != 0) {
2279 error(connectError, errorString);
2309 bool openForReading =
false;
2313 if (!openForReading && (isCacheOnly || offline)) {
2315 *cacheHasPage =
false;
2318 }
else if (offline) {
2325 if (openForReading) {
2327 *cacheHasPage =
true;
2332 *cacheHasPage =
false;
2345 if (protocol.startsWith(QLatin1String(
"webdav"))) {
2346 protocol.replace(0, qstrlen(
"webdav"), QLatin1String(
"http"));
2403 kDebug(7113) <<
"Couldn't connect, oopsie!";
2415 bool hasBodyData =
false;
2416 bool hasDavData =
false;
2426 bool cacheHasPage =
false;
2428 kDebug(7113) <<
"cacheHasPage =" << cacheHasPage;
2429 return cacheHasPage;
2431 if (!cacheHasPage) {
2448 davHeader = QLatin1String(
"Depth: ");
2449 if ( hasMetaData( QLatin1String(
"davDepth") ) )
2451 kDebug(7113) <<
"Reading DAV depth from metadata:" << metaData( QLatin1String(
"davDepth") );
2452 davHeader += metaData( QLatin1String(
"davDepth") );
2457 davHeader += QLatin1String(
"infinity");
2461 davHeader += QLatin1String(
"\r\n");
2473 davHeader += QLatin1String(
"\r\nDepth: infinity\r\nOverwrite: ");
2475 davHeader += QLatin1String(
"\r\n");
2478 davHeader = QLatin1String(
"Timeout: ");
2481 if ( hasMetaData( QLatin1String(
"davTimeout") ) )
2482 timeout = metaData( QLatin1String(
"davTimeout") ).toUInt();
2484 davHeader += QLatin1String(
"Infinite");
2486 davHeader += QLatin1String(
"Seconds-") + QString::number(timeout);
2488 davHeader += QLatin1String(
"\r\n");
2492 davHeader = QLatin1String(
"Lock-token: ") + metaData(QLatin1String(
"davLockToken")) + QLatin1String(
"\r\n");
2499 case DAV_UNSUBSCRIBE:
2513 header += QLatin1Char(
':') + QString::number(
m_request.
url.port());
2515 header += QLatin1String(
"\r\n");
2522 header += QLatin1String(
"Proxy-Connection: ");
2524 header += QLatin1String(
"Connection: ");
2527 header += QLatin1String(
"keep-alive\r\n");
2529 header += QLatin1String(
"close\r\n");
2534 header += QLatin1String(
"User-Agent: ");
2536 header += QLatin1String(
"\r\n");
2541 header += QLatin1String(
"Referer: ");
2543 header += QLatin1String(
"\r\n");
2548 header += QLatin1String(
"Range: bytes=");
2550 header += QLatin1Char(
'-');
2552 header += QLatin1String(
"\r\n");
2558 header += QLatin1String(
"Range: bytes=");
2560 header += QLatin1String(
"-\r\n");
2567 header += QLatin1String(
"Pragma: no-cache\r\n");
2568 header += QLatin1String(
"Cache-control: no-cache\r\n");
2572 kDebug(7113) <<
"needs validation, performing conditional get.";
2579 header += QLatin1String(
"If-Modified-Since: ") + httpDate + QLatin1String(
"\r\n");
2580 setMetaData(QLatin1String(
"modified"), httpDate);
2584 header += QLatin1String(
"Accept: ");
2585 const QString acceptHeader = metaData(QLatin1String(
"accept"));
2586 if (!acceptHeader.isEmpty())
2587 header += acceptHeader;
2590 header += QLatin1String(
"\r\n");
2593 header += QLatin1String(
"Accept-Encoding: gzip, deflate, x-gzip, x-deflate\r\n");
2596 header += QLatin1String(
"Accept-Charset: ") +
m_request.
charsets + QLatin1String(
"\r\n");
2599 header += QLatin1String(
"Accept-Language: ") +
m_request.
languages + QLatin1String(
"\r\n");
2602 const QString cookieMode = metaData(QLatin1String(
"cookies")).toLower();
2604 if (cookieMode == QLatin1String(
"none"))
2608 else if (cookieMode == QLatin1String(
"manual"))
2611 cookieStr = metaData(QLatin1String(
"setcookies"));
2620 if (!cookieStr.isEmpty())
2621 header += cookieStr + QLatin1String(
"\r\n");
2623 const QString customHeader = metaData( QLatin1String(
"customHTTPHeader") );
2624 if (!customHeader.isEmpty())
2627 header += QLatin1String(
"\r\n");
2630 const QString contentType = metaData(QLatin1String(
"content-type"));
2631 if (!contentType.isEmpty())
2633 if (!contentType.startsWith(QLatin1String(
"content-type"), Qt::CaseInsensitive))
2634 header += QLatin1String(
"Content-Type: ");
2635 header += contentType;
2636 header += QLatin1String(
"\r\n");
2641 header += QLatin1String(
"DNT: 1\r\n");
2654 davHeader += metaData(QLatin1String(
"davHeader"));
2658 davHeader += QLatin1String(
"Content-Type: text/xml; charset=utf-8\r\n");
2661 header += davHeader;
2665 kDebug(7103) <<
"============ Sending Header:";
2666 Q_FOREACH (
const QString &s, header.split(QLatin1String(
"\r\n"), QString::SkipEmptyParts)) {
2672 if (!hasBodyData && !hasDavData)
2673 header += QLatin1String(
"\r\n");
2682 const QByteArray headerBytes = header.toLatin1();
2683 ssize_t written =
write(headerBytes.constData(), headerBytes.length());
2684 bool sendOk = (written == (ssize_t) headerBytes.length());
2688 <<
" -- intended to write" << headerBytes.length()
2689 <<
"bytes but wrote" << (int)written <<
".";
2699 kDebug(7113) <<
"sendOk == false. Connection broken !"
2700 <<
" -- intended to write" << headerBytes.length()
2701 <<
"bytes but wrote" << (int)written <<
".";
2706 kDebug(7113) <<
"sent it!";
2709 if (hasBodyData || hasDavData)
2712 infoMessage(
i18n(
"%1 contacted. Waiting for reply...",
m_request.
url.host()));
2725 if (forwardImmediately)
2738 if (header.startsWith(QLatin1String(
"content-type:"), Qt::CaseInsensitive)) {
2739 int pos = header.indexOf(QLatin1String(
"charset="), Qt::CaseInsensitive);
2741 const QString charset = header.mid(pos + 8).toLower();
2743 setMetaData(QLatin1String(
"charset"), charset);
2745 }
else if (header.startsWith(QLatin1String(
"content-language:"), Qt::CaseInsensitive)) {
2746 const QString language = header.mid(17).trimmed().toLower();
2747 setMetaData(QLatin1String(
"content-language"), language);
2748 }
else if (header.startsWith(QLatin1String(
"content-disposition:"), Qt::CaseInsensitive)) {
2775 if (
m_mimeType == QLatin1String(
"application/x-targz"))
2776 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2777 else if (
m_mimeType == QLatin1String(
"image/x-png"))
2781 else if (
m_mimeType == QLatin1String(
"audio/microsoft-wave"))
2783 else if (
m_mimeType == QLatin1String(
"image/x-ms-bmp"))
2787 else if (
m_mimeType == QLatin1String(
"application/pkix-cert") ||
2788 m_mimeType == QLatin1String(
"application/binary-certificate")) {
2789 m_mimeType = QLatin1String(
"application/x-x509-ca-cert");
2793 else if (
m_mimeType == QLatin1String(
"application/x-gzip")) {
2796 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2798 m_mimeType = QLatin1String(
"application/x-gzpostscript");
2803 else if(
m_mimeType == QLatin1String(
"application/x-xz")) {
2806 m_mimeType = QLatin1String(
"application/x-xz-compressed-tar");
2811 else if ((
m_mimeType == QLatin1String(
"text/plain")) || (
m_mimeType == QLatin1String(
"application/octet-stream"))) {
2813 if (ext == QLatin1String(
"BZ2"))
2814 m_mimeType = QLatin1String(
"application/x-bzip");
2815 else if (ext == QLatin1String(
"PEM"))
2816 m_mimeType = QLatin1String(
"application/x-x509-ca-cert");
2817 else if (ext == QLatin1String(
"SWF"))
2818 m_mimeType = QLatin1String(
"application/x-shockwave-flash");
2819 else if (ext == QLatin1String(
"PLS"))
2821 else if (ext == QLatin1String(
"WMV"))
2822 m_mimeType = QLatin1String(
"video/x-ms-wmv");
2823 else if (ext == QLatin1String(
"WEBM"))
2825 else if (ext == QLatin1String(
"DEB"))
2826 m_mimeType = QLatin1String(
"application/x-deb");
2840 if (
m_mimeType == QLatin1String(
"application/x-tar")) {
2842 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2843 }
else if (
m_mimeType == QLatin1String(
"application/postscript")) {
2847 m_mimeType = QLatin1String(
"application/x-gzpostscript");
2852 m_mimeType != QLatin1String(
"application/x-compressed-tar") &&
2853 m_mimeType != QLatin1String(
"application/x-tgz") &&
2854 m_mimeType != QLatin1String(
"application/x-targz") &&
2855 m_mimeType != QLatin1String(
"application/x-gzip"))) {
2859 m_mimeType = QLatin1String(
"application/x-gzip");
2871 m_mimeType = QLatin1String(
"application/x-bzip");
2878 static bool consume(
const char input[],
int *pos,
int end,
const char *term)
2882 if (idx + (
int)strlen(term) >= end) {
2886 if (strncasecmp(&input[idx], term, strlen(term)) == 0) {
2887 *pos = idx + strlen(term);
2911 bool upgradeRequired =
false;
2915 bool noHeadersFound =
false;
2920 static const int maxHeaderSize = 128 * 1024;
2922 char buffer[maxHeaderSize];
2924 bool bCanResume =
false;
2927 kDebug(7113) <<
"No connection.";
2937 kDebug(7113) <<
"Got socket error:" <<
socket()->errorString();
2946 if (!foundDelimiter && bufPos < maxHeaderSize) {
2947 kDebug(7113) <<
"EOF while waiting for header start.";
2964 kDebug(7113) <<
"Connection broken !";
2968 if (!foundDelimiter) {
2973 kDebug(7103) <<
"============ Received Status Response:";
2974 kDebug(7103) << QByteArray(buffer, bufPos).trimmed();
2979 if (idx != bufPos && buffer[idx] ==
'<') {
2980 kDebug(7103) <<
"No valid HTTP header found! Document starts with XML/HTML tag";
2986 noHeadersFound =
true;
2993 if (
consume(buffer, &idx, bufPos,
"ICY ")) {
2996 }
else if (
consume(buffer, &idx, bufPos,
"HTTP/")) {
2997 if (
consume(buffer, &idx, bufPos,
"1.0")) {
3000 }
else if (
consume(buffer, &idx, bufPos,
"1.1")) {
3005 if (httpRev ==
HTTP_None && bufPos != 0) {
3008 kDebug(7113) <<
"DO NOT WANT." << bufPos;
3016 noHeadersFound =
true;
3027 if (idx != bufPos) {
3043 messageBox(WarningYesNo,
3044 i18nc(
"@info Security check on url being accessed",
3045 "<p>You are about to log in to the site \"%1\" "
3046 "with the username \"%2\", but the website "
3047 "does not require authentication. "
3048 "This may be an attempt to trick you.</p>"
3049 "<p>Is \"%1\" the site you want to visit?</p>",
3051 i18nc(
"@title:window",
"Confirm Website Access"));
3056 setMetaData(QLatin1String(
"{internal~currenthost}LastSpoofedUserName"),
m_request.
url.
user());
3078 upgradeRequired =
true;
3092 setMetaData(QLatin1String(
"permanent-redirect"), QLatin1String(
"true"));
3126 infoMessage(
i18n(
"Server processing request, please wait..." ) );
3135 bool authRequiresAnotherRoundtrip =
false;
3138 if (!noHeadersFound) {
3143 kDebug(7113) <<
"wasAuthError=" << wasAuthError <<
"isAuthError=" << isAuthError
3144 <<
"sameAuthError=" << sameAuthError;
3156 kDebug(7113) <<
" -- full response:" << endl << QByteArray(buffer, bufPos).trimmed();
3159 Q_ASSERT(foundDelimiter);
3166 tokenizer.
tokenize(idx,
sizeof(buffer));
3171 if (tIt.
hasNext() && tIt.
next().toLower().startsWith(
"none")) {
3175 tIt = tokenizer.iterator(
"keep-alive");
3177 QByteArray ka = tIt.
next().trimmed().toLower();
3178 if (ka.startsWith(
"timeout=")) {
3179 int ka_timeout = ka.mid(qstrlen(
"timeout=")).trimmed().toInt();
3191 tIt = tokenizer.iterator(
"content-length");
3196 tIt = tokenizer.iterator(
"content-location");
3198 setMetaData(QLatin1String(
"content-location"),
toQString(tIt.
next().trimmed()));
3204 tIt = tokenizer.iterator(
"content-type");
3210 if (
m_mimeType.startsWith(QLatin1Char(
'"'))) {
3222 Q_FOREACH (
const QByteArray &statement, l) {
3223 const int index = statement.indexOf(
'=');
3225 mediaAttribute =
toQString(statement.mid(0, index));
3227 mediaAttribute =
toQString(statement.mid(0, index));
3228 mediaValue =
toQString(statement.mid(index+1));
3230 mediaAttribute = mediaAttribute.trimmed();
3231 mediaValue = mediaValue.trimmed();
3233 bool quoted =
false;
3234 if (mediaValue.startsWith(QLatin1Char(
'"'))) {
3236 mediaValue.remove(0, 1);
3239 if (mediaValue.endsWith(QLatin1Char(
'"'))) {
3243 kDebug (7113) <<
"Encoding-type:" << mediaAttribute <<
"=" << mediaValue;
3245 if (mediaAttribute == QLatin1String(
"charset")) {
3246 mediaValue = mediaValue.toLower();
3248 setMetaData(QLatin1String(
"charset"), mediaValue);
3250 setMetaData(QLatin1String(
"media-") + mediaAttribute, mediaValue);
3252 setMetaData(QLatin1String(
"media-") + mediaAttribute + QLatin1String(
"-kio-quoted"),
3253 QLatin1String(
"true"));
3260 tIt = tokenizer.iterator(
"content-encoding");
3278 tIt = tokenizer.iterator(
"content-disposition");
3282 tIt = tokenizer.iterator(
"content-language");
3285 if (!language.isEmpty()) {
3286 setMetaData(QLatin1String(
"content-language"), language);
3290 tIt = tokenizer.iterator(
"proxy-connection");
3292 QByteArray pc = tIt.
next().toLower();
3293 if (pc.startsWith(
"close")) {
3295 }
else if (pc.startsWith(
"keep-alive")) {
3300 tIt = tokenizer.iterator(
"link");
3304 if (link.count() == 2) {
3305 QString rel = link[1].trimmed();
3306 if (rel.startsWith(QLatin1String(
"rel=\""))) {
3307 rel = rel.mid(5, rel.length() - 6);
3308 if (rel.toLower() == QLatin1String(
"pageservices")) {
3310 QString url = link[0].remove(QRegExp(QLatin1String(
"[<>]"))).trimmed();
3311 setMetaData(QLatin1String(
"PageServices"), url);
3317 tIt = tokenizer.iterator(
"p3p");
3323 .split(QLatin1Char(
'='), QString::SkipEmptyParts);
3324 if (policy.count() == 2) {
3325 if (policy[0].toLower() == QLatin1String(
"policyref")) {
3326 policyrefs << policy[1].remove(QRegExp(QLatin1String(
"[\")\']"))).trimmed();
3327 }
else if (policy[0].toLower() == QLatin1String(
"cp")) {
3331 const QString s = policy[1].remove(QRegExp(QLatin1String(
"[\")\']")));
3332 const QStringList cps = s.split(QLatin1Char(
' '), QString::SkipEmptyParts);
3337 if (!policyrefs.isEmpty()) {
3338 setMetaData(QLatin1String(
"PrivacyPolicy"), policyrefs.join(QLatin1String(
"\n")));
3340 if (!compact.isEmpty()) {
3341 setMetaData(QLatin1String(
"PrivacyCompactPolicy"), compact.join(QLatin1String(
"\n")));
3348 tIt = tokenizer.iterator(
"connection");
3350 QByteArray connection = tIt.
next().toLower();
3352 if (connection.startsWith(
"close")) {
3354 }
else if (connection.startsWith(
"keep-alive")) {
3358 if (connection.startsWith(
"upgrade")) {
3361 upgradeRequired =
true;
3362 }
else if (upgradeRequired) {
3368 tIt = tokenizer.iterator(
"transfer-encoding");
3377 tIt = tokenizer.iterator(
"content-md5");
3384 tIt = tokenizer.iterator(
"dav");
3394 tIt = tokenizer.iterator(
"upgrade");
3398 upgradeOffers = offered.split(QRegExp(QLatin1String(
"[ \n,\r\t]")), QString::SkipEmptyParts);
3400 Q_FOREACH (
const QString &opt, upgradeOffers) {
3401 if (opt == QLatin1String(
"TLS/1.0")) {
3402 if (!
startSsl() && upgradeRequired) {
3406 }
else if (opt == QLatin1String(
"HTTP/1.1")) {
3408 }
else if (upgradeRequired) {
3416 QByteArray cookieStr;
3417 tIt = tokenizer.iterator(
"set-cookie");
3419 cookieStr +=
"Set-Cookie: ";
3420 cookieStr += tIt.
next();
3423 if (!cookieStr.isEmpty()) {
3428 cookieStr =
"Cross-Domain\n" + cookieStr;
3433 setMetaData(QLatin1String(
"setcookies"), QString::fromUtf8(cookieStr));
3441 kDebug(7113) <<
"cont; returning to mark try_again";
3447 kDebug(7113) <<
"Ignoring keep-alive: otherwise unable to determine response body length.";
3462 authRequiresAnotherRoundtrip =
false;
3467 tIt = tokenizer.iterator(
"location");
3469 locationStr = QString::fromUtf8(tIt.
next().trimmed());
3472 if (!locationStr.isEmpty())
3499 if(u.
protocol() == QLatin1String(
"http")){
3501 }
else if(u.
protocol() == QLatin1String(
"https")){
3541 kDebug(7113) <<
"Reading resource from cache even though the cache plan is not "
3542 "UseCached; the server is probably sending wrong expiry information.";
3552 int nextLinePos = 0;
3553 int prevLinePos = 0;
3554 bool haveMore =
true;
3556 haveMore =
nextLine(buffer, &nextLinePos, bufPos);
3557 int prevLineEnd = nextLinePos;
3558 while (buffer[prevLineEnd - 1] ==
'\r' || buffer[prevLineEnd - 1] ==
'\n') {
3563 prevLineEnd - prevLinePos));
3564 prevLinePos = nextLinePos;
3591 return !authRequiresAnotherRoundtrip;
3599 while (i != parameters.constEnd()) {
3600 setMetaData(QLatin1String(
"content-disposition-") + i.key(), i.value());
3601 kDebug(7113) <<
"Content-Disposition:" << i.key() <<
"=" << i.value();
3608 QString encoding = _encoding.trimmed().toLower();
3610 if (encoding == QLatin1String(
"identity")) {
3612 }
else if (encoding == QLatin1String(
"8bit")) {
3615 }
else if (encoding == QLatin1String(
"chunked")) {
3620 }
else if ((encoding == QLatin1String(
"x-gzip")) || (encoding == QLatin1String(
"gzip"))) {
3621 encs.append(QLatin1String(
"gzip"));
3622 }
else if ((encoding == QLatin1String(
"x-bzip2")) || (encoding == QLatin1String(
"bzip2"))) {
3623 encs.append(QLatin1String(
"bzip2"));
3624 }
else if ((encoding == QLatin1String(
"x-deflate")) || (encoding == QLatin1String(
"deflate"))) {
3625 encs.append(QLatin1String(
"deflate"));
3627 kDebug(7113) <<
"Unknown encoding encountered. "
3628 <<
"Please write code. Encoding =" << encoding;
3647 const qint64 currentDate = time(0);
3664 tIt = tokenizer.iterator(
"date");
3671 tIt = tokenizer.iterator(
"age");
3673 ageHeader = tIt.
next().toLongLong();
3677 if (dateHeader != -1) {
3679 }
else if (ageHeader) {
3686 bool hasCacheDirective =
false;
3691 tIt = tokenizer.iterator(
"cache-control");
3693 QByteArray cacheStr = tIt.
next().toLower();
3694 if (cacheStr.startsWith(
"no-cache") || cacheStr.startsWith(
"no-store")) {
3697 hasCacheDirective =
true;
3698 }
else if (cacheStr.startsWith(
"max-age=")) {
3699 QByteArray ba = cacheStr.mid(qstrlen(
"max-age=")).trimmed();
3701 maxAgeHeader = ba.toLongLong(&ok);
3703 hasCacheDirective =
true;
3708 qint64 expiresHeader = -1;
3709 tIt = tokenizer.iterator(
"expires");
3712 kDebug(7113) <<
"parsed expire date from 'expires' header:" << tIt.
current();
3717 }
else if (expiresHeader != -1) {
3726 expAge = qMin(expAge,
qint64(3600 * 24));
3739 tIt = tokenizer.iterator(
"etag");
3744 kDebug(7103) <<
"304 Not Modified but new entity tag - I don't think this is legal HTTP.";
3749 tIt = tokenizer.iterator(
"warning");
3757 tIt = tokenizer.iterator(
"pragma");
3759 if (tIt.
next().toLower().startsWith(
"no-cache")) {
3761 hasCacheDirective =
true;
3766 tIt = tokenizer.iterator(
"refresh");
3769 setMetaData(QLatin1String(
"http-refresh"),
toQString(tIt.
next().trimmed()));
3773 if (
m_mimeType.startsWith(QLatin1String(
"text/")) && (
m_mimeType != QLatin1String(
"text/css")) &&
3774 (
m_mimeType != QLatin1String(
"text/x-javascript")) && !hasCacheDirective) {
3785 kDebug(7113) <<
"Cache needs validation";
3787 kDebug(7113) <<
"...was revalidated by response code but not by updated expire times. "
3788 "We're going to set the expire date to 60 seconds in the future...";
3794 kDebug(7113) <<
"this proxy or server apparently sends bogus expiry information.";
3811 kDebug(7113) <<
"This webserver is confused about the cacheability of the data it sends.";
3825 if (!cachingAllowed) {
3826 setMetaData(QLatin1String(
"no-cache"), QLatin1String(
"true"));
3827 setMetaData(QLatin1String(
"expire-date"), QLatin1String(
"1"));
3831 setMetaData(QLatin1String(
"expire-date"), tmp);
3834 setMetaData(QLatin1String(
"cache-creation-date"), tmp);
3842 QByteArray cLength (
"Content-Length: ");
3843 cLength += QByteArray::number(
m_POSTbuf->size());
3844 cLength +=
"\r\n\r\n";
3846 kDebug(7113) <<
"sending cached data (size=" <<
m_POSTbuf->size() <<
")";
3849 bool sendOk = (
write(cLength.data(), cLength.size()) == (ssize_t) cLength.size());
3851 kDebug( 7113 ) <<
"Connection broken when sending "
3863 sendOk = (
write(buffer.data(), buffer.size()) == (ssize_t) buffer.size());
3865 kDebug(7113) <<
"Connection broken when sending message body: ("
3896 QByteArray cLength (
"Content-Length: ");
3898 cLength +=
"\r\n\r\n";
3900 kDebug(7113) << cLength.trimmed();
3903 bool sendOk = (
write(cLength.data(), cLength.size()) == (ssize_t) cLength.size());
3913 kDebug(7113) <<
"Connection broken while sending POST content size to" <<
m_request.
url.host();
3932 const int bytesRead = readData(buffer);
3935 if (bytesRead == 0) {
3941 if (bytesRead < 0) {
3955 if (
write(buffer.data(), bytesRead) == static_cast<ssize_t>(bytesRead)) {
3956 bytesSent += bytesRead;
3957 processedSize(bytesSent);
3961 kDebug(7113) <<
"Connection broken while sending POST content to" <<
m_request.
url.host();
3971 kDebug(7113) <<
"keepAlive =" << keepAlive;
3987 QDataStream stream( &data, QIODevice::WriteOnly );
4009 setTimeoutSpecialCommand(-1);
4046 QDataStream stream(data);
4054 stream >> url >> size;
4063 stream >> url >> no_cache >> expireDate;
4069 QFile::remove(filename);
4090 stream >> url >> scope >> type >> owner;
4091 davLock( url, scope, type, owner );
4106 stream >> url >> method >> size;
4107 davGeneric( url, (KIO::HTTP_METHOD) method, size );
4136 if (foundCrLf && bufPos == 2) {
4143 kDebug(7113) <<
"Failed to read chunk header.";
4146 Q_ASSERT(bufPos > 2);
4149 if (nextChunkSize < 0)
4151 kDebug(7113) <<
"Negative chunk size";
4168 int trashBufPos = 2;
4171 if (trashBufPos > 3) {
4173 for (
int i = 0; i < 3; i++) {
4174 trash[i] = trash[trashBufPos - 3 + i];
4181 kDebug(7113) <<
"Failed to read chunk trailer.";
4193 return bytesReceived;
4211 if (bytesReceived <= 0)
4215 return bytesReceived;
4222 kDebug(7113) <<
"Unbounded datastream on a Keep-alive connection!";
4262 kDebug(7113) <<
"Determining mime-type from content...";
4276 if( mime && !mime->isDefault() )
4357 if ( !dataInternal ) {
4368 kDebug(7113) <<
"reading data from cache...";
4380 if (!dataInternal) {
4387 if (!dataInternal) {
4415 QObject::connect(&chain, SIGNAL(
output(QByteArray)),
4425 if ( enc == QLatin1String(
"gzip") )
4427 else if ( enc == QLatin1String(
"deflate") )
4455 if ( enc == QLatin1String(
"gzip") )
4457 else if ( enc == QLatin1String(
"deflate") )
4476 if (bytesReceived == -1)
4486 kDebug(7113) <<
"bytesReceived==-1 sz=" << (int)sz
4487 <<
" Connection broken !";
4494 if (bytesReceived > 0)
4505 sz += bytesReceived;
4507 processedSize( sz );
4531 kWarning(7113) <<
"MD5 checksum MISMATCH! Expected:"
4540 if (!dataInternal && sz <= 1)
4553 data( QByteArray() );
4581 SlaveBase::error( _err, _text );
4589 QDBusInterface kcookiejar( QLatin1String(
"org.kde.kded"), QLatin1String(
"/modules/kcookiejar"), QLatin1String(
"org.kde.KCookieServer") );
4590 (void)kcookiejar.call( QDBus::NoBlock, QLatin1String(
"addCookies"), url,
4591 cookieHeader, windowId );
4597 QDBusInterface kcookiejar( QLatin1String(
"org.kde.kded"), QLatin1String(
"/modules/kcookiejar"), QLatin1String(
"org.kde.KCookieServer") );
4598 QDBusReply<QString> reply = kcookiejar.call( QLatin1String(
"findCookies"), url, windowId );
4600 if ( !reply.isValid() )
4602 kWarning(7113) <<
"Can't communicate with kded_kcookiejar!";
4631 time_t currentDate = time(0);
4644 struct BinaryCacheFileHeader
4656 static const int size = 36;
4668 BinaryCacheFileHeader
header;
4677 QDataStream stream(&ret, QIODevice::WriteOnly);
4678 stream << quint8(
'A');
4679 stream << quint8(
'\n');
4680 stream << quint8(0);
4681 stream << quint8(0);
4683 stream << fileUseCount;
4686 stream <<
qint64(servedDate);
4687 stream << qint64(lastModifiedDate);
4688 stream << qint64(expireDate);
4690 stream << bytesCached;
4691 Q_ASSERT(ret.size() == BinaryCacheFileHeader::size);
4700 return byte == value;
4703 static bool readTime(QDataStream *stream, time_t *time)
4707 *time =
static_cast<time_t
>(intTime);
4710 return check == intTime;
4719 if (d.size() != BinaryCacheFileHeader::size) {
4722 QDataStream stream(d);
4723 stream.setVersion(QDataStream::Qt_4_5);
4734 stream >> fileUseCount;
4737 ok = ok &&
readTime(&stream, &servedDate);
4738 ok = ok &&
readTime(&stream, &lastModifiedDate);
4739 ok = ok &&
readTime(&stream, &expireDate);
4744 stream >> bytesCached;
4769 static const char linefeed =
'\n';
4771 dev->write(&linefeed, 1);
4778 Q_ASSERT(file->openMode() & QIODevice::WriteOnly);
4780 file->seek(BinaryCacheFileHeader::size);
4794 if (line->isEmpty() || !line->endsWith(
'\n')) {
4806 Q_ASSERT(file->openMode() == QIODevice::ReadOnly);
4810 if (
storableUrl(desiredUrl).toEncoded() != readBuf) {
4811 kDebug(7103) <<
"You have witnessed a very improbable hash collision!";
4825 Q_ASSERT(file->openMode() == QIODevice::ReadOnly);
4831 qint64 oldPos = file->pos();
4832 file->seek(BinaryCacheFileHeader::size);
4835 Q_ASSERT(file->pos() == oldPos);
4844 if (ok && !readBuf.isEmpty()) {
4855 QCryptographicHash hash(QCryptographicHash::Sha1);
4857 return toQString(hash.result().toHex());
4863 if (!filePath.endsWith(QLatin1Char(
'/'))) {
4864 filePath.append(QLatin1Char(
'/'));
4877 kDebug(7113) <<
"File unexpectedly open; old file is" << file->fileName()
4878 <<
"new name is" << filename;
4879 Q_ASSERT(file->fileName() == filename);
4882 file =
new QFile(filename);
4883 if (file->open(QIODevice::ReadOnly)) {
4884 QByteArray
header = file->read(BinaryCacheFileHeader::size);
4886 kDebug(7103) <<
"Cache file header is invalid.";
4896 if (!file->isOpen()) {
4914 Q_ASSERT(!qobject_cast<QTemporaryFile *>(file));
4915 Q_ASSERT((file->openMode() & QIODevice::WriteOnly) == 0);
4916 Q_ASSERT(file->fileName() == filename);
4917 kDebug(7113) <<
"deleting expired cache entry and recreating.";
4925 file->open(QIODevice::WriteOnly);
4931 if ((file->openMode() & QIODevice::WriteOnly) == 0) {
4932 kDebug(7113) <<
"Could not open file for writing:" << file->fileName()
4933 <<
"due to error" << file->error();
4944 QDataStream stream(&ret, QIODevice::WriteOnly);
4945 stream.setVersion(QDataStream::Qt_4_5);
4947 stream.skipRawData(BinaryCacheFileHeader::size);
4952 int basenameStart = fileName.lastIndexOf(QLatin1Char(
'/')) + 1;
4954 stream.writeRawData(baseName.constData(), baseName.size());
4956 Q_ASSERT(ret.size() == BinaryCacheFileHeader::size +
sizeof(quint32) +
s_hashedUrlNibbles);
4972 QByteArray ccCommand;
4975 if (file->openMode() & QIODevice::WriteOnly) {
4981 tempFile->write(header);
4985 QString oldName = tempFile->fileName();
4987 int basenameStart = newName.lastIndexOf(QLatin1Char(
'/')) + 1;
4990 kDebug(7113) <<
"Renaming temporary file" << oldName <<
"to" << newName;
4993 tempFile->setAutoRemove(
false);
4997 if (!QFile::rename(oldName, newName)) {
5000 kDebug(7113) <<
"Renaming temporary file failed, deleting it instead.";
5001 QFile::remove(oldName);
5008 }
else if (file->openMode() == QIODevice::ReadOnly) {
5009 Q_ASSERT(!tempFile);
5015 if (!ccCommand.isEmpty()) {
5026 if (attempts == 2) {
5040 kDebug(7113) <<
"Could not connect to cache cleaner, not updating stats of this cache file.";
5050 if (ret.isEmpty()) {
5067 kDebug(7113) <<
"Caching disabled because content size is too big.";
5097 m_POSTbuf->write (data.constData(), data.size());
5123 const int bytesRead = readData(buffer);
5125 if (bytesRead < 0) {
5130 if (bytesRead == 0) {
5134 m_POSTbuf->write(buffer.constData(), buffer.size());
5162 if (useCachedAuth && checkCachedAuthentication(authinfo)) {
5163 const QByteArray cachedChallenge =
config()->readEntry(
"www-auth-challenge", QByteArray());
5164 if (!cachedChallenge.isEmpty()) {
5167 kDebug(7113) <<
"creating www authentcation header from cached info";
5185 if (checkCachedAuthentication(authinfo)) {
5186 const QByteArray cachedChallenge =
config()->readEntry(
"proxy-auth-challenge", QByteArray());
5187 if (!cachedChallenge.isEmpty()) {
5190 kDebug(7113) <<
"creating proxy authentcation header from cached info";
5200 ret +=
"Authorization: ";
5205 ret +=
"Proxy-Authorization: ";
5215 case QNetworkProxy::DefaultProxy:
5217 case QNetworkProxy::Socks5Proxy:
5218 return QLatin1String(
"socks");
5219 case QNetworkProxy::NoProxy:
5221 case QNetworkProxy::HttpProxy:
5222 case QNetworkProxy::HttpCachingProxy:
5223 case QNetworkProxy::FtpCachingProxy:
5228 return QLatin1String(
"http");
5233 kDebug(7113) <<
"realm:" << authenticator->realm() <<
"user:" << authenticator->user();
5244 info.
username = authenticator->user();
5247 const bool haveCachedCredentials = checkCachedAuthentication(info);
5252 if (!haveCachedCredentials || retryAuth) {
5255 connect(
socket(), SIGNAL(connected()),
5258 info.
prompt =
i18n(
"You need to supply a username and a password for "
5259 "the proxy server listed below before you are allowed "
5260 "to access any sites.");
5265 const QString errMsg ((retryAuth ?
i18n(
"Proxy Authentication Failed.") :
QString()));
5267 if (!openPasswordDialog(info, errMsg)) {
5268 kDebug(7113) <<
"looks like the user canceled proxy authentication.";
5275 authenticator->setUser(info.
username);
5276 authenticator->setPassword(info.
password);
5277 authenticator->setOption(QLatin1String(
"keepalive"), info.
keepPassword);
5292 kDebug(7113) <<
"Saving authenticator";
5293 disconnect(
socket(), SIGNAL(connected()),
5305 cacheAuthentication(a);
5314 bool alreadyCached =
false;
5319 alreadyCached =
config()->readEntry(
"cached-www-auth",
false);
5323 alreadyCached =
config()->readEntry(
"cached-proxy-auth",
false);
5330 if (auth && (!auth->
realm().isEmpty() || !alreadyCached)) {
5333 setMetaData(QLatin1String(
"{internal~currenthost}cached-www-auth"), QLatin1String(
"true"));
5335 setMetaData(QLatin1String(
"{internal~currenthost}www-auth-realm"), authinfo.
realmValue);
5337 setMetaData(QLatin1String(
"{internal~currenthost}www-auth-challenge"), authinfo.
digestInfo);
5339 setMetaData(QLatin1String(
"{internal~allhosts}cached-proxy-auth"), QLatin1String(
"true"));
5341 setMetaData(QLatin1String(
"{internal~allhosts}proxy-auth-realm"), authinfo.
realmValue);
5343 setMetaData(QLatin1String(
"{internal~allhosts}proxy-auth-challenge"), authinfo.
digestInfo);
5349 cacheAuthentication(authinfo);
5365 authTokens = tokenizer->iterator(
"www-authenticate").all();
5368 authinfo.
prompt =
i18n(
"You need to supply a username and a "
5369 "password to access this site.");
5375 Q_ASSERT(QNetworkProxy::applicationProxy().type() == QNetworkProxy::NoProxy);
5377 authTokens = tokenizer->iterator(
"proxy-authenticate").all();
5380 authinfo.
prompt =
i18n(
"You need to supply a username and a password for "
5381 "the proxy server listed below before you are allowed "
5382 "to access any sites." );
5386 bool authRequiresAnotherRoundtrip =
false;
5391 if (!authTokens.isEmpty()) {
5393 authRequiresAnotherRoundtrip =
true;
5397 if ((*auth)->wasFinalStage()) {
5399 i18n(
"Authentication Failed.") :
5400 i18n(
"Proxy Authentication Failed."));
5408 QMutableListIterator<QByteArray> it (authTokens);
5409 const QByteArray authScheme ((*auth)->scheme().trimmed());
5410 while (it.hasNext()) {
5411 if (qstrnicmp(authScheme.constData(), it.next().constData(), authScheme.length()) != 0) {
5418 try_next_auth_scheme:
5421 const QByteArray authScheme ((*auth)->scheme().trimmed());
5422 if (qstrnicmp(authScheme.constData(), bestOffer.constData(), authScheme.length()) != 0) {
5434 kDebug(7113) <<
"Trying authentication scheme:" << (*auth)->scheme();
5440 bool generateAuthHeader =
true;
5441 if ((*auth)->needCredentials()) {
5452 if (authinfo.
realmValue.isEmpty() && !(*auth)->supportsPathMatching())
5453 authinfo.
realmValue = QLatin1String((*auth)->scheme());
5458 const KUrl reqUrl = authinfo.
url;
5459 if (!errorMsg.isEmpty() || !checkCachedAuthentication(authinfo)) {
5461 authinfo.
url = reqUrl;
5466 if (!openPasswordDialog(authinfo, errorMsg)) {
5467 generateAuthHeader =
false;
5468 authRequiresAnotherRoundtrip =
false;
5472 kDebug(7113) <<
"looks like the user canceled the authentication dialog";
5482 if (generateAuthHeader) {
5483 (*auth)->generateResponse(username, password);
5484 (*auth)->setCachePasswordEnabled(authinfo.
keepPassword);
5486 kDebug(7113) <<
"isError=" << (*auth)->isError()
5487 <<
"needCredentials=" << (*auth)->needCredentials()
5488 <<
"forceKeepAlive=" << (*auth)->forceKeepAlive()
5489 <<
"forceDisconnect=" << (*auth)->forceDisconnect();
5491 if ((*auth)->isError()) {
5492 authTokens.removeOne(bestOffer);
5493 if (!authTokens.isEmpty()) {
5494 goto try_next_auth_scheme;
5497 authRequiresAnotherRoundtrip =
false;
5500 }
else if ((*auth)->forceKeepAlive()) {
5503 }
else if ((*auth)->forceDisconnect()) {
5510 authRequiresAnotherRoundtrip =
false;
5517 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 ...
static bool readTime(QDataStream *stream, time_t *time)
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.
CachePlan plan(time_t maxCacheAge) const
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)
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)
int kdemain(int argc, char **argv)
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
long parseDateTime(const QString &input, const QString &type)
Parses a date & time string.
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)
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 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
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
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())