/* Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) These were part of the QtNetwork module of the Qt Toolkit. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #include "qhttpheader_p.h" using namespace WebKit; static QString contentLengthString = QLatin1String("content-length"); static QString contentTypeString = QLatin1String("content-type"); QHttpHeader::QHttpHeader() { setValid(true); } QHttpHeader::QHttpHeader(const QString& str) { setValid(true); parse(str); } QHttpHeader::~QHttpHeader() { } bool QHttpHeader::parse(const QString& str) { QStringList lst; int pos = str.indexOf(QLatin1Char('\n')); if (pos > 0 && str.at(pos - 1) == QLatin1Char('\r')) lst = str.trimmed().split(QLatin1String("\r\n")); else lst = str.trimmed().split(QLatin1String("\n")); lst.removeAll(QString()); if (lst.isEmpty()) return true; QStringList lines; QStringList::Iterator it = lst.begin(); for (; it != lst.end(); ++it) { if (!(*it).isEmpty()) { if ((*it)[0].isSpace()) { if (!lines.isEmpty()) { lines.last() += QLatin1Char(' '); lines.last() += (*it).trimmed(); } } else lines.append((*it)); } } int number = 0; for (it = lines.begin(); it != lines.end(); ++it) { if (!parseLine(*it, number++)) { setValid(false); return false; } } return true; } QString QHttpHeader::value(const QString& key) const { QString lowercaseKey = key.toLower(); QList >::ConstIterator it = m_values.constBegin(); while (it != m_values.constEnd()) { if ((*it).first.toLower() == lowercaseKey) return (*it).second; ++it; } return QString(); } bool QHttpHeader::hasKey(const QString& key) const { QString lowercaseKey = key.toLower(); QList >::ConstIterator it = m_values.constBegin(); while (it != m_values.constEnd()) { if ((*it).first.toLower() == lowercaseKey) return true; ++it; } return false; } void QHttpHeader::setValue(const QString& key, const QString& value) { QString lowercaseKey = key.toLower(); QList >::Iterator it = m_values.begin(); while (it != m_values.end()) { if ((*it).first.toLower() == lowercaseKey) { (*it).second = value; return; } ++it; } addValue(key, value); } void QHttpHeader::addValue(const QString& key, const QString& value) { m_values.append(qMakePair(key, value)); } bool QHttpHeader::parseLine(const QString& line, int) { int i = line.indexOf(QLatin1Char(':')); if (i == -1) return false; addValue(line.left(i).trimmed(), line.mid(i + 1).trimmed()); return true; } QString QHttpHeader::toString() const { if (!isValid()) return QLatin1String(""); QString ret = QLatin1String(""); QList >::ConstIterator it = m_values.constBegin(); while (it != m_values.constEnd()) { ret += (*it).first + QLatin1String(": ") + (*it).second + QLatin1String("\r\n"); ++it; } return ret; } bool QHttpHeader::hasContentLength() const { return hasKey(contentLengthString); } uint QHttpHeader::contentLength() const { return value(contentLengthString).toUInt(); } void QHttpHeader::setContentLength(int len) { setValue(contentLengthString, QString::number(len)); } bool QHttpHeader::hasContentType() const { return hasKey(contentTypeString); } QString QHttpHeader::contentType() const { QString type = value(contentTypeString); if (type.isEmpty()) return QString(); int pos = type.indexOf(QLatin1Char(';')); if (pos == -1) return type; return type.left(pos).trimmed(); } void QHttpHeader::setContentType(const QString &type) { setValue(contentTypeString, type); } QHttpResponseHeader::QHttpResponseHeader(int code, const QString &text, int majorVer, int minorVer) : QHttpHeader() , m_statusCode(code) , m_reasonPhrase(text) , m_majorVersion(majorVer) , m_minorVersion(minorVer) { } bool QHttpResponseHeader::parseLine(const QString& line, int number) { if (number) return QHttpHeader::parseLine(line, number); QString l = line.simplified(); if (l.length() < 10) return false; if (l.left(5) == QLatin1String("HTTP/") && l[5].isDigit() && l[6] == QLatin1Char('.') && l[7].isDigit() && l[8] == QLatin1Char(' ') && l[9].isDigit()) { m_majorVersion = l[5].toLatin1() - '0'; m_minorVersion = l[7].toLatin1() - '0'; int pos = l.indexOf(QLatin1Char(' '), 9); if (pos != -1) { m_reasonPhrase = l.mid(pos + 1); m_statusCode = l.mid(9, pos - 9).toInt(); } else { m_statusCode = l.mid(9).toInt(); m_reasonPhrase.clear(); } } else return false; return true; } QString QHttpResponseHeader::toString() const { static QString ret(QLatin1String("HTTP/%1.%2 %3 %4\r\n%5\r\n")); return ret.arg(m_majorVersion).arg(m_minorVersion).arg(m_statusCode).arg(m_reasonPhrase).arg(QHttpHeader::toString()); } QHttpRequestHeader::QHttpRequestHeader() : QHttpHeader() { setValid(false); } QHttpRequestHeader::QHttpRequestHeader(const QString& str) { parse(str); } bool QHttpRequestHeader::parseLine(const QString& line, int number) { if (number) return QHttpHeader::parseLine(line, number); QStringList lst = line.simplified().split(QLatin1String(" ")); if (lst.count() > 0) { m_method = lst[0]; if (lst.count() > 1) { m_path = lst[1]; if (lst.count() > 2) { QString v = lst[2]; if (v.length() >= 8 && v.left(5) == QLatin1String("HTTP/") && v[5].isDigit() && v[6] == QLatin1Char('.') && v[7].isDigit()) { m_majorVersion = v[5].toLatin1() - '0'; m_minorVersion = v[7].toLatin1() - '0'; return true; } } } } return false; } QString QHttpRequestHeader::toString() const { static QString first(QLatin1String("%1 %2")); static QString last(QLatin1String(" HTTP/%3.%4\r\n%5\r\n")); return first.arg(m_method).arg(m_path) + last.arg(m_majorVersion).arg(m_minorVersion).arg(QHttpHeader::toString()); }