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); |