00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 static void skipSpace(const char input[], int *pos, int end)
00023 {
00024 int idx = *pos;
00025 while (idx < end && (input[idx] == ' ' || input[idx] == '\t')) {
00026 idx++;
00027 }
00028 *pos = idx;
00029 return;
00030 }
00031
00032
00033 static void skipNonSpace(const char input[], int *pos, int end)
00034 {
00035 int idx = *pos;
00036 while (idx < end && input[idx] != ' ' && input[idx] != '\t' &&
00037 input[idx] != '\r' && input[idx] != '\n') {
00038 idx++;
00039 }
00040 *pos = idx;
00041 return;
00042 }
00043
00044
00045
00046 static bool nextLine(const char input[], int *pos, int end)
00047 {
00048 int idx = *pos;
00049 while (idx < end && input[idx] != '\r' && input[idx] != '\n') {
00050 idx++;
00051 }
00052 int rCount = 0;
00053 int nCount = 0;
00054 while (idx < end && qMax(rCount, nCount) < 2 && (input[idx] == '\r' || input[idx] == '\n')) {
00055 input[idx] == '\r' ? rCount++ : nCount++;
00056 idx++;
00057 }
00058 if (idx < end && qMax(rCount, nCount) == 2 && qMin(rCount, nCount) == 1) {
00059
00060
00061
00062 if ((rCount == 1 && input[idx] == '\r') || (nCount == 1 && input[idx] == '\n')) {
00063 idx++;
00064 }
00065 }
00066
00067 *pos = idx;
00068 return idx < end && rCount < 2 && nCount < 2;
00069 }
00070
00071
00072
00073
00074 static bool consume(const char input[], int *pos, int end, const char *term)
00075 {
00076
00077 int idx = *pos;
00078 if (idx + (int)strlen(term) >= end) {
00079 *pos = end;
00080 return false;
00081 }
00082 if (strncasecmp(&input[idx], term, strlen(term)) == 0) {
00083 *pos = idx + strlen(term);
00084 return true;
00085 }
00086 return false;
00087 }
00088
00089
00090 QByteArray TokenIterator::next()
00091 {
00092 QPair<int, int> token = m_tokens[m_currentToken++];
00093
00094
00095
00096
00097 return QByteArray(&m_buffer[token.first], token.second - token.first);
00098 }
00099
00100 QByteArray TokenIterator::current() const
00101 {
00102 QPair<int, int> token = m_tokens[m_currentToken - 1];
00103
00104 return QByteArray(&m_buffer[token.first], token.second - token.first);
00105 }
00106
00107 QList<QByteArray> TokenIterator::all() const
00108 {
00109 QList<QByteArray> ret;
00110 for (int i = 0; i < m_tokens.count(); i++) {
00111 QPair<int, int> token = m_tokens[i];
00112 ret.append(QByteArray(&m_buffer[token.first], token.second - token.first));
00113 }
00114 return ret;
00115 }
00116
00117
00118 HeaderTokenizer::HeaderTokenizer(char *buffer)
00119 : m_buffer(buffer)
00120 {
00121
00122
00123
00124
00125
00126
00127 static const HeaderFieldTemplate headerFieldTemplates[] = {
00128 {"accept-ranges", false},
00129 {"cache-control", true},
00130 {"connection", true},
00131 {"content-disposition", false},
00132 {"content-encoding", true},
00133 {"content-language", true},
00134 {"content-length", false},
00135 {"content-location", false},
00136 {"content-md5", false},
00137 {"content-type", false},
00138 {"date", false},
00139 {"dav", true},
00140 {"etag", false},
00141 {"expires", false},
00142 {"keep-alive", false},
00143 {"last-modified", false},
00144 {"link", false},
00145 {"location", false},
00146 {"p3p", true},
00147 {"pragma", true},
00148 {"proxy-authenticate", false},
00149
00150 {"proxy-connection", true},
00151
00152 {"refresh", false},
00153 {"set-cookie", false},
00154
00155
00156 {"transfer-encoding", true},
00157 {"upgrade", true},
00158 {"warning", true},
00159 {"www-authenticate", false}
00160 };
00161
00162 for (uint i = 0; i < sizeof(headerFieldTemplates) / sizeof(HeaderFieldTemplate); i++) {
00163 const HeaderFieldTemplate &ft = headerFieldTemplates[i];
00164 insert(QByteArray(ft.name), HeaderField(ft.isMultiValued));
00165 }
00166 }
00167
00168 int HeaderTokenizer::tokenize(int begin, int end)
00169 {
00170 char *buf = m_buffer;
00171 int idx = begin;
00172 int startIdx = begin;
00173 bool multiValuedEndedWithComma = false;
00174 QByteArray headerKey;
00175 do {
00176
00177 if (buf[idx] == ' ' || buf [idx] == '\t') {
00178
00179 if (headerKey.isEmpty()) {
00180 continue;
00181 }
00182
00183 int backIdx = idx - 1;
00184 while (backIdx >= begin && (buf[backIdx] == '\r' || buf[backIdx] == '\n')) {
00185 buf[backIdx--] = ' ';
00186 }
00187
00188
00189 if (operator[](headerKey).isMultiValued) {
00190 if (multiValuedEndedWithComma) {
00191
00192 skipSpace(buf, &idx, end);
00193 startIdx = idx;
00194 } else {
00195
00196 if (operator[](headerKey).beginEnd.last().first == startIdx) {
00197
00198 operator[](headerKey).beginEnd.removeLast();
00199 } else {
00200
00201 skipSpace(buf, &idx, end);
00202 startIdx = idx;
00203 }
00204 }
00205 }
00206
00207 } else {
00208
00209 startIdx = idx;
00210
00211 while (idx < (end - 1) && buf[idx] != ':' && buf[idx] != '\r' && buf[idx] != '\n') {
00212 buf[idx] = tolower(buf[idx]);
00213 idx++;
00214 }
00215 if (buf[idx] != ':') {
00216
00217 headerKey.clear();
00218 continue;
00219 }
00220 headerKey = QByteArray(&buf[startIdx], idx - startIdx);
00221 if (!contains(headerKey)) {
00222
00223 headerKey.clear();
00224 continue;
00225 }
00226
00227 idx++;
00228 skipSpace(buf, &idx, end);
00229 startIdx = idx;
00230 }
00231
00232
00233 if (!operator[](headerKey).isMultiValued) {
00234
00235
00236 while (idx < end && buf[idx] != '\r' && buf[idx] != '\n') {
00237 idx++;
00238 }
00239 if (!operator[](headerKey).beginEnd.isEmpty()) {
00240
00241 if (operator[](headerKey).beginEnd.last().first == startIdx) {
00242
00243 operator[](headerKey).beginEnd.removeLast();
00244 }
00245 }
00246 operator[](headerKey).beginEnd.append(QPair<int, int>(startIdx, idx));
00247
00248 } else {
00249
00250
00251 while (true) {
00252
00253 while (idx < end && buf[idx] != '\r' && buf[idx] != '\n' && buf[idx] != ',') {
00254 idx++;
00255 }
00256 if (idx != startIdx) {
00257 operator[](headerKey).beginEnd.append(QPair<int, int>(startIdx, idx));
00258 }
00259 multiValuedEndedWithComma = buf[idx] == ',';
00260
00261 while (idx < end && buf[idx] == ',') {
00262 idx++;
00263 }
00264 skipSpace(buf, &idx, end);
00265
00266 if (buf[idx] >= end || buf[idx] == '\r' || buf[idx] == '\n') {
00267 break;
00268 }
00269
00270 startIdx = idx;
00271 }
00272 }
00273 } while (nextLine(buf, &idx, end));
00274 return idx;
00275 }
00276
00277
00278 TokenIterator HeaderTokenizer::iterator(const char *key)
00279 {
00280 QByteArray keyBa = QByteArray::fromRawData(key, strlen(key));
00281 if (contains(keyBa)) {
00282 return TokenIterator(value(keyBa).beginEnd, m_buffer);
00283 } else {
00284 return TokenIterator(m_nullTokens, m_buffer);
00285 }
00286 }