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"));
126 extern "C" int KDE_EXPORT
kdemain(
int argc,
char **argv )
128 QCoreApplication app( argc, argv );
134 fprintf(stderr,
"Usage: kio_http protocol domain-socket1 domain-socket2\n");
147 return QString::fromLatin1(value.constData(), value.size());
153 if (originURL == QLatin1String(
"true"))
156 KUrl url ( originURL );
159 QString a = url.host();
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)
186 QString sanitizedHeaders;
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)) {
223 const QString userName = config->
readEntry(QLatin1String(
"LastSpoofedUserName"), QString());
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) {
337 kDebug(7113) <<
"Setting" << mime->
name() <<
"as guessed mime type for" <<
name;
345 const QString protocol(url->
protocol());
346 if (protocol == QLatin1String(
"webdavs")) {
348 }
else if (protocol == QLatin1String(
"webdav")) {
358 if (!methodStringOverride.isEmpty())
359 return (methodStringOverride).toLatin1();
392 case DAV_UNSUBSCRIBE:
393 return "UNSUBSCRIBE";
413 if (!dt.
time().second()) {
414 ret.append(QLatin1String(
":00"));
416 ret.append(QLatin1String(
" GMT"));
422 return (responseCode == 401) || (responseCode == 407);
425 #define NO_SIZE ((KIO::filesize_t) -1) 428 #define STRTOLL strtoll 430 #define STRTOLL strtol 438 const QByteArray &app )
446 , m_protocol(protocol)
449 , m_socketProxyAuth(0)
451 , m_isLoadingErrorPage(false)
453 , m_iEOFRetryCount(0)
457 connect(
socket(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
477 TCPSlaveBase::reparseConfiguration();
531 kDebug(7113) <<
"ssl_was_in_use =" <<
metaData(QLatin1String(
"ssl_was_in_use"));
540 if (refUrl.isValid()) {
542 QString protocol = refUrl.
protocol();
543 if (protocol.startsWith(QLatin1String(
"webdav"))) {
544 protocol.replace(0, 6, QLatin1String(
"http"));
548 if (protocol.startsWith(QLatin1String(
"http"))) {
566 QString resumeOffset =
metaData(QLatin1String(
"resume"));
567 if (!resumeOffset.isEmpty()) {
573 QString resumeEndOffset =
metaData(QLatin1String(
"resume_until"));
574 if (!resumeEndOffset.isEmpty()) {
619 const QString& user,
const QString& pass )
628 if (host.indexOf(QLatin1Char(
':')) == -1) {
631 int pos = host.indexOf(QLatin1Char(
'%'));
657 if (u.host().isEmpty()) {
662 if (u.
path().isEmpty()) {
664 newUrl.
setPath(QLatin1String(
"/"));
687 if (dataInternal || !status) {
765 QString statSide =
metaData(QLatin1String(
"statSide"));
766 if (statSide != QLatin1String(
"source"))
813 QString query =
metaData(QLatin1String(
"davSearchQuery"));
814 if ( !query.isEmpty() )
816 QByteArray request =
"<?xml version=\"1.0\"?>\r\n";
817 request.append(
"<D:searchrequest xmlns:D=\"DAV:\">\r\n" );
818 request.append( query.toUtf8() );
819 request.append(
"</D:searchrequest>\r\n" );
825 request =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" 826 "<D:propfind xmlns:D=\"DAV:\">";
829 if (
hasMetaData(QLatin1String(
"davRequestResponse")) )
830 request +=
metaData(QLatin1String(
"davRequestResponse")).toUtf8();
833 request +=
"<D:prop>" 835 "<D:getcontentlength/>" 838 "<D:getcontentlanguage/>" 839 "<D:getcontenttype/>" 840 "<D:getlastmodified/>" 847 request +=
"</D:propfind>";
871 QDomDocument multiResponse;
874 bool hasResponse =
false;
878 for ( QDomNode n = multiResponse.documentElement().firstChild();
879 !n.isNull(); n = n.nextSibling()) {
880 QDomElement thisResponse = n.toElement();
881 if (thisResponse.isNull())
886 QDomElement href = thisResponse.namedItem(QLatin1String(
"href")).toElement();
887 if ( !href.isNull() ) {
890 QString urlStr = QUrl::fromPercentEncoding(href.text().toUtf8());
891 #if 0 // qt4/kde4 say: it's all utf8... 896 KUrl thisURL ( urlStr, encoding );
898 KUrl thisURL( urlStr );
901 if ( thisURL.isValid() ) {
906 name = QLatin1Char(
'.');
911 QDomNodeList propstats = thisResponse.elementsByTagName(QLatin1String(
"propstat"));
926 kDebug(7113) <<
"Error: no URL contained in response to PROPFIND on" << url;
930 if ( stat || !hasResponse ) {
962 const int firstSpace = response.indexOf( QLatin1Char(
' ') );
963 const int secondSpace = response.indexOf( QLatin1Char(
' '), firstSpace + 1 );
964 return response.mid( firstSpace + 1, secondSpace - firstSpace - 1 ).toInt();
970 bool foundExecutable =
false;
971 bool isDirectory =
false;
973 uint supportedLockCount = 0;
975 for (
int i = 0; i < propstats.count(); i++)
977 QDomElement propstat = propstats.item(i).toElement();
979 QDomElement status = propstat.namedItem(QLatin1String(
"status")).toElement();
980 if ( status.isNull() )
983 kDebug(7113) <<
"Error, no status code in this propstat";
991 kDebug(7113) <<
"Got status code" << code <<
"(this may mean that some properties are unavailable)";
995 QDomElement prop = propstat.namedItem( QLatin1String(
"prop") ).toElement();
998 kDebug(7113) <<
"Error: no prop segment in this propstat.";
1002 if (
hasMetaData( QLatin1String(
"davRequestResponse") ) )
1005 doc.appendChild(prop);
1009 for ( QDomNode n = prop.firstChild(); !n.isNull(); n = n.nextSibling() )
1011 QDomElement
property = n.toElement();
1012 if (property.isNull())
1015 if ( property.namespaceURI() != QLatin1String(
"DAV:") )
1021 if ( property.tagName() == QLatin1String(
"creationdate") )
1026 else if ( property.tagName() == QLatin1String(
"getcontentlength") )
1031 else if ( property.tagName() == QLatin1String(
"displayname") )
1034 setMetaData( QLatin1String(
"davDisplayName"), property.text() );
1036 else if ( property.tagName() == QLatin1String(
"source") )
1039 QDomElement source =
property.namedItem( QLatin1String(
"link") ).toElement()
1040 .namedItem( QLatin1String(
"dst") ).toElement();
1041 if ( !source.isNull() )
1042 setMetaData( QLatin1String(
"davSource"), source.text() );
1044 else if ( property.tagName() == QLatin1String(
"getcontentlanguage") )
1047 setMetaData( QLatin1String(
"davContentLanguage"), property.text() );
1049 else if ( property.tagName() == QLatin1String(
"getcontenttype") )
1054 if ( property.text() == QLatin1String(
"httpd/unix-directory") )
1060 mimeType =
property.text();
1063 else if ( property.tagName() == QLatin1String(
"executable") )
1066 if ( property.text() == QLatin1String(
"T") )
1067 foundExecutable =
true;
1070 else if ( property.tagName() == QLatin1String(
"getlastmodified") )
1075 else if ( property.tagName() == QLatin1String(
"getetag") )
1078 setMetaData( QLatin1String(
"davEntityTag"), property.text() );
1080 else if ( property.tagName() == QLatin1String(
"supportedlock") )
1083 for ( QDomNode n2 = property.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
1085 QDomElement lockEntry = n2.toElement();
1086 if ( lockEntry.tagName() == QLatin1String(
"lockentry") )
1088 QDomElement lockScope = lockEntry.namedItem( QLatin1String(
"lockscope") ).toElement();
1089 QDomElement lockType = lockEntry.namedItem( QLatin1String(
"locktype") ).toElement();
1090 if ( !lockScope.isNull() && !lockType.isNull() )
1093 supportedLockCount++;
1094 const QString lockCountStr = QString::number(supportedLockCount);
1095 const QString scope = lockScope.firstChild().toElement().tagName();
1096 const QString type = lockType.firstChild().toElement().tagName();
1098 setMetaData( QLatin1String(
"davSupportedLockScope") + lockCountStr, scope );
1099 setMetaData( QLatin1String(
"davSupportedLockType") + lockCountStr, type );
1104 else if ( property.tagName() == QLatin1String(
"lockdiscovery") )
1107 davParseActiveLocks( property.elementsByTagName( QLatin1String(
"activelock") ), lockCount );
1109 else if ( property.tagName() == QLatin1String(
"resourcetype") )
1112 if ( !property.namedItem( QLatin1String(
"collection") ).toElement().isNull() )
1120 kDebug(7113) <<
"Found unknown webdav property:" <<
property.tagName();
1125 setMetaData( QLatin1String(
"davLockCount"), QString::number(lockCount) );
1126 setMetaData( QLatin1String(
"davSupportedLockCount"), QString::number(supportedLockCount) );
1130 if ( foundExecutable || isDirectory )
1140 if ( !isDirectory && !mimeType.isEmpty() )
1149 for (
int i = 0; i < activeLocks.count(); i++ )
1151 const QDomElement activeLock = activeLocks.item(i).toElement();
1155 const QDomElement lockScope = activeLock.namedItem( QLatin1String(
"lockscope") ).toElement();
1156 const QDomElement lockType = activeLock.namedItem( QLatin1String(
"locktype") ).toElement();
1157 const QDomElement lockDepth = activeLock.namedItem( QLatin1String(
"depth") ).toElement();
1159 const QDomElement lockOwner = activeLock.namedItem( QLatin1String(
"owner") ).toElement();
1160 const QDomElement lockTimeout = activeLock.namedItem( QLatin1String(
"timeout") ).toElement();
1161 const QDomElement lockToken = activeLock.namedItem( QLatin1String(
"locktoken") ).toElement();
1163 if ( !lockScope.isNull() && !lockType.isNull() && !lockDepth.isNull() )
1167 const QString lockCountStr = QString::number(lockCount);
1168 const QString scope = lockScope.firstChild().toElement().tagName();
1169 const QString type = lockType.firstChild().toElement().tagName();
1170 const QString depth = lockDepth.text();
1172 setMetaData( QLatin1String(
"davLockScope") + lockCountStr, scope );
1173 setMetaData( QLatin1String(
"davLockType") + lockCountStr, type );
1174 setMetaData( QLatin1String(
"davLockDepth") + lockCountStr, depth );
1176 if ( !lockOwner.isNull() )
1177 setMetaData( QLatin1String(
"davLockOwner") + lockCountStr, lockOwner.text() );
1179 if ( !lockTimeout.isNull() )
1180 setMetaData( QLatin1String(
"davLockTimeout") + lockCountStr, lockTimeout.text() );
1182 if ( !lockToken.isNull() )
1184 QDomElement tokenVal = lockScope.namedItem( QLatin1String(
"href") ).toElement();
1185 if ( !tokenVal.isNull() )
1186 setMetaData( QLatin1String(
"davLockToken") + lockCountStr, tokenVal.text() );
1194 if (
hasMetaData( QLatin1String(
"davLockCount") ) )
1196 QString response = QLatin1String(
"If:");
1197 int numLocks =
metaData( QLatin1String(
"davLockCount") ).toInt();
1198 bool bracketsOpen =
false;
1199 for (
int i = 0; i < numLocks; i++ )
1201 const QString countStr = QString::number(i);
1202 if (
hasMetaData( QLatin1String(
"davLockToken") + countStr ) )
1204 if (
hasMetaData( QLatin1String(
"davLockURL") + countStr ) )
1208 response += QLatin1Char(
')');
1209 bracketsOpen =
false;
1211 response += QLatin1String(
" <") +
metaData( QLatin1String(
"davLockURL") + countStr ) + QLatin1Char(
'>');
1214 if ( !bracketsOpen )
1216 response += QLatin1String(
" (");
1217 bracketsOpen =
true;
1221 response += QLatin1Char(
' ');
1224 if (
hasMetaData( QLatin1String(
"davLockNot") + countStr ) )
1225 response += QLatin1String(
"Not ");
1227 response += QLatin1Char(
'<') +
metaData( QLatin1String(
"davLockToken") + countStr ) + QLatin1Char(
'>');
1232 response += QLatin1Char(
')');
1234 response += QLatin1String(
"\r\n");
1254 kDebug(7113) <<
" false";
1277 if (ok && verNo > 0 && verNo < 3)
1280 kDebug(7113) <<
"Server supports DAV version" << verNo;
1331 const QString tmp (
metaData(QLatin1String(
"cache")));
1368 kDebug(7113) << src <<
"->" << dest;
1371 const bool isDestinationLocal = dest.isLocalFile();
1373 if (isSourceLocal && !isDestinationLocal) {
1383 KUrl newDest (dest);
1405 kDebug(7113) << src <<
"->" << dest;
1493 const QString& type,
const QString& owner )
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() )
1591 QString action, errorString;
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>");
1698 Q_FOREACH(
const QString&
error, errors)
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);
1830 const QString action (
i18nc(
"request type",
"upload %1", request.
url.
prettyUrl()));
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);
1889 QString errorString;
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) {
1974 QString tmp =
metaData(QLatin1String(
"cache"));
1989 while (it.hasNext()) {
2001 while (it.hasNext()) {
2018 setMetaData(QLatin1String(
"request-id"), QString::number(requestId++));
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")) {
2197 int connectError = 0;
2198 QString errorString;
2207 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2212 if (proxyUrl == QLatin1String(
"DIRECT")) {
2213 QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy);
2215 if (connectError == 0) {
2223 const KUrl url(proxyUrl);
2224 const QString proxyScheme(url.
protocol());
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;
2428 bool cacheHasPage =
false;
2430 kDebug(7113) <<
"cacheHasPage =" << cacheHasPage;
2431 return cacheHasPage;
2433 if (!cacheHasPage) {
2450 davHeader = QLatin1String(
"Depth: ");
2453 kDebug(7113) <<
"Reading DAV depth from metadata:" <<
metaData( QLatin1String(
"davDepth") );
2454 davHeader +=
metaData( QLatin1String(
"davDepth") );
2459 davHeader += QLatin1String(
"infinity");
2463 davHeader += QLatin1String(
"\r\n");
2475 davHeader += QLatin1String(
"\r\nDepth: infinity\r\nOverwrite: ");
2477 davHeader += QLatin1String(
"\r\n");
2480 davHeader = QLatin1String(
"Timeout: ");
2484 timeout =
metaData( QLatin1String(
"davTimeout") ).toUInt();
2486 davHeader += QLatin1String(
"Infinite");
2488 davHeader += QLatin1String(
"Seconds-") + QString::number(timeout);
2490 davHeader += QLatin1String(
"\r\n");
2494 davHeader = QLatin1String(
"Lock-token: ") +
metaData(QLatin1String(
"davLockToken")) + QLatin1String(
"\r\n");
2501 case DAV_UNSUBSCRIBE:
2515 header += QLatin1Char(
':') + QString::number(
m_request.
url.port());
2517 header += QLatin1String(
"\r\n");
2524 header += QLatin1String(
"Proxy-Connection: ");
2526 header += QLatin1String(
"Connection: ");
2529 header += QLatin1String(
"keep-alive\r\n");
2531 header += QLatin1String(
"close\r\n");
2536 header += QLatin1String(
"User-Agent: ");
2538 header += QLatin1String(
"\r\n");
2543 header += QLatin1String(
"Referer: ");
2545 header += QLatin1String(
"\r\n");
2550 header += QLatin1String(
"Range: bytes=");
2552 header += QLatin1Char(
'-');
2554 header += QLatin1String(
"\r\n");
2560 header += QLatin1String(
"Range: bytes=");
2562 header += QLatin1String(
"-\r\n");
2569 header += QLatin1String(
"Pragma: no-cache\r\n");
2570 header += QLatin1String(
"Cache-control: no-cache\r\n");
2574 kDebug(7113) <<
"needs validation, performing conditional get.";
2581 header += QLatin1String(
"If-Modified-Since: ") + httpDate + QLatin1String(
"\r\n");
2586 header += QLatin1String(
"Accept: ");
2587 const QString acceptHeader =
metaData(QLatin1String(
"accept"));
2588 if (!acceptHeader.isEmpty())
2589 header += acceptHeader;
2592 header += QLatin1String(
"\r\n");
2595 header += QLatin1String(
"Accept-Encoding: gzip, deflate, x-gzip, x-deflate\r\n");
2598 header += QLatin1String(
"Accept-Charset: ") +
m_request.
charsets + QLatin1String(
"\r\n");
2601 header += QLatin1String(
"Accept-Language: ") +
m_request.
languages + QLatin1String(
"\r\n");
2604 const QString cookieMode =
metaData(QLatin1String(
"cookies")).toLower();
2606 if (cookieMode == QLatin1String(
"none"))
2610 else if (cookieMode == QLatin1String(
"manual"))
2613 cookieStr =
metaData(QLatin1String(
"setcookies"));
2622 if (!cookieStr.isEmpty())
2623 header += cookieStr + QLatin1String(
"\r\n");
2625 const QString customHeader =
metaData( QLatin1String(
"customHTTPHeader") );
2626 if (!customHeader.isEmpty())
2629 header += QLatin1String(
"\r\n");
2632 const QString contentType =
metaData(QLatin1String(
"content-type"));
2633 if (!contentType.isEmpty())
2635 if (!contentType.startsWith(QLatin1String(
"content-type"), Qt::CaseInsensitive))
2636 header += QLatin1String(
"Content-Type: ");
2637 header += contentType;
2638 header += QLatin1String(
"\r\n");
2643 header += QLatin1String(
"DNT: 1\r\n");
2656 davHeader +=
metaData(QLatin1String(
"davHeader"));
2660 davHeader += QLatin1String(
"Content-Type: text/xml; charset=utf-8\r\n");
2663 header += davHeader;
2667 kDebug(7103) <<
"============ Sending Header:";
2668 Q_FOREACH (
const QString &s, header.split(QLatin1String(
"\r\n"), QString::SkipEmptyParts)) {
2674 if (!hasBodyData && !hasDavData)
2675 header += QLatin1String(
"\r\n");
2684 const QByteArray headerBytes = header.toLatin1();
2685 ssize_t
written =
write(headerBytes.constData(), headerBytes.length());
2686 bool sendOk = (written == (ssize_t) headerBytes.length());
2690 <<
" -- intended to write" << headerBytes.length()
2691 <<
"bytes but wrote" << (int)written <<
".";
2701 kDebug(7113) <<
"sendOk == false. Connection broken !" 2702 <<
" -- intended to write" << headerBytes.length()
2703 <<
"bytes but wrote" << (int)written <<
".";
2708 kDebug(7113) <<
"sent it!";
2711 if (hasBodyData || hasDavData)
2727 if (forwardImmediately)
2739 const QString
header = str.trimmed();
2740 if (header.startsWith(QLatin1String(
"content-type:"), Qt::CaseInsensitive)) {
2741 int pos = header.indexOf(QLatin1String(
"charset="), Qt::CaseInsensitive);
2743 const QString charset = header.mid(pos + 8).toLower();
2747 }
else if (header.startsWith(QLatin1String(
"content-language:"), Qt::CaseInsensitive)) {
2748 const QString language = header.mid(17).trimmed().toLower();
2749 setMetaData(QLatin1String(
"content-language"), language);
2750 }
else if (header.startsWith(QLatin1String(
"content-disposition:"), Qt::CaseInsensitive)) {
2777 if (
m_mimeType == QLatin1String(
"application/x-targz"))
2778 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2779 else if (
m_mimeType == QLatin1String(
"image/x-png"))
2783 else if (
m_mimeType == QLatin1String(
"audio/microsoft-wave"))
2785 else if (
m_mimeType == QLatin1String(
"image/x-ms-bmp"))
2789 else if (
m_mimeType == QLatin1String(
"application/pkix-cert") ||
2790 m_mimeType == QLatin1String(
"application/binary-certificate")) {
2791 m_mimeType = QLatin1String(
"application/x-x509-ca-cert");
2795 else if (
m_mimeType == QLatin1String(
"application/x-gzip")) {
2798 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2800 m_mimeType = QLatin1String(
"application/x-gzpostscript");
2805 else if(
m_mimeType == QLatin1String(
"application/x-xz")) {
2808 m_mimeType = QLatin1String(
"application/x-xz-compressed-tar");
2813 else if ((
m_mimeType == QLatin1String(
"text/plain")) || (
m_mimeType == QLatin1String(
"application/octet-stream"))) {
2815 if (ext == QLatin1String(
"BZ2"))
2816 m_mimeType = QLatin1String(
"application/x-bzip");
2817 else if (ext == QLatin1String(
"PEM"))
2818 m_mimeType = QLatin1String(
"application/x-x509-ca-cert");
2819 else if (ext == QLatin1String(
"SWF"))
2820 m_mimeType = QLatin1String(
"application/x-shockwave-flash");
2821 else if (ext == QLatin1String(
"PLS"))
2823 else if (ext == QLatin1String(
"WMV"))
2824 m_mimeType = QLatin1String(
"video/x-ms-wmv");
2825 else if (ext == QLatin1String(
"WEBM"))
2827 else if (ext == QLatin1String(
"DEB"))
2828 m_mimeType = QLatin1String(
"application/x-deb");
2842 if (
m_mimeType == QLatin1String(
"application/x-tar")) {
2844 m_mimeType = QLatin1String(
"application/x-compressed-tar");
2845 }
else if (
m_mimeType == QLatin1String(
"application/postscript")) {
2849 m_mimeType = QLatin1String(
"application/x-gzpostscript");
2854 m_mimeType != QLatin1String(
"application/x-compressed-tar") &&
2855 m_mimeType != QLatin1String(
"application/x-tgz") &&
2856 m_mimeType != QLatin1String(
"application/x-targz") &&
2857 m_mimeType != QLatin1String(
"application/x-gzip"))) {
2861 m_mimeType = QLatin1String(
"application/x-gzip");
2873 m_mimeType = QLatin1String(
"application/x-bzip");
2880 static bool consume(
const char input[],
int *pos,
int end,
const char *term)
2884 if (idx + (
int)strlen(term) >= end) {
2888 if (strncasecmp(&input[idx], term, strlen(term)) == 0) {
2889 *pos = idx + strlen(term);
2913 bool upgradeRequired =
false;
2917 bool noHeadersFound =
false;
2922 static const int maxHeaderSize = 128 * 1024;
2924 char buffer[maxHeaderSize];
2926 bool bCanResume =
false;
2929 kDebug(7113) <<
"No connection.";
2939 kDebug(7113) <<
"Got socket error:" <<
socket()->errorString();
2948 if (!foundDelimiter && bufPos < maxHeaderSize) {
2949 kDebug(7113) <<
"EOF while waiting for header start.";
2966 kDebug(7113) <<
"Connection broken !";
2970 if (!foundDelimiter) {
2975 kDebug(7103) <<
"============ Received Status Response:";
2976 kDebug(7103) << QByteArray(buffer, bufPos).trimmed();
2981 if (idx != bufPos && buffer[idx] ==
'<') {
2982 kDebug(7103) <<
"No valid HTTP header found! Document starts with XML/HTML tag";
2988 noHeadersFound =
true;
2995 if (
consume(buffer, &idx, bufPos,
"ICY ")) {
2998 }
else if (
consume(buffer, &idx, bufPos,
"HTTP/")) {
2999 if (
consume(buffer, &idx, bufPos,
"1.0")) {
3002 }
else if (
consume(buffer, &idx, bufPos,
"1.1")) {
3007 if (httpRev ==
HTTP_None && bufPos != 0) {
3010 kDebug(7113) <<
"DO NOT WANT." << bufPos;
3018 noHeadersFound =
true;
3029 if (idx != bufPos) {
3046 i18nc(
"@info Security check on url being accessed",
3047 "<p>You are about to log in to the site \"%1\" " 3048 "with the username \"%2\", but the website " 3049 "does not require authentication. " 3050 "This may be an attempt to trick you.</p>" 3051 "<p>Is \"%1\" the site you want to visit?</p>",
3053 i18nc(
"@title:window",
"Confirm Website Access"));
3080 upgradeRequired =
true;
3102 setMetaData(QLatin1String(
"permanent-redirect"), QLatin1String(
"true"));
3106 setMetaData(QLatin1String(
"redirect-to-get"), QLatin1String(
"true"));
3111 setMetaData(QLatin1String(
"redirect-to-get"), QLatin1String(
"true"));
3115 setMetaData(QLatin1String(
"permanent-redirect"), QLatin1String(
"true"));
3150 bool authRequiresAnotherRoundtrip =
false;
3153 if (!noHeadersFound) {
3158 kDebug(7113) <<
"wasAuthError=" << wasAuthError <<
"isAuthError=" << isAuthError
3159 <<
"sameAuthError=" << sameAuthError;
3171 kDebug(7113) <<
" -- full response:" << endl << QByteArray(buffer, bufPos).trimmed();
3174 Q_ASSERT(foundDelimiter);
3181 tokenizer.
tokenize(idx,
sizeof(buffer));
3186 if (tIt.
hasNext() && tIt.
next().toLower().startsWith(
"none")) {
3190 tIt = tokenizer.iterator(
"keep-alive");
3192 QByteArray ka = tIt.
next().trimmed().toLower();
3193 if (ka.startsWith(
"timeout=")) {
3194 int ka_timeout = ka.mid(qstrlen(
"timeout=")).trimmed().toInt();
3206 tIt = tokenizer.iterator(
"content-length");
3211 tIt = tokenizer.iterator(
"content-location");
3212 if (tIt.hasNext()) {
3218 QString mediaAttribute;
3219 tIt = tokenizer.iterator(
"content-type");
3220 if (tIt.hasNext()) {
3225 if (
m_mimeType.startsWith(QLatin1Char(
'"'))) {
3237 Q_FOREACH (
const QByteArray &statement, l) {
3238 const int index = statement.indexOf(
'=');
3240 mediaAttribute =
toQString(statement.mid(0, index));
3242 mediaAttribute =
toQString(statement.mid(0, index));
3243 mediaValue =
toQString(statement.mid(index+1));
3245 mediaAttribute = mediaAttribute.trimmed();
3246 mediaValue = mediaValue.trimmed();
3248 bool quoted =
false;
3249 if (mediaValue.startsWith(QLatin1Char(
'"'))) {
3251 mediaValue.remove(0, 1);
3254 if (mediaValue.endsWith(QLatin1Char(
'"'))) {
3258 kDebug (7113) <<
"Encoding-type:" << mediaAttribute <<
"=" << mediaValue;
3260 if (mediaAttribute == QLatin1String(
"charset")) {
3261 mediaValue = mediaValue.toLower();
3263 setMetaData(QLatin1String(
"charset"), mediaValue);
3265 setMetaData(QLatin1String(
"media-") + mediaAttribute, mediaValue);
3267 setMetaData(QLatin1String(
"media-") + mediaAttribute + QLatin1String(
"-kio-quoted"),
3268 QLatin1String(
"true"));
3275 tIt = tokenizer.iterator(
"content-encoding");
3276 while (tIt.hasNext()) {
3293 tIt = tokenizer.iterator(
"content-disposition");
3294 if (tIt.hasNext()) {
3297 tIt = tokenizer.iterator(
"content-language");
3298 if (tIt.hasNext()) {
3299 QString language =
toQString(tIt.next().trimmed());
3300 if (!language.isEmpty()) {
3301 setMetaData(QLatin1String(
"content-language"), language);
3305 tIt = tokenizer.iterator(
"proxy-connection");
3307 QByteArray pc = tIt.next().toLower();
3308 if (pc.startsWith(
"close")) {
3310 }
else if (pc.startsWith(
"keep-alive")) {
3315 tIt = tokenizer.iterator(
"link");
3316 if (tIt.hasNext()) {
3318 QStringList
link =
toQString(tIt.next()).split(QLatin1Char(
';'), QString::SkipEmptyParts);
3319 if (link.count() == 2) {
3320 QString rel = link[1].trimmed();
3321 if (rel.startsWith(QLatin1String(
"rel=\""))) {
3322 rel = rel.mid(5, rel.length() - 6);
3323 if (rel.toLower() == QLatin1String(
"pageservices")) {
3325 QString url = link[0].remove(QRegExp(QLatin1String(
"[<>]"))).trimmed();
3332 tIt = tokenizer.iterator(
"p3p");
3333 if (tIt.hasNext()) {
3335 QStringList policyrefs, compact;
3336 while (tIt.hasNext()) {
3337 QStringList policy =
toQString(tIt.next().simplified())
3338 .split(QLatin1Char(
'='), QString::SkipEmptyParts);
3339 if (policy.count() == 2) {
3340 if (policy[0].toLower() == QLatin1String(
"policyref")) {
3341 policyrefs << policy[1].remove(QRegExp(QLatin1String(
"[\")\']"))).trimmed();
3342 }
else if (policy[0].toLower() == QLatin1String(
"cp")) {
3346 const QString s = policy[1].remove(QRegExp(QLatin1String(
"[\")\']")));
3347 const QStringList cps = s.split(QLatin1Char(
' '), QString::SkipEmptyParts);
3352 if (!policyrefs.isEmpty()) {
3353 setMetaData(QLatin1String(
"PrivacyPolicy"), policyrefs.join(QLatin1String(
"\n")));
3355 if (!compact.isEmpty()) {
3356 setMetaData(QLatin1String(
"PrivacyCompactPolicy"), compact.join(QLatin1String(
"\n")));
3363 tIt = tokenizer.iterator(
"connection");
3364 while (tIt.hasNext()) {
3365 QByteArray connection = tIt.next().toLower();
3367 if (connection.startsWith(
"close")) {
3369 }
else if (connection.startsWith(
"keep-alive")) {
3373 if (connection.startsWith(
"upgrade")) {
3376 upgradeRequired =
true;
3377 }
else if (upgradeRequired) {
3383 tIt = tokenizer.iterator(
"transfer-encoding");
3384 while (tIt.hasNext()) {
3392 tIt = tokenizer.iterator(
"content-md5");
3393 if (tIt.hasNext()) {
3399 tIt = tokenizer.iterator(
"dav");
3400 while (tIt.hasNext()) {
3408 QStringList upgradeOffers;
3409 tIt = tokenizer.iterator(
"upgrade");
3410 if (tIt.hasNext()) {
3412 QString offered =
toQString(tIt.next());
3413 upgradeOffers = offered.split(QRegExp(QLatin1String(
"[ \n,\r\t]")), QString::SkipEmptyParts);
3415 Q_FOREACH (
const QString &opt, upgradeOffers) {
3416 if (opt == QLatin1String(
"TLS/1.0")) {
3417 if (!
startSsl() && upgradeRequired) {
3421 }
else if (opt == QLatin1String(
"HTTP/1.1")) {
3423 }
else if (upgradeRequired) {
3431 QByteArray cookieStr;
3432 tIt = tokenizer.iterator(
"set-cookie");
3433 while (tIt.hasNext()) {
3434 cookieStr +=
"Set-Cookie: ";
3435 cookieStr += tIt.next();
3438 if (!cookieStr.isEmpty()) {
3443 cookieStr =
"Cross-Domain\n" + cookieStr;
3448 setMetaData(QLatin1String(
"setcookies"), QString::fromUtf8(cookieStr));
3456 kDebug(7113) <<
"cont; returning to mark try_again";
3462 kDebug(7113) <<
"Ignoring keep-alive: otherwise unable to determine response body length.";
3477 authRequiresAnotherRoundtrip =
false;
3480 QString locationStr;
3482 tIt = tokenizer.iterator(
"location");
3484 locationStr = QString::fromUtf8(tIt.next().trimmed());
3487 if (!locationStr.isEmpty())
3514 if(u.
protocol() == QLatin1String(
"http")){
3516 }
else if(u.
protocol() == QLatin1String(
"https")){
3556 kDebug(7113) <<
"Reading resource from cache even though the cache plan is not " 3557 "UseCached; the server is probably sending wrong expiry information.";
3567 int nextLinePos = 0;
3568 int prevLinePos = 0;
3569 bool haveMore =
true;
3571 haveMore =
nextLine(buffer, &nextLinePos, bufPos);
3572 int prevLineEnd = nextLinePos;
3573 while (buffer[prevLineEnd - 1] ==
'\r' || buffer[prevLineEnd - 1] ==
'\n') {
3578 prevLineEnd - prevLinePos));
3579 prevLinePos = nextLinePos;
3606 return !authRequiresAnotherRoundtrip;
3614 while (i != parameters.constEnd()) {
3615 setMetaData(QLatin1String(
"content-disposition-") + i.key(), i.value());
3616 kDebug(7113) <<
"Content-Disposition:" << i.key() <<
"=" << i.value();
3623 QString encoding = _encoding.trimmed().toLower();
3625 if (encoding == QLatin1String(
"identity")) {
3627 }
else if (encoding == QLatin1String(
"8bit")) {
3630 }
else if (encoding == QLatin1String(
"chunked")) {
3635 }
else if ((encoding == QLatin1String(
"x-gzip")) || (encoding == QLatin1String(
"gzip"))) {
3636 encs.append(QLatin1String(
"gzip"));
3637 }
else if ((encoding == QLatin1String(
"x-bzip2")) || (encoding == QLatin1String(
"bzip2"))) {
3638 encs.append(QLatin1String(
"bzip2"));
3639 }
else if ((encoding == QLatin1String(
"x-deflate")) || (encoding == QLatin1String(
"deflate"))) {
3640 encs.append(QLatin1String(
"deflate"));
3642 kDebug(7113) <<
"Unknown encoding encountered. " 3643 <<
"Please write code. Encoding =" << encoding;
3661 const qint64 currentDate = QDateTime::currentMSecsSinceEpoch()/1000;
3676 qint64 dateHeader = -1;
3677 tIt = tokenizer.iterator(
"date");
3683 qint64 ageHeader = 0;
3684 tIt = tokenizer.iterator(
"age");
3686 ageHeader = tIt.
next().toLongLong();
3690 if (dateHeader != -1) {
3692 }
else if (ageHeader) {
3699 bool hasCacheDirective =
false;
3703 qint64 maxAgeHeader = 0;
3704 tIt = tokenizer.iterator(
"cache-control");
3706 QByteArray cacheStr = tIt.
next().toLower();
3707 if (cacheStr.startsWith(
"no-cache") || cacheStr.startsWith(
"no-store")) {
3710 hasCacheDirective =
true;
3711 }
else if (cacheStr.startsWith(
"max-age=")) {
3712 QByteArray ba = cacheStr.mid(qstrlen(
"max-age=")).trimmed();
3714 maxAgeHeader = ba.toLongLong(&ok);
3716 hasCacheDirective =
true;
3721 qint64 expiresHeader = -1;
3722 tIt = tokenizer.iterator(
"expires");
3725 kDebug(7113) <<
"parsed expire date from 'expires' header:" << tIt.
current();
3730 }
else if (expiresHeader != -1) {
3739 expAge = qMin(expAge, qint64(3600 * 24));
3752 tIt = tokenizer.iterator(
"etag");
3757 kDebug(7103) <<
"304 Not Modified but new entity tag - I don't think this is legal HTTP.";
3762 tIt = tokenizer.iterator(
"warning");
3770 tIt = tokenizer.iterator(
"pragma");
3772 if (tIt.
next().toLower().startsWith(
"no-cache")) {
3774 hasCacheDirective =
true;
3779 tIt = tokenizer.iterator(
"refresh");
3786 if (
m_mimeType.startsWith(QLatin1String(
"text/")) && (
m_mimeType != QLatin1String(
"text/css")) &&
3787 (
m_mimeType != QLatin1String(
"text/x-javascript")) && !hasCacheDirective) {
3798 kDebug(7113) <<
"Cache needs validation";
3800 kDebug(7113) <<
"...was revalidated by response code but not by updated expire times. " 3801 "We're going to set the expire date to 60 seconds in the future...";
3807 kDebug(7113) <<
"this proxy or server apparently sends bogus expiry information.";
3824 kDebug(7113) <<
"This webserver is confused about the cacheability of the data it sends.";
3838 if (!cachingAllowed) {
3839 setMetaData(QLatin1String(
"no-cache"), QLatin1String(
"true"));
3840 setMetaData(QLatin1String(
"expire-date"), QLatin1String(
"1"));
3847 setMetaData(QLatin1String(
"cache-creation-date"), tmp);
3856 QByteArray cLength (
"Content-Length: ");
3857 cLength += QByteArray::number(size);
3858 cLength +=
"\r\n\r\n";
3860 kDebug(7113) <<
"sending cached data (size=" << size <<
")";
3863 bool sendOk = (
write(cLength.data(), cLength.size()) == (ssize_t) cLength.size());
3865 kDebug( 7113 ) <<
"Connection broken when sending " 3878 const QByteArray buffer =
m_POSTbuf->read(65536);
3879 const ssize_t bytesSent =
write(buffer.data(), buffer.size());
3880 if (bytesSent != static_cast<ssize_t>(buffer.size())) {
3881 kDebug(7113) <<
"Connection broken when sending message body: (" 3887 totalBytesSent += bytesSent;
3915 QByteArray cLength (
"Content-Length: ");
3917 cLength +=
"\r\n\r\n";
3919 kDebug(7113) << cLength.trimmed();
3922 bool sendOk = (
write(cLength.data(), cLength.size()) == (ssize_t) cLength.size());
3932 kDebug(7113) <<
"Connection broken while sending POST content size to" <<
m_request.
url.host();
3951 const int bytesRead =
readData(buffer);
3954 if (bytesRead == 0) {
3960 if (bytesRead < 0) {
3974 if (
write(buffer.data(), bytesRead) == static_cast<ssize_t>(bytesRead)) {
3975 bytesSent += bytesRead;
3980 kDebug(7113) <<
"Connection broken while sending POST content to" <<
m_request.
url.host();
3990 kDebug(7113) <<
"keepAlive =" << keepAlive;
4006 QDataStream stream( &data, QIODevice::WriteOnly );
4065 QDataStream stream(data);
4073 stream >> url >> size;
4082 stream >> url >> no_cache >> expireDate;
4088 QFile::remove(filename);
4108 QString scope, type, owner;
4109 stream >> url >> scope >> type >> owner;
4110 davLock( url, scope, type, owner );
4125 stream >> url >> method >> size;
4126 davGeneric( url, (KIO::HTTP_METHOD) method, size );
4155 if (foundCrLf && bufPos == 2) {
4162 kDebug(7113) <<
"Failed to read chunk header.";
4165 Q_ASSERT(bufPos > 2);
4168 if (nextChunkSize < 0)
4170 kDebug(7113) <<
"Negative chunk size";
4187 int trashBufPos = 2;
4190 if (trashBufPos > 3) {
4192 for (
int i = 0; i < 3; i++) {
4193 trash[i] = trash[trashBufPos - 3 + i];
4200 kDebug(7113) <<
"Failed to read chunk trailer.";
4212 return bytesReceived;
4230 if (bytesReceived <= 0)
4234 return bytesReceived;
4241 kDebug(7113) <<
"Unbounded datastream on a Keep-alive connection!";
4281 kDebug(7113) <<
"Determining mime-type from content...";
4376 if ( !dataInternal ) {
4387 kDebug(7113) <<
"reading data from cache...";
4399 if (!dataInternal) {
4406 if (!dataInternal) {
4434 QObject::connect(&chain, SIGNAL(
output(QByteArray)),
4437 QObject::connect(&chain, SIGNAL(
error(QString)),
4444 if ( enc == QLatin1String(
"gzip") )
4446 else if ( enc == QLatin1String(
"deflate") )
4474 if ( enc == QLatin1String(
"gzip") )
4476 else if ( enc == QLatin1String(
"deflate") )
4495 if (bytesReceived == -1)
4505 kDebug(7113) <<
"bytesReceived==-1 sz=" << (int)sz
4506 <<
" Connection broken !";
4513 if (bytesReceived > 0)
4524 sz += bytesReceived;
4547 QString calculatedMD5 = md5Filter->
md5();
4550 kWarning(7113) <<
"MD5 checksum MISMATCH! Expected:" 4559 if (!dataInternal && sz <= 1)
4572 data( QByteArray() );
4600 SlaveBase::error( _err, _text );
4608 QDBusInterface kcookiejar( QLatin1String(
"org.kde.kded"), QLatin1String(
"/modules/kcookiejar"), QLatin1String(
"org.kde.KCookieServer") );
4609 (void)kcookiejar.call( QDBus::NoBlock, QLatin1String(
"addCookies"), url,
4610 cookieHeader, windowId );
4616 QDBusInterface kcookiejar( QLatin1String(
"org.kde.kded"), QLatin1String(
"/modules/kcookiejar"), QLatin1String(
"org.kde.KCookieServer") );
4617 QDBusReply<QString> reply = kcookiejar.call( QLatin1String(
"findCookies"), url, windowId );
4619 if ( !reply.isValid() )
4621 kWarning(7113) <<
"Can't communicate with kded_kcookiejar!";
4636 if (lastModifiedDate != -1 || !etag.isEmpty()) {
4637 return ValidateCached;
4641 return IgnoreCached;
4650 qint64 currentDate = QDateTime::currentMSecsSinceEpoch()/1000;
4651 if ((servedDate != -1 && currentDate > (servedDate + maxCacheAge)) ||
4652 (expireDate != -1 && currentDate > expireDate)) {
4653 return ValidateCached;
4663 struct BinaryCacheFileHeader
4670 qint64 lastModifiedDate;
4675 static const int size = 36;
4687 BinaryCacheFileHeader
header;
4688 quint32 commandCode;
4696 QDataStream stream(&ret, QIODevice::WriteOnly);
4697 stream << quint8(
'A');
4698 stream << quint8(
'\n');
4699 stream << quint8(0);
4700 stream << quint8(0);
4702 stream << fileUseCount;
4703 stream << servedDate;
4704 stream << lastModifiedDate;
4705 stream << expireDate;
4707 stream << bytesCached;
4708 Q_ASSERT(ret.size() == BinaryCacheFileHeader::size);
4716 return byte == value;
4725 if (d.size() != BinaryCacheFileHeader::size) {
4728 QDataStream stream(d);
4729 stream.setVersion(QDataStream::Qt_4_5);
4740 stream >> fileUseCount;
4741 stream >> servedDate;
4742 stream >> lastModifiedDate;
4743 stream >> expireDate;
4744 stream >> bytesCached;
4762 ret.setPassword(QString());
4763 ret.setFragment(QString());
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);
4949 stream << quint32(cmd);
4951 QString fileName = cacheTag.
file->fileName();
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();
4986 QString newName = oldName;
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()) {
5023 Q_ASSERT(command.size() == BinaryCacheFileHeader::size +
s_hashedUrlNibbles +
sizeof(quint32));
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());
5163 const QByteArray cachedChallenge =
config()->
readEntry(
"www-auth-challenge", QByteArray());
5164 if (!cachedChallenge.isEmpty()) {
5167 kDebug(7113) <<
"creating www authentcation header from cached info";
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();
5252 if (!haveCachedCredentials || retryAuth) {
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()));
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";
5314 bool alreadyCached =
false;
5330 if (auth && (!auth->
realm().isEmpty() || !alreadyCached)) {
5333 setMetaData(QLatin1String(
"{internal~currenthost}cached-www-auth"), QLatin1String(
"true"));
5339 setMetaData(QLatin1String(
"{internal~allhosts}cached-proxy-auth"), QLatin1String(
"true"));
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();
5439 QString username, password;
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;
5461 authinfo.
url = reqUrl;
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;
5522 kDebug(7113) << src <<
"->" << dest;
5543 if (!
m_POSTbuf->open(QFile::ReadOnly)) {
5556 const QByteArray request (
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" 5557 "<D:propfind xmlns:D=\"DAV:\"><D:prop>" 5559 "<D:getcontentlength/>" 5562 "</D:prop></D:propfind>");
#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)
QString encodedPathAndQuery(AdjustPathOption trailing=LeaveTrailingSlash, const EncodedPathAndQueryOptions &options=PermitEmptyPath) const
QString stringValue(uint field) const
void redirection(const KUrl &_url)
void adjustPath(AdjustPathOption trailing)
bool m_davHostUnsupported
void davStatList(const KUrl &url, bool stat=true)
void cacheParseResponseHeader(const HeaderTokenizer &tokenizer)
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
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.
static List split(const QString &_url)
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
QString formatRequestUri() const
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.
bool openPasswordDialog(KIO::AuthInfo &info, const QString &errorMsg=QString())
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)
static bool isEncryptedHttpVariety(const QByteArray &p)
static bool isHttpProxy(const KUrl &u)
KIO::filesize_t m_iPostDataSize
virtual void closeConnection()
Forced close of connection.
CachePlan plan(int maxCacheAge) 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)
QString cacheFilePathFromUrl(const KUrl &url) const
MetaData mIncomingMetaData
bool checkCachedAuthentication(AuthInfo &info)
virtual void get(const KUrl &url)
#define DEFAULT_CACHE_EXPIRE
QString methodStringOverride
QIODevice * socket() const
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)
void setMetaData(const QString &key, const QString &value)
QString prettyUrl(AdjustPathOption trailing=LeaveTrailingSlash) const
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)
static void changeProtocolToHttp(KUrl *url)
void error(int errid, const QString &text)
#define DEFAULT_MIME_TYPE
void mimeType(const QString &_type)
void setPath(const QString &path)
virtual void put(const KUrl &url, int _mode, KIO::JobFlags flags)
void totalSize(KIO::filesize_t _bytes)
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 hasMetaData(const QString &key) const
bool deserialize(const QByteArray &)
virtual void fillKioAuthInfo(KIO::AuthInfo *ai) const =0
KIO compatible data to find cached credentials.
QString realm() const
Returns the realm sent by the server.
QByteArray m_webDavDataBuf
QStringList m_responseHeaders
All headers.
QString toString(const QString &format) const
int messageBox(MessageBoxType type, const QString &text, const QString &caption=QString(), const QString &buttonYes=i18n("&Yes"), const QString &buttonNo=i18n("&No"))
int readUnlimited()
Read as much as possible.
void setProtocol(const QString &proto)
void infoMessage(const QString &msg)
void processedSize(KIO::filesize_t _bytes)
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.
void setTimeoutSpecialCommand(int timeout, const QByteArray &data=QByteArray())
#define DEFAULT_PARTIAL_CHARSET_HEADER
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.
long long numberValue(uint field, long long defaultValue=0) const
static const int s_hashedUrlBytes
virtual void mimetype(const KUrl &url)
void statEntry(const UDSEntry &_entry)
QAuthenticator * m_socketProxyAuth
bool satisfyRequestFromCache(bool *cacheHasPage)
Return true if the request is already "done", false otherwise.
bool davStatDestination()
Stats a remote DAV file and returns true if it exists.
virtual void setHost(const QString &host, quint16 port, const QString &user, const QString &pass)
void updateCredentials(const HTTPRequest &request)
KAbstractHttpAuthentication * m_wwwAuth
bool cacheAuthentication(const AuthInfo &info)
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
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)
void davUnlock(const KUrl &url)
int readChunked()
Read a chunk.
QString readPathEntry(const QString &pKey, const QString &aDefault) const
void data(const QByteArray &data)
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
void written(KIO::filesize_t _bytes)
bool proceedUntilResponseHeader()
Ensure we are connected, send our query, and get the response header.
QByteArray methodString() const
KIO::CacheControl parseCacheControl(const QString &cacheControl)
KRemoteEncoding * remoteEncoding()
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.
KIO::filesize_t m_iContentLeft
of content bytes left
static Ptr findByNameAndContent(const QString &name, const QByteArray &data, mode_t mode=0, int *accuracy=0)
QByteArray serialize() const
void forwardHttpResponseHeader(bool forwardImmediately=true)
void resetSessionSettings()
Resets any per session settings.
void sendAndKeepMetaData()
void httpClose(bool keepAlive)
Close transfer.
virtual void slave_status()
#define DEFAULT_LANGUAGE_HEADER
bool handleAuthenticationHeader(const HeaderTokenizer *tokenizer)
Handles HTTP authentication.
void listEntry(const UDSEntry &_entry, bool ready)
void clearPostDataBuffer()
Clears the POST data buffer.
static QMap< QString, QString > contentDispositionParser(const QString &disposition)
T readEntry(const QString &key, const T &aDefault) const
bool readBody(bool dataInternal=false)
This function is our "receive" function.
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.
static Ptr findByUrl(const KUrl &url, mode_t mode=0, bool is_local_file=false, bool fast_mode=false, int *accuracy=0)
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)
static const char version[]
void proxyAuthenticationForSocket(const QNetworkProxy &, QAuthenticator *)
QByteArray current() const
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()
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
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 copyPut(const KUrl &src, const KUrl &dest, KIO::JobFlags flags)
Handles file -> webdav put requests.
ERR_CANNOT_OPEN_FOR_READING
void unread(char *buf, size_t size)
virtual void stat(const KUrl &url)
static QString htmlEscape(const QString &plain)
virtual void del(const KUrl &url, bool _isfile)
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 slaveStatus(const QString &host, bool connected)
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)
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
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.
int readData(QByteArray &buffer)
QByteArray headerFragment() const
insert this into the next request header after "Authorization: " or "Proxy-Authorization: " ...
QString metaData(const QString &key) const
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
static bool isAuthenticationRequired(int responseCode)
CopyJob * trash(const KUrl &src, JobFlags flags=DefaultFlags)
void initFrom(const HTTPRequest &request)
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)
quint16 defaultPort() const
QStringList m_transferEncodings
bool doNotProxyAuthenticate
int m_maxCacheAge
Maximum age of a cache entry in seconds.
void slotFilterError(const QString &text)
QDateTime dateTime() const
QString davError(int code=-1, const QString &url=QString())