src/network/access/qnetworkrequest.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    45 #include "qnetworkrequest_p.h"
    45 #include "qnetworkrequest_p.h"
    46 #include "qsslconfiguration.h"
    46 #include "qsslconfiguration.h"
    47 #include "QtCore/qshareddata.h"
    47 #include "QtCore/qshareddata.h"
    48 #include "QtCore/qlocale.h"
    48 #include "QtCore/qlocale.h"
    49 #include "QtCore/qdatetime.h"
    49 #include "QtCore/qdatetime.h"
       
    50 
       
    51 #include <ctype.h>
       
    52 #ifndef QT_NO_DATESTRING
       
    53 # include <stdio.h>
       
    54 #endif
    50 
    55 
    51 QT_BEGIN_NAMESPACE
    56 QT_BEGIN_NAMESPACE
    52 
    57 
    53 /*!
    58 /*!
    54     \class QNetworkRequest
    59     \class QNetworkRequest
   604 
   609 
   605 static QNetworkRequest::KnownHeaders parseHeaderName(const QByteArray &headerName)
   610 static QNetworkRequest::KnownHeaders parseHeaderName(const QByteArray &headerName)
   606 {
   611 {
   607     // headerName is not empty here
   612     // headerName is not empty here
   608 
   613 
   609     QByteArray lower = headerName.toLower();
   614     switch (tolower(headerName.at(0))) {
   610     switch (lower.at(0)) {
       
   611     case 'c':
   615     case 'c':
   612         if (lower == "content-type")
   616         if (qstricmp(headerName.constData(), "content-type") == 0)
   613             return QNetworkRequest::ContentTypeHeader;
   617             return QNetworkRequest::ContentTypeHeader;
   614         else if (lower == "content-length")
   618         else if (qstricmp(headerName.constData(), "content-length") == 0)
   615             return QNetworkRequest::ContentLengthHeader;
   619             return QNetworkRequest::ContentLengthHeader;
   616         else if (lower == "cookie")
   620         else if (qstricmp(headerName.constData(), "cookie") == 0)
   617             return QNetworkRequest::CookieHeader;
   621             return QNetworkRequest::CookieHeader;
   618         break;
   622         break;
   619 
   623 
   620     case 'l':
   624     case 'l':
   621         if (lower == "location")
   625         if (qstricmp(headerName.constData(), "location") == 0)
   622             return QNetworkRequest::LocationHeader;
   626             return QNetworkRequest::LocationHeader;
   623         else if (lower == "last-modified")
   627         else if (qstricmp(headerName.constData(), "last-modified") == 0)
   624             return QNetworkRequest::LastModifiedHeader;
   628             return QNetworkRequest::LastModifiedHeader;
   625         break;
   629         break;
   626 
   630 
   627     case 's':
   631     case 's':
   628         if (lower == "set-cookie")
   632         if (qstricmp(headerName.constData(), "set-cookie") == 0)
   629             return QNetworkRequest::SetCookieHeader;
   633             return QNetworkRequest::SetCookieHeader;
   630         break;
   634         break;
   631     }
   635     }
   632 
   636 
   633     return QNetworkRequest::KnownHeaders(-1); // nothing found
   637     return QNetworkRequest::KnownHeaders(-1); // nothing found
   695 }
   699 }
   696 
   700 
   697 QNetworkHeadersPrivate::RawHeadersList::ConstIterator
   701 QNetworkHeadersPrivate::RawHeadersList::ConstIterator
   698 QNetworkHeadersPrivate::findRawHeader(const QByteArray &key) const
   702 QNetworkHeadersPrivate::findRawHeader(const QByteArray &key) const
   699 {
   703 {
   700     QByteArray lowerKey = key.toLower();
       
   701     RawHeadersList::ConstIterator it = rawHeaders.constBegin();
   704     RawHeadersList::ConstIterator it = rawHeaders.constBegin();
   702     RawHeadersList::ConstIterator end = rawHeaders.constEnd();
   705     RawHeadersList::ConstIterator end = rawHeaders.constEnd();
   703     for ( ; it != end; ++it)
   706     for ( ; it != end; ++it)
   704         if (it->first.toLower() == lowerKey)
   707         if (qstricmp(it->first.constData(), key.constData()) == 0)
   705             return it;
   708             return it;
   706 
   709 
   707     return end;                 // not found
   710     return end;                 // not found
   708 }
   711 }
   709 
   712 
   773     }
   776     }
   774 }
   777 }
   775 
   778 
   776 void QNetworkHeadersPrivate::setRawHeaderInternal(const QByteArray &key, const QByteArray &value)
   779 void QNetworkHeadersPrivate::setRawHeaderInternal(const QByteArray &key, const QByteArray &value)
   777 {
   780 {
   778     QByteArray lowerKey = key.toLower();
       
   779     RawHeadersList::Iterator it = rawHeaders.begin();
   781     RawHeadersList::Iterator it = rawHeaders.begin();
   780     while (it != rawHeaders.end()) {
   782     while (it != rawHeaders.end()) {
   781         if (it->first.toLower() == lowerKey)
   783         if (qstricmp(it->first.constData(), key.constData()) == 0)
   782             it = rawHeaders.erase(it);
   784             it = rawHeaders.erase(it);
   783         else
   785         else
   784             ++it;
   786             ++it;
   785     }
   787     }
   786 
   788 
   803         else
   805         else
   804             cookedHeaders.insert(parsedKey, parseHeaderValue(parsedKey, value));
   806             cookedHeaders.insert(parsedKey, parseHeaderValue(parsedKey, value));
   805     }
   807     }
   806 }
   808 }
   807 
   809 
       
   810 // Fast month string to int conversion. This code
       
   811 // assumes that the Month name is correct and that
       
   812 // the string is at least three chars long.
       
   813 static int name_to_month(const char* month_str)
       
   814 {
       
   815     switch (month_str[0]) {
       
   816     case 'J':
       
   817         switch (month_str[1]) {
       
   818         case 'a':
       
   819             return 1;
       
   820             break;
       
   821         case 'u':
       
   822             switch (month_str[2] ) {
       
   823             case 'n':
       
   824                 return 6;
       
   825                 break;
       
   826             case 'l':
       
   827                 return 7;
       
   828                 break;
       
   829             }
       
   830         }
       
   831         break;
       
   832     case 'F':
       
   833         return 2;
       
   834         break;
       
   835     case 'M':
       
   836         switch (month_str[2] ) {
       
   837         case 'r':
       
   838             return 3;
       
   839             break;
       
   840         case 'y':
       
   841             return 5;
       
   842             break;
       
   843         }
       
   844         break;
       
   845     case 'A':
       
   846         switch (month_str[1]) {
       
   847         case 'p':
       
   848             return 4;
       
   849             break;
       
   850         case 'u':
       
   851             return 8;
       
   852             break;
       
   853         }
       
   854         break;
       
   855     case 'O':
       
   856         return 10;
       
   857         break;
       
   858     case 'S':
       
   859         return 9;
       
   860         break;
       
   861     case 'N':
       
   862         return 11;
       
   863         break;
       
   864     case 'D':
       
   865         return 12;
       
   866         break;
       
   867     }
       
   868 
       
   869     return 0;
       
   870 }
       
   871 
   808 QDateTime QNetworkHeadersPrivate::fromHttpDate(const QByteArray &value)
   872 QDateTime QNetworkHeadersPrivate::fromHttpDate(const QByteArray &value)
   809 {
   873 {
   810     // HTTP dates have three possible formats:
   874     // HTTP dates have three possible formats:
   811     //  RFC 1123/822      -   ddd, dd MMM yyyy hh:mm:ss "GMT"
   875     //  RFC 1123/822      -   ddd, dd MMM yyyy hh:mm:ss "GMT"
   812     //  RFC 850           -   dddd, dd-MMM-yy hh:mm:ss "GMT"
   876     //  RFC 850           -   dddd, dd-MMM-yy hh:mm:ss "GMT"
   818 #ifndef QT_NO_DATESTRING
   882 #ifndef QT_NO_DATESTRING
   819     if (pos == -1) {
   883     if (pos == -1) {
   820         // no comma -> asctime(3) format
   884         // no comma -> asctime(3) format
   821         dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
   885         dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
   822     } else {
   886     } else {
   823         // eat the weekday, the comma and the space following it
   887         // Use sscanf over QLocal/QDateTimeParser for speed reasons. See the
   824         QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
   888         // QtWebKit performance benchmarks to get an idea.
   825 
   889         if (pos == 3) {
   826         QLocale c = QLocale::c();
   890             char month_name[4];
   827         if (pos == 3)
   891             int day, year, hour, minute, second;
   828             // must be RFC 1123 date
   892             if (sscanf(value.constData(), "%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, &year, &hour, &minute, &second) == 6)
   829             dt = c.toDateTime(sansWeekday, QLatin1String("dd MMM yyyy hh:mm:ss 'GMT"));
   893                 dt = QDateTime(QDate(year, name_to_month(month_name), day), QTime(hour, minute, second));
   830         else
   894         } else {
       
   895             QLocale c = QLocale::c();
       
   896             // eat the weekday, the comma and the space following it
       
   897             QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
   831             // must be RFC 850 date
   898             // must be RFC 850 date
   832             dt = c.toDateTime(sansWeekday, QLatin1String("dd-MMM-yy hh:mm:ss 'GMT'"));
   899             dt = c.toDateTime(sansWeekday, QLatin1String("dd-MMM-yy hh:mm:ss 'GMT'"));
       
   900         }
   833     }
   901     }
   834 #endif // QT_NO_DATESTRING
   902 #endif // QT_NO_DATESTRING
   835 
   903 
   836     if (dt.isValid())
   904     if (dt.isValid())
   837         dt.setTimeSpec(Qt::UTC);
   905         dt.setTimeSpec(Qt::UTC);