Qt 4.8
Macros | Functions | Variables
qnetworkcookie.cpp File Reference
#include "qnetworkcookie.h"
#include "qnetworkcookie_p.h"
#include "qnetworkrequest.h"
#include "qnetworkreply.h"
#include "QtCore/qbytearray.h"
#include "QtCore/qdebug.h"
#include "QtCore/qlist.h"
#include "QtCore/qlocale.h"
#include "QtCore/qstring.h"
#include "QtCore/qstringlist.h"
#include "QtCore/qurl.h"
#include "private/qobject_p.h"

Go to the source code of this file.

Macros

#define ADAY   1
 
#define AMONTH   2
 
#define AYEAR   4
 

Functions

static bool checkStaticArray (int &val, const QByteArray &dateString, int at, const char *array, int size)
 
static bool isNumber (char s)
 
static bool isTerminator (char c)
 
static bool isValueSeparator (char c)
 
static bool isWhitespace (char c)
 
static QPair< QByteArray, QByteArraynextField (const QByteArray &text, int &position, bool isNameValue)
 
QDebug operator<< (QDebug s, const QNetworkCookie &cookie)
 
static QDateTime parseDateString (const QByteArray &dateString)
 

Variables

static const char months []
 
static int zoneOffsets [] = {-8, -8, -7, -7, -6, -6, -5, -5, -4, -3, 0, 0, 0, 1, 2, 9 }
 
static const char zones []
 

Macro Definition Documentation

◆ ADAY

#define ADAY   1

Definition at line 618 of file qnetworkcookie.cpp.

Referenced by parseDateString().

◆ AMONTH

#define AMONTH   2

Definition at line 619 of file qnetworkcookie.cpp.

Referenced by parseDateString().

◆ AYEAR

#define AYEAR   4

Definition at line 620 of file qnetworkcookie.cpp.

Referenced by parseDateString().

Function Documentation

◆ checkStaticArray()

static bool checkStaticArray ( int &  val,
const QByteArray dateString,
int  at,
const char *  array,
int  size 
)
static

Definition at line 594 of file qnetworkcookie.cpp.

Referenced by parseDateString().

595 {
596  if (dateString[at] < 'a' || dateString[at] > 'z')
597  return false;
598  if (val == -1 && dateString.length() >= at + 3) {
599  int j = 0;
600  int i = 0;
601  while (i <= size) {
602  const char *str = array + i;
603  if (str[0] == dateString[at]
604  && str[1] == dateString[at + 1]
605  && str[2] == dateString[at + 2]) {
606  val = j;
607  return true;
608  }
609  i += strlen(str) + 1;
610  ++j;
611  }
612  }
613  return false;
614 }
#define at(className, varName)
int length() const
Same as size().
Definition: qbytearray.h:356

◆ isNumber()

static bool isNumber ( char  s)
inlinestatic

Definition at line 582 of file qnetworkcookie.cpp.

Referenced by QAxBase::dynamicCallHelper(), QChar::isNull(), and parseDateString().

583 { return s >= '0' && s <= '9'; }

◆ isTerminator()

static bool isTerminator ( char  c)
inlinestatic

Definition at line 585 of file qnetworkcookie.cpp.

Referenced by isValueSeparator().

586 { return c == '\n' || c == '\r'; }
unsigned char c[8]
Definition: qnumeric_p.h:62

◆ isValueSeparator()

static bool isValueSeparator ( char  c)
inlinestatic

Definition at line 588 of file qnetworkcookie.cpp.

Referenced by QNetworkCookiePrivate::parseSetCookieHeaderLine().

589 { return isTerminator(c) || c == ';'; }
unsigned char c[8]
Definition: qnumeric_p.h:62
static bool isTerminator(char c)

◆ isWhitespace()

static bool isWhitespace ( char  c)
inlinestatic

Definition at line 591 of file qnetworkcookie.cpp.

Referenced by QXmlStreamReader::isCharacters(), QXmlStreamReaderPrivate::parse(), and parseDateString().

592 { return c == ' ' || c == '\t'; }
unsigned char c[8]
Definition: qnumeric_p.h:62

◆ nextField()

static QPair<QByteArray, QByteArray> nextField ( const QByteArray text,
int &  position,
bool  isNameValue 
)
static

Definition at line 374 of file qnetworkcookie.cpp.

Referenced by QNetworkCookiePrivate::parseSetCookieHeaderLine().

375 {
376  // format is one of:
377  // (1) token
378  // (2) token = token
379  // (3) token = quoted-string
380  int i;
381  const int length = text.length();
383 
384  // parse the first part, before the equal sign
385  for (i = position; i < length; ++i) {
386  register char c = text.at(i);
387  if (c == ';' || c == '=')
388  break;
389  }
390 
391  QByteArray first = text.mid(position, i - position).trimmed();
392  position = i;
393 
394  if (first.isEmpty())
395  return qMakePair(QByteArray(), QByteArray());
396  if (i == length || text.at(i) != '=')
397  // no equal sign, we found format (1)
398  return qMakePair(first, QByteArray());
399 
400  QByteArray second;
401  second.reserve(32); // arbitrary but works for most cases
402 
403  i = nextNonWhitespace(text, position + 1);
404  if (i < length && text.at(i) == '"') {
405  // a quote, we found format (3), where:
406  // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
407  // qdtext = <any TEXT except <">>
408  // quoted-pair = "\" CHAR
409 
410  // If it is NAME=VALUE, retain the value as is
411  // refer to http://bugreports.qt-project.org/browse/QTBUG-17746
412  if (isNameValue)
413  second += '"';
414  ++i;
415  while (i < length) {
416  register char c = text.at(i);
417  if (c == '"') {
418  // end of quoted text
419  if (isNameValue)
420  second += '"';
421  break;
422  } else if (c == '\\') {
423  if (isNameValue)
424  second += '\\';
425  ++i;
426  if (i >= length)
427  // broken line
428  return qMakePair(QByteArray(), QByteArray());
429  c = text.at(i);
430  }
431 
432  second += c;
433  ++i;
434  }
435 
436  for ( ; i < length; ++i) {
437  register char c = text.at(i);
438  if (c == ';')
439  break;
440  }
441  position = i;
442  } else {
443  // no quote, we found format (2)
444  position = i;
445  for ( ; i < length; ++i) {
446  register char c = text.at(i);
447  // for name value pairs, we want to parse until reaching the next ';'
448  // and not break when reaching a space char
449  if (c == ';' || ((isNameValue && (c == '\n' || c == '\r')) || (!isNameValue && isLWS(c))))
450  break;
451  }
452 
453  second = text.mid(position, i - position).trimmed();
454  position = i;
455  }
456 
457  if (second.isNull())
458  second.resize(0); // turns into empty-but-not-null
459  return qMakePair(first, second);
460 }
unsigned char c[8]
Definition: qnumeric_p.h:62
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
static int nextNonWhitespace(const QByteArray &text, int from)
QByteArray trimmed() const
Returns a byte array that has whitespace removed from the start and the end.
bool isNull() const
Returns true if this byte array is null; otherwise returns false.
QByteArray mid(int index, int len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos...
static bool isLWS(register char c)
int length() const
Same as size().
Definition: qbytearray.h:356
Q_OUTOFLINE_TEMPLATE QPair< T1, T2 > qMakePair(const T1 &x, const T2 &y)
Definition: qpair.h:102
void resize(int size)
Sets the size of the byte array to size bytes.
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
char at(int i) const
Returns the character at index position i in the byte array.
Definition: qbytearray.h:413
void reserve(int size)
Attempts to allocate memory for at least size bytes.
Definition: qbytearray.h:449

◆ operator<<()

QDebug operator<< ( QDebug  s,
const QNetworkCookie cookie 
)

Definition at line 1053 of file qnetworkcookie.cpp.

1054 {
1055  s.nospace() << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ')';
1056  return s.space();
1057 }
QDebug & nospace()
Clears the stream&#39;s internal flag that records whether the last character was a space and returns a r...
Definition: qdebug.h:92
QByteArray toRawForm(RawForm form=Full) const
Returns the raw form of this QNetworkCookie.
QDebug & space()
Writes a space character to the debug stream and returns a reference to the stream.
Definition: qdebug.h:91

◆ parseDateString()

static QDateTime parseDateString ( const QByteArray dateString)
static

Definition at line 641 of file qnetworkcookie.cpp.

Referenced by QNetworkCookiePrivate::parseSetCookieHeaderLine().

642 {
643  QTime time;
644  // placeholders for values when we are not sure it is a year, month or day
645  int unknown[3] = {-1, -1, -1};
646  int month = -1;
647  int day = -1;
648  int year = -1;
649  int zoneOffset = -1;
650 
651  // hour:minute:second.ms pm
652  QRegExp timeRx(QLatin1String("(\\d{1,2}):(\\d{1,2})(:(\\d{1,2})|)(\\.(\\d{1,3})|)((\\s{0,}(am|pm))|)"));
653 
654  int at = 0;
655  while (at < dateString.length()) {
656 #ifdef PARSEDATESTRINGDEBUG
657  qDebug() << dateString.mid(at);
658 #endif
659  bool isNum = isNumber(dateString[at]);
660 
661  // Month
662  if (!isNum
663  && checkStaticArray(month, dateString, at, months, sizeof(months)- 1)) {
664  ++month;
665 #ifdef PARSEDATESTRINGDEBUG
666  qDebug() << "Month:" << month;
667 #endif
668  at += 3;
669  continue;
670  }
671  // Zone
672  if (!isNum
673  && zoneOffset == -1
674  && checkStaticArray(zoneOffset, dateString, at, zones, sizeof(zones)- 1)) {
675  int sign = (at >= 0 && dateString[at - 1] == '-') ? -1 : 1;
676  zoneOffset = sign * zoneOffsets[zoneOffset] * 60 * 60;
677 #ifdef PARSEDATESTRINGDEBUG
678  qDebug() << "Zone:" << month;
679 #endif
680  at += 3;
681  continue;
682  }
683  // Zone offset
684  if (!isNum
685  && (zoneOffset == -1 || zoneOffset == 0) // Can only go after gmt
686  && (dateString[at] == '+' || dateString[at] == '-')
687  && (at == 0
688  || isWhitespace(dateString[at - 1])
689  || dateString[at - 1] == ','
690  || (at >= 3
691  && (dateString[at - 3] == 'g')
692  && (dateString[at - 2] == 'm')
693  && (dateString[at - 1] == 't')))) {
694 
695  int end = 1;
696  while (end < 5 && dateString.length() > at+end
697  && dateString[at + end] >= '0' && dateString[at + end] <= '9')
698  ++end;
699  int minutes = 0;
700  int hours = 0;
701  switch (end - 1) {
702  case 4:
703  minutes = atoi(dateString.mid(at + 3, 2).constData());
704  // fall through
705  case 2:
706  hours = atoi(dateString.mid(at + 1, 2).constData());
707  break;
708  case 1:
709  hours = atoi(dateString.mid(at + 1, 1).constData());
710  break;
711  default:
712  at += end;
713  continue;
714  }
715  if (end != 1) {
716  int sign = dateString[at] == '-' ? -1 : 1;
717  zoneOffset = sign * ((minutes * 60) + (hours * 60 * 60));
718 #ifdef PARSEDATESTRINGDEBUG
719  qDebug() << "Zone offset:" << zoneOffset << hours << minutes;
720 #endif
721  at += end;
722  continue;
723  }
724  }
725 
726  // Time
727  if (isNum && time.isNull()
728  && dateString.length() >= at + 3
729  && (dateString[at + 2] == ':' || dateString[at + 1] == ':')) {
730  // While the date can be found all over the string the format
731  // for the time is set and a nice regexp can be used.
732  int pos = timeRx.indexIn(QLatin1String(dateString), at);
733  if (pos != -1) {
734  QStringList list = timeRx.capturedTexts();
735  int h = atoi(list.at(1).toLatin1().constData());
736  int m = atoi(list.at(2).toLatin1().constData());
737  int s = atoi(list.at(4).toLatin1().constData());
738  int ms = atoi(list.at(6).toLatin1().constData());
739  if (h < 12 && !list.at(9).isEmpty())
740  if (list.at(9) == QLatin1String("pm"))
741  h += 12;
742  time = QTime(h, m, s, ms);
743 #ifdef PARSEDATESTRINGDEBUG
744  qDebug() << "Time:" << list << timeRx.matchedLength();
745 #endif
746  at += timeRx.matchedLength();
747  continue;
748  }
749  }
750 
751  // 4 digit Year
752  if (isNum
753  && year == -1
754  && dateString.length() > at + 3) {
755  if (isNumber(dateString[at + 1])
756  && isNumber(dateString[at + 2])
757  && isNumber(dateString[at + 3])) {
758  year = atoi(dateString.mid(at, 4).constData());
759  at += 4;
760 #ifdef PARSEDATESTRINGDEBUG
761  qDebug() << "Year:" << year;
762 #endif
763  continue;
764  }
765  }
766 
767  // a one or two digit number
768  // Could be month, day or year
769  if (isNum) {
770  int length = 1;
771  if (dateString.length() > at + 1
772  && isNumber(dateString[at + 1]))
773  ++length;
774  int x = atoi(dateString.mid(at, length).constData());
775  if (year == -1 && (x > 31 || x == 0)) {
776  year = x;
777  } else {
778  if (unknown[0] == -1) unknown[0] = x;
779  else if (unknown[1] == -1) unknown[1] = x;
780  else if (unknown[2] == -1) unknown[2] = x;
781  }
782  at += length;
783 #ifdef PARSEDATESTRINGDEBUG
784  qDebug() << "Saving" << x;
785 #endif
786  continue;
787  }
788 
789  // Unknown character, typically a weekday such as 'Mon'
790  ++at;
791  }
792 
793  // Once we are done parsing the string take the digits in unknown
794  // and determine which is the unknown year/month/day
795 
796  int couldBe[3] = { 0, 0, 0 };
797  int unknownCount = 3;
798  for (int i = 0; i < unknownCount; ++i) {
799  if (unknown[i] == -1) {
800  couldBe[i] = ADAY | AYEAR | AMONTH;
801  unknownCount = i;
802  continue;
803  }
804 
805  if (unknown[i] >= 1)
806  couldBe[i] = ADAY;
807 
808  if (month == -1 && unknown[i] >= 1 && unknown[i] <= 12)
809  couldBe[i] |= AMONTH;
810 
811  if (year == -1)
812  couldBe[i] |= AYEAR;
813  }
814 
815  // For any possible day make sure one of the values that could be a month
816  // can contain that day.
817  // For any possible month make sure one of the values that can be a
818  // day that month can have.
819  // Example: 31 11 06
820  // 31 can't be a day because 11 and 6 don't have 31 days
821  for (int i = 0; i < unknownCount; ++i) {
822  int currentValue = unknown[i];
823  bool findMatchingMonth = couldBe[i] & ADAY && currentValue >= 29;
824  bool findMatchingDay = couldBe[i] & AMONTH;
825  if (!findMatchingMonth || !findMatchingDay)
826  continue;
827  for (int j = 0; j < 3; ++j) {
828  if (j == i)
829  continue;
830  for (int k = 0; k < 2; ++k) {
831  if (k == 0 && !(findMatchingMonth && (couldBe[j] & AMONTH)))
832  continue;
833  else if (k == 1 && !(findMatchingDay && (couldBe[j] & ADAY)))
834  continue;
835  int m = currentValue;
836  int d = unknown[j];
837  if (k == 0)
838  qSwap(m, d);
839  if (m == -1) m = month;
840  bool found = true;
841  switch(m) {
842  case 2:
843  // When we get 29 and the year ends up having only 28
844  // See date.isValid below
845  // Example: 29 23 Feb
846  if (d <= 29)
847  found = false;
848  break;
849  case 4: case 6: case 9: case 11:
850  if (d <= 30)
851  found = false;
852  break;
853  default:
854  if (d > 0 && d <= 31)
855  found = false;
856  }
857  if (k == 0) findMatchingMonth = found;
858  else if (k == 1) findMatchingDay = found;
859  }
860  }
861  if (findMatchingMonth)
862  couldBe[i] &= ~ADAY;
863  if (findMatchingDay)
864  couldBe[i] &= ~AMONTH;
865  }
866 
867  // First set the year/month/day that have been deduced
868  // and reduce the set as we go along to deduce more
869  for (int i = 0; i < unknownCount; ++i) {
870  int unset = 0;
871  for (int j = 0; j < 3; ++j) {
872  if (couldBe[j] == ADAY && day == -1) {
873  day = unknown[j];
874  unset |= ADAY;
875  } else if (couldBe[j] == AMONTH && month == -1) {
876  month = unknown[j];
877  unset |= AMONTH;
878  } else if (couldBe[j] == AYEAR && year == -1) {
879  year = unknown[j];
880  unset |= AYEAR;
881  } else {
882  // common case
883  break;
884  }
885  couldBe[j] &= ~unset;
886  }
887  }
888 
889  // Now fallback to a standardized order to fill in the rest with
890  for (int i = 0; i < unknownCount; ++i) {
891  if (couldBe[i] & AMONTH && month == -1) month = unknown[i];
892  else if (couldBe[i] & ADAY && day == -1) day = unknown[i];
893  else if (couldBe[i] & AYEAR && year == -1) year = unknown[i];
894  }
895 #ifdef PARSEDATESTRINGDEBUG
896  qDebug() << "Final set" << year << month << day;
897 #endif
898 
899  if (year == -1 || month == -1 || day == -1) {
900 #ifdef PARSEDATESTRINGDEBUG
901  qDebug() << "Parser failure" << year << month << day;
902 #endif
903  return QDateTime();
904  }
905 
906  // Y2k behavior
907  int y2k = 0;
908  if (year < 70)
909  y2k = 2000;
910  else if (year < 100)
911  y2k = 1900;
912 
913  QDate date(year + y2k, month, day);
914 
915  // When we were given a bad cookie that when parsed
916  // set the day to 29 and the year to one that doesn't
917  // have the 29th of Feb rather then adding the extra
918  // complicated checking earlier just swap here.
919  // Example: 29 23 Feb
920  if (!date.isValid())
921  date = QDate(day + y2k, month, year);
922 
923  QDateTime dateTime(date, time, Qt::UTC);
924 
925  if (zoneOffset != -1) {
926  dateTime = dateTime.addSecs(zoneOffset);
927  }
928  if (!dateTime.isValid())
929  return QDateTime();
930  return dateTime;
931 }
double d
Definition: qnumeric_p.h:62
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
bool isNull() const
Returns true if the time is null (i.
Definition: qdatetime.h:158
#define at(className, varName)
static bool isWhitespace(char c)
The QDate class provides date functions.
Definition: qdatetime.h:55
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
static bool isNumber(char s)
#define ADAY
static int sign(int x)
Q_CORE_EXPORT void qDebug(const char *,...)
The QTime class provides clock time functions.
Definition: qdatetime.h:148
#define AYEAR
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
#define AMONTH
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
QByteArray mid(int index, int len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos...
void qSwap(T &value1, T &value2)
Definition: qglobal.h:2181
int length() const
Same as size().
Definition: qbytearray.h:356
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
static bool checkStaticArray(int &val, const QByteArray &dateString, int at, const char *array, int size)
static int zoneOffsets[]
static const char months[]
static const KeyPair *const end
static const char zones[]

Variable Documentation

◆ months

const char months[]
static
Initial value:
=
"jan\0"
"feb\0"
"mar\0"
"apr\0"
"may\0"
"jun\0"
"jul\0"
"aug\0"
"sep\0"
"oct\0"
"nov\0"
"dec\0"
"\0"

Definition at line 567 of file qnetworkcookie.cpp.

Referenced by QDate::isNull(), and parseDateString().

◆ zoneOffsets

int zoneOffsets[] = {-8, -8, -7, -7, -6, -6, -5, -5, -4, -3, 0, 0, 0, 1, 2, 9 }
static

Definition at line 565 of file qnetworkcookie.cpp.

Referenced by parseDateString().

◆ zones

const char zones[]
static
Initial value:
=
"pst\0"
"pdt\0"
"mst\0"
"mdt\0"
"cst\0"
"cdt\0"
"est\0"
"edt\0"
"ast\0"
"nst\0"
"gmt\0"
"utc\0"
"bst\0"
"met\0"
"eet\0"
"jst\0"
"\0"

Definition at line 547 of file qnetworkcookie.cpp.

Referenced by parseDateString().