~clint-fewbar/ubuntu/precise/squid3/ignore-sighup-early

« back to all changes in this revision

Viewing changes to src/HttpHeader.cc

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2010-05-04 11:15:49 UTC
  • mfrom: (1.3.1 upstream)
  • mto: (20.3.1 squeeze) (21.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: james.westby@ubuntu.com-20100504111549-1apjh2g5sndki4te
Tags: upstream-3.1.3
ImportĀ upstreamĀ versionĀ 3.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*
3
 
 * $Id: HttpHeader.cc,v 1.138.2.1 2008/02/27 05:59:29 amosjeffries Exp $
 
3
 * $Id$
4
4
 *
5
5
 * DEBUG: section 55    HTTP Header
6
6
 * AUTHOR: Alex Rousskov
21
21
 *  it under the terms of the GNU General Public License as published by
22
22
 *  the Free Software Foundation; either version 2 of the License, or
23
23
 *  (at your option) any later version.
24
 
 *  
 
24
 *
25
25
 *  This program is distributed in the hope that it will be useful,
26
26
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
27
27
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28
28
 *  GNU General Public License for more details.
29
 
 *  
 
29
 *
30
30
 *  You should have received a copy of the GNU General Public License
31
31
 *  along with this program; if not, write to the Free Software
32
32
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
43
43
 
44
44
/*
45
45
 * On naming conventions:
46
 
 * 
47
 
 * HTTP/1.1 defines message-header as 
48
 
 * 
 
46
 *
 
47
 * HTTP/1.1 defines message-header as
 
48
 *
49
49
 * message-header = field-name ":" [ field-value ] CRLF
50
50
 * field-name     = token
51
51
 * field-value    = *( field-content | LWS )
52
 
 * 
 
52
 *
53
53
 * HTTP/1.1 does not give a name name a group of all message-headers in a message.
54
54
 * Squid 1.1 seems to refer to that group _plus_ start-line as "headers".
55
 
 * 
 
55
 *
56
56
 * HttpHeader is an object that represents all message-headers in a message.
57
57
 * HttpHeader does not manage start-line.
58
 
 * 
 
58
 *
59
59
 * HttpHeader is implemented as a collection of header "entries".
60
60
 * An entry is a (field_id, field_name, field_value) triplet.
61
61
 */
66
66
 */
67
67
 
68
68
/*
69
 
 * A table with major attributes for every known field. 
70
 
 * We calculate name lengths and reorganize this array on start up. 
 
69
 * A table with major attributes for every known field.
 
70
 * We calculate name lengths and reorganize this array on start up.
71
71
 * After reorganization, field id can be used as an index to the table.
72
72
 */
73
 
static const HttpHeaderFieldAttrs HeadersAttrs[] =
74
 
    {
75
 
        {"Accept", HDR_ACCEPT, ftStr},
 
73
static const HttpHeaderFieldAttrs HeadersAttrs[] = {
 
74
    {"Accept", HDR_ACCEPT, ftStr},
76
75
 
77
 
        {"Accept-Charset", HDR_ACCEPT_CHARSET, ftStr},
78
 
        {"Accept-Encoding", HDR_ACCEPT_ENCODING, ftStr},
79
 
        {"Accept-Language", HDR_ACCEPT_LANGUAGE, ftStr},
80
 
        {"Accept-Ranges", HDR_ACCEPT_RANGES, ftStr},
81
 
        {"Age", HDR_AGE, ftInt},
82
 
        {"Allow", HDR_ALLOW, ftStr},
83
 
        {"Authorization", HDR_AUTHORIZATION, ftStr},    /* for now */
84
 
        {"Cache-Control", HDR_CACHE_CONTROL, ftPCc},
85
 
        {"Connection", HDR_CONNECTION, ftStr},
86
 
        {"Content-Base", HDR_CONTENT_BASE, ftStr},
87
 
        {"Content-Disposition", HDR_CONTENT_DISPOSITION, ftStr},  /* for now */
88
 
        {"Content-Encoding", HDR_CONTENT_ENCODING, ftStr},
89
 
        {"Content-Language", HDR_CONTENT_LANGUAGE, ftStr},
90
 
        {"Content-Length", HDR_CONTENT_LENGTH, ftInt64},
91
 
        {"Content-Location", HDR_CONTENT_LOCATION, ftStr},
92
 
        {"Content-MD5", HDR_CONTENT_MD5, ftStr},        /* for now */
93
 
        {"Content-Range", HDR_CONTENT_RANGE, ftPContRange},
94
 
        {"Content-Type", HDR_CONTENT_TYPE, ftStr},
95
 
        {"Cookie", HDR_COOKIE, ftStr},
96
 
        {"Date", HDR_DATE, ftDate_1123},
97
 
        {"ETag", HDR_ETAG, ftETag},
98
 
        {"Expires", HDR_EXPIRES, ftDate_1123},
99
 
        {"From", HDR_FROM, ftStr},
100
 
        {"Host", HDR_HOST, ftStr},
101
 
        {"If-Match", HDR_IF_MATCH, ftStr},      /* for now */
102
 
        {"If-Modified-Since", HDR_IF_MODIFIED_SINCE, ftDate_1123},
103
 
        {"If-None-Match", HDR_IF_NONE_MATCH, ftStr},    /* for now */
104
 
        {"If-Range", HDR_IF_RANGE, ftDate_1123_or_ETag},
105
 
        {"Keep-Alive", HDR_KEEP_ALIVE, ftStr},
106
 
        {"Last-Modified", HDR_LAST_MODIFIED, ftDate_1123},
107
 
        {"Link", HDR_LINK, ftStr},
108
 
        {"Location", HDR_LOCATION, ftStr},
109
 
        {"Max-Forwards", HDR_MAX_FORWARDS, ftInt64},
110
 
        {"Mime-Version", HDR_MIME_VERSION, ftStr},      /* for now */
111
 
        {"Pragma", HDR_PRAGMA, ftStr},
112
 
        {"Proxy-Authenticate", HDR_PROXY_AUTHENTICATE, ftStr},
113
 
        {"Proxy-Authentication-Info", HDR_PROXY_AUTHENTICATION_INFO, ftStr},
114
 
        {"Proxy-Authorization", HDR_PROXY_AUTHORIZATION, ftStr},
115
 
        {"Proxy-Connection", HDR_PROXY_CONNECTION, ftStr},
116
 
        {"Public", HDR_PUBLIC, ftStr},
117
 
        {"Range", HDR_RANGE, ftPRange},
118
 
        {"Referer", HDR_REFERER, ftStr},
119
 
        {"Request-Range", HDR_REQUEST_RANGE, ftPRange}, /* usually matches HDR_RANGE */
120
 
        {"Retry-After", HDR_RETRY_AFTER, ftStr},        /* for now (ftDate_1123 or ftInt!) */
121
 
        {"Server", HDR_SERVER, ftStr},
122
 
        {"Set-Cookie", HDR_SET_COOKIE, ftStr},
123
 
        {"TE", HDR_TE, ftStr},
124
 
        {"Title", HDR_TITLE, ftStr},
125
 
        {"Trailers", HDR_TRAILERS, ftStr},
126
 
        {"Transfer-Encoding", HDR_TRANSFER_ENCODING, ftStr},
127
 
        {"Translate", HDR_TRANSLATE, ftStr},    /* for now. may need to crop */
128
 
        {"Unless-Modified-Since", HDR_UNLESS_MODIFIED_SINCE, ftStr},  /* for now ignore. may need to crop */
129
 
        {"Upgrade", HDR_UPGRADE, ftStr},        /* for now */
130
 
        {"User-Agent", HDR_USER_AGENT, ftStr},
131
 
        {"Vary", HDR_VARY, ftStr},      /* for now */
132
 
        {"Via", HDR_VIA, ftStr},        /* for now */
133
 
        {"Warning", HDR_WARNING, ftStr},        /* for now */
134
 
        {"WWW-Authenticate", HDR_WWW_AUTHENTICATE, ftStr},
135
 
        {"Authentication-Info", HDR_AUTHENTICATION_INFO, ftStr},
136
 
        {"X-Cache", HDR_X_CACHE, ftStr},
137
 
        {"X-Cache-Lookup", HDR_X_CACHE_LOOKUP, ftStr},
138
 
        {"X-Forwarded-For", HDR_X_FORWARDED_FOR, ftStr},
139
 
        {"X-Request-URI", HDR_X_REQUEST_URI, ftStr},
140
 
        {"X-Squid-Error", HDR_X_SQUID_ERROR, ftStr},
141
 
        {"Negotiate", HDR_NEGOTIATE, ftStr},
 
76
    {"Accept-Charset", HDR_ACCEPT_CHARSET, ftStr},
 
77
    {"Accept-Encoding", HDR_ACCEPT_ENCODING, ftStr},
 
78
    {"Accept-Language", HDR_ACCEPT_LANGUAGE, ftStr},
 
79
    {"Accept-Ranges", HDR_ACCEPT_RANGES, ftStr},
 
80
    {"Age", HDR_AGE, ftInt},
 
81
    {"Allow", HDR_ALLOW, ftStr},
 
82
    {"Authorization", HDR_AUTHORIZATION, ftStr},        /* for now */
 
83
    {"Cache-Control", HDR_CACHE_CONTROL, ftPCc},
 
84
    {"Connection", HDR_CONNECTION, ftStr},
 
85
    {"Content-Base", HDR_CONTENT_BASE, ftStr},
 
86
    {"Content-Disposition", HDR_CONTENT_DISPOSITION, ftStr},  /* for now */
 
87
    {"Content-Encoding", HDR_CONTENT_ENCODING, ftStr},
 
88
    {"Content-Language", HDR_CONTENT_LANGUAGE, ftStr},
 
89
    {"Content-Length", HDR_CONTENT_LENGTH, ftInt64},
 
90
    {"Content-Location", HDR_CONTENT_LOCATION, ftStr},
 
91
    {"Content-MD5", HDR_CONTENT_MD5, ftStr},    /* for now */
 
92
    {"Content-Range", HDR_CONTENT_RANGE, ftPContRange},
 
93
    {"Content-Type", HDR_CONTENT_TYPE, ftStr},
 
94
    {"Cookie", HDR_COOKIE, ftStr},
 
95
    {"Date", HDR_DATE, ftDate_1123},
 
96
    {"ETag", HDR_ETAG, ftETag},
 
97
    {"Expires", HDR_EXPIRES, ftDate_1123},
 
98
    {"Expect", HDR_EXPECT, ftStr},
 
99
    {"From", HDR_FROM, ftStr},
 
100
    {"Host", HDR_HOST, ftStr},
 
101
    {"If-Match", HDR_IF_MATCH, ftStr},  /* for now */
 
102
    {"If-Modified-Since", HDR_IF_MODIFIED_SINCE, ftDate_1123},
 
103
    {"If-None-Match", HDR_IF_NONE_MATCH, ftStr},        /* for now */
 
104
    {"If-Range", HDR_IF_RANGE, ftDate_1123_or_ETag},
 
105
    {"Keep-Alive", HDR_KEEP_ALIVE, ftStr},
 
106
    {"Last-Modified", HDR_LAST_MODIFIED, ftDate_1123},
 
107
    {"Link", HDR_LINK, ftStr},
 
108
    {"Location", HDR_LOCATION, ftStr},
 
109
    {"Max-Forwards", HDR_MAX_FORWARDS, ftInt64},
 
110
    {"Mime-Version", HDR_MIME_VERSION, ftStr},  /* for now */
 
111
    {"Pragma", HDR_PRAGMA, ftStr},
 
112
    {"Proxy-Authenticate", HDR_PROXY_AUTHENTICATE, ftStr},
 
113
    {"Proxy-Authentication-Info", HDR_PROXY_AUTHENTICATION_INFO, ftStr},
 
114
    {"Proxy-Authorization", HDR_PROXY_AUTHORIZATION, ftStr},
 
115
    {"Proxy-Connection", HDR_PROXY_CONNECTION, ftStr},
 
116
    {"Proxy-support", HDR_PROXY_SUPPORT, ftStr},
 
117
    {"Public", HDR_PUBLIC, ftStr},
 
118
    {"Range", HDR_RANGE, ftPRange},
 
119
    {"Referer", HDR_REFERER, ftStr},
 
120
    {"Request-Range", HDR_REQUEST_RANGE, ftPRange},     /* usually matches HDR_RANGE */
 
121
    {"Retry-After", HDR_RETRY_AFTER, ftStr},    /* for now (ftDate_1123 or ftInt!) */
 
122
    {"Server", HDR_SERVER, ftStr},
 
123
    {"Set-Cookie", HDR_SET_COOKIE, ftStr},
 
124
    {"TE", HDR_TE, ftStr},
 
125
    {"Title", HDR_TITLE, ftStr},
 
126
    {"Trailers", HDR_TRAILERS, ftStr},
 
127
    {"Transfer-Encoding", HDR_TRANSFER_ENCODING, ftStr},
 
128
    {"Translate", HDR_TRANSLATE, ftStr},        /* for now. may need to crop */
 
129
    {"Unless-Modified-Since", HDR_UNLESS_MODIFIED_SINCE, ftStr},  /* for now ignore. may need to crop */
 
130
    {"Upgrade", HDR_UPGRADE, ftStr},    /* for now */
 
131
    {"User-Agent", HDR_USER_AGENT, ftStr},
 
132
    {"Vary", HDR_VARY, ftStr},  /* for now */
 
133
    {"Via", HDR_VIA, ftStr},    /* for now */
 
134
    {"Warning", HDR_WARNING, ftStr},    /* for now */
 
135
    {"WWW-Authenticate", HDR_WWW_AUTHENTICATE, ftStr},
 
136
    {"Authentication-Info", HDR_AUTHENTICATION_INFO, ftStr},
 
137
    {"X-Cache", HDR_X_CACHE, ftStr},
 
138
    {"X-Cache-Lookup", HDR_X_CACHE_LOOKUP, ftStr},
 
139
    {"X-Forwarded-For", HDR_X_FORWARDED_FOR, ftStr},
 
140
    {"X-Request-URI", HDR_X_REQUEST_URI, ftStr},
 
141
    {"X-Squid-Error", HDR_X_SQUID_ERROR, ftStr},
 
142
    {"Negotiate", HDR_NEGOTIATE, ftStr},
142
143
#if X_ACCELERATOR_VARY
143
 
        {"X-Accelerator-Vary", HDR_X_ACCELERATOR_VARY, ftStr},
144
 
#endif
145
 
        {"Surrogate-Capability", HDR_SURROGATE_CAPABILITY, ftStr},
146
 
        {"Surrogate-Control", HDR_SURROGATE_CONTROL, ftPSc},
147
 
        {"Front-End-Https", HDR_FRONT_END_HTTPS, ftStr},
148
 
        {"Other:", HDR_OTHER, ftStr}    /* ':' will not allow matches */
149
 
    };
 
144
    {"X-Accelerator-Vary", HDR_X_ACCELERATOR_VARY, ftStr},
 
145
#endif
 
146
#if USE_ADAPTATION
 
147
    {"X-Next-Services", HDR_X_NEXT_SERVICES, ftStr},
 
148
#endif
 
149
    {"Surrogate-Capability", HDR_SURROGATE_CAPABILITY, ftStr},
 
150
    {"Surrogate-Control", HDR_SURROGATE_CONTROL, ftPSc},
 
151
    {"Front-End-Https", HDR_FRONT_END_HTTPS, ftStr},
 
152
    {"Other:", HDR_OTHER, ftStr}        /* ':' will not allow matches */
 
153
};
150
154
 
151
155
static HttpHeaderFieldInfo *Headers = NULL;
152
156
 
163
167
 * Headers that are currently not recognized, are commented out.
164
168
 */
165
169
static HttpHeaderMask ListHeadersMask;  /* set run-time using  ListHeadersArr */
166
 
static http_hdr_type ListHeadersArr[] =
167
 
    {
168
 
        HDR_ACCEPT,
169
 
        HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE,
170
 
        HDR_ACCEPT_RANGES, HDR_ALLOW,
171
 
        HDR_CACHE_CONTROL,
172
 
        HDR_CONTENT_ENCODING,
173
 
        HDR_CONTENT_LANGUAGE,
174
 
        HDR_CONNECTION,
175
 
        HDR_IF_MATCH, HDR_IF_NONE_MATCH,
176
 
        HDR_LINK, HDR_PRAGMA,
177
 
        HDR_PROXY_CONNECTION,
178
 
        HDR_TRANSFER_ENCODING,
179
 
        HDR_UPGRADE,
180
 
        HDR_VARY,
181
 
        HDR_VIA,
182
 
        /* HDR_WARNING, */
183
 
        HDR_WWW_AUTHENTICATE,
184
 
        HDR_AUTHENTICATION_INFO,
185
 
        HDR_PROXY_AUTHENTICATION_INFO,
186
 
        /* HDR_EXPECT, HDR_TE, HDR_TRAILER */
 
170
static http_hdr_type ListHeadersArr[] = {
 
171
    HDR_ACCEPT,
 
172
    HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE,
 
173
    HDR_ACCEPT_RANGES, HDR_ALLOW,
 
174
    HDR_CACHE_CONTROL,
 
175
    HDR_CONTENT_ENCODING,
 
176
    HDR_CONTENT_LANGUAGE,
 
177
    HDR_CONNECTION,
 
178
    HDR_EXPECT,
 
179
    HDR_IF_MATCH, HDR_IF_NONE_MATCH,
 
180
    HDR_LINK, HDR_PRAGMA,
 
181
    HDR_PROXY_CONNECTION,
 
182
    HDR_PROXY_SUPPORT,
 
183
    HDR_TRANSFER_ENCODING,
 
184
    HDR_UPGRADE,
 
185
    HDR_VARY,
 
186
    HDR_VIA,
 
187
    /* HDR_WARNING, */
 
188
    HDR_WWW_AUTHENTICATE,
 
189
    HDR_AUTHENTICATION_INFO,
 
190
    HDR_PROXY_AUTHENTICATION_INFO,
 
191
    /* HDR_TE, HDR_TRAILER */
187
192
#if X_ACCELERATOR_VARY
188
 
        HDR_X_ACCELERATOR_VARY,
189
 
#endif
190
 
        HDR_SURROGATE_CAPABILITY,
191
 
        HDR_SURROGATE_CONTROL,
192
 
        HDR_X_FORWARDED_FOR
193
 
    };
 
193
    HDR_X_ACCELERATOR_VARY,
 
194
#endif
 
195
#if USE_ADAPTATION
 
196
    HDR_X_NEXT_SERVICES,
 
197
#endif
 
198
    HDR_SURROGATE_CAPABILITY,
 
199
    HDR_SURROGATE_CONTROL,
 
200
    HDR_X_FORWARDED_FOR
 
201
};
194
202
 
195
203
/* general-headers */
196
 
static http_hdr_type GeneralHeadersArr[] =
197
 
    {
198
 
        HDR_CACHE_CONTROL, HDR_CONNECTION, HDR_DATE, HDR_PRAGMA,
199
 
        HDR_TRANSFER_ENCODING,
200
 
        HDR_UPGRADE,
201
 
        /* HDR_TRAILER, */
202
 
        HDR_VIA,
203
 
    };
 
204
static http_hdr_type GeneralHeadersArr[] = {
 
205
    HDR_CACHE_CONTROL, HDR_CONNECTION, HDR_DATE, HDR_PRAGMA,
 
206
    HDR_TRANSFER_ENCODING,
 
207
    HDR_UPGRADE,
 
208
    /* HDR_TRAILER, */
 
209
    HDR_VIA,
 
210
};
204
211
 
205
212
/* entity-headers */
206
 
static http_hdr_type EntityHeadersArr[] =
207
 
    {
208
 
        HDR_ALLOW, HDR_CONTENT_BASE, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE,
209
 
        HDR_CONTENT_LENGTH, HDR_CONTENT_LOCATION, HDR_CONTENT_MD5,
210
 
        HDR_CONTENT_RANGE, HDR_CONTENT_TYPE, HDR_ETAG, HDR_EXPIRES, HDR_LAST_MODIFIED, HDR_LINK,
211
 
        HDR_OTHER
212
 
    };
 
213
static http_hdr_type EntityHeadersArr[] = {
 
214
    HDR_ALLOW, HDR_CONTENT_BASE, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE,
 
215
    HDR_CONTENT_LENGTH, HDR_CONTENT_LOCATION, HDR_CONTENT_MD5,
 
216
    HDR_CONTENT_RANGE, HDR_CONTENT_TYPE, HDR_ETAG, HDR_EXPIRES, HDR_LAST_MODIFIED, HDR_LINK,
 
217
    HDR_OTHER
 
218
};
213
219
 
214
220
static HttpHeaderMask ReplyHeadersMask;         /* set run-time using ReplyHeaders */
215
 
static http_hdr_type ReplyHeadersArr[] =
216
 
    {
217
 
        HDR_ACCEPT, HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE,
218
 
        HDR_ACCEPT_RANGES, HDR_AGE,
219
 
        HDR_LOCATION, HDR_MAX_FORWARDS,
220
 
        HDR_MIME_VERSION, HDR_PUBLIC, HDR_RETRY_AFTER, HDR_SERVER, HDR_SET_COOKIE,
221
 
        HDR_VARY,
222
 
        HDR_WARNING, HDR_PROXY_CONNECTION, HDR_X_CACHE,
223
 
        HDR_X_CACHE_LOOKUP,
224
 
        HDR_X_REQUEST_URI,
 
221
static http_hdr_type ReplyHeadersArr[] = {
 
222
    HDR_ACCEPT, HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE,
 
223
    HDR_ACCEPT_RANGES, HDR_AGE,
 
224
    HDR_LOCATION, HDR_MAX_FORWARDS,
 
225
    HDR_MIME_VERSION, HDR_PUBLIC, HDR_RETRY_AFTER, HDR_SERVER, HDR_SET_COOKIE,
 
226
    HDR_VARY,
 
227
    HDR_WARNING, HDR_PROXY_CONNECTION, HDR_X_CACHE,
 
228
    HDR_X_CACHE_LOOKUP,
 
229
    HDR_X_REQUEST_URI,
225
230
#if X_ACCELERATOR_VARY
226
 
        HDR_X_ACCELERATOR_VARY,
227
 
#endif
228
 
        HDR_X_SQUID_ERROR,
229
 
        HDR_SURROGATE_CONTROL
230
 
    };
 
231
    HDR_X_ACCELERATOR_VARY,
 
232
#endif
 
233
#if USE_ADAPTATION
 
234
    HDR_X_NEXT_SERVICES,
 
235
#endif
 
236
    HDR_X_SQUID_ERROR,
 
237
    HDR_SURROGATE_CONTROL
 
238
};
231
239
 
232
240
static HttpHeaderMask RequestHeadersMask;       /* set run-time using RequestHeaders */
233
 
static http_hdr_type RequestHeadersArr[] =
234
 
    {
235
 
        HDR_AUTHORIZATION, HDR_FROM, HDR_HOST,
236
 
        HDR_IF_MATCH, HDR_IF_MODIFIED_SINCE, HDR_IF_NONE_MATCH,
237
 
        HDR_IF_RANGE, HDR_MAX_FORWARDS, HDR_PROXY_CONNECTION,
238
 
        HDR_PROXY_AUTHORIZATION, HDR_RANGE, HDR_REFERER, HDR_REQUEST_RANGE,
239
 
        HDR_USER_AGENT, HDR_X_FORWARDED_FOR, HDR_SURROGATE_CAPABILITY
240
 
    };
 
241
static http_hdr_type RequestHeadersArr[] = {
 
242
    HDR_AUTHORIZATION, HDR_FROM, HDR_HOST,
 
243
    HDR_IF_MATCH, HDR_IF_MODIFIED_SINCE, HDR_IF_NONE_MATCH,
 
244
    HDR_IF_RANGE, HDR_MAX_FORWARDS, HDR_PROXY_CONNECTION,
 
245
    HDR_PROXY_AUTHORIZATION, HDR_RANGE, HDR_REFERER, HDR_REQUEST_RANGE,
 
246
    HDR_USER_AGENT, HDR_X_FORWARDED_FOR, HDR_SURROGATE_CAPABILITY
 
247
};
241
248
 
242
 
static http_hdr_type HopByHopHeadersArr[] =
243
 
    {
244
 
        HDR_CONNECTION, HDR_KEEP_ALIVE, HDR_PROXY_AUTHENTICATE, HDR_PROXY_AUTHORIZATION,
245
 
        HDR_TE, HDR_TRAILERS, HDR_TRANSFER_ENCODING, HDR_UPGRADE
246
 
    };
 
249
static HttpHeaderMask HopByHopHeadersMask;
 
250
static http_hdr_type HopByHopHeadersArr[] = {
 
251
    HDR_CONNECTION, HDR_KEEP_ALIVE, /*HDR_PROXY_AUTHENTICATE,*/ HDR_PROXY_AUTHORIZATION,
 
252
    HDR_TE, HDR_TRAILERS, HDR_TRANSFER_ENCODING, HDR_UPGRADE, HDR_PROXY_CONNECTION
 
253
};
247
254
 
248
255
/* header accounting */
249
 
static HttpHeaderStat HttpHeaderStats[] =
250
 
    {
251
 
        {"all"},
 
256
static HttpHeaderStat HttpHeaderStats[] = {
 
257
    {"all"},
252
258
#if USE_HTCP
253
 
        {"HTCP reply"},
 
259
    {"HTCP reply"},
254
260
#endif
255
 
        {"request"},
256
 
        {"reply"}
257
 
    };
 
261
    {"request"},
 
262
    {"reply"}
 
263
};
258
264
static int HttpHeaderStatCount = countof(HttpHeaderStats);
259
265
 
260
266
static int HeaderEntryParsedCount = 0;
274
280
 * Module initialization routines
275
281
 */
276
282
 
 
283
static void
 
284
httpHeaderRegisterWithCacheManager(void)
 
285
{
 
286
    CacheManager::GetInstance()->
 
287
    registerAction("http_headers",
 
288
                   "HTTP Header Statistics",
 
289
                   httpHeaderStoreReport, 0, 1);
 
290
}
 
291
 
277
292
void
278
293
httpHeaderInitModule(void)
279
294
{
307
322
 
308
323
    httpHeaderCalcMask(&RequestHeadersMask, EntityHeadersArr, countof(EntityHeadersArr));
309
324
 
 
325
    httpHeaderMaskInit(&HopByHopHeadersMask, 0);
 
326
 
 
327
    httpHeaderCalcMask(&HopByHopHeadersMask, HopByHopHeadersArr, countof(HopByHopHeadersArr));
 
328
 
310
329
    /* init header stats */
311
330
    assert(HttpHeaderStatCount == hoReply + 1);
312
331
 
326
345
    httpHdrCcInitModule();
327
346
 
328
347
    httpHdrScInitModule();
329
 
}
330
348
 
331
 
void
332
 
httpHeaderRegisterWithCacheManager(CacheManager & manager)
333
 
{
334
 
    /* register with cache manager */
335
 
    manager.registerAction("http_headers",
336
 
                           "HTTP Header Statistics",
337
 
                           httpHeaderStoreReport, 0, 1);
 
349
    httpHeaderRegisterWithCacheManager();
338
350
}
339
351
 
340
352
void
465
477
        if (e->id != HDR_OTHER)
466
478
            delById(e->id);
467
479
        else
468
 
            delByName(e->name.buf());
 
480
            delByName(e->name.termedBuf());
469
481
    }
470
482
 
471
483
    pos = HttpHeaderInitPos;
504
516
    debugs(55, 7, "parsing hdr: (" << this << ")" << std::endl << getStringPrefix(header_start, header_end));
505
517
    HttpHeaderStats[owner].parsedCount++;
506
518
 
507
 
    if (memchr(header_start, '\0', header_end - header_start)) {
508
 
        debugs(55, 1, "WARNING: HTTP header contains NULL characters {" << 
509
 
                      getStringPrefix(header_start, header_end) << "}");
 
519
    char *nulpos;
 
520
    if ((nulpos = (char*)memchr(header_start, '\0', header_end - header_start))) {
 
521
        debugs(55, 1, "WARNING: HTTP header contains NULL characters {" <<
 
522
               getStringPrefix(header_start, nulpos) << "}\nNULL\n{" << getStringPrefix(nulpos+1, header_end));
510
523
        goto reset;
511
524
    }
512
525
 
533
546
 
534
547
                if (Config.onoff.relaxed_header_parser && field_end > this_line + 1 && field_end[-1] == '\r') {
535
548
                    debugs(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2,
536
 
                    "WARNING: Double CR characters in HTTP header {" << getStringPrefix(field_start, field_end) << "}");
 
549
                           "WARNING: Double CR characters in HTTP header {" << getStringPrefix(field_start, field_end) << "}");
537
550
                    field_end--;
538
551
                }
539
552
            }
541
554
            /* Barf on stray CR characters */
542
555
            if (memchr(this_line, '\r', field_end - this_line)) {
543
556
                debugs(55, 1, "WARNING: suspicious CR characters in HTTP header {" <<
544
 
                              getStringPrefix(field_start, field_end) << "}");
 
557
                       getStringPrefix(field_start, field_end) << "}");
545
558
 
546
559
                if (Config.onoff.relaxed_header_parser) {
547
560
                    char *p = (char *) this_line;       /* XXX Warning! This destroys original header content and violates specifications somewhat */
554
567
 
555
568
            if (this_line + 1 == field_end && this_line > field_start) {
556
569
                debugs(55, 1, "WARNING: Blank continuation line in HTTP header {" <<
557
 
                              getStringPrefix(header_start, header_end) << "}");
 
570
                       getStringPrefix(header_start, header_end) << "}");
558
571
                goto reset;
559
572
            }
560
573
        } while (field_ptr < header_end && (*field_ptr == ' ' || *field_ptr == '\t'));
562
575
        if (field_start == field_end) {
563
576
            if (field_ptr < header_end) {
564
577
                debugs(55, 1, "WARNING: unparseable HTTP header field near {" <<
565
 
                              getStringPrefix(field_start, header_end) << "}");
 
578
                       getStringPrefix(field_start, header_end) << "}");
566
579
                goto reset;
567
580
            }
568
581
 
570
583
        }
571
584
 
572
585
        if ((e = HttpHeaderEntry::parse(field_start, field_end)) == NULL) {
573
 
            debugs(55, 1, "WARNING: unparseable HTTP header field {" << 
574
 
                          getStringPrefix(field_start, field_end) << "}");
 
586
            debugs(55, 1, "WARNING: unparseable HTTP header field {" <<
 
587
                   getStringPrefix(field_start, field_end) << "}");
575
588
            debugs(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2,
576
 
            " in {" << getStringPrefix(header_start, header_end) << "}");
 
589
                   " in {" << getStringPrefix(header_start, header_end) << "}");
577
590
 
578
591
            if (Config.onoff.relaxed_header_parser)
579
592
                continue;
582
595
        }
583
596
 
584
597
        if (e->id == HDR_CONTENT_LENGTH && (e2 = findEntry(e->id)) != NULL) {
585
 
            if (e->value.cmp(e2->value.buf()) != 0) {
 
598
//            if (e->value.cmp(e2->value.termedBuf()) != 0) {
 
599
            if (e->value != e2->value) {
586
600
                int64_t l1, l2;
587
601
                debugs(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2,
588
 
                  "WARNING: found two conflicting content-length headers in {" << getStringPrefix(header_start, header_end) << "}");
 
602
                       "WARNING: found two conflicting content-length headers in {" << getStringPrefix(header_start, header_end) << "}");
589
603
 
590
604
                if (!Config.onoff.relaxed_header_parser) {
591
605
                    delete e;
592
606
                    goto reset;
593
607
                }
594
608
 
595
 
                if (!httpHeaderParseOffset(e->value.buf(), &l1)) {
596
 
                    debugs(55, 1, "WARNING: Unparseable content-length '" << e->value.buf() << "'");
 
609
                if (!httpHeaderParseOffset(e->value.termedBuf(), &l1)) {
 
610
                    debugs(55, 1, "WARNING: Unparseable content-length '" << e->value << "'");
597
611
                    delete e;
598
612
                    continue;
599
 
                } else if (!httpHeaderParseOffset(e2->value.buf(), &l2)) {
600
 
                    debugs(55, 1, "WARNING: Unparseable content-length '" << e2->value.buf() << "'");
 
613
                } else if (!httpHeaderParseOffset(e2->value.termedBuf(), &l2)) {
 
614
                    debugs(55, 1, "WARNING: Unparseable content-length '" << e2->value << "'");
601
615
                    delById(e2->id);
602
616
                } else if (l1 > l2) {
603
617
                    delById(e2->id);
607
621
                }
608
622
            } else {
609
623
                debugs(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2,
610
 
                "NOTICE: found double content-length header");
 
624
                       "NOTICE: found double content-length header");
611
625
 
612
626
                if (Config.onoff.relaxed_header_parser) {
613
627
                    delete e;
619
633
            }
620
634
        }
621
635
 
622
 
        if (e->id == HDR_OTHER && stringHasWhitespace(e->name.buf())) {
 
636
        if (e->id == HDR_OTHER && stringHasWhitespace(e->name.termedBuf())) {
623
637
            debugs(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2,
624
 
                   "WARNING: found whitespace in HTTP header name {" << 
 
638
                   "WARNING: found whitespace in HTTP header name {" <<
625
639
                   getStringPrefix(field_start, field_end) << "}");
626
640
 
627
641
            if (!Config.onoff.relaxed_header_parser) {
673
687
}
674
688
 
675
689
/*
676
 
 * returns a pointer to a specified entry if any 
 
690
 * returns a pointer to a specified entry if any
677
691
 * note that we return one entry so it does not make much sense to ask for
678
692
 * "list" headers
679
693
 */
730
744
}
731
745
 
732
746
/*
733
 
 * deletes all fields with a given name if any, returns #fields deleted; 
 
747
 * deletes all fields with a given name if any, returns #fields deleted;
734
748
 */
735
749
int
736
750
HttpHeader::delByName(const char *name)
814
828
    debugs(55, 7, "refreshing the mask in hdr " << this);
815
829
    HttpHeaderPos pos = HttpHeaderInitPos;
816
830
    while (HttpHeaderEntry *e = getEntry(&pos)) {
817
 
       CBIT_SET(mask, e->id);
 
831
        CBIT_SET(mask, e->id);
818
832
    }
819
833
}
820
834
 
879
893
 
880
894
    while ((e = getEntry(&pos))) {
881
895
        if (e->id == id)
882
 
            strListAdd(s, e->value.buf(), ',');
 
896
            strListAdd(s, e->value.termedBuf(), ',');
883
897
    }
884
898
 
885
899
    /*
913
927
 
914
928
    while ((e = getEntry(&pos))) {
915
929
        if (e->id == id)
916
 
            strListAdd(&s, e->value.buf(), ',');
 
930
            strListAdd(&s, e->value.termedBuf(), ',');
917
931
    }
918
932
 
919
933
    /*
968
982
    /* Sorry, an unknown header name. Do linear search */
969
983
    while ((e = getEntry(&pos))) {
970
984
        if (e->id == HDR_OTHER && e->name.caseCmp(name) == 0) {
971
 
            strListAdd(&result, e->value.buf(), ',');
 
985
            strListAdd(&result, e->value.termedBuf(), ',');
972
986
        }
973
987
    }
974
988
 
1213
1227
    assert(Headers[id].type == ftDate_1123);    /* must be of an appropriate type */
1214
1228
 
1215
1229
    if ((e = findEntry(id))) {
1216
 
        value = parse_rfc1123(e->value.buf());
 
1230
        value = parse_rfc1123(e->value.termedBuf());
1217
1231
        httpHeaderNoteParsedEntry(e->id, e->value, value < 0);
1218
1232
    }
1219
1233
 
1230
1244
 
1231
1245
    if ((e = findEntry(id))) {
1232
1246
        httpHeaderNoteParsedEntry(e->id, e->value, 0);  /* no errors are possible */
1233
 
        return e->value.buf();
 
1247
        return e->value.termedBuf();
1234
1248
    }
1235
1249
 
1236
1250
    return NULL;
1246
1260
 
1247
1261
    if ((e = findLastEntry(id))) {
1248
1262
        httpHeaderNoteParsedEntry(e->id, e->value, 0);  /* no errors are possible */
1249
 
        return e->value.buf();
 
1263
        return e->value.termedBuf();
1250
1264
    }
1251
1265
 
1252
1266
    return NULL;
1304
1318
        return NULL;
1305
1319
 
1306
1320
    String s;
1307
 
   
 
1321
 
1308
1322
    (void) getList(HDR_SURROGATE_CONTROL, &s);
1309
1323
 
1310
1324
    HttpHdrSc *sc = httpHdrScParseCreate(&s);
1326
1340
    HttpHeaderEntry *e;
1327
1341
 
1328
1342
    if ((e = findEntry(HDR_CONTENT_RANGE))) {
1329
 
        cr = httpHdrContRangeParseCreate(e->value.buf());
 
1343
        cr = httpHdrContRangeParseCreate(e->value.termedBuf());
1330
1344
        httpHeaderNoteParsedEntry(e->id, e->value, !cr);
1331
1345
    }
1332
1346
 
1366
1380
ETag
1367
1381
HttpHeader::getETag(http_hdr_type id) const
1368
1382
{
1369
 
    ETag etag =
1370
 
        {NULL, -1};
 
1383
    ETag etag = {NULL, -1};
1371
1384
    HttpHeaderEntry *e;
1372
1385
    assert(Headers[id].type == ftETag);         /* must be of an appropriate type */
1373
1386
 
1374
1387
    if ((e = findEntry(id)))
1375
 
        etagParseInit(&etag, e->value.buf());
 
1388
        etagParseInit(&etag, e->value.termedBuf());
1376
1389
 
1377
1390
    return etag;
1378
1391
}
1386
1399
    memset(&tot, 0, sizeof(tot));
1387
1400
 
1388
1401
    if ((e = findEntry(id))) {
1389
 
        const char *str = e->value.buf();
 
1402
        const char *str = e->value.termedBuf();
1390
1403
        /* try as an ETag */
1391
1404
 
1392
1405
        if (etagParseInit(&tot.tag, str)) {
1422
1435
 
1423
1436
    Headers[id].stat.aliveCount++;
1424
1437
 
1425
 
    debugs(55, 9, "created HttpHeaderEntry " << this << ": '" << name.buf() << " : " << value.buf());
 
1438
    debugs(55, 9, "created HttpHeaderEntry " << this << ": '" << name << " : " << value );
1426
1439
}
1427
1440
 
1428
1441
HttpHeaderEntry::~HttpHeaderEntry()
1429
1442
{
1430
1443
    assert_eid(id);
1431
 
    debugs(55, 9, "destroying entry " << this << ": '" << name.buf() << ": " << value.buf() << "'");
 
1444
    debugs(55, 9, "destroying entry " << this << ": '" << name << ": " << value << "'");
1432
1445
    /* clean name if needed */
1433
1446
 
1434
1447
    if (id == HDR_OTHER)
1449
1462
{
1450
1463
    /* note: name_start == field_start */
1451
1464
    const char *name_end = (const char *)memchr(field_start, ':', field_end - field_start);
1452
 
    int name_len = name_end ? name_end - field_start : 0;
 
1465
    int name_len = name_end ? name_end - field_start :0;
1453
1466
    const char *value_start = field_start + name_len + 1;       /* skip ':' */
1454
1467
    /* note: value_end == field_end */
1455
1468
 
1508
1521
 
1509
1522
    if (field_end - value_start > 65534) {
1510
1523
        /* String must be LESS THAN 64K and it adds a terminating NULL */
1511
 
        debugs(55, 1, "WARNING: ignoring '" << name.buf() << "' header of " << (field_end - value_start) << " bytes");
 
1524
        debugs(55, 1, "WARNING: ignoring '" << name << "' header of " << (field_end - value_start) << " bytes");
1512
1525
 
1513
1526
        if (id == HDR_OTHER)
1514
1527
            name.clean();
1523
1536
 
1524
1537
    Headers[id].stat.aliveCount++;
1525
1538
 
1526
 
    debugs(55, 9, "parsed HttpHeaderEntry: '" << name.buf() << ": " << value.buf() << "'");
 
1539
    debugs(55, 9, "parsed HttpHeaderEntry: '" << name << ": " << value << "'");
1527
1540
 
1528
 
    return new HttpHeaderEntry(id, name.buf(), value.buf());
 
1541
    return new HttpHeaderEntry(id, name.termedBuf(), value.termedBuf());
1529
1542
}
1530
1543
 
1531
1544
HttpHeaderEntry *
1532
1545
HttpHeaderEntry::clone() const
1533
1546
{
1534
 
    return new HttpHeaderEntry(id, name.buf(), value.buf());
 
1547
    return new HttpHeaderEntry(id, name.termedBuf(), value.termedBuf());
1535
1548
}
1536
1549
 
1537
1550
void
1538
1551
HttpHeaderEntry::packInto(Packer * p) const
1539
1552
{
1540
1553
    assert(p);
1541
 
    packerAppend(p, name.buf(), name.size());
 
1554
    packerAppend(p, name.rawBuf(), name.size());
1542
1555
    packerAppend(p, ": ", 2);
1543
 
    packerAppend(p, value.buf(), value.size());
 
1556
    packerAppend(p, value.rawBuf(), value.size());
1544
1557
    packerAppend(p, "\r\n", 2);
1545
1558
}
1546
1559
 
1550
1563
    assert_eid (id);
1551
1564
    assert (Headers[id].type == ftInt);
1552
1565
    int val = -1;
1553
 
    int ok = httpHeaderParseInt(value.buf(), &val);
 
1566
    int ok = httpHeaderParseInt(value.termedBuf(), &val);
1554
1567
    httpHeaderNoteParsedEntry(id, value, !ok);
1555
1568
    /* XXX: Should we check ok - ie
1556
1569
     * return ok ? -1 : value;
1564
1577
    assert_eid (id);
1565
1578
    assert (Headers[id].type == ftInt64);
1566
1579
    int64_t val = -1;
1567
 
    int ok = httpHeaderParseOffset(value.buf(), &val);
 
1580
    int ok = httpHeaderParseOffset(value.termedBuf(), &val);
1568
1581
    httpHeaderNoteParsedEntry(id, value, !ok);
1569
1582
    /* XXX: Should we check ok - ie
1570
1583
     * return ok ? -1 : value;
1579
1592
 
1580
1593
    if (error) {
1581
1594
        Headers[id].stat.errCount++;
1582
 
        debugs(55, 2, "cannot parse hdr field: '" << Headers[id].name.buf() << ": " << context.buf() << "'");
 
1595
        debugs(55, 2, "cannot parse hdr field: '" << Headers[id].name << ": " << context << "'");
1583
1596
    }
1584
1597
}
1585
1598
 
1596
1609
{
1597
1610
    const int id = (int) val;
1598
1611
    const int valid_id = id >= 0 && id < HDR_ENUM_END;
1599
 
    const char *name = valid_id ? Headers[id].name.buf() : "INVALID";
 
1612
    const char *name = valid_id ? Headers[id].name.termedBuf() : "INVALID";
1600
1613
    int visible = count > 0;
1601
1614
    /* for entries with zero count, list only those that belong to current type of message */
1602
1615
 
1674
1687
    for (ht = (http_hdr_type)0; ht < HDR_ENUM_END; ++ht) {
1675
1688
        HttpHeaderFieldInfo *f = Headers + ht;
1676
1689
        storeAppendPrintf(e, "%2d\t %-25s\t %5d\t %6.3f\t %6.3f\n",
1677
 
                          f->id, f->name.buf(), f->stat.aliveCount,
 
1690
                          f->id, f->name.termedBuf(), f->stat.aliveCount,
1678
1691
                          xpercent(f->stat.errCount, f->stat.parsCount),
1679
1692
                          xpercent(f->stat.repCount, f->stat.seenCount));
1680
1693
    }
1687
1700
}
1688
1701
 
1689
1702
http_hdr_type
1690
 
httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * info, int end)
 
1703
httpHeaderIdByName(const char *name, size_t name_len, const HttpHeaderFieldInfo * info, int end)
1691
1704
{
1692
1705
    int i;
1693
1706
 
1695
1708
        if (name_len >= 0 && name_len != info[i].name.size())
1696
1709
            continue;
1697
1710
 
1698
 
        if (!strncasecmp(name, info[i].name.buf(),
 
1711
        if (!strncasecmp(name, info[i].name.termedBuf(),
1699
1712
                         name_len < 0 ? info[i].name.size() + 1 : name_len))
1700
1713
            return info[i].id;
1701
1714
    }
1720
1733
 
1721
1734
    assert(id >= 0 && id < HDR_ENUM_END);
1722
1735
 
1723
 
    return Headers[id].name.buf();
 
1736
    return Headers[id].name.termedBuf();
1724
1737
}
1725
1738
 
1726
1739
int
1775
1788
HttpHeader::removeHopByHopEntries()
1776
1789
{
1777
1790
    removeConnectionHeaderEntries();
1778
 
    
1779
 
    int count = countof(HopByHopHeadersArr);
1780
 
    
1781
 
    for (int i=0; i<count; i++)
1782
 
        delById(HopByHopHeadersArr[i]);    
1783
 
    
 
1791
 
 
1792
    const HttpHeaderEntry *e;
 
1793
    HttpHeaderPos pos = HttpHeaderInitPos;
 
1794
    int headers_deleted = 0;
 
1795
    while ((e = getEntry(&pos))) {
 
1796
        int id = e->id;
 
1797
        if (CBIT_TEST(HopByHopHeadersMask, id)) {
 
1798
            delAt(pos, headers_deleted);
 
1799
            CBIT_CLR(mask, id);
 
1800
        }
 
1801
    }
1784
1802
}
1785
1803
 
1786
1804
void
1789
1807
    if (has(HDR_CONNECTION)) {
1790
1808
        /* anything that matches Connection list member will be deleted */
1791
1809
        String strConnection;
1792
 
        
1793
 
        (void) getList(HDR_CONNECTION, &strConnection);
 
1810
 
 
1811
        (void) getList(HDR_CONNECTION, &strConnection);
1794
1812
        const HttpHeaderEntry *e;
1795
1813
        HttpHeaderPos pos = HttpHeaderInitPos;
1796
1814
        /*
1804
1822
 
1805
1823
        int headers_deleted = 0;
1806
1824
        while ((e = getEntry(&pos))) {
1807
 
            if (strListIsMember(&strConnection, e->name.buf(), ','))
 
1825
            if (strListIsMember(&strConnection, e->name.termedBuf(), ','))
1808
1826
                delAt(pos, headers_deleted);
1809
1827
        }
1810
1828
        if (headers_deleted)
1811
1829
            refreshMask();
1812
 
 
1813
 
        delById(HDR_CONNECTION);
1814
1830
    }
1815
1831
}