00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "ink_defs.h"
00025 #include "libts.h"
00026 #include <assert.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include "MIME.h"
00030 #include "HdrHeap.h"
00031 #include "HdrToken.h"
00032 #include "HdrUtils.h"
00033 #include "HttpCompat.h"
00034
00035
00036
00037
00038
00039
00040 #define TRACK_FIELD_FIND_CALLS 0
00041 #define TRACK_COOKING 0
00042 #define MIME_FORMAT_DATE_USE_LOOKUP_TABLE 1
00043
00044
00045
00046
00047
00048
00049
00050 static DFA *day_names_dfa = NULL;
00051 static DFA *month_names_dfa = NULL;
00052
00053 static const char *day_names[] = {
00054 "Sun",
00055 "Mon",
00056 "Tue",
00057 "Wed",
00058 "Thu",
00059 "Fri",
00060 "Sat",
00061 };
00062
00063 static const char *month_names[] = {
00064 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00065 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
00066 };
00067
00068 struct MDY
00069 {
00070 uint8_t m;
00071 uint8_t d;
00072 uint16_t y;
00073 };
00074
00075 static MDY *_days_to_mdy_fast_lookup_table = NULL;
00076 static unsigned int _days_to_mdy_fast_lookup_table_first_day;
00077 static unsigned int _days_to_mdy_fast_lookup_table_last_day;
00078
00079
00080
00081
00082
00083
00084
00085 const char *MIME_FIELD_ACCEPT;
00086 const char *MIME_FIELD_ACCEPT_CHARSET;
00087 const char *MIME_FIELD_ACCEPT_ENCODING;
00088 const char *MIME_FIELD_ACCEPT_LANGUAGE;
00089 const char *MIME_FIELD_ACCEPT_RANGES;
00090 const char *MIME_FIELD_AGE;
00091 const char *MIME_FIELD_ALLOW;
00092 const char *MIME_FIELD_APPROVED;
00093 const char *MIME_FIELD_AUTHORIZATION;
00094 const char *MIME_FIELD_BYTES;
00095 const char *MIME_FIELD_CACHE_CONTROL;
00096 const char *MIME_FIELD_CLIENT_IP;
00097 const char *MIME_FIELD_CONNECTION;
00098 const char *MIME_FIELD_CONTENT_BASE;
00099 const char *MIME_FIELD_CONTENT_ENCODING;
00100 const char *MIME_FIELD_CONTENT_LANGUAGE;
00101 const char *MIME_FIELD_CONTENT_LENGTH;
00102 const char *MIME_FIELD_CONTENT_LOCATION;
00103 const char *MIME_FIELD_CONTENT_MD5;
00104 const char *MIME_FIELD_CONTENT_RANGE;
00105 const char *MIME_FIELD_CONTENT_TYPE;
00106 const char *MIME_FIELD_CONTROL;
00107 const char *MIME_FIELD_COOKIE;
00108 const char *MIME_FIELD_DATE;
00109 const char *MIME_FIELD_DISTRIBUTION;
00110 const char *MIME_FIELD_ETAG;
00111 const char *MIME_FIELD_EXPECT;
00112 const char *MIME_FIELD_EXPIRES;
00113 const char *MIME_FIELD_FOLLOWUP_TO;
00114 const char *MIME_FIELD_FROM;
00115 const char *MIME_FIELD_HOST;
00116 const char *MIME_FIELD_IF_MATCH;
00117 const char *MIME_FIELD_IF_MODIFIED_SINCE;
00118 const char *MIME_FIELD_IF_NONE_MATCH;
00119 const char *MIME_FIELD_IF_RANGE;
00120 const char *MIME_FIELD_IF_UNMODIFIED_SINCE;
00121 const char *MIME_FIELD_KEEP_ALIVE;
00122 const char *MIME_FIELD_KEYWORDS;
00123 const char *MIME_FIELD_LAST_MODIFIED;
00124 const char *MIME_FIELD_LINES;
00125 const char *MIME_FIELD_LOCATION;
00126 const char *MIME_FIELD_MAX_FORWARDS;
00127 const char *MIME_FIELD_MESSAGE_ID;
00128 const char *MIME_FIELD_NEWSGROUPS;
00129 const char *MIME_FIELD_ORGANIZATION;
00130 const char *MIME_FIELD_PATH;
00131 const char *MIME_FIELD_PRAGMA;
00132 const char *MIME_FIELD_PROXY_AUTHENTICATE;
00133 const char *MIME_FIELD_PROXY_AUTHORIZATION;
00134 const char *MIME_FIELD_PROXY_CONNECTION;
00135 const char *MIME_FIELD_PUBLIC;
00136 const char *MIME_FIELD_RANGE;
00137 const char *MIME_FIELD_REFERENCES;
00138 const char *MIME_FIELD_REFERER;
00139 const char *MIME_FIELD_REPLY_TO;
00140 const char *MIME_FIELD_RETRY_AFTER;
00141 const char *MIME_FIELD_SENDER;
00142 const char *MIME_FIELD_SERVER;
00143 const char *MIME_FIELD_SET_COOKIE;
00144 const char *MIME_FIELD_STRICT_TRANSPORT_SECURITY;
00145 const char *MIME_FIELD_SUBJECT;
00146 const char *MIME_FIELD_SUMMARY;
00147 const char *MIME_FIELD_TE;
00148 const char *MIME_FIELD_TRANSFER_ENCODING;
00149 const char *MIME_FIELD_UPGRADE;
00150 const char *MIME_FIELD_USER_AGENT;
00151 const char *MIME_FIELD_VARY;
00152 const char *MIME_FIELD_VIA;
00153 const char *MIME_FIELD_WARNING;
00154 const char *MIME_FIELD_WWW_AUTHENTICATE;
00155 const char *MIME_FIELD_XREF;
00156 const char *MIME_FIELD_INT_DATA_INFO;
00157 const char *MIME_FIELD_X_ID;
00158 const char *MIME_FIELD_X_FORWARDED_FOR;
00159 const char *MIME_FIELD_SEC_WEBSOCKET_KEY;
00160 const char *MIME_FIELD_SEC_WEBSOCKET_VERSION;
00161
00162 const char *MIME_VALUE_BYTES;
00163 const char *MIME_VALUE_CHUNKED;
00164 const char *MIME_VALUE_CLOSE;
00165 const char *MIME_VALUE_COMPRESS;
00166 const char *MIME_VALUE_DEFLATE;
00167 const char *MIME_VALUE_GZIP;
00168 const char *MIME_VALUE_IDENTITY;
00169 const char *MIME_VALUE_KEEP_ALIVE;
00170 const char *MIME_VALUE_MAX_AGE;
00171 const char *MIME_VALUE_MAX_STALE;
00172 const char *MIME_VALUE_MIN_FRESH;
00173 const char *MIME_VALUE_MUST_REVALIDATE;
00174 const char *MIME_VALUE_NONE;
00175 const char *MIME_VALUE_NO_CACHE;
00176 const char *MIME_VALUE_NO_STORE;
00177 const char *MIME_VALUE_NO_TRANSFORM;
00178 const char *MIME_VALUE_ONLY_IF_CACHED;
00179 const char *MIME_VALUE_PRIVATE;
00180 const char *MIME_VALUE_PROXY_REVALIDATE;
00181 const char *MIME_VALUE_PUBLIC;
00182 const char *MIME_VALUE_S_MAXAGE;
00183 const char *MIME_VALUE_NEED_REVALIDATE_ONCE;
00184 const char *MIME_VALUE_WEBSOCKET;
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 int MIME_LEN_ACCEPT;
00199 int MIME_LEN_ACCEPT_CHARSET;
00200 int MIME_LEN_ACCEPT_ENCODING;
00201 int MIME_LEN_ACCEPT_LANGUAGE;
00202 int MIME_LEN_ACCEPT_RANGES;
00203 int MIME_LEN_AGE;
00204 int MIME_LEN_ALLOW;
00205 int MIME_LEN_APPROVED;
00206 int MIME_LEN_AUTHORIZATION;
00207 int MIME_LEN_BYTES;
00208 int MIME_LEN_CACHE_CONTROL;
00209 int MIME_LEN_CLIENT_IP;
00210 int MIME_LEN_CONNECTION;
00211 int MIME_LEN_CONTENT_BASE;
00212 int MIME_LEN_CONTENT_ENCODING;
00213 int MIME_LEN_CONTENT_LANGUAGE;
00214 int MIME_LEN_CONTENT_LENGTH;
00215 int MIME_LEN_CONTENT_LOCATION;
00216 int MIME_LEN_CONTENT_MD5;
00217 int MIME_LEN_CONTENT_RANGE;
00218 int MIME_LEN_CONTENT_TYPE;
00219 int MIME_LEN_CONTROL;
00220 int MIME_LEN_COOKIE;
00221 int MIME_LEN_DATE;
00222 int MIME_LEN_DISTRIBUTION;
00223 int MIME_LEN_ETAG;
00224 int MIME_LEN_EXPECT;
00225 int MIME_LEN_EXPIRES;
00226 int MIME_LEN_FOLLOWUP_TO;
00227 int MIME_LEN_FROM;
00228 int MIME_LEN_HOST;
00229 int MIME_LEN_IF_MATCH;
00230 int MIME_LEN_IF_MODIFIED_SINCE;
00231 int MIME_LEN_IF_NONE_MATCH;
00232 int MIME_LEN_IF_RANGE;
00233 int MIME_LEN_IF_UNMODIFIED_SINCE;
00234 int MIME_LEN_KEEP_ALIVE;
00235 int MIME_LEN_KEYWORDS;
00236 int MIME_LEN_LAST_MODIFIED;
00237 int MIME_LEN_LINES;
00238 int MIME_LEN_LOCATION;
00239 int MIME_LEN_MAX_FORWARDS;
00240 int MIME_LEN_MESSAGE_ID;
00241 int MIME_LEN_NEWSGROUPS;
00242 int MIME_LEN_ORGANIZATION;
00243 int MIME_LEN_PATH;
00244 int MIME_LEN_PRAGMA;
00245 int MIME_LEN_PROXY_AUTHENTICATE;
00246 int MIME_LEN_PROXY_AUTHORIZATION;
00247 int MIME_LEN_PROXY_CONNECTION;
00248 int MIME_LEN_PUBLIC;
00249 int MIME_LEN_RANGE;
00250 int MIME_LEN_REFERENCES;
00251 int MIME_LEN_REFERER;
00252 int MIME_LEN_REPLY_TO;
00253 int MIME_LEN_RETRY_AFTER;
00254 int MIME_LEN_SENDER;
00255 int MIME_LEN_SERVER;
00256 int MIME_LEN_SET_COOKIE;
00257 int MIME_LEN_STRICT_TRANSPORT_SECURITY;
00258 int MIME_LEN_SUBJECT;
00259 int MIME_LEN_SUMMARY;
00260 int MIME_LEN_TE;
00261 int MIME_LEN_TRANSFER_ENCODING;
00262 int MIME_LEN_UPGRADE;
00263 int MIME_LEN_USER_AGENT;
00264 int MIME_LEN_VARY;
00265 int MIME_LEN_VIA;
00266 int MIME_LEN_WARNING;
00267 int MIME_LEN_WWW_AUTHENTICATE;
00268 int MIME_LEN_XREF;
00269 int MIME_LEN_INT_DATA_INFO;
00270 int MIME_LEN_X_ID;
00271 int MIME_LEN_X_FORWARDED_FOR;
00272 int MIME_LEN_SEC_WEBSOCKET_KEY;
00273 int MIME_LEN_SEC_WEBSOCKET_VERSION;
00274
00275 int MIME_WKSIDX_ACCEPT;
00276 int MIME_WKSIDX_ACCEPT_CHARSET;
00277 int MIME_WKSIDX_ACCEPT_ENCODING;
00278 int MIME_WKSIDX_ACCEPT_LANGUAGE;
00279 int MIME_WKSIDX_ACCEPT_RANGES;
00280 int MIME_WKSIDX_AGE;
00281 int MIME_WKSIDX_ALLOW;
00282 int MIME_WKSIDX_APPROVED;
00283 int MIME_WKSIDX_AUTHORIZATION;
00284 int MIME_WKSIDX_BYTES;
00285 int MIME_WKSIDX_CACHE_CONTROL;
00286 int MIME_WKSIDX_CLIENT_IP;
00287 int MIME_WKSIDX_CONNECTION;
00288 int MIME_WKSIDX_CONTENT_BASE;
00289 int MIME_WKSIDX_CONTENT_ENCODING;
00290 int MIME_WKSIDX_CONTENT_LANGUAGE;
00291 int MIME_WKSIDX_CONTENT_LENGTH;
00292 int MIME_WKSIDX_CONTENT_LOCATION;
00293 int MIME_WKSIDX_CONTENT_MD5;
00294 int MIME_WKSIDX_CONTENT_RANGE;
00295 int MIME_WKSIDX_CONTENT_TYPE;
00296 int MIME_WKSIDX_CONTROL;
00297 int MIME_WKSIDX_COOKIE;
00298 int MIME_WKSIDX_DATE;
00299 int MIME_WKSIDX_DISTRIBUTION;
00300 int MIME_WKSIDX_ETAG;
00301 int MIME_WKSIDX_EXPECT;
00302 int MIME_WKSIDX_EXPIRES;
00303 int MIME_WKSIDX_FOLLOWUP_TO;
00304 int MIME_WKSIDX_FROM;
00305 int MIME_WKSIDX_HOST;
00306 int MIME_WKSIDX_IF_MATCH;
00307 int MIME_WKSIDX_IF_MODIFIED_SINCE;
00308 int MIME_WKSIDX_IF_NONE_MATCH;
00309 int MIME_WKSIDX_IF_RANGE;
00310 int MIME_WKSIDX_IF_UNMODIFIED_SINCE;
00311 int MIME_WKSIDX_KEEP_ALIVE;
00312 int MIME_WKSIDX_KEYWORDS;
00313 int MIME_WKSIDX_LAST_MODIFIED;
00314 int MIME_WKSIDX_LINES;
00315 int MIME_WKSIDX_LOCATION;
00316 int MIME_WKSIDX_MAX_FORWARDS;
00317 int MIME_WKSIDX_MESSAGE_ID;
00318 int MIME_WKSIDX_NEWSGROUPS;
00319 int MIME_WKSIDX_ORGANIZATION;
00320 int MIME_WKSIDX_PATH;
00321 int MIME_WKSIDX_PRAGMA;
00322 int MIME_WKSIDX_PROXY_AUTHENTICATE;
00323 int MIME_WKSIDX_PROXY_AUTHORIZATION;
00324 int MIME_WKSIDX_PROXY_CONNECTION;
00325 int MIME_WKSIDX_PUBLIC;
00326 int MIME_WKSIDX_RANGE;
00327 int MIME_WKSIDX_REFERENCES;
00328 int MIME_WKSIDX_REFERER;
00329 int MIME_WKSIDX_REPLY_TO;
00330 int MIME_WKSIDX_RETRY_AFTER;
00331 int MIME_WKSIDX_SENDER;
00332 int MIME_WKSIDX_SERVER;
00333 int MIME_WKSIDX_SET_COOKIE;
00334 int MIME_WKSIDX_STRICT_TRANSPORT_SECURITY;
00335 int MIME_WKSIDX_SUBJECT;
00336 int MIME_WKSIDX_SUMMARY;
00337 int MIME_WKSIDX_TE;
00338 int MIME_WKSIDX_TRANSFER_ENCODING;
00339 int MIME_WKSIDX_UPGRADE;
00340 int MIME_WKSIDX_USER_AGENT;
00341 int MIME_WKSIDX_VARY;
00342 int MIME_WKSIDX_VIA;
00343 int MIME_WKSIDX_WARNING;
00344 int MIME_WKSIDX_WWW_AUTHENTICATE;
00345 int MIME_WKSIDX_XREF;
00346 int MIME_WKSIDX_INT_DATA_INFO;
00347 int MIME_WKSIDX_X_ID;
00348 int MIME_WKSIDX_X_FORWARDED_FOR;
00349 int MIME_WKSIDX_SEC_WEBSOCKET_KEY;
00350 int MIME_WKSIDX_SEC_WEBSOCKET_VERSION;
00351
00352
00353
00354
00355
00356
00357 inline static int
00358 is_digit(char c)
00359 {
00360 return ((c <= '9') && (c >= '0'));
00361 }
00362
00363 inline static int
00364 is_ws(char c)
00365 {
00366 return ((c == ParseRules::CHAR_SP) || (c == ParseRules::CHAR_HT));
00367 }
00368
00369
00370
00371
00372
00373
00374
00375 uint64_t
00376 mime_field_presence_mask(const char *well_known_str)
00377 {
00378 return hdrtoken_wks_to_mask(well_known_str);
00379 }
00380
00381 uint64_t
00382 mime_field_presence_mask(int well_known_str_index)
00383 {
00384 return hdrtoken_index_to_mask(well_known_str_index);
00385 }
00386
00387 int
00388 mime_field_presence_get(MIMEHdrImpl *h, const char *well_known_str)
00389 {
00390 uint64_t mask = mime_field_presence_mask(well_known_str);
00391 return ((mask == 0) ? 1 : ((h->m_presence_bits & mask) == 0 ? 0 : 1));
00392 }
00393
00394 int
00395 mime_field_presence_get(MIMEHdrImpl *h, int well_known_str_index)
00396 {
00397 const char *wks = hdrtoken_index_to_wks(well_known_str_index);
00398 return mime_field_presence_get(h, wks);
00399 }
00400
00401 void
00402 mime_hdr_presence_set(MIMEHdrImpl *h, const char *well_known_str)
00403 {
00404 uint64_t mask = mime_field_presence_mask(well_known_str);
00405 if (mask != 0)
00406 h->m_presence_bits |= mask;
00407 }
00408
00409 void
00410 mime_hdr_presence_set(MIMEHdrImpl *h, int well_known_str_index)
00411 {
00412 const char *wks = hdrtoken_index_to_wks(well_known_str_index);
00413 mime_hdr_presence_set(h, wks);
00414 }
00415
00416 void
00417 mime_hdr_presence_unset(MIMEHdrImpl *h, const char *well_known_str)
00418 {
00419 uint64_t mask = mime_field_presence_mask(well_known_str);
00420 if (mask != 0)
00421 h->m_presence_bits &= (~mask);
00422 }
00423
00424 void
00425 mime_hdr_presence_unset(MIMEHdrImpl *h, int well_known_str_index)
00426 {
00427 const char *wks = hdrtoken_index_to_wks(well_known_str_index);
00428 mime_hdr_presence_unset(h, wks);
00429 }
00430
00431
00432
00433
00434
00435
00436 inline void
00437 mime_hdr_init_accelerators_and_presence_bits(MIMEHdrImpl* mh)
00438 {
00439 mh->m_presence_bits = 0;
00440 mh->m_slot_accelerators[0] = 0xFFFFFFFF;
00441 mh->m_slot_accelerators[1] = 0xFFFFFFFF;
00442 mh->m_slot_accelerators[2] = 0xFFFFFFFF;
00443 mh->m_slot_accelerators[3] = 0xFFFFFFFF;
00444 }
00445
00446 inline uint32_t
00447 mime_hdr_get_accelerator_slotnum(MIMEHdrImpl *mh, int32_t slot_id)
00448 {
00449 ink_assert((slot_id != MIME_SLOTID_NONE) && (slot_id < 32));
00450
00451 uint32_t word_index = slot_id / 8;
00452 uint32_t word = mh->m_slot_accelerators[word_index];
00453 uint32_t nybble = slot_id % 8;
00454 uint32_t slot = ((word >> (nybble * 4)) & 15);
00455 return slot;
00456 }
00457
00458 inline void
00459 mime_hdr_set_accelerator_slotnum(MIMEHdrImpl *mh, int32_t slot_id, uint32_t slot_num)
00460 {
00461 ink_assert((slot_id != MIME_SLOTID_NONE) && (slot_id < 32));
00462 ink_assert(slot_num < 16);
00463
00464 uint32_t word_index = slot_id / 8;
00465 uint32_t word = mh->m_slot_accelerators[word_index];
00466 uint32_t nybble = slot_id % 8;
00467 uint32_t shift = nybble * 4;
00468 uint32_t mask = ~(MIME_FIELD_SLOTNUM_MASK << shift);
00469 uint32_t graft = (slot_num << shift);
00470 uint32_t new_word = (word & mask) | graft;
00471
00472 mh->m_slot_accelerators[word_index] = new_word;
00473 }
00474
00475 inline void
00476 mime_hdr_set_accelerators_and_presence_bits(MIMEHdrImpl *mh, MIMEField *field)
00477 {
00478 int slot_id, slot_num;
00479 if (field->m_wks_idx < 0)
00480 return;
00481
00482 mime_hdr_presence_set(mh, field->m_wks_idx);
00483
00484 slot_id = hdrtoken_index_to_slotid(field->m_wks_idx);
00485 if (slot_id != MIME_SLOTID_NONE) {
00486 slot_num = (field - &(mh->m_first_fblock.m_field_slots[0]));
00487 if ((slot_num >= 0) && (slot_num < MIME_FIELD_SLOTNUM_UNKNOWN))
00488 mime_hdr_set_accelerator_slotnum(mh, slot_id, slot_num);
00489 else
00490 mime_hdr_set_accelerator_slotnum(mh, slot_id, MIME_FIELD_SLOTNUM_UNKNOWN);
00491 }
00492 }
00493
00494 inline void
00495 mime_hdr_unset_accelerators_and_presence_bits(MIMEHdrImpl *mh, MIMEField *field)
00496 {
00497 int slot_id;
00498 if (field->m_wks_idx < 0)
00499 return;
00500
00501 mime_hdr_presence_unset(mh, field->m_wks_idx);
00502
00503 slot_id = hdrtoken_index_to_slotid(field->m_wks_idx);
00504 if (slot_id != MIME_SLOTID_NONE)
00505 mime_hdr_set_accelerator_slotnum(mh, slot_id, MIME_FIELD_SLOTNUM_MAX);
00506 }
00507
00508
00509
00510
00511 inline void
00512 mime_hdr_reset_accelerators_and_presence_bits(MIMEHdrImpl* mh) {
00513 mime_hdr_init_accelerators_and_presence_bits(mh);
00514
00515 for (MIMEFieldBlockImpl* fblock = &(mh->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
00516 for ( MIMEField *field = fblock->m_field_slots, *limit = field + fblock->m_freetop ; field < limit ; ++field) {
00517 if (field->is_live()) {
00518 field->m_wks_idx = hdrtoken_tokenize(field->m_ptr_name, field->m_len_name);
00519 if (field->is_dup_head())
00520 mime_hdr_set_accelerators_and_presence_bits(mh, field);
00521 }
00522 }
00523 }
00524 }
00525
00526 int
00527 checksum_block(const char *s, int len)
00528 {
00529 int sum = 0;
00530 while (len--)
00531 sum ^= *s++;
00532 return sum;
00533 }
00534
00535
00536 #ifdef DEBUG
00537 void
00538 mime_hdr_sanity_check(MIMEHdrImpl *mh)
00539 {
00540 MIMEFieldBlockImpl *fblock, *blk, *last_fblock;
00541 MIMEField *field, *next_dup;
00542 uint32_t slot_index, index;
00543 uint64_t masksum;
00544
00545 masksum = 0;
00546 slot_index = 0;
00547 last_fblock = NULL;
00548
00549 for (fblock = &(mh->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
00550 for (index = 0; index < fblock->m_freetop; index++) {
00551 field = &(fblock->m_field_slots[index]);
00552
00553 if (field->is_live()) {
00554
00555 checksum_block(field->m_ptr_name, field->m_len_name);
00556 if (field->m_ptr_value)
00557 checksum_block(field->m_ptr_value, field->m_len_value);
00558
00559 if (field->m_n_v_raw_printable) {
00560 int total_len = field->m_len_name + field->m_len_value + field->m_n_v_raw_printable_pad;
00561 checksum_block(field->m_ptr_name, total_len);
00562 }
00563
00564 if (field->m_next_dup != NULL) {
00565 int field_slotnum = mime_hdr_field_slotnum(mh, field);
00566
00567 for (next_dup = field->m_next_dup; next_dup; next_dup = next_dup->m_next_dup) {
00568 int next_slotnum = mime_hdr_field_slotnum(mh, next_dup);
00569 ink_release_assert((next_dup->m_flags & MIME_FIELD_SLOT_FLAGS_DUP_HEAD) == 0);
00570 ink_release_assert((next_dup->m_readiness == MIME_FIELD_SLOT_READINESS_LIVE));
00571 ink_release_assert(next_dup->m_wks_idx == field->m_wks_idx);
00572 ink_release_assert(next_dup->m_len_name == field->m_len_name);
00573 ink_release_assert(strncasecmp(field->m_ptr_name, next_dup->m_ptr_name, field->m_len_name) == 0);
00574 ink_release_assert(next_slotnum > field_slotnum);
00575 }
00576 }
00577
00578 if (field->m_wks_idx >= 0) {
00579 const char *wks = hdrtoken_index_to_wks(field->m_wks_idx);
00580 int len = hdrtoken_index_to_length(field->m_wks_idx);
00581
00582 if (field->m_len_name != len || strncasecmp(field->m_ptr_name, wks, field->m_len_name) != 0)
00583 Warning("Encountered WKS hash collision on '%.*s'", field->m_len_name, field->m_ptr_name);
00584
00585 uint64_t mask = mime_field_presence_mask(field->m_wks_idx);
00586 masksum |= mask;
00587
00588 int32_t slot_id = hdrtoken_index_to_slotid(field->m_wks_idx);
00589 if ((slot_id != MIME_SLOTID_NONE) &&
00590 (slot_index < MIME_FIELD_SLOTNUM_UNKNOWN) && (field->m_flags & MIME_FIELD_SLOT_FLAGS_DUP_HEAD)) {
00591 uint32_t slot_num = mime_hdr_get_accelerator_slotnum(mh, slot_id);
00592 if (slot_num <= 14)
00593 ink_release_assert(slot_num == slot_index);
00594 }
00595 } else {
00596 int idx = hdrtoken_tokenize(field->m_ptr_name, field->m_len_name, NULL);
00597 ink_release_assert(idx < 0);
00598 }
00599
00600
00601 if (field->m_next_dup) {
00602 bool found = false;
00603 for (blk = &(mh->m_first_fblock); blk != NULL; blk = blk->m_next) {
00604 const char *addr = (const char *) (field->m_next_dup);
00605 if ((addr >= (const char *) (blk)) && (addr < (const char *) (blk) + sizeof(MIMEFieldBlockImpl))) {
00606 found = true;
00607 break;
00608 }
00609 }
00610 ink_release_assert(found);
00611 }
00612
00613 MIMEField *mf = mime_hdr_field_find(mh, field->m_ptr_name, field->m_len_name);
00614 ink_release_assert(mf != NULL);
00615 if (mf == field)
00616 ink_release_assert((field->m_flags & MIME_FIELD_SLOT_FLAGS_DUP_HEAD) != 0);
00617 else
00618 ink_release_assert((field->m_flags & MIME_FIELD_SLOT_FLAGS_DUP_HEAD) == 0);
00619 }
00620
00621 ++slot_index;
00622 }
00623 last_fblock = fblock;
00624 }
00625
00626 ink_release_assert(last_fblock == mh->m_fblock_list_tail);
00627 ink_release_assert(masksum == mh->m_presence_bits);
00628 }
00629 #endif
00630
00631
00632 void
00633 mime_init()
00634 {
00635 static int init = 1;
00636
00637 if (init) {
00638 init = 0;
00639
00640 hdrtoken_init();
00641 day_names_dfa = new DFA;
00642 day_names_dfa->compile(day_names, SIZEOF(day_names), RE_CASE_INSENSITIVE);
00643
00644 month_names_dfa = new DFA;
00645 month_names_dfa->compile(month_names, SIZEOF(month_names), RE_CASE_INSENSITIVE);
00646
00647 MIME_FIELD_ACCEPT = hdrtoken_string_to_wks("Accept");
00648 MIME_FIELD_ACCEPT_CHARSET = hdrtoken_string_to_wks("Accept-Charset");
00649 MIME_FIELD_ACCEPT_ENCODING = hdrtoken_string_to_wks("Accept-Encoding");
00650 MIME_FIELD_ACCEPT_LANGUAGE = hdrtoken_string_to_wks("Accept-Language");
00651 MIME_FIELD_ACCEPT_RANGES = hdrtoken_string_to_wks("Accept-Ranges");
00652 MIME_FIELD_AGE = hdrtoken_string_to_wks("Age");
00653 MIME_FIELD_ALLOW = hdrtoken_string_to_wks("Allow");
00654 MIME_FIELD_APPROVED = hdrtoken_string_to_wks("Approved");
00655 MIME_FIELD_AUTHORIZATION = hdrtoken_string_to_wks("Authorization");
00656 MIME_FIELD_BYTES = hdrtoken_string_to_wks("Bytes");
00657 MIME_FIELD_CACHE_CONTROL = hdrtoken_string_to_wks("Cache-Control");
00658 MIME_FIELD_CLIENT_IP = hdrtoken_string_to_wks("Client-ip");
00659 MIME_FIELD_CONNECTION = hdrtoken_string_to_wks("Connection");
00660 MIME_FIELD_CONTENT_BASE = hdrtoken_string_to_wks("Content-Base");
00661 MIME_FIELD_CONTENT_ENCODING = hdrtoken_string_to_wks("Content-Encoding");
00662 MIME_FIELD_CONTENT_LANGUAGE = hdrtoken_string_to_wks("Content-Language");
00663 MIME_FIELD_CONTENT_LENGTH = hdrtoken_string_to_wks("Content-Length");
00664 MIME_FIELD_CONTENT_LOCATION = hdrtoken_string_to_wks("Content-Location");
00665 MIME_FIELD_CONTENT_MD5 = hdrtoken_string_to_wks("Content-MD5");
00666 MIME_FIELD_CONTENT_RANGE = hdrtoken_string_to_wks("Content-Range");
00667 MIME_FIELD_CONTENT_TYPE = hdrtoken_string_to_wks("Content-Type");
00668 MIME_FIELD_CONTROL = hdrtoken_string_to_wks("Control");
00669 MIME_FIELD_COOKIE = hdrtoken_string_to_wks("Cookie");
00670 MIME_FIELD_DATE = hdrtoken_string_to_wks("Date");
00671 MIME_FIELD_DISTRIBUTION = hdrtoken_string_to_wks("Distribution");
00672 MIME_FIELD_ETAG = hdrtoken_string_to_wks("Etag");
00673 MIME_FIELD_EXPECT = hdrtoken_string_to_wks("Expect");
00674 MIME_FIELD_EXPIRES = hdrtoken_string_to_wks("Expires");
00675 MIME_FIELD_FOLLOWUP_TO = hdrtoken_string_to_wks("Followup-To");
00676 MIME_FIELD_FROM = hdrtoken_string_to_wks("From");
00677 MIME_FIELD_HOST = hdrtoken_string_to_wks("Host");
00678 MIME_FIELD_IF_MATCH = hdrtoken_string_to_wks("If-Match");
00679 MIME_FIELD_IF_MODIFIED_SINCE = hdrtoken_string_to_wks("If-Modified-Since");
00680 MIME_FIELD_IF_NONE_MATCH = hdrtoken_string_to_wks("If-None-Match");
00681 MIME_FIELD_IF_RANGE = hdrtoken_string_to_wks("If-Range");
00682 MIME_FIELD_IF_UNMODIFIED_SINCE = hdrtoken_string_to_wks("If-Unmodified-Since");
00683 MIME_FIELD_KEEP_ALIVE = hdrtoken_string_to_wks("Keep-Alive");
00684 MIME_FIELD_KEYWORDS = hdrtoken_string_to_wks("Keywords");
00685 MIME_FIELD_LAST_MODIFIED = hdrtoken_string_to_wks("Last-Modified");
00686 MIME_FIELD_LINES = hdrtoken_string_to_wks("Lines");
00687 MIME_FIELD_LOCATION = hdrtoken_string_to_wks("Location");
00688 MIME_FIELD_MAX_FORWARDS = hdrtoken_string_to_wks("Max-Forwards");
00689 MIME_FIELD_MESSAGE_ID = hdrtoken_string_to_wks("Message-ID");
00690 MIME_FIELD_NEWSGROUPS = hdrtoken_string_to_wks("Newsgroups");
00691 MIME_FIELD_ORGANIZATION = hdrtoken_string_to_wks("Organization");
00692 MIME_FIELD_PATH = hdrtoken_string_to_wks("Path");
00693 MIME_FIELD_PRAGMA = hdrtoken_string_to_wks("Pragma");
00694 MIME_FIELD_PROXY_AUTHENTICATE = hdrtoken_string_to_wks("Proxy-Authenticate");
00695 MIME_FIELD_PROXY_AUTHORIZATION = hdrtoken_string_to_wks("Proxy-Authorization");
00696 MIME_FIELD_PROXY_CONNECTION = hdrtoken_string_to_wks("Proxy-Connection");
00697 MIME_FIELD_PUBLIC = hdrtoken_string_to_wks("Public");
00698 MIME_FIELD_RANGE = hdrtoken_string_to_wks("Range");
00699 MIME_FIELD_REFERENCES = hdrtoken_string_to_wks("References");
00700 MIME_FIELD_REFERER = hdrtoken_string_to_wks("Referer");
00701 MIME_FIELD_REPLY_TO = hdrtoken_string_to_wks("Reply-To");
00702 MIME_FIELD_RETRY_AFTER = hdrtoken_string_to_wks("Retry-After");
00703 MIME_FIELD_SENDER = hdrtoken_string_to_wks("Sender");
00704 MIME_FIELD_SERVER = hdrtoken_string_to_wks("Server");
00705 MIME_FIELD_SET_COOKIE = hdrtoken_string_to_wks("Set-Cookie");
00706 MIME_FIELD_STRICT_TRANSPORT_SECURITY = hdrtoken_string_to_wks("Strict-Transport-Security");
00707 MIME_FIELD_SUBJECT = hdrtoken_string_to_wks("Subject");
00708 MIME_FIELD_SUMMARY = hdrtoken_string_to_wks("Summary");
00709 MIME_FIELD_TE = hdrtoken_string_to_wks("TE");
00710 MIME_FIELD_TRANSFER_ENCODING = hdrtoken_string_to_wks("Transfer-Encoding");
00711 MIME_FIELD_UPGRADE = hdrtoken_string_to_wks("Upgrade");
00712 MIME_FIELD_USER_AGENT = hdrtoken_string_to_wks("User-Agent");
00713 MIME_FIELD_VARY = hdrtoken_string_to_wks("Vary");
00714 MIME_FIELD_VIA = hdrtoken_string_to_wks("Via");
00715 MIME_FIELD_WARNING = hdrtoken_string_to_wks("Warning");
00716 MIME_FIELD_WWW_AUTHENTICATE = hdrtoken_string_to_wks("Www-Authenticate");
00717 MIME_FIELD_XREF = hdrtoken_string_to_wks("Xref");
00718 MIME_FIELD_INT_DATA_INFO = hdrtoken_string_to_wks("@DataInfo");
00719 MIME_FIELD_X_ID = hdrtoken_string_to_wks("X-ID");
00720 MIME_FIELD_X_FORWARDED_FOR = hdrtoken_string_to_wks("X-Forwarded-For");
00721
00722 MIME_FIELD_SEC_WEBSOCKET_KEY = hdrtoken_string_to_wks("Sec-WebSocket-Key");
00723 MIME_FIELD_SEC_WEBSOCKET_VERSION = hdrtoken_string_to_wks("Sec-WebSocket-Version");
00724
00725
00726 MIME_LEN_ACCEPT = hdrtoken_wks_to_length(MIME_FIELD_ACCEPT);
00727 MIME_LEN_ACCEPT_CHARSET = hdrtoken_wks_to_length(MIME_FIELD_ACCEPT_CHARSET);
00728 MIME_LEN_ACCEPT_ENCODING = hdrtoken_wks_to_length(MIME_FIELD_ACCEPT_ENCODING);
00729 MIME_LEN_ACCEPT_LANGUAGE = hdrtoken_wks_to_length(MIME_FIELD_ACCEPT_LANGUAGE);
00730 MIME_LEN_ACCEPT_RANGES = hdrtoken_wks_to_length(MIME_FIELD_ACCEPT_RANGES);
00731 MIME_LEN_AGE = hdrtoken_wks_to_length(MIME_FIELD_AGE);
00732 MIME_LEN_ALLOW = hdrtoken_wks_to_length(MIME_FIELD_ALLOW);
00733 MIME_LEN_APPROVED = hdrtoken_wks_to_length(MIME_FIELD_APPROVED);
00734 MIME_LEN_AUTHORIZATION = hdrtoken_wks_to_length(MIME_FIELD_AUTHORIZATION);
00735 MIME_LEN_BYTES = hdrtoken_wks_to_length(MIME_FIELD_BYTES);
00736 MIME_LEN_CACHE_CONTROL = hdrtoken_wks_to_length(MIME_FIELD_CACHE_CONTROL);
00737 MIME_LEN_CLIENT_IP = hdrtoken_wks_to_length(MIME_FIELD_CLIENT_IP);
00738 MIME_LEN_CONNECTION = hdrtoken_wks_to_length(MIME_FIELD_CONNECTION);
00739 MIME_LEN_CONTENT_BASE = hdrtoken_wks_to_length(MIME_FIELD_CONTENT_BASE);
00740 MIME_LEN_CONTENT_ENCODING = hdrtoken_wks_to_length(MIME_FIELD_CONTENT_ENCODING);
00741 MIME_LEN_CONTENT_LANGUAGE = hdrtoken_wks_to_length(MIME_FIELD_CONTENT_LANGUAGE);
00742 MIME_LEN_CONTENT_LENGTH = hdrtoken_wks_to_length(MIME_FIELD_CONTENT_LENGTH);
00743 MIME_LEN_CONTENT_LOCATION = hdrtoken_wks_to_length(MIME_FIELD_CONTENT_LOCATION);
00744 MIME_LEN_CONTENT_MD5 = hdrtoken_wks_to_length(MIME_FIELD_CONTENT_MD5);
00745 MIME_LEN_CONTENT_RANGE = hdrtoken_wks_to_length(MIME_FIELD_CONTENT_RANGE);
00746 MIME_LEN_CONTENT_TYPE = hdrtoken_wks_to_length(MIME_FIELD_CONTENT_TYPE);
00747 MIME_LEN_CONTROL = hdrtoken_wks_to_length(MIME_FIELD_CONTROL);
00748 MIME_LEN_COOKIE = hdrtoken_wks_to_length(MIME_FIELD_COOKIE);
00749 MIME_LEN_DATE = hdrtoken_wks_to_length(MIME_FIELD_DATE);
00750 MIME_LEN_DISTRIBUTION = hdrtoken_wks_to_length(MIME_FIELD_DISTRIBUTION);
00751 MIME_LEN_ETAG = hdrtoken_wks_to_length(MIME_FIELD_ETAG);
00752 MIME_LEN_EXPECT = hdrtoken_wks_to_length(MIME_FIELD_EXPECT);
00753 MIME_LEN_EXPIRES = hdrtoken_wks_to_length(MIME_FIELD_EXPIRES);
00754 MIME_LEN_FOLLOWUP_TO = hdrtoken_wks_to_length(MIME_FIELD_FOLLOWUP_TO);
00755 MIME_LEN_FROM = hdrtoken_wks_to_length(MIME_FIELD_FROM);
00756 MIME_LEN_HOST = hdrtoken_wks_to_length(MIME_FIELD_HOST);
00757 MIME_LEN_IF_MATCH = hdrtoken_wks_to_length(MIME_FIELD_IF_MATCH);
00758 MIME_LEN_IF_MODIFIED_SINCE = hdrtoken_wks_to_length(MIME_FIELD_IF_MODIFIED_SINCE);
00759 MIME_LEN_IF_NONE_MATCH = hdrtoken_wks_to_length(MIME_FIELD_IF_NONE_MATCH);
00760 MIME_LEN_IF_RANGE = hdrtoken_wks_to_length(MIME_FIELD_IF_RANGE);
00761 MIME_LEN_IF_UNMODIFIED_SINCE = hdrtoken_wks_to_length(MIME_FIELD_IF_UNMODIFIED_SINCE);
00762 MIME_LEN_KEEP_ALIVE = hdrtoken_wks_to_length(MIME_FIELD_KEEP_ALIVE);
00763 MIME_LEN_KEYWORDS = hdrtoken_wks_to_length(MIME_FIELD_KEYWORDS);
00764 MIME_LEN_LAST_MODIFIED = hdrtoken_wks_to_length(MIME_FIELD_LAST_MODIFIED);
00765 MIME_LEN_LINES = hdrtoken_wks_to_length(MIME_FIELD_LINES);
00766 MIME_LEN_LOCATION = hdrtoken_wks_to_length(MIME_FIELD_LOCATION);
00767 MIME_LEN_MAX_FORWARDS = hdrtoken_wks_to_length(MIME_FIELD_MAX_FORWARDS);
00768 MIME_LEN_MESSAGE_ID = hdrtoken_wks_to_length(MIME_FIELD_MESSAGE_ID);
00769 MIME_LEN_NEWSGROUPS = hdrtoken_wks_to_length(MIME_FIELD_NEWSGROUPS);
00770 MIME_LEN_ORGANIZATION = hdrtoken_wks_to_length(MIME_FIELD_ORGANIZATION);
00771 MIME_LEN_PATH = hdrtoken_wks_to_length(MIME_FIELD_PATH);
00772 MIME_LEN_PRAGMA = hdrtoken_wks_to_length(MIME_FIELD_PRAGMA);
00773 MIME_LEN_PROXY_AUTHENTICATE = hdrtoken_wks_to_length(MIME_FIELD_PROXY_AUTHENTICATE);
00774 MIME_LEN_PROXY_AUTHORIZATION = hdrtoken_wks_to_length(MIME_FIELD_PROXY_AUTHORIZATION);
00775 MIME_LEN_PROXY_CONNECTION = hdrtoken_wks_to_length(MIME_FIELD_PROXY_CONNECTION);
00776 MIME_LEN_PUBLIC = hdrtoken_wks_to_length(MIME_FIELD_PUBLIC);
00777 MIME_LEN_RANGE = hdrtoken_wks_to_length(MIME_FIELD_RANGE);
00778 MIME_LEN_REFERENCES = hdrtoken_wks_to_length(MIME_FIELD_REFERENCES);
00779 MIME_LEN_REFERER = hdrtoken_wks_to_length(MIME_FIELD_REFERER);
00780 MIME_LEN_REPLY_TO = hdrtoken_wks_to_length(MIME_FIELD_REPLY_TO);
00781 MIME_LEN_RETRY_AFTER = hdrtoken_wks_to_length(MIME_FIELD_RETRY_AFTER);
00782 MIME_LEN_SENDER = hdrtoken_wks_to_length(MIME_FIELD_SENDER);
00783 MIME_LEN_SERVER = hdrtoken_wks_to_length(MIME_FIELD_SERVER);
00784 MIME_LEN_SET_COOKIE = hdrtoken_wks_to_length(MIME_FIELD_SET_COOKIE);
00785 MIME_LEN_STRICT_TRANSPORT_SECURITY = hdrtoken_wks_to_length(MIME_FIELD_STRICT_TRANSPORT_SECURITY);
00786 MIME_LEN_SUBJECT = hdrtoken_wks_to_length(MIME_FIELD_SUBJECT);
00787 MIME_LEN_SUMMARY = hdrtoken_wks_to_length(MIME_FIELD_SUMMARY);
00788 MIME_LEN_TE = hdrtoken_wks_to_length(MIME_FIELD_TE);
00789 MIME_LEN_TRANSFER_ENCODING = hdrtoken_wks_to_length(MIME_FIELD_TRANSFER_ENCODING);
00790 MIME_LEN_UPGRADE = hdrtoken_wks_to_length(MIME_FIELD_UPGRADE);
00791 MIME_LEN_USER_AGENT = hdrtoken_wks_to_length(MIME_FIELD_USER_AGENT);
00792 MIME_LEN_VARY = hdrtoken_wks_to_length(MIME_FIELD_VARY);
00793 MIME_LEN_VIA = hdrtoken_wks_to_length(MIME_FIELD_VIA);
00794 MIME_LEN_WARNING = hdrtoken_wks_to_length(MIME_FIELD_WARNING);
00795 MIME_LEN_WWW_AUTHENTICATE = hdrtoken_wks_to_length(MIME_FIELD_WWW_AUTHENTICATE);
00796 MIME_LEN_XREF = hdrtoken_wks_to_length(MIME_FIELD_XREF);
00797 MIME_LEN_INT_DATA_INFO = hdrtoken_wks_to_length(MIME_FIELD_INT_DATA_INFO);
00798 MIME_LEN_X_ID = hdrtoken_wks_to_length(MIME_FIELD_X_ID);
00799 MIME_LEN_X_FORWARDED_FOR = hdrtoken_wks_to_length(MIME_FIELD_X_FORWARDED_FOR);
00800
00801 MIME_LEN_SEC_WEBSOCKET_KEY = hdrtoken_wks_to_length(MIME_FIELD_SEC_WEBSOCKET_KEY);
00802 MIME_LEN_SEC_WEBSOCKET_VERSION = hdrtoken_wks_to_length(MIME_FIELD_SEC_WEBSOCKET_VERSION);
00803
00804
00805 MIME_WKSIDX_ACCEPT = hdrtoken_wks_to_index(MIME_FIELD_ACCEPT);
00806 MIME_WKSIDX_ACCEPT_CHARSET = hdrtoken_wks_to_index(MIME_FIELD_ACCEPT_CHARSET);
00807 MIME_WKSIDX_ACCEPT_ENCODING = hdrtoken_wks_to_index(MIME_FIELD_ACCEPT_ENCODING);
00808 MIME_WKSIDX_ACCEPT_LANGUAGE = hdrtoken_wks_to_index(MIME_FIELD_ACCEPT_LANGUAGE);
00809 MIME_WKSIDX_ACCEPT_RANGES = hdrtoken_wks_to_index(MIME_FIELD_ACCEPT_RANGES);
00810 MIME_WKSIDX_AGE = hdrtoken_wks_to_index(MIME_FIELD_AGE);
00811 MIME_WKSIDX_ALLOW = hdrtoken_wks_to_index(MIME_FIELD_ALLOW);
00812 MIME_WKSIDX_APPROVED = hdrtoken_wks_to_index(MIME_FIELD_APPROVED);
00813 MIME_WKSIDX_AUTHORIZATION = hdrtoken_wks_to_index(MIME_FIELD_AUTHORIZATION);
00814 MIME_WKSIDX_BYTES = hdrtoken_wks_to_index(MIME_FIELD_BYTES);
00815 MIME_WKSIDX_CACHE_CONTROL = hdrtoken_wks_to_index(MIME_FIELD_CACHE_CONTROL);
00816 MIME_WKSIDX_CLIENT_IP = hdrtoken_wks_to_index(MIME_FIELD_CLIENT_IP);
00817 MIME_WKSIDX_CONNECTION = hdrtoken_wks_to_index(MIME_FIELD_CONNECTION);
00818 MIME_WKSIDX_CONTENT_BASE = hdrtoken_wks_to_index(MIME_FIELD_CONTENT_BASE);
00819 MIME_WKSIDX_CONTENT_ENCODING = hdrtoken_wks_to_index(MIME_FIELD_CONTENT_ENCODING);
00820 MIME_WKSIDX_CONTENT_LANGUAGE = hdrtoken_wks_to_index(MIME_FIELD_CONTENT_LANGUAGE);
00821 MIME_WKSIDX_CONTENT_LENGTH = hdrtoken_wks_to_index(MIME_FIELD_CONTENT_LENGTH);
00822 MIME_WKSIDX_CONTENT_LOCATION = hdrtoken_wks_to_index(MIME_FIELD_CONTENT_LOCATION);
00823 MIME_WKSIDX_CONTENT_MD5 = hdrtoken_wks_to_index(MIME_FIELD_CONTENT_MD5);
00824 MIME_WKSIDX_CONTENT_RANGE = hdrtoken_wks_to_index(MIME_FIELD_CONTENT_RANGE);
00825 MIME_WKSIDX_CONTENT_TYPE = hdrtoken_wks_to_index(MIME_FIELD_CONTENT_TYPE);
00826 MIME_WKSIDX_CONTROL = hdrtoken_wks_to_index(MIME_FIELD_CONTROL);
00827 MIME_WKSIDX_COOKIE = hdrtoken_wks_to_index(MIME_FIELD_COOKIE);
00828 MIME_WKSIDX_DATE = hdrtoken_wks_to_index(MIME_FIELD_DATE);
00829 MIME_WKSIDX_DISTRIBUTION = hdrtoken_wks_to_index(MIME_FIELD_DISTRIBUTION);
00830 MIME_WKSIDX_ETAG = hdrtoken_wks_to_index(MIME_FIELD_ETAG);
00831 MIME_WKSIDX_EXPECT = hdrtoken_wks_to_index(MIME_FIELD_EXPECT);
00832 MIME_WKSIDX_EXPIRES = hdrtoken_wks_to_index(MIME_FIELD_EXPIRES);
00833 MIME_WKSIDX_FOLLOWUP_TO = hdrtoken_wks_to_index(MIME_FIELD_FOLLOWUP_TO);
00834 MIME_WKSIDX_FROM = hdrtoken_wks_to_index(MIME_FIELD_FROM);
00835 MIME_WKSIDX_HOST = hdrtoken_wks_to_index(MIME_FIELD_HOST);
00836 MIME_WKSIDX_IF_MATCH = hdrtoken_wks_to_index(MIME_FIELD_IF_MATCH);
00837 MIME_WKSIDX_IF_MODIFIED_SINCE = hdrtoken_wks_to_index(MIME_FIELD_IF_MODIFIED_SINCE);
00838 MIME_WKSIDX_IF_NONE_MATCH = hdrtoken_wks_to_index(MIME_FIELD_IF_NONE_MATCH);
00839 MIME_WKSIDX_IF_RANGE = hdrtoken_wks_to_index(MIME_FIELD_IF_RANGE);
00840 MIME_WKSIDX_IF_UNMODIFIED_SINCE = hdrtoken_wks_to_index(MIME_FIELD_IF_UNMODIFIED_SINCE);
00841 MIME_WKSIDX_KEEP_ALIVE = hdrtoken_wks_to_index(MIME_FIELD_KEEP_ALIVE);
00842 MIME_WKSIDX_KEYWORDS = hdrtoken_wks_to_index(MIME_FIELD_KEYWORDS);
00843 MIME_WKSIDX_LAST_MODIFIED = hdrtoken_wks_to_index(MIME_FIELD_LAST_MODIFIED);
00844 MIME_WKSIDX_LINES = hdrtoken_wks_to_index(MIME_FIELD_LINES);
00845 MIME_WKSIDX_LOCATION = hdrtoken_wks_to_index(MIME_FIELD_LOCATION);
00846 MIME_WKSIDX_MAX_FORWARDS = hdrtoken_wks_to_index(MIME_FIELD_MAX_FORWARDS);
00847 MIME_WKSIDX_MESSAGE_ID = hdrtoken_wks_to_index(MIME_FIELD_MESSAGE_ID);
00848 MIME_WKSIDX_NEWSGROUPS = hdrtoken_wks_to_index(MIME_FIELD_NEWSGROUPS);
00849 MIME_WKSIDX_ORGANIZATION = hdrtoken_wks_to_index(MIME_FIELD_ORGANIZATION);
00850 MIME_WKSIDX_PATH = hdrtoken_wks_to_index(MIME_FIELD_PATH);
00851 MIME_WKSIDX_PRAGMA = hdrtoken_wks_to_index(MIME_FIELD_PRAGMA);
00852 MIME_WKSIDX_PROXY_AUTHENTICATE = hdrtoken_wks_to_index(MIME_FIELD_PROXY_AUTHENTICATE);
00853 MIME_WKSIDX_PROXY_AUTHORIZATION = hdrtoken_wks_to_index(MIME_FIELD_PROXY_AUTHORIZATION);
00854 MIME_WKSIDX_PROXY_CONNECTION = hdrtoken_wks_to_index(MIME_FIELD_PROXY_CONNECTION);
00855 MIME_WKSIDX_PUBLIC = hdrtoken_wks_to_index(MIME_FIELD_PUBLIC);
00856 MIME_WKSIDX_RANGE = hdrtoken_wks_to_index(MIME_FIELD_RANGE);
00857 MIME_WKSIDX_REFERENCES = hdrtoken_wks_to_index(MIME_FIELD_REFERENCES);
00858 MIME_WKSIDX_REFERER = hdrtoken_wks_to_index(MIME_FIELD_REFERER);
00859 MIME_WKSIDX_REPLY_TO = hdrtoken_wks_to_index(MIME_FIELD_REPLY_TO);
00860 MIME_WKSIDX_RETRY_AFTER = hdrtoken_wks_to_index(MIME_FIELD_RETRY_AFTER);
00861 MIME_WKSIDX_SENDER = hdrtoken_wks_to_index(MIME_FIELD_SENDER);
00862 MIME_WKSIDX_SERVER = hdrtoken_wks_to_index(MIME_FIELD_SERVER);
00863 MIME_WKSIDX_SET_COOKIE = hdrtoken_wks_to_index(MIME_FIELD_SET_COOKIE);
00864 MIME_WKSIDX_STRICT_TRANSPORT_SECURITY = hdrtoken_wks_to_index(MIME_FIELD_STRICT_TRANSPORT_SECURITY);
00865 MIME_WKSIDX_SUBJECT = hdrtoken_wks_to_index(MIME_FIELD_SUBJECT);
00866 MIME_WKSIDX_SUMMARY = hdrtoken_wks_to_index(MIME_FIELD_SUMMARY);
00867 MIME_WKSIDX_TE = hdrtoken_wks_to_index(MIME_FIELD_TE);
00868 MIME_WKSIDX_TRANSFER_ENCODING = hdrtoken_wks_to_index(MIME_FIELD_TRANSFER_ENCODING);
00869 MIME_WKSIDX_UPGRADE = hdrtoken_wks_to_index(MIME_FIELD_UPGRADE);
00870 MIME_WKSIDX_USER_AGENT = hdrtoken_wks_to_index(MIME_FIELD_USER_AGENT);
00871 MIME_WKSIDX_VARY = hdrtoken_wks_to_index(MIME_FIELD_VARY);
00872 MIME_WKSIDX_VIA = hdrtoken_wks_to_index(MIME_FIELD_VIA);
00873 MIME_WKSIDX_WARNING = hdrtoken_wks_to_index(MIME_FIELD_WARNING);
00874 MIME_WKSIDX_WWW_AUTHENTICATE = hdrtoken_wks_to_index(MIME_FIELD_WWW_AUTHENTICATE);
00875 MIME_WKSIDX_XREF = hdrtoken_wks_to_index(MIME_FIELD_XREF);
00876 MIME_WKSIDX_X_ID = hdrtoken_wks_to_index(MIME_FIELD_X_ID);
00877 MIME_WKSIDX_X_FORWARDED_FOR = hdrtoken_wks_to_index(MIME_FIELD_X_FORWARDED_FOR);
00878 MIME_WKSIDX_SEC_WEBSOCKET_KEY = hdrtoken_wks_to_index(MIME_FIELD_SEC_WEBSOCKET_KEY);
00879 MIME_WKSIDX_SEC_WEBSOCKET_VERSION = hdrtoken_wks_to_index(MIME_FIELD_SEC_WEBSOCKET_VERSION);
00880
00881 MIME_VALUE_BYTES = hdrtoken_string_to_wks("bytes");
00882 MIME_VALUE_CHUNKED = hdrtoken_string_to_wks("chunked");
00883 MIME_VALUE_CLOSE = hdrtoken_string_to_wks("close");
00884 MIME_VALUE_COMPRESS = hdrtoken_string_to_wks("compress");
00885 MIME_VALUE_DEFLATE = hdrtoken_string_to_wks("deflate");
00886 MIME_VALUE_GZIP = hdrtoken_string_to_wks("gzip");
00887 MIME_VALUE_IDENTITY = hdrtoken_string_to_wks("identity");
00888 MIME_VALUE_KEEP_ALIVE = hdrtoken_string_to_wks("keep-alive");
00889 MIME_VALUE_MAX_AGE = hdrtoken_string_to_wks("max-age");
00890 MIME_VALUE_MAX_STALE = hdrtoken_string_to_wks("max-stale");
00891 MIME_VALUE_MIN_FRESH = hdrtoken_string_to_wks("min-fresh");
00892 MIME_VALUE_MUST_REVALIDATE = hdrtoken_string_to_wks("must-revalidate");
00893 MIME_VALUE_NONE = hdrtoken_string_to_wks("none");
00894 MIME_VALUE_NO_CACHE = hdrtoken_string_to_wks("no-cache");
00895 MIME_VALUE_NO_STORE = hdrtoken_string_to_wks("no-store");
00896 MIME_VALUE_NO_TRANSFORM = hdrtoken_string_to_wks("no-transform");
00897 MIME_VALUE_ONLY_IF_CACHED = hdrtoken_string_to_wks("only-if-cached");
00898 MIME_VALUE_PRIVATE = hdrtoken_string_to_wks("private");
00899 MIME_VALUE_PROXY_REVALIDATE = hdrtoken_string_to_wks("proxy-revalidate");
00900 MIME_VALUE_PUBLIC = hdrtoken_string_to_wks("public");
00901 MIME_VALUE_S_MAXAGE = hdrtoken_string_to_wks("s-maxage");
00902 MIME_VALUE_NEED_REVALIDATE_ONCE = hdrtoken_string_to_wks("need-revalidate-once");
00903 MIME_VALUE_WEBSOCKET = hdrtoken_string_to_wks("websocket");
00904
00905
00906 mime_init_date_format_table();
00907 mime_init_cache_control_cooking_masks();
00908 }
00909 }
00910
00911 void
00912 mime_init_cache_control_cooking_masks()
00913 {
00914 static struct
00915 {
00916 const char *name;
00917 uint32_t mask;
00918 } cc_mask_table[] = {
00919 {
00920 "max-age", MIME_COOKED_MASK_CC_MAX_AGE}, {
00921 "no-cache", MIME_COOKED_MASK_CC_NO_CACHE}, {
00922 "no-store", MIME_COOKED_MASK_CC_NO_STORE}, {
00923 "no-transform", MIME_COOKED_MASK_CC_NO_TRANSFORM}, {
00924 "max-stale", MIME_COOKED_MASK_CC_MAX_STALE}, {
00925 "min-fresh", MIME_COOKED_MASK_CC_MIN_FRESH}, {
00926 "only-if-cached", MIME_COOKED_MASK_CC_ONLY_IF_CACHED}, {
00927 "public", MIME_COOKED_MASK_CC_PUBLIC}, {
00928 "private", MIME_COOKED_MASK_CC_PRIVATE}, {
00929 "must-revalidate", MIME_COOKED_MASK_CC_MUST_REVALIDATE}, {
00930 "proxy-revalidate", MIME_COOKED_MASK_CC_PROXY_REVALIDATE}, {
00931 "s-maxage", MIME_COOKED_MASK_CC_S_MAXAGE}, {
00932 "need-revalidate-once", MIME_COOKED_MASK_CC_NEED_REVALIDATE_ONCE}, {
00933 NULL, 0}
00934 };
00935
00936 for (int i = 0; cc_mask_table[i].name != NULL; i++) {
00937 const char *wks = hdrtoken_string_to_wks(cc_mask_table[i].name);
00938 HdrTokenHeapPrefix *p = hdrtoken_wks_to_prefix(wks);
00939 p->wks_type_specific.u.cache_control.cc_mask = cc_mask_table[i].mask;
00940 }
00941 }
00942
00943 void
00944 mime_init_date_format_table()
00945 {
00946
00947
00948
00949
00950
00951
00952
00953 time_t now_secs;
00954 int i, now_days, first_days, last_days, num_days;
00955 int m=0, d=0, y=0;
00956
00957 time(&now_secs);
00958 now_days = (int) (now_secs / (60 * 60 * 24));
00959 first_days = now_days - 366;
00960 last_days = now_days + 366;
00961 num_days = last_days - first_days + 1;
00962
00963 _days_to_mdy_fast_lookup_table = (MDY *)ats_malloc(num_days * sizeof(MDY));
00964 _days_to_mdy_fast_lookup_table_first_day = first_days;
00965 _days_to_mdy_fast_lookup_table_last_day = last_days;
00966
00967 for (i = 0; i < num_days; i++) {
00968 mime_days_since_epoch_to_mdy_slowcase(first_days + i, &m, &d, &y);
00969 _days_to_mdy_fast_lookup_table[i].m = m;
00970 _days_to_mdy_fast_lookup_table[i].d = d;
00971 _days_to_mdy_fast_lookup_table[i].y = y;
00972 }
00973 }
00974
00975 MIMEHdrImpl *
00976 mime_hdr_create(HdrHeap *heap)
00977 {
00978 MIMEHdrImpl *mh;
00979
00980 mh = (MIMEHdrImpl *) heap->allocate_obj(sizeof(MIMEHdrImpl), HDR_HEAP_OBJ_MIME_HEADER);
00981 mime_hdr_init(mh);
00982 return mh;
00983 }
00984
00985 void
00986 _mime_hdr_field_block_init(MIMEFieldBlockImpl *fblock)
00987 {
00988 fblock->m_freetop = 0;
00989 fblock->m_next = NULL;
00990
00991 #ifdef BLOCK_INIT_PARANOIA
00992 int i;
00993
00994
00995
00996
00997
00998
00999 for (i = 0; i < MIME_FIELD_BLOCK_SLOTS; i++) {
01000 MIMEField *field = &(fblock->m_field_slots[i]);
01001 field->m_readiness = MIME_FIELD_SLOT_READINESS_EMPTY;
01002 }
01003 #endif
01004 }
01005
01006 void
01007 mime_hdr_cooked_stuff_init(MIMEHdrImpl *mh, MIMEField *changing_field_or_null)
01008 {
01009
01010
01011 if ((changing_field_or_null == NULL) || (changing_field_or_null->m_wks_idx != MIME_WKSIDX_PRAGMA)) {
01012 mh->m_cooked_stuff.m_cache_control.m_mask = 0;
01013 mh->m_cooked_stuff.m_cache_control.m_secs_max_age = 0;
01014 mh->m_cooked_stuff.m_cache_control.m_secs_s_maxage = 0;
01015 mh->m_cooked_stuff.m_cache_control.m_secs_max_stale = 0;
01016 mh->m_cooked_stuff.m_cache_control.m_secs_min_fresh = 0;
01017 }
01018 if ((changing_field_or_null == NULL) || (changing_field_or_null->m_wks_idx != MIME_WKSIDX_CACHE_CONTROL)) {
01019 mh->m_cooked_stuff.m_pragma.m_no_cache = 0;
01020 }
01021 }
01022
01023 void
01024 mime_hdr_init(MIMEHdrImpl *mh)
01025 {
01026 mime_hdr_init_accelerators_and_presence_bits(mh);
01027
01028 mime_hdr_cooked_stuff_init(mh, NULL);
01029
01030
01031 obj_init_header((HdrHeapObjImpl *) & (mh->m_first_fblock), HDR_HEAP_OBJ_FIELD_BLOCK, sizeof(MIMEFieldBlockImpl), 0);
01032
01033 _mime_hdr_field_block_init(&(mh->m_first_fblock));
01034 mh->m_fblock_list_tail = &(mh->m_first_fblock);
01035
01036 MIME_HDR_SANITY_CHECK(mh);
01037 }
01038
01039 MIMEFieldBlockImpl *
01040 _mime_field_block_copy(MIMEFieldBlockImpl *s_fblock, HdrHeap * , HdrHeap *d_heap)
01041 {
01042 MIMEFieldBlockImpl *d_fblock;
01043
01044 d_fblock = (MIMEFieldBlockImpl *)
01045 d_heap->allocate_obj(sizeof(MIMEFieldBlockImpl), HDR_HEAP_OBJ_FIELD_BLOCK);
01046 memcpy(d_fblock, s_fblock, sizeof(MIMEFieldBlockImpl));
01047 return d_fblock;
01048 }
01049
01050 void
01051 _mime_field_block_destroy(HdrHeap *heap, MIMEFieldBlockImpl *fblock)
01052 {
01053 heap->deallocate_obj(fblock);
01054 }
01055
01056 void
01057 mime_hdr_destroy_field_block_list(HdrHeap *heap, MIMEFieldBlockImpl *head)
01058 {
01059 MIMEFieldBlockImpl *next;
01060
01061 while (head != NULL) {
01062 next = head->m_next;
01063 _mime_field_block_destroy(heap, head);
01064 head = next;
01065 }
01066 }
01067
01068 void
01069 mime_hdr_destroy(HdrHeap *heap, MIMEHdrImpl *mh)
01070 {
01071 mime_hdr_destroy_field_block_list(heap, mh->m_first_fblock.m_next);
01072
01073
01074
01075
01076
01077
01078 }
01079
01080 void
01081 mime_hdr_copy_onto(MIMEHdrImpl *s_mh, HdrHeap *s_heap, MIMEHdrImpl *d_mh, HdrHeap *d_heap, bool inherit_strs)
01082 {
01083 int block_count;
01084 MIMEFieldBlockImpl *s_fblock, *d_fblock, *prev_d_fblock;
01085
01086
01087
01088
01089
01090 if (d_mh->m_first_fblock.m_next) {
01091 mime_hdr_destroy_field_block_list(d_heap, d_mh->m_first_fblock.m_next);
01092 }
01093
01094 ink_assert(((char *) &(s_mh->m_first_fblock.m_field_slots[MIME_FIELD_BLOCK_SLOTS]) - (char *) s_mh) ==
01095 sizeof(struct MIMEHdrImpl));
01096
01097 int top = s_mh->m_first_fblock.m_freetop;
01098 char *end = (char *) &(s_mh->m_first_fblock.m_field_slots[top]);
01099 int bytes_below_top = end - (char *) s_mh;
01100
01101
01102 memcpy(d_mh, s_mh, bytes_below_top);
01103
01104 if (d_mh->m_first_fblock.m_next == NULL)
01105 {
01106 d_mh->m_fblock_list_tail = &(d_mh->m_first_fblock);
01107 block_count = 1;
01108 } else
01109 {
01110 prev_d_fblock = &(d_mh->m_first_fblock);
01111 block_count = 1;
01112 for (s_fblock = s_mh->m_first_fblock.m_next; s_fblock != NULL; s_fblock = s_fblock->m_next) {
01113 ++block_count;
01114 d_fblock = _mime_field_block_copy(s_fblock, s_heap, d_heap);
01115 prev_d_fblock->m_next = d_fblock;
01116 prev_d_fblock = d_fblock;
01117 }
01118 d_mh->m_fblock_list_tail = prev_d_fblock;
01119 }
01120
01121 if (inherit_strs)
01122 d_heap->inherit_string_heaps(s_heap);
01123
01124 mime_hdr_field_block_list_adjust(block_count, &(s_mh->m_first_fblock), &(d_mh->m_first_fblock));
01125
01126 MIME_HDR_SANITY_CHECK(s_mh);
01127 MIME_HDR_SANITY_CHECK(d_mh);
01128 }
01129
01130 MIMEHdrImpl *
01131 mime_hdr_clone(MIMEHdrImpl *s_mh, HdrHeap *s_heap, HdrHeap *d_heap, bool inherit_strs)
01132 {
01133 MIMEHdrImpl *d_mh;
01134
01135 d_mh = mime_hdr_create(d_heap);
01136 mime_hdr_copy_onto(s_mh, s_heap, d_mh, d_heap, inherit_strs);
01137 return d_mh;
01138 }
01139
01140
01141
01142
01143
01144 static inline MIMEField *rebase(
01145 MIMEField *dest_ptr,
01146 void *dest_base,
01147 void *src_base
01148 ) {
01149 return reinterpret_cast<MIMEField *>
01150 (reinterpret_cast<char *>(dest_ptr) + (static_cast<char *>(dest_base) - static_cast<char *>(src_base)));
01151 }
01152
01153 static inline void relocate(MIMEField *field, MIMEFieldBlockImpl *dest_block, MIMEFieldBlockImpl *src_block)
01154 {
01155 for ( ; src_block; src_block = src_block->m_next, dest_block = dest_block->m_next) {
01156 ink_release_assert(dest_block) ;
01157
01158 if (field->m_next_dup >= src_block->m_field_slots &&
01159 field->m_next_dup < src_block->m_field_slots + src_block->m_freetop) {
01160 field->m_next_dup = rebase(field->m_next_dup, dest_block->m_field_slots, src_block->m_field_slots);
01161 return;
01162 }
01163 }
01164 }
01165
01166 void
01167 mime_hdr_field_block_list_adjust(int , MIMEFieldBlockImpl *old_list,
01168 MIMEFieldBlockImpl *new_list)
01169 {
01170 for (MIMEFieldBlockImpl *new_blk = new_list; new_blk; new_blk = new_blk->m_next) {
01171 for (MIMEField *field = new_blk->m_field_slots, *end=field + new_blk->m_freetop; field != end; ++field) {
01172 if (field->is_live() && field->m_next_dup) {
01173 relocate(field, new_list, old_list);
01174 }
01175 }
01176 }
01177 }
01178
01179 int
01180 mime_hdr_length_get(MIMEHdrImpl *mh)
01181 {
01182 unsigned int length, index;
01183 MIMEFieldBlockImpl *fblock;
01184 MIMEField *field;
01185
01186 length = 2;
01187
01188 for (fblock = &(mh->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
01189 for (index = 0; index < fblock->m_freetop; index++) {
01190 field = &(fblock->m_field_slots[index]);
01191 if (field->is_live()) {
01192 length += mime_field_length_get(field);
01193 }
01194 }
01195 }
01196
01197 return length;
01198 }
01199
01200 void
01201 mime_hdr_fields_clear(HdrHeap *heap, MIMEHdrImpl *mh)
01202 {
01203 mime_hdr_destroy_field_block_list(heap, mh->m_first_fblock.m_next);
01204 mime_hdr_init(mh);
01205 }
01206
01207 MIMEField *
01208 _mime_hdr_field_list_search_by_wks(MIMEHdrImpl *mh, int wks_idx)
01209 {
01210 MIMEFieldBlockImpl *fblock;
01211 MIMEField *field, *too_far_field;
01212
01213 ink_assert(hdrtoken_is_valid_wks_idx(wks_idx));
01214
01215 for (fblock = &(mh->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
01216 field = &(fblock->m_field_slots[0]);
01217
01218 too_far_field = &(fblock->m_field_slots[fblock->m_freetop]);
01219 while (field < too_far_field) {
01220 if (field->is_live() && (field->m_wks_idx == wks_idx))
01221 return field;
01222 ++field;
01223 }
01224 }
01225
01226 return NULL;
01227 }
01228
01229 MIMEField *
01230 _mime_hdr_field_list_search_by_string(MIMEHdrImpl *mh, const char *field_name_str, int field_name_len)
01231 {
01232 MIMEFieldBlockImpl *fblock;
01233 MIMEField *field, *too_far_field;
01234
01235 ink_assert(mh);
01236 for (fblock = &(mh->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
01237 field = &(fblock->m_field_slots[0]);
01238
01239 too_far_field = &(fblock->m_field_slots[fblock->m_freetop]);
01240 while (field < too_far_field) {
01241 if (field->is_live() &&
01242 (field_name_len == field->m_len_name) &&
01243 (strncasecmp(field->m_ptr_name, field_name_str, field_name_len) == 0)) {
01244 return field;
01245 }
01246 ++field;
01247 }
01248 }
01249
01250 return NULL;
01251 }
01252
01253 MIMEField *
01254 _mime_hdr_field_list_search_by_slotnum(MIMEHdrImpl *mh, int slotnum)
01255 {
01256 unsigned int block_num, block_index;
01257 MIMEFieldBlockImpl *fblock;
01258
01259 if (slotnum < MIME_FIELD_BLOCK_SLOTS) {
01260 fblock = &(mh->m_first_fblock);
01261 block_index = slotnum;
01262 if (block_index >= fblock->m_freetop) {
01263 return NULL;
01264 } else {
01265 return &(fblock->m_field_slots[block_index]);
01266 }
01267 } else {
01268 block_num = slotnum / MIME_FIELD_BLOCK_SLOTS;
01269 block_index = slotnum % MIME_FIELD_BLOCK_SLOTS;
01270
01271 fblock = &(mh->m_first_fblock);
01272 while (block_num-- && fblock)
01273 fblock = fblock->m_next;
01274 if ((fblock == NULL) || (block_index >= fblock->m_freetop))
01275 return NULL;
01276 else
01277 return &(fblock->m_field_slots[block_index]);
01278 }
01279 }
01280
01281 MIMEField *
01282 mime_hdr_field_find(MIMEHdrImpl *mh, const char *field_name_str, int field_name_len)
01283 {
01284 int is_wks;
01285 HdrTokenHeapPrefix *token_info;
01286
01287 ink_assert(field_name_len >= 0);
01288
01289
01290
01291
01292
01293 is_wks = hdrtoken_is_wks(field_name_str);
01294 #if TRACK_FIELD_FIND_CALLS
01295 Debug("http", "mime_hdr_field_find(hdr 0x%X, field %.*s): is_wks = %d\n", mh, field_name_len, field_name_str, is_wks);
01296 #endif
01297
01298 if (is_wks) {
01299 token_info = hdrtoken_wks_to_prefix(field_name_str);
01300 if ((token_info->wks_info.mask) && ((mh->m_presence_bits & token_info->wks_info.mask) == 0)) {
01301 #if TRACK_FIELD_FIND_CALLS
01302 Debug("http", "mime_hdr_field_find(hdr 0x%X, field %.*s): MISS (due to presence bits)\n",
01303 mh, field_name_len, field_name_str);
01304 #endif
01305 return NULL;
01306 }
01307
01308 int32_t slot_id = token_info->wks_info.slotid;
01309
01310 if (slot_id != MIME_SLOTID_NONE) {
01311 uint32_t slotnum = mime_hdr_get_accelerator_slotnum(mh, slot_id);
01312
01313 if (slotnum != MIME_FIELD_SLOTNUM_UNKNOWN) {
01314 MIMEField *f = _mime_hdr_field_list_search_by_slotnum(mh, slotnum);
01315 ink_assert((f == NULL) || f->is_live());
01316 #if TRACK_FIELD_FIND_CALLS
01317 Debug("http", "mime_hdr_field_find(hdr 0x%X, field %.*s): %s (due to slot accelerators)\n",
01318 mh, field_name_len, field_name_str, (f ? "HIT" : "MISS"));
01319 #endif
01320 return f;
01321 } else {
01322 #if TRACK_FIELD_FIND_CALLS
01323 Debug("http", "mime_hdr_field_find(hdr 0x%X, field %.*s): UNKNOWN (slot too big)\n",
01324 mh, field_name_len, field_name_str);
01325 #endif
01326 }
01327 }
01328 }
01329
01330
01331
01332
01333 if (is_wks) {
01334 MIMEField *f = _mime_hdr_field_list_search_by_wks(mh, token_info->wks_idx);
01335 ink_assert((f == NULL) || f->is_live());
01336 #if TRACK_FIELD_FIND_CALLS
01337 Debug("http", "mime_hdr_field_find(hdr 0x%X, field %.*s): %s (due to WKS list walk)\n",
01338 mh, field_name_len, field_name_str, (f ? "HIT" : "MISS"));
01339 #endif
01340 return f;
01341 } else {
01342 MIMEField *f = _mime_hdr_field_list_search_by_string(mh, field_name_str, field_name_len);
01343
01344 ink_assert((f == NULL) || f->is_live());
01345 #if TRACK_FIELD_FIND_CALLS
01346 Debug("http", "mime_hdr_field_find(hdr 0x%X, field %.*s): %s (due to strcmp list walk)\n",
01347 mh, field_name_len, field_name_str, (f ? "HIT" : "MISS"));
01348 #endif
01349 return f;
01350 }
01351 }
01352
01353 MIMEField *
01354 mime_hdr_field_get(MIMEHdrImpl *mh, int idx)
01355 {
01356 unsigned int index;
01357 MIMEFieldBlockImpl *fblock;
01358 MIMEField *field;
01359 int got_idx;
01360
01361 got_idx = -1;
01362
01363 for (fblock = &(mh->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
01364 for (index = 0; index < fblock->m_freetop; index++) {
01365 field = &(fblock->m_field_slots[index]);
01366 if (field->is_live())
01367 ++got_idx;
01368 if (got_idx == idx)
01369 return field;
01370 }
01371 }
01372
01373 return NULL;
01374 }
01375
01376 MIMEField *
01377 mime_hdr_field_get_slotnum(MIMEHdrImpl *mh, int slotnum)
01378 {
01379 return _mime_hdr_field_list_search_by_slotnum(mh, slotnum);
01380 }
01381
01382 int
01383 mime_hdr_fields_count(MIMEHdrImpl *mh)
01384 {
01385 unsigned int index;
01386 MIMEFieldBlockImpl *fblock;
01387 MIMEField *field;
01388 int count;
01389
01390 count = 0;
01391
01392 for (fblock = &(mh->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
01393 for (index = 0; index < fblock->m_freetop; index++) {
01394 field = &(fblock->m_field_slots[index]);
01395 if (field->is_live())
01396 ++count;
01397 }
01398 }
01399
01400 return count;
01401 }
01402
01403 void
01404 mime_field_init(MIMEField *field)
01405 {
01406 memset(field, 0, sizeof(MIMEField));
01407 field->m_readiness = MIME_FIELD_SLOT_READINESS_DETACHED;
01408 field->m_wks_idx = -1;
01409 }
01410
01411 MIMEField *
01412 mime_field_create(HdrHeap *heap, MIMEHdrImpl *mh)
01413 {
01414 MIMEField *field;
01415 MIMEFieldBlockImpl *tail_fblock, *new_fblock;
01416
01417 tail_fblock = mh->m_fblock_list_tail;
01418 if (tail_fblock->m_freetop >= MIME_FIELD_BLOCK_SLOTS) {
01419 new_fblock = (MIMEFieldBlockImpl *)
01420 heap->allocate_obj(sizeof(MIMEFieldBlockImpl), HDR_HEAP_OBJ_FIELD_BLOCK);
01421 _mime_hdr_field_block_init(new_fblock);
01422 tail_fblock->m_next = new_fblock;
01423 tail_fblock = new_fblock;
01424 mh->m_fblock_list_tail = new_fblock;
01425 }
01426
01427 field = &(tail_fblock->m_field_slots[tail_fblock->m_freetop]);
01428 ++tail_fblock->m_freetop;
01429
01430 mime_field_init(field);
01431
01432 return field;
01433 }
01434
01435 MIMEField *
01436 mime_field_create_named(HdrHeap *heap, MIMEHdrImpl *mh, const char *name, int length)
01437 {
01438 MIMEField *field = mime_field_create(heap, mh);
01439 int field_name_wks_idx = hdrtoken_tokenize(name, length);
01440 mime_field_name_set(heap, mh, field, field_name_wks_idx, name, length, 1);
01441 return field;
01442 }
01443
01444 void
01445 mime_hdr_field_attach(MIMEHdrImpl *mh, MIMEField *field, int check_for_dups, MIMEField *prev_dup)
01446 {
01447 MIME_HDR_SANITY_CHECK(mh);
01448
01449 if (!field->is_detached()) {
01450 return;
01451 }
01452
01453 ink_assert(field->m_ptr_name != NULL);
01454
01455
01456
01457
01458
01459
01460 if (check_for_dups || (prev_dup && (!prev_dup->is_dup_head()))) {
01461 int length;
01462 const char *name = mime_field_name_get(field, &length);
01463 prev_dup = mime_hdr_field_find(mh, name, length);
01464 ink_assert((prev_dup == NULL) || (prev_dup->is_dup_head()));
01465 }
01466
01467 field->m_readiness = MIME_FIELD_SLOT_READINESS_LIVE;
01468
01469
01470
01471
01472
01473
01474
01475 if (prev_dup) {
01476 MIMEField *next_dup;
01477 int field_slotnum, prev_slotnum, next_slotnum;
01478
01479
01480
01481
01482
01483
01484
01485
01486 field_slotnum = mime_hdr_field_slotnum(mh, field);
01487 prev_slotnum = mime_hdr_field_slotnum(mh, prev_dup);
01488 next_dup = prev_dup->m_next_dup;
01489 next_slotnum = (next_dup ? mime_hdr_field_slotnum(mh, next_dup) : -1);
01490
01491 ink_assert(field_slotnum != prev_slotnum);
01492
01493 while (prev_slotnum < field_slotnum)
01494 {
01495 if (next_dup == NULL)
01496 break;
01497 if (next_slotnum > field_slotnum)
01498 break;
01499 prev_dup = next_dup;
01500 prev_slotnum = next_slotnum;
01501 next_dup = prev_dup->m_next_dup;
01502 }
01503
01504
01505
01506
01507
01508
01509
01510 if (prev_slotnum > field_slotnum)
01511 {
01512
01513
01514
01515
01516
01517
01518 field->m_flags = (field->m_flags | MIME_FIELD_SLOT_FLAGS_DUP_HEAD);
01519 field->m_next_dup = prev_dup;
01520 prev_dup->m_flags = (prev_dup->m_flags & ~MIME_FIELD_SLOT_FLAGS_DUP_HEAD);
01521 mime_hdr_set_accelerators_and_presence_bits(mh, field);
01522 } else
01523 {
01524 ink_assert(prev_slotnum < field_slotnum);
01525 ink_assert((next_dup == NULL) || (next_slotnum > field_slotnum));
01526 field->m_flags = (field->m_flags & ~MIME_FIELD_SLOT_FLAGS_DUP_HEAD);
01527 ink_assert((next_dup == NULL) || next_dup->is_live());
01528 prev_dup->m_next_dup = field;
01529 field->m_next_dup = next_dup;
01530 }
01531 } else {
01532 field->m_flags = (field->m_flags | MIME_FIELD_SLOT_FLAGS_DUP_HEAD);
01533 mime_hdr_set_accelerators_and_presence_bits(mh, field);
01534 }
01535
01536
01537 ink_assert(field->is_live());
01538 if (field->m_ptr_value && field->is_cooked())
01539 mh->recompute_cooked_stuff(field);
01540
01541 MIME_HDR_SANITY_CHECK(mh);
01542 }
01543
01544 void
01545 mime_hdr_field_detach(MIMEHdrImpl *mh, MIMEField *field, bool detach_all_dups)
01546 {
01547 MIMEField *next_dup = field->m_next_dup;
01548
01549
01550
01551 if (field->is_detached()) {
01552 ink_assert(next_dup == NULL);
01553 return;
01554 }
01555
01556 ink_assert(field->is_live());
01557 MIME_HDR_SANITY_CHECK(mh);
01558
01559
01560
01561
01562
01563
01564
01565 if (field->m_flags & MIME_FIELD_SLOT_FLAGS_DUP_HEAD)
01566 {
01567 if (!next_dup)
01568 {
01569 mime_hdr_unset_accelerators_and_presence_bits(mh, field);
01570 } else
01571 {
01572 next_dup->m_flags |= MIME_FIELD_SLOT_FLAGS_DUP_HEAD;
01573 mime_hdr_set_accelerators_and_presence_bits(mh, next_dup);
01574 }
01575 } else
01576 {
01577 int name_length;
01578 const char *name = mime_field_name_get(field, &name_length);
01579 MIMEField *prev = mime_hdr_field_find(mh, name, name_length);
01580
01581 while (prev && (prev->m_next_dup != field))
01582 prev = prev->m_next_dup;
01583 ink_assert(prev != NULL);
01584
01585 if (prev->m_next_dup == field)
01586 prev->m_next_dup = next_dup;
01587 }
01588
01589
01590 field->m_readiness = MIME_FIELD_SLOT_READINESS_DETACHED;
01591 field->m_next_dup = NULL;
01592
01593
01594 if (field->is_cooked())
01595 mh->recompute_cooked_stuff(field);
01596
01597 MIME_HDR_SANITY_CHECK(mh);
01598
01599
01600
01601
01602
01603
01604 if (detach_all_dups && next_dup)
01605 mime_hdr_field_detach(mh, next_dup, detach_all_dups);
01606 }
01607
01608 void
01609 mime_hdr_field_delete(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, bool delete_all_dups)
01610 {
01611 if (delete_all_dups) {
01612 while (field) {
01613
01614
01615 MIMEField *next = field->m_next_dup;
01616
01617 heap->free_string(field->m_ptr_name, field->m_len_name);
01618 heap->free_string(field->m_ptr_value, field->m_len_value);
01619
01620 MIME_HDR_SANITY_CHECK(mh);
01621 mime_hdr_field_detach(mh, field, 0);
01622
01623 MIME_HDR_SANITY_CHECK(mh);
01624 mime_field_destroy(mh, field);
01625
01626 MIME_HDR_SANITY_CHECK(mh);
01627 field = next;
01628 }
01629 } else {
01630 heap->free_string(field->m_ptr_name, field->m_len_name);
01631 heap->free_string(field->m_ptr_value, field->m_len_value);
01632
01633 MIME_HDR_SANITY_CHECK(mh);
01634 mime_hdr_field_detach(mh, field, 0);
01635
01636 MIME_HDR_SANITY_CHECK(mh);
01637 mime_field_destroy(mh, field);
01638 }
01639
01640 MIME_HDR_SANITY_CHECK(mh);
01641 }
01642
01643 int
01644 mime_hdr_field_slotnum(MIMEHdrImpl *mh, MIMEField *field)
01645 {
01646 int slots_so_far;
01647 MIMEFieldBlockImpl *fblock;
01648
01649 slots_so_far = 0;
01650 for (fblock = &(mh->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
01651 MIMEField *first = &(fblock->m_field_slots[0]);
01652 int block_slot = (int) (field - first);
01653 if ((block_slot >= 0) && (block_slot < MIME_FIELD_BLOCK_SLOTS))
01654 return (slots_so_far + block_slot);
01655 slots_so_far += MIME_FIELD_BLOCK_SLOTS;
01656 }
01657 return -1;
01658 }
01659
01660 MIMEField *
01661 mime_hdr_prepare_for_value_set(HdrHeap *heap, MIMEHdrImpl *mh, const char *name, int name_length)
01662 {
01663 int wks_idx;
01664 MIMEField *field;
01665
01666 field = mime_hdr_field_find(mh, name, name_length);
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678 if (field == NULL)
01679 {
01680 wks_idx = hdrtoken_tokenize(name, name_length);
01681 field = mime_field_create(heap, mh);
01682 mime_field_name_set(heap, mh, field, wks_idx, name, name_length, 1);
01683 mime_hdr_field_attach(mh, field, 0, NULL);
01684
01685 } else if (field->m_next_dup)
01686 {
01687 wks_idx = field->m_wks_idx;
01688 mime_hdr_field_delete(heap, mh, field, true);
01689 field = mime_field_create(heap, mh);
01690 mime_field_name_set(heap, mh, field, wks_idx, name, name_length, 1);
01691 mime_hdr_field_attach(mh, field, 0, NULL);
01692 }
01693 return field;
01694 }
01695
01696 void
01697 mime_field_destroy(MIMEHdrImpl *, MIMEField *field)
01698 {
01699 ink_assert(field->m_readiness == MIME_FIELD_SLOT_READINESS_DETACHED);
01700 field->m_readiness = MIME_FIELD_SLOT_READINESS_DELETED;
01701 }
01702
01703 const char *
01704 mime_field_name_get(MIMEField *field, int *length)
01705 {
01706 *length = field->m_len_name;
01707 if (field->m_wks_idx >= 0)
01708 return hdrtoken_index_to_wks(field->m_wks_idx);
01709 else
01710 return field->m_ptr_name;
01711 }
01712
01713 void
01714 mime_field_name_set(HdrHeap *heap, MIMEHdrImpl *, MIMEField *field, int16_t name_wks_idx_or_neg1,
01715 const char *name, int length, bool must_copy_string)
01716 {
01717 ink_assert(field->m_readiness == MIME_FIELD_SLOT_READINESS_DETACHED);
01718
01719 field->m_wks_idx = name_wks_idx_or_neg1;
01720 mime_str_u16_set(heap, name, length, &(field->m_ptr_name), &(field->m_len_name), must_copy_string);
01721
01722 if ((name_wks_idx_or_neg1 == MIME_WKSIDX_CACHE_CONTROL) || (name_wks_idx_or_neg1 == MIME_WKSIDX_PRAGMA)) {
01723 field->m_flags |= MIME_FIELD_SLOT_FLAGS_COOKED;
01724 }
01725 }
01726
01727 const char *
01728 mime_field_value_get(MIMEField *field, int *length)
01729 {
01730 *length = field->m_len_value;
01731 return field->m_ptr_value;
01732 }
01733
01734 int32_t
01735 mime_field_value_get_int(MIMEField *field)
01736 {
01737 int length;
01738 const char *str = mime_field_value_get(field, &length);
01739
01740 return mime_parse_int(str, str + length);
01741 }
01742
01743 uint32_t
01744 mime_field_value_get_uint(MIMEField *field)
01745 {
01746 int length;
01747 const char *str = mime_field_value_get(field, &length);
01748 return mime_parse_uint(str, str + length);
01749 }
01750
01751 int64_t
01752 mime_field_value_get_int64(MIMEField *field)
01753 {
01754 int length;
01755 const char *str = mime_field_value_get(field, &length);
01756
01757 return mime_parse_int64(str, str + length);
01758 }
01759
01760 time_t
01761 mime_field_value_get_date(MIMEField *field)
01762 {
01763 int length;
01764 const char *str = mime_field_value_get(field, &length);
01765 return mime_parse_date(str, str + length);
01766 }
01767
01768 const char *
01769 mime_field_value_get_comma_val(MIMEField *field, int *length, int idx)
01770 {
01771
01772 if (!field->supports_commas()) {
01773 if (idx == 0)
01774 return mime_field_value_get(field, length);
01775 else
01776 return NULL;
01777 } else {
01778 Str *str;
01779 StrList list(false);
01780
01781 mime_field_value_get_comma_list(field, &list);
01782 str = list.get_idx(idx);
01783 if (str != NULL) {
01784 *length = (int) (str->len);
01785 return str->str;
01786 } else {
01787 *length = 0;
01788 return NULL;
01789 }
01790 }
01791 }
01792
01793 int
01794 mime_field_value_get_comma_val_count(MIMEField *field)
01795 {
01796
01797 if (!field->supports_commas()) {
01798 return ((field->m_len_value == 0) ? 0 : 1);
01799 } else {
01800 StrList list(false);
01801 int count = mime_field_value_get_comma_list(field, &list);
01802 return count;
01803 }
01804 }
01805
01806 int
01807 mime_field_value_get_comma_list(MIMEField *field, StrList *list)
01808 {
01809 const char *str;
01810 int len;
01811
01812 str = mime_field_value_get(field, &len);
01813
01814
01815 if (!field->supports_commas())
01816 list->append_string(str, len);
01817 else
01818 HttpCompat::parse_tok_list(list, 1, str, len, ',');
01819
01820 return list->count;
01821 }
01822
01823 const char *
01824 mime_field_value_str_from_strlist(HdrHeap *heap, int *new_str_len_return, StrList *list)
01825 {
01826 Str *cell;
01827 char *new_value, *dest;
01828 int i, new_value_len;
01829
01830 HdrHeap::HeapGuard guard(heap, list->head->str);
01831
01832 new_value_len = 0;
01833
01834
01835
01836 cell = list->head;
01837 for (i = 0; i < list->count; i++) {
01838 new_value_len += cell->len;
01839 cell = cell->next;
01840 }
01841 if (list->count > 1)
01842 new_value_len += (2 * (list->count - 1));
01843
01844
01845 new_value = heap->allocate_str(new_value_len);
01846
01847
01848 dest = new_value;
01849 cell = list->head;
01850 for (i = 0; i < list->count; i++) {
01851 if (i != 0) {
01852 *dest++ = ',';
01853 *dest++ = ' ';
01854 }
01855 memcpy(dest, cell->str, cell->len);
01856 dest += cell->len;
01857 cell = cell->next;
01858 }
01859 ink_assert(dest - new_value == new_value_len);
01860
01861 *new_str_len_return = new_value_len;
01862 return new_value;
01863 }
01864
01865 void
01866 mime_field_value_set_comma_val(HdrHeap *heap, MIMEHdrImpl *mh,
01867 MIMEField *field, int idx, const char *new_piece_str, int new_piece_len)
01868 {
01869 int len;
01870 Str *cell;
01871 StrList list(false);
01872
01873
01874 HttpCompat::parse_tok_list(&list, 0, field->m_ptr_value, field->m_len_value, ',');
01875
01876
01877 if ((idx<0) || (idx>= list.count))
01878 return;
01879
01880
01881 cell = list.get_idx(idx);
01882 ink_assert(cell != NULL);
01883 cell->str = new_piece_str;
01884 cell->len = new_piece_len;
01885
01886
01887 field->m_ptr_value = mime_field_value_str_from_strlist(heap, &len, &list);
01888 field->m_len_value = len;
01889
01890
01891 field->m_n_v_raw_printable = 0;
01892 if (field->is_live() && field->is_cooked())
01893 mh->recompute_cooked_stuff(field);
01894 }
01895
01896 void
01897 mime_field_value_delete_comma_val(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int idx)
01898 {
01899 int len;
01900 Str *cell;
01901 StrList list(false);
01902
01903
01904 HttpCompat::parse_tok_list(&list, 0, field->m_ptr_value, field->m_len_value, ',');
01905
01906
01907 if ((idx<0) || (idx>= list.count))
01908 return;
01909
01910
01911 cell = list.get_idx(idx);
01912 list.detach(cell);
01913
01914
01915
01916
01917
01918
01919
01920
01921 if (list.count == 0) {
01922 field->m_ptr_value = 0;
01923 field->m_len_value = 0;
01924 } else {
01925
01926
01927
01928
01929
01930
01931 field->m_ptr_value = mime_field_value_str_from_strlist(heap, &len, &list);
01932 field->m_len_value = len;
01933 }
01934
01935
01936 field->m_n_v_raw_printable = 0;
01937 if (field->is_live() && field->is_cooked())
01938 mh->recompute_cooked_stuff(field);
01939 }
01940
01941 void
01942 mime_field_value_insert_comma_val(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int idx,
01943 const char *new_piece_str, int new_piece_len)
01944 {
01945 int len;
01946 Str *cell, *prev;
01947 StrList list(false);
01948
01949
01950 HttpCompat::parse_tok_list(&list, 0, field->m_ptr_value, field->m_len_value, ',');
01951
01952
01953 if (idx < 0)
01954 idx = list.count;
01955 if (idx > list.count)
01956 return;
01957
01958
01959 cell = list.new_cell(new_piece_str, new_piece_len);
01960
01961
01962 if (idx == 0) {
01963 list.prepend(cell);
01964 } else {
01965 prev = list.get_idx(idx - 1);
01966 list.add_after(prev, cell);
01967 }
01968
01969
01970 field->m_ptr_value = mime_field_value_str_from_strlist(heap, &len, &list);
01971 field->m_len_value = len;
01972
01973
01974 field->m_n_v_raw_printable = 0;
01975 if (field->is_live() && field->is_cooked())
01976 mh->recompute_cooked_stuff(field);
01977 }
01978
01979 void
01980 mime_field_value_extend_comma_val(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int idx,
01981 const char *new_piece_str, int new_piece_len)
01982 {
01983 Str *cell;
01984 StrList list(false);
01985 int trimmed, len;
01986 size_t extended_len;
01987 char *dest, *temp_ptr, temp_buf[128];
01988
01989
01990 HttpCompat::parse_tok_list(&list, 0, field->m_ptr_value, field->m_len_value, ',');
01991
01992
01993 if ((idx<0) || (idx>= list.count))
01994 return;
01995
01996
01997 cell = list.get_idx(idx);
01998 ink_assert(cell != NULL);
01999
02000
02001 if ((cell->len >= 2) && (cell->str[0] == '\"') && (cell->str[cell->len - 1] == '\"')) {
02002 trimmed = 1;
02003 cell->str += 1;
02004 cell->len -= 2;
02005 } else {
02006 trimmed = 0;
02007 }
02008
02009
02010 extended_len = cell->len + new_piece_len + (trimmed ? 2 : 0);
02011
02012
02013 if (extended_len <= sizeof(temp_buf))
02014 temp_ptr = temp_buf;
02015 else
02016 temp_ptr = (char *)ats_malloc(extended_len);
02017
02018
02019 dest = temp_ptr;
02020 if (trimmed)
02021 *dest++ = '\"';
02022 memcpy(dest, cell->str, cell->len);
02023 dest += cell->len;
02024 memcpy(dest, new_piece_str, new_piece_len);
02025 dest += new_piece_len;
02026 if (trimmed)
02027 *dest++ = '\"';
02028 ink_assert((size_t) (dest - temp_ptr) == extended_len);
02029
02030
02031 cell->str = temp_ptr;
02032 cell->len = extended_len;
02033
02034
02035 field->m_ptr_value = mime_field_value_str_from_strlist(heap, &len, &list);
02036 field->m_len_value = len;
02037
02038
02039 field->m_n_v_raw_printable = 0;
02040 if (field->is_live() && field->is_cooked())
02041 mh->recompute_cooked_stuff(field);
02042
02043
02044 if (extended_len > sizeof(temp_buf))
02045 ats_free(temp_ptr);
02046 }
02047
02048 void
02049 mime_field_value_set(HdrHeap *heap,
02050 MIMEHdrImpl *mh, MIMEField *field, const char *value, int length, bool must_copy_string)
02051 {
02052
02053 heap->free_string(field->m_ptr_value, field->m_len_value);
02054
02055 if (must_copy_string && value)
02056 field->m_ptr_value = heap->duplicate_str(value, length);
02057 else
02058 field->m_ptr_value = value;
02059
02060 field->m_len_value = length;
02061 field->m_n_v_raw_printable = 0;
02062
02063
02064 if (field->is_live() && field->is_cooked())
02065 mh->recompute_cooked_stuff(field);
02066 }
02067
02068 void
02069 mime_field_value_set_int(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int32_t value)
02070 {
02071 char buf[16];
02072 int len = mime_format_int(buf, value, sizeof(buf));
02073 mime_field_value_set(heap, mh, field, buf, len, 1);
02074 }
02075
02076 void
02077 mime_field_value_set_uint(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, uint32_t value)
02078 {
02079 char buf[16];
02080 int len = mime_format_uint(buf, value, sizeof(buf));
02081 mime_field_value_set(heap, mh, field, buf, len, 1);
02082 }
02083
02084 void
02085 mime_field_value_set_int64(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int64_t value)
02086 {
02087 char buf[20];
02088 int len = mime_format_int64(buf, value, sizeof(buf));
02089 mime_field_value_set(heap, mh, field, buf, len, 1);
02090 }
02091
02092 void
02093 mime_field_value_set_date(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, time_t value)
02094 {
02095 char buf[33];
02096 int len = mime_format_date(buf, value);
02097 mime_field_value_set(heap, mh, field, buf, len, 1);
02098 }
02099
02100 void
02101 mime_field_name_value_set(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int16_t name_wks_idx_or_neg1,
02102 const char *name, int name_length, const char *value, int value_length, int n_v_raw_printable,
02103 int n_v_raw_length, bool must_copy_strings)
02104 {
02105 unsigned int n_v_raw_pad = n_v_raw_length - (name_length + value_length);
02106
02107 ink_assert(field->m_readiness == MIME_FIELD_SLOT_READINESS_DETACHED);
02108
02109 if (must_copy_strings) {
02110 mime_field_name_set(heap, mh, field, name_wks_idx_or_neg1, name, name_length, 1);
02111 mime_field_value_set(heap, mh, field, value, value_length, 1);
02112 } else {
02113 field->m_wks_idx = name_wks_idx_or_neg1;
02114 field->m_ptr_name = name;
02115 field->m_ptr_value = value;
02116 field->m_len_name = name_length;
02117 field->m_len_value = value_length;
02118 if (n_v_raw_printable && (n_v_raw_pad <= 7)) {
02119 field->m_n_v_raw_printable = n_v_raw_printable;
02120 field->m_n_v_raw_printable_pad = n_v_raw_pad;
02121 } else {
02122 field->m_n_v_raw_printable = 0;
02123 }
02124
02125
02126 if ((name_wks_idx_or_neg1 == MIME_WKSIDX_CACHE_CONTROL) || (name_wks_idx_or_neg1 == MIME_WKSIDX_PRAGMA)) {
02127 field->m_flags |= MIME_FIELD_SLOT_FLAGS_COOKED;
02128 }
02129 if (field->is_live() && field->is_cooked())
02130 mh->recompute_cooked_stuff(field);
02131 }
02132 }
02133
02134 void
02135 mime_field_value_append(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, const char *value, int length,
02136 bool prepend_comma, const char separator)
02137 {
02138 int new_length = field->m_len_value + length;
02139 if (prepend_comma && field->m_len_value)
02140 new_length += 2;
02141
02142
02143 char *new_str = heap->expand_str(field->m_ptr_value, field->m_len_value, new_length);
02144
02145 if (new_str == NULL) {
02146
02147 new_str = heap->allocate_str(new_length);
02148 memcpy(new_str, field->m_ptr_value, field->m_len_value);
02149 }
02150
02151 char *ptr = new_str + field->m_len_value;
02152 if (prepend_comma && field->m_len_value) {
02153 *ptr++ = separator;
02154 *ptr++ = ' ';
02155 }
02156
02157 memcpy(ptr, value, length);
02158
02159 field->m_ptr_value = new_str;
02160 field->m_len_value = new_length;
02161 field->m_n_v_raw_printable = 0;
02162
02163
02164 if (field->is_live() && field->is_cooked())
02165 mh->recompute_cooked_stuff(field);
02166 }
02167
02168 MIMEField* MIMEHdr::get_host_port_values(
02169 char const** host_ptr,
02170 int* host_len,
02171 char const** port_ptr,
02172 int* port_len
02173 )
02174 {
02175 MIMEField* field = this->field_find(MIME_FIELD_HOST, MIME_LEN_HOST);
02176 if (host_ptr)
02177 *host_ptr = 0;
02178 if (host_len)
02179 *host_len = 0;
02180 if (port_ptr)
02181 *port_ptr = 0;
02182 if (port_len)
02183 *port_len = 0;
02184
02185 if (field) {
02186 ts::ConstBuffer b(field->m_ptr_value, field->m_len_value);
02187 ts::ConstBuffer host, port;
02188
02189 if (b) {
02190 char const* x;
02191
02192 if ('[' == *b) {
02193 x = static_cast<char const*>(memchr(b._ptr, ']', b._size));
02194 if (x && b.contains(x+1) && ':' == x[1]) {
02195 host = b.splitOn(x+1);
02196 port = b;
02197 } else {
02198 host = b;
02199 }
02200 } else {
02201 x = static_cast<char const*>(memchr(b._ptr, ':', b._size));
02202 if (x) {
02203 host = b.splitOn(x);
02204 port = b;
02205 } else {
02206 host = b;
02207 }
02208 }
02209
02210 if (host) {
02211 if (host_ptr) *host_ptr = host._ptr;
02212 if (host_len) *host_len = static_cast<int>(host._size);
02213 }
02214 if (port) {
02215 if (port_ptr) *port_ptr = port._ptr;
02216 if (port_len) *port_len = static_cast<int>(port._size);
02217 }
02218 } else {
02219 field = 0;
02220 }
02221 }
02222 return field;
02223 }
02224
02225
02226
02227
02228
02229
02230 void
02231 _mime_scanner_init(MIMEScanner *scanner)
02232 {
02233 scanner->m_line = NULL;
02234 scanner->m_line_size = 0;
02235 scanner->m_line_length = 0;
02236 scanner->m_state = MIME_PARSE_BEFORE;
02237
02238 }
02239
02240
02241
02242
02243
02244 void
02245 mime_scanner_init(MIMEScanner *scanner)
02246 {
02247 _mime_scanner_init(scanner);
02248 }
02249
02250
02251 void
02252 mime_scanner_clear(MIMEScanner *scanner)
02253 {
02254 ats_free(scanner->m_line);
02255 _mime_scanner_init(scanner);
02256 }
02257
02258 void
02259 mime_scanner_append(MIMEScanner *scanner, const char *data, int data_size)
02260 {
02261 int free_size = scanner->m_line_size - scanner->m_line_length;
02262
02263
02264
02265
02266 if (data_size > free_size) {
02267 if (scanner->m_line_size == 0)
02268 scanner->m_line_size = 128;
02269
02270 while (free_size < data_size) {
02271 scanner->m_line_size *= 2;
02272 free_size = scanner->m_line_size - scanner->m_line_length;
02273 }
02274
02275 if (scanner->m_line == NULL) {
02276 scanner->m_line = (char *)ats_malloc(scanner->m_line_size);
02277 } else {
02278 scanner->m_line = (char *)ats_realloc(scanner->m_line, scanner->m_line_size);
02279 }
02280 }
02281
02282
02283
02284
02285 memcpy(&(scanner->m_line[scanner->m_line_length]), data, data_size);
02286 scanner->m_line_length += data_size;
02287 }
02288
02289 MIMEParseResult
02290 mime_scanner_get(MIMEScanner *S,
02291 const char **raw_input_s,
02292 const char *raw_input_e,
02293 const char **output_s,
02294 const char **output_e,
02295 bool *output_shares_raw_input,
02296 bool raw_input_eof,
02297 int raw_input_scan_type)
02298 {
02299 const char *raw_input_c, *lf_ptr;
02300 MIMEParseResult zret = PARSE_CONT;
02301
02302 static char const RAW_CR = ParseRules::CHAR_CR;
02303
02304 ink_assert((raw_input_s != NULL) && (*raw_input_s != NULL));
02305 ink_assert(raw_input_e != NULL);
02306
02307 raw_input_c = *raw_input_s;
02308
02309 while (PARSE_CONT == zret && raw_input_c < raw_input_e) {
02310 ptrdiff_t runway = raw_input_e - raw_input_c;
02311 switch (S->m_state) {
02312 case MIME_PARSE_BEFORE:
02313 if (ParseRules::is_cr(*raw_input_c)) {
02314 ++raw_input_c;
02315 if (runway >= 2 && ParseRules::is_lf(*raw_input_c)) {
02316
02317 ++raw_input_c;
02318 zret = PARSE_DONE;
02319 } else {
02320 S->m_state = MIME_PARSE_FOUND_CR;
02321 }
02322 } else if (ParseRules::is_lf(*raw_input_c)) {
02323 ++raw_input_c;
02324 zret = PARSE_DONE;
02325 } else {
02326
02327 S->m_state = MIME_PARSE_INSIDE;
02328 }
02329 break;
02330 case MIME_PARSE_FOUND_CR:
02331
02332
02333
02334 if (ParseRules::is_lf(*raw_input_c)) {
02335
02336 ++raw_input_c;
02337 zret = PARSE_DONE;
02338 } else {
02339
02340
02341 mime_scanner_append(S, &RAW_CR, 1);
02342 S->m_state = MIME_PARSE_INSIDE;
02343 }
02344 break;
02345 case MIME_PARSE_INSIDE:
02346 lf_ptr = static_cast<char const*>(memchr(raw_input_c, ParseRules::CHAR_LF, runway));
02347 if (lf_ptr) {
02348 raw_input_c = lf_ptr + 1;
02349 if (MIME_SCANNER_TYPE_LINE == raw_input_scan_type) {
02350 zret = PARSE_OK;
02351 S->m_state = MIME_PARSE_BEFORE;
02352 } else {
02353 S->m_state = MIME_PARSE_AFTER;
02354 }
02355 } else {
02356 raw_input_c = raw_input_e;
02357 }
02358 break;
02359 case MIME_PARSE_AFTER:
02360
02361 if (ParseRules::is_ws(*raw_input_c)) {
02362 S->m_state = MIME_PARSE_INSIDE;
02363 } else {
02364 S->m_state = MIME_PARSE_BEFORE;
02365 zret = PARSE_OK;
02366 }
02367 break;
02368 }
02369 }
02370
02371 ptrdiff_t data_size = raw_input_c - *raw_input_s;
02372
02373 if (PARSE_CONT == zret) {
02374
02375
02376
02377
02378 if (raw_input_eof) {
02379
02380 if (0 == data_size) {
02381
02382 if (MIME_PARSE_INSIDE != S->m_state) {
02383 S->m_state = MIME_PARSE_BEFORE;
02384 zret = PARSE_DONE;
02385 } else {
02386 zret = PARSE_ERROR;
02387 }
02388 } else if (MIME_PARSE_AFTER == S->m_state) {
02389
02390
02391
02392
02393 S->m_state = MIME_PARSE_BEFORE;
02394 zret = PARSE_OK;
02395 } else {
02396
02397 zret = PARSE_ERROR;
02398 }
02399 } else if (data_size) {
02400
02401 mime_scanner_append(S, *raw_input_s, data_size);
02402 data_size = 0;
02403 }
02404 }
02405
02406 if (data_size && S->m_line_length) {
02407
02408 mime_scanner_append(S, *raw_input_s, data_size);
02409 }
02410
02411
02412 if (PARSE_CONT != zret) {
02413 if (0 != S->m_line_length) {
02414 *output_s = S->m_line;
02415 *output_e = *output_s + S->m_line_length;
02416 *output_shares_raw_input = false;
02417 S->m_line_length = 0;
02418 } else {
02419 *output_s = *raw_input_s;
02420 *output_e = raw_input_c;
02421 *output_shares_raw_input = true;
02422 }
02423 }
02424
02425 *raw_input_s = raw_input_c;
02426 return zret;
02427 }
02428
02429 void
02430 _mime_parser_init(MIMEParser *parser)
02431 {
02432 parser->m_field = 0;
02433 parser->m_field_flags = 0;
02434 parser->m_value = -1;
02435 }
02436
02437
02438
02439
02440 void
02441 mime_parser_init(MIMEParser *parser)
02442 {
02443 mime_scanner_init(&parser->m_scanner);
02444 _mime_parser_init(parser);
02445 }
02446
02447 void
02448 mime_parser_clear(MIMEParser *parser)
02449 {
02450 mime_scanner_clear(&parser->m_scanner);
02451 _mime_parser_init(parser);
02452 }
02453
02454 MIMEParseResult
02455 mime_parser_parse(MIMEParser *parser, HdrHeap *heap, MIMEHdrImpl *mh, const char **real_s, const char *real_e,
02456 bool must_copy_strings, bool eof)
02457 {
02458 MIMEParseResult err;
02459 bool line_is_real;
02460 const char *colon;
02461 const char *line_c;
02462 const char *line_s;
02463 const char *line_e;
02464 const char *field_name_first;
02465 const char *field_name_last;
02466 const char *field_value_first;
02467 const char *field_value_last;
02468 const char *field_line_first;
02469 const char *field_line_last;
02470 int field_name_length, field_value_length;
02471
02472 MIMEScanner *scanner = &parser->m_scanner;
02473
02474 while (1) {
02475
02476
02477
02478
02479 err = mime_scanner_get(scanner, real_s, real_e, &line_s, &line_e, &line_is_real, eof, MIME_SCANNER_TYPE_FIELD);
02480 if (err != PARSE_OK)
02481 return err;
02482
02483 line_c = line_s;
02484
02485
02486
02487
02488
02489 if ((line_e - line_c >= 2) && (line_c[0] == ParseRules::CHAR_CR) && (line_c[1] == ParseRules::CHAR_LF))
02490 return PARSE_DONE;
02491
02492 if ((line_e - line_c >= 1) && (line_c[0] == ParseRules::CHAR_LF))
02493 return PARSE_DONE;
02494
02495
02496
02497
02498
02499 field_line_first = line_c;
02500 field_line_last = line_e - 1;
02501
02502
02503 field_name_first = line_c;
02504
02505
02506
02507
02508
02509
02510 if ((!ParseRules::is_token(*field_name_first)) && (*field_name_first != '@'))
02511 continue;
02512
02513
02514 colon = (char *) memchr(line_c, ':', (line_e - line_c));
02515 if (!colon)
02516 continue;
02517 field_name_last = colon - 1;
02518 while ((field_name_last >= field_name_first) && is_ws(*field_name_last))
02519 --field_name_last;
02520
02521
02522 field_value_first = colon + 1;
02523 while ((field_value_first < line_e) && is_ws(*field_value_first))
02524 ++field_value_first;
02525
02526
02527 field_value_last = line_e - 1;
02528 while ((field_value_last >= field_value_first) && ParseRules::is_wslfcr(*field_value_last))
02529 --field_value_last;
02530
02531 field_name_length = (int) (field_name_last - field_name_first + 1);
02532 field_value_length = (int) (field_value_last - field_value_first + 1);
02533
02534
02535 if (field_name_length >= UINT16_MAX || field_value_length >= UINT16_MAX)
02536 return PARSE_ERROR;
02537
02538 int total_line_length = (int) (field_line_last - field_line_first + 1);
02539
02540
02541
02542
02543
02544 if (must_copy_strings || (!line_is_real)) {
02545 int length = total_line_length;
02546 char *dup = heap->duplicate_str(field_name_first, length);
02547 intptr_t delta = dup - field_name_first;
02548
02549 field_name_first += delta;
02550 field_value_first += delta;
02551 }
02552
02553
02554
02555
02556 int field_name_wks_idx = hdrtoken_tokenize(field_name_first, field_name_length);
02557
02558
02559
02560
02561
02562
02563 MIMEField *field = mime_field_create(heap, mh);
02564 mime_field_name_value_set(heap, mh, field,
02565 field_name_wks_idx,
02566 field_name_first, field_name_length,
02567 field_value_first, field_value_length, true, total_line_length, 0);
02568 mime_hdr_field_attach(mh, field, 1, NULL);
02569 }
02570 }
02571
02572 void
02573 mime_hdr_describe(HdrHeapObjImpl *raw, bool recurse)
02574 {
02575 MIMEFieldBlockImpl *fblock;
02576 MIMEHdrImpl *obj = (MIMEHdrImpl *) raw;
02577
02578 Debug("http", "\n\t[PBITS: 0x%08X%08X, SLACC: 0x%04X%04X%04X%04X, HEADBLK: %p, TAILBLK: %p]\n",
02579 (uint32_t) ((obj->m_presence_bits >> 32) & (TOK_64_CONST(0xFFFFFFFF))),
02580 (uint32_t) ((obj->m_presence_bits >> 0) & (TOK_64_CONST(0xFFFFFFFF))),
02581 obj->m_slot_accelerators[0], obj->m_slot_accelerators[1],
02582 obj->m_slot_accelerators[2], obj->m_slot_accelerators[3], &(obj->m_first_fblock), obj->m_fblock_list_tail);
02583
02584 Debug("http", "\t[CBITS: 0x%08X, T_MAXAGE: %d, T_SMAXAGE: %d, T_MAXSTALE: %d, T_MINFRESH: %d, PNO$: %d]\n",
02585 obj->m_cooked_stuff.m_cache_control.m_mask,
02586 obj->m_cooked_stuff.m_cache_control.m_secs_max_age,
02587 obj->m_cooked_stuff.m_cache_control.m_secs_s_maxage,
02588 obj->m_cooked_stuff.m_cache_control.m_secs_max_stale,
02589 obj->m_cooked_stuff.m_cache_control.m_secs_min_fresh, obj->m_cooked_stuff.m_pragma.m_no_cache);
02590 for (fblock = &(obj->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
02591 if (recurse || (fblock == &(obj->m_first_fblock)))
02592 obj_describe((HdrHeapObjImpl *) fblock, recurse);
02593 }
02594 }
02595
02596 void
02597 mime_field_block_describe(HdrHeapObjImpl *raw, bool )
02598 {
02599 unsigned int i;
02600 static const char *readiness_names[] = { "EMPTY", "DETACHED", "LIVE", "DELETED" };
02601
02602 MIMEFieldBlockImpl *obj = (MIMEFieldBlockImpl *) raw;
02603
02604 Debug("http", "[FREETOP: %d, NEXTBLK: %p]\n", obj->m_freetop, obj->m_next);
02605
02606 for (i = 0; i < obj->m_freetop; i++) {
02607 MIMEField *f = &(obj->m_field_slots[i]);
02608 Debug("http", "\tSLOT #%2d (%p), %-8s", i, f, readiness_names[f->m_readiness]);
02609
02610 switch (f->m_readiness) {
02611 case MIME_FIELD_SLOT_READINESS_EMPTY:
02612 break;
02613 case MIME_FIELD_SLOT_READINESS_DETACHED:
02614 case MIME_FIELD_SLOT_READINESS_LIVE:
02615 case MIME_FIELD_SLOT_READINESS_DELETED:
02616 Debug("http", "[N: \"%.*s\", N_LEN: %d, N_IDX: %d, ",
02617 f->m_len_name, (f->m_ptr_name ? f->m_ptr_name : "NULL"), f->m_len_name, f->m_wks_idx);
02618 Debug("http", "V: \"%.*s\", V_LEN: %d, ",
02619 f->m_len_value, (f->m_ptr_value ? f->m_ptr_value : "NULL"), f->m_len_value);
02620 Debug("http", "NEXTDUP: %p, RAW: %d, RAWLEN: %d, F: %d]",
02621 f->m_next_dup, f->m_n_v_raw_printable,
02622 f->m_len_name + f->m_len_value + f->m_n_v_raw_printable_pad, f->m_flags);
02623 break;
02624 }
02625 Debug("http", "\n");
02626 }
02627 }
02628
02629 int
02630 mime_hdr_print(HdrHeap * , MIMEHdrImpl *mh, char *buf_start, int buf_length, int *buf_index_inout,
02631 int *buf_chars_to_skip_inout)
02632 {
02633 MIMEFieldBlockImpl *fblock;
02634 MIMEField *field;
02635 uint32_t index;
02636
02637 #define SIMPLE_MIME_HDR_PRINT
02638 #ifdef SIMPLE_MIME_HDR_PRINT
02639 for (fblock = &(mh->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
02640 for (index = 0; index < fblock->m_freetop; index++) {
02641 field = &(fblock->m_field_slots[index]);
02642 if (field->is_live()) {
02643 if (!mime_field_print(field, buf_start, buf_length, buf_index_inout, buf_chars_to_skip_inout))
02644 return 0;
02645 }
02646 }
02647 }
02648 #else
02649
02650
02651 for (fblock = &(mh->m_first_fblock); fblock != NULL; fblock = fblock->m_next) {
02652 const char *contig_start = NULL;
02653 int this_length, contig_length = 0;
02654 for (index = 0; index < fblock->m_freetop; index++) {
02655 field = &(fblock->m_field_slots[index]);
02656 this_length = field->m_len_name + field->m_len_value + field->m_n_v_raw_printable_pad;
02657 if (field->is_live()) {
02658 if ((field->m_ptr_name == contig_start + contig_length)
02659 && field->m_n_v_raw_printable
02660 && ((buf_index_inout == NULL) || (contig_length + this_length <= buf_length - *buf_index_inout))) {
02661
02662 contig_length += this_length;
02663 } else {
02664 if (contig_length > 0) {
02665 if (!mime_mem_print(contig_start, contig_length, buf_start, buf_length,
02666 buf_index_inout, buf_chars_to_skip_inout))
02667 return 0;
02668 }
02669 contig_start = field->m_ptr_name;
02670 contig_length = this_length;
02671 }
02672 }
02673 }
02674
02675 if (contig_length > 0) {
02676 if (!mime_mem_print(contig_start, contig_length, buf_start, buf_length, buf_index_inout, buf_chars_to_skip_inout))
02677 return 0;
02678 }
02679 }
02680 #endif
02681
02682 if (!mime_mem_print("\r\n", 2, buf_start, buf_length, buf_index_inout, buf_chars_to_skip_inout)) {
02683 return 0;
02684 }
02685
02686 return 1;
02687 }
02688
02689 int
02690 mime_mem_print(const char *src_d, int src_l, char *buf_start, int buf_length, int *buf_index_inout,
02691 int *buf_chars_to_skip_inout)
02692 {
02693 int copy_l;
02694
02695 if (buf_start == NULL) {
02696 ink_release_assert(buf_index_inout == NULL);
02697 ink_release_assert(buf_chars_to_skip_inout == NULL);
02698 while (src_l--)
02699 putchar(*src_d++);
02700 return 1;
02701 }
02702
02703 ink_assert(buf_start != NULL);
02704 ink_assert(src_d != NULL);
02705
02706 if (*buf_chars_to_skip_inout > 0) {
02707 if (*buf_chars_to_skip_inout >= src_l) {
02708 *buf_chars_to_skip_inout -= src_l;
02709 return 1;
02710 } else {
02711 src_l -= *buf_chars_to_skip_inout;
02712 src_d += *buf_chars_to_skip_inout;
02713 *buf_chars_to_skip_inout = 0;
02714 }
02715 }
02716
02717 copy_l = min(buf_length - *buf_index_inout, src_l);
02718 if (copy_l > 0) {
02719 memcpy(buf_start + *buf_index_inout, src_d, copy_l);
02720 *buf_index_inout += copy_l;
02721 }
02722 return (src_l == copy_l);
02723 }
02724
02725 int
02726 mime_field_print(MIMEField *field, char *buf_start, int buf_length, int *buf_index_inout, int *buf_chars_to_skip_inout)
02727 {
02728 #define TRY(x) if (!x) return 0
02729
02730 int total_len;
02731
02732
02733 if (field->m_ptr_name[0] == '@') {
02734 return 1;
02735 }
02736
02737 if (field->m_n_v_raw_printable) {
02738
02739 total_len = field->m_len_name + field->m_len_value + field->m_n_v_raw_printable_pad;
02740
02741 if ((buf_start != NULL) && (*buf_chars_to_skip_inout == 0) && (total_len <= (buf_length - *buf_index_inout))) {
02742
02743 buf_start += *buf_index_inout;
02744 memcpy(buf_start, field->m_ptr_name, total_len);
02745 *buf_index_inout += total_len;
02746
02747 } else {
02748 TRY(mime_mem_print(field->m_ptr_name, total_len, buf_start, buf_length, buf_index_inout, buf_chars_to_skip_inout));
02749 }
02750 } else {
02751 total_len = field->m_len_name + field->m_len_value + 2 + 2;
02752
02753
02754
02755 if ((buf_start != NULL) && (*buf_chars_to_skip_inout == 0) && (total_len <= (buf_length - *buf_index_inout))) {
02756 buf_start += *buf_index_inout;
02757
02758 memcpy(buf_start, field->m_ptr_name, field->m_len_name);
02759 buf_start += field->m_len_name;
02760
02761 buf_start[0] = ':';
02762 buf_start[1] = ' ';
02763 buf_start += 2;
02764
02765 memcpy(buf_start, field->m_ptr_value, field->m_len_value);
02766 buf_start += field->m_len_value;
02767
02768 buf_start[0] = '\r';
02769 buf_start[1] = '\n';
02770
02771 *buf_index_inout += total_len;
02772 } else {
02773 TRY(mime_mem_print(field->m_ptr_name, field->m_len_name, buf_start, buf_length, buf_index_inout,
02774 buf_chars_to_skip_inout));
02775 TRY(mime_mem_print(": ", 2, buf_start, buf_length, buf_index_inout, buf_chars_to_skip_inout));
02776 TRY(mime_mem_print(field->m_ptr_value, field->m_len_value, buf_start, buf_length, buf_index_inout,
02777 buf_chars_to_skip_inout));
02778 TRY(mime_mem_print("\r\n", 2, buf_start, buf_length, buf_index_inout, buf_chars_to_skip_inout));
02779 }
02780 }
02781
02782 return 1;
02783
02784 #undef TRY
02785 }
02786
02787 const char *
02788 mime_str_u16_set(HdrHeap *heap, const char *s_str, int s_len, const char **d_str, uint16_t *d_len, bool must_copy)
02789 {
02790 ink_assert(s_len >= 0 && s_len < UINT16_MAX);
02791
02792
02793
02794
02795 heap->free_string(*d_str, *d_len);
02796
02797 if (must_copy && s_str) {
02798 s_str = heap->duplicate_str(s_str, s_len);
02799 }
02800 *d_str = s_str;
02801 *d_len = s_len;
02802 return s_str;
02803 }
02804
02805 int
02806 mime_field_length_get(MIMEField *field)
02807 {
02808 if (field->m_n_v_raw_printable) {
02809 return (field->m_len_name + field->m_len_value + field->m_n_v_raw_printable_pad);
02810 } else {
02811 return (field->m_len_name + field->m_len_value + 4);
02812 }
02813 }
02814
02815 int
02816 mime_format_int(char *buf, int32_t val, size_t buf_len)
02817 {
02818 return ink_fast_itoa(val, buf, buf_len);
02819 }
02820
02821 int
02822 mime_format_uint(char *buf, uint32_t val, size_t buf_len)
02823 {
02824 return ink_fast_uitoa(val, buf, buf_len);
02825 }
02826
02827 int
02828 mime_format_int64(char *buf, int64_t val, size_t buf_len)
02829 {
02830 return ink_fast_ltoa(val, buf, buf_len);
02831 }
02832
02833 void
02834 mime_days_since_epoch_to_mdy_slowcase(unsigned int days_since_jan_1_1970, int *m_return, int *d_return, int *y_return)
02835 {
02836 static const int DAYS_OFFSET = 25508;
02837
02838 static const char months[] = {
02839 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
02840 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
02841 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
02842 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
02843 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
02844 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,
02845 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
02846 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
02847 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
02848 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7,
02849 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
02850 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8,
02851 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
02852 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9,
02853 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
02854 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
02855 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
02856 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
02857 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
02858 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02859 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02860 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
02861 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
02862 };
02863
02864 static const int days[12] = {
02865 305, 336, -1, 30, 60, 91, 121, 152, 183, 213, 244, 274
02866 };
02867
02868 int mday, year, month, d, dp;
02869
02870 mday = days_since_jan_1_1970;
02871
02872
02873 year = mday / 365 + 69;
02874 d = dp = (year * 365) + (year / 4) - (year / 100) + (year / 100 + 3) / 4 - DAYS_OFFSET - 1;
02875
02876 while (dp < mday) {
02877 d = dp;
02878 year += 1;
02879 dp = (year * 365) + (year / 4) - (year / 100) + (year / 100 + 3) / 4 - DAYS_OFFSET - 1;
02880 }
02881
02882
02883 d = mday - d;
02884 if ((d<0) || (d> 366))
02885 ink_assert(!"bad date");
02886 else {
02887 month = months[d];
02888 if (month > 1)
02889 year -= 1;
02890
02891 mday = d - days[month] - 1;
02892 year += 1900;
02893
02894 *m_return = month;
02895 *d_return = mday;
02896 *y_return = year;
02897 }
02898 }
02899
02900 void
02901 mime_days_since_epoch_to_mdy(unsigned int days_since_jan_1_1970, int *m_return, int *d_return, int *y_return)
02902 {
02903 ink_assert(_days_to_mdy_fast_lookup_table != NULL);
02904
02905
02906
02907
02908
02909 if ((days_since_jan_1_1970 >= _days_to_mdy_fast_lookup_table_first_day) &&
02910 (days_since_jan_1_1970 <= _days_to_mdy_fast_lookup_table_last_day)) {
02911
02912
02913
02914
02915
02916
02917 int i = days_since_jan_1_1970 - _days_to_mdy_fast_lookup_table_first_day;
02918 *m_return = _days_to_mdy_fast_lookup_table[i].m;
02919 *d_return = _days_to_mdy_fast_lookup_table[i].d;
02920 *y_return = _days_to_mdy_fast_lookup_table[i].y;
02921 return;
02922 }
02923
02924
02925
02926
02927 mime_days_since_epoch_to_mdy_slowcase(days_since_jan_1_1970, m_return, d_return, y_return);
02928 }
02929
02930 int
02931 mime_format_date(char *buffer, time_t value)
02932 {
02933
02934 static const char *daystrs[] = {
02935 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
02936 };
02937
02938
02939 static const char *monthstrs[] = {
02940 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
02941 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
02942 };
02943
02944 static const char *digitstrs[] = {
02945 "00", "01", "02", "03", "04", "05", "06", "07", "08", "09",
02946 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
02947 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
02948 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
02949 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
02950 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
02951 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
02952 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
02953 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
02954 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
02955 };
02956
02957 char *buf;
02958 int sec, min, hour, wday, mday=0, year=0, month=0;
02959
02960 buf = buffer;
02961
02962 sec = (int) (value % 60);
02963 value /= 60;
02964 min = (int) (value % 60);
02965 value /= 60;
02966 hour = (int) (value % 24);
02967 value /= 24;
02968
02969
02970 wday = (int) ((4 + value) % 7);
02971
02972
02973 #if MIME_FORMAT_DATE_USE_LOOKUP_TABLE
02974 mime_days_since_epoch_to_mdy(value, &month, &mday, &year);
02975 #else
02976 mime_days_since_epoch_to_mdy_slowcase(value, &month, &mday, &year);
02977 #endif
02978
02979
02980 ink_assert((mday >= 0) && (mday <= 99));
02981 ink_assert((hour >= 0) && (hour <= 99));
02982 ink_assert((min >= 0) && (min <= 99));
02983 ink_assert((sec >= 0) && (sec <= 99));
02984
02985
02986 const char *three_char_day = daystrs[wday];
02987 buf[0] = three_char_day[0];
02988 buf[1] = three_char_day[1];
02989 buf[2] = three_char_day[2];
02990 buf += 3;
02991
02992 buf[0] = ',';
02993 buf[1] = ' ';
02994 buf += 2;
02995
02996
02997 buf[0] = digitstrs[mday][0];
02998 buf[1] = digitstrs[mday][1];
02999 buf[2] = ' ';
03000 buf += 3;
03001
03002
03003 const char *three_char_month = monthstrs[month];
03004 buf[0] = three_char_month[0];
03005 buf[1] = three_char_month[1];
03006 buf[2] = three_char_month[2];
03007 buf += 3;
03008
03009
03010 buf[0] = ' ';
03011
03012 if ((year >= 2000) && (year <= 2009)) {
03013 buf[1] = '2';
03014 buf[2] = '0';
03015 buf[3] = '0';
03016 buf[4] = (year - 2000) + '0';
03017 } else if ((year >= 1990) && (year <= 1999)) {
03018 buf[1] = '1';
03019 buf[2] = '9';
03020 buf[3] = '9';
03021 buf[4] = (year - 1990) + '0';
03022 } else {
03023 buf[4] = (year % 10) + '0';
03024 year /= 10;
03025 buf[3] = (year % 10) + '0';
03026 year /= 10;
03027 buf[2] = (year % 10) + '0';
03028 year /= 10;
03029 buf[1] = (year % 10) + '0';
03030 }
03031 buf[5] = ' ';
03032 buf += 6;
03033
03034
03035 buf[0] = digitstrs[hour][0];
03036 buf[1] = digitstrs[hour][1];
03037 buf[2] = ':';
03038 buf += 3;
03039
03040
03041 buf[0] = digitstrs[min][0];
03042 buf[1] = digitstrs[min][1];
03043 buf[2] = ':';
03044 buf += 3;
03045
03046
03047 buf[0] = digitstrs[sec][0];
03048 buf[1] = digitstrs[sec][1];
03049 buf[2] = ' ';
03050 buf += 3;
03051
03052
03053 buf[0] = 'G';
03054 buf[1] = 'M';
03055 buf[2] = 'T';
03056 buf[3] = '\0';
03057 buf += 3;
03058
03059 return buf - buffer;
03060 }
03061
03062 int32_t
03063 mime_parse_int(const char *buf, const char *end)
03064 {
03065 int32_t num;
03066 bool negative;
03067
03068 if (!buf || (buf == end))
03069 return 0;
03070
03071 if (is_digit(*buf))
03072 {
03073 num = *buf++ - '0';
03074 while ((buf != end) && is_digit(*buf))
03075 num = (num * 10) + (*buf++ - '0');
03076 return num;
03077 } else {
03078 num = 0;
03079 negative = false;
03080
03081 while ((buf != end) && ParseRules::is_space(*buf))
03082 buf += 1;
03083
03084 if ((buf != end) && (*buf == '-')) {
03085 negative = true;
03086 buf += 1;
03087 }
03088
03089
03090 while ((buf != end) && is_digit(*buf))
03091 num = (num * 10) - (*buf++ - '0');
03092
03093 if (!negative)
03094 num = -num;
03095
03096 return num;
03097 }
03098 }
03099
03100 uint32_t
03101 mime_parse_uint(const char *buf, const char *end)
03102 {
03103 uint32_t num;
03104
03105 if (!buf || (buf == end))
03106 return 0;
03107
03108 if (is_digit(*buf))
03109 {
03110 num = *buf++ - '0';
03111 while ((buf != end) && is_digit(*buf))
03112 num = (num * 10) + (*buf++ - '0');
03113 return num;
03114 } else {
03115 num = 0;
03116 while ((buf != end) && ParseRules::is_space(*buf))
03117 buf += 1;
03118 while ((buf != end) && is_digit(*buf))
03119 num = (num * 10) + (*buf++ - '0');
03120 return num;
03121 }
03122 }
03123
03124 int64_t
03125 mime_parse_int64(const char *buf, const char *end)
03126 {
03127 int64_t num;
03128 bool negative;
03129
03130 if (!buf || (buf == end))
03131 return 0;
03132
03133 if (is_digit(*buf))
03134 {
03135 num = *buf++ - '0';
03136 while ((buf != end) && is_digit(*buf))
03137 num = (num * 10) + (*buf++ - '0');
03138 return num;
03139 } else {
03140 num = 0;
03141 negative = false;
03142
03143 while ((buf != end) && ParseRules::is_space(*buf))
03144 buf += 1;
03145
03146 if ((buf != end) && (*buf == '-')) {
03147 negative = true;
03148 buf += 1;
03149 }
03150
03151
03152 while ((buf != end) && is_digit(*buf))
03153 num = (num * 10) - (*buf++ - '0');
03154
03155 if (!negative)
03156 num = -num;
03157
03158 return num;
03159 }
03160 }
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197 int
03198 mime_parse_rfc822_date_fastcase(const char *buf, int length, struct tm *tp)
03199 {
03200 unsigned int three_char_wday, three_char_mon;
03201
03202 ink_assert(length >= 29);
03203 ink_assert(!is_ws(buf[0]));
03204 ink_assert(buf[3] == ',');
03205
03206
03207
03208
03209 tp->tm_wday = -1;
03210 three_char_wday = (buf[0] << 16) | (buf[1] << 8) | buf[2];
03211 if (three_char_wday <= 0x53756E) {
03212 if (three_char_wday == 0x467269)
03213 tp->tm_wday = 5;
03214 else if (three_char_wday == 0x4D6F6E)
03215 tp->tm_wday = 1;
03216 else if (three_char_wday == 0x536174)
03217 tp->tm_wday = 6;
03218 else if (three_char_wday == 0x53756E)
03219 tp->tm_wday = 0;
03220 } else {
03221 if (three_char_wday == 0x546875)
03222 tp->tm_wday = 4;
03223 else if (three_char_wday == 0x547565)
03224 tp->tm_wday = 2;
03225 else if (three_char_wday == 0x576564)
03226 tp->tm_wday = 3;
03227 }
03228 if (tp->tm_wday < 0) {
03229 tp->tm_wday = day_names_dfa->match(buf, length);
03230 if (tp->tm_wday < 0)
03231 return 0;
03232 }
03233
03234
03235
03236 tp->tm_mday = (buf[5] - '0') * 10 + (buf[6] - '0');
03237
03238
03239
03240
03241 tp->tm_mon = -1;
03242 three_char_mon = (buf[8] << 16) | (buf[9] << 8) | buf[10];
03243 if (three_char_mon <= 0x4A756C) {
03244 if (three_char_mon <= 0x446563) {
03245 if (three_char_mon == 0x417072)
03246 tp->tm_mon = 3;
03247 else if (three_char_mon == 0x417567)
03248 tp->tm_mon = 7;
03249 else if (three_char_mon == 0x446563)
03250 tp->tm_mon = 11;
03251 } else {
03252 if (three_char_mon == 0x466562)
03253 tp->tm_mon = 1;
03254 else if (three_char_mon == 0x4A616E)
03255 tp->tm_mon = 0;
03256 else if (three_char_mon == 0x4A756C)
03257 tp->tm_mon = 6;
03258 }
03259 } else {
03260 if (three_char_mon <= 0x4D6179) {
03261 if (three_char_mon == 0x4A756E)
03262 tp->tm_mon = 5;
03263 else if (three_char_mon == 0x4D6172)
03264 tp->tm_mon = 2;
03265 else if (three_char_mon == 0x4D6179)
03266 tp->tm_mon = 4;
03267 } else {
03268 if (three_char_mon == 0x4E6F76)
03269 tp->tm_mon = 10;
03270 else if (three_char_mon == 0x4F6374)
03271 tp->tm_mon = 9;
03272 else if (three_char_mon == 0x536570)
03273 tp->tm_mon = 8;
03274 }
03275 }
03276 if (tp->tm_mon < 0) {
03277 tp->tm_mon = month_names_dfa->match(buf, length);
03278 if (tp->tm_mon < 0)
03279 return 0;
03280 }
03281
03282
03283
03284 tp->tm_year = ((buf[12] - '0') * 1000 + (buf[13] - '0') * 100 + (buf[14] - '0') * 10 + (buf[15] - '0')) - 1900;
03285
03286
03287
03288
03289 tp->tm_hour = (buf[17] - '0') * 10 + (buf[18] - '0');
03290 tp->tm_min = (buf[20] - '0') * 10 + (buf[21] - '0');
03291 tp->tm_sec = (buf[23] - '0') * 10 + (buf[24] - '0');
03292 if ((buf[19] != ':') || (buf[22] != ':'))
03293 return 0;
03294 return 1;
03295 }
03296
03297
03298
03299
03300
03301
03302
03303 time_t
03304 mime_parse_date(const char *buf, const char *end)
03305 {
03306 static const int DAYS_OFFSET = 25508;
03307 static const int days[12] = {
03308 305, 336, -1, 30, 60, 91, 121, 152, 183, 213, 244, 274
03309 };
03310
03311 struct tm tp;
03312 time_t t;
03313 int year;
03314 int month;
03315 int mday;
03316
03317 if (!buf)
03318 return (time_t)0;
03319
03320 while ((buf != end) && is_ws(*buf))
03321 buf += 1;
03322
03323 if ((buf != end) && is_digit(*buf)) {
03324 if (!mime_parse_mday(buf, end, &tp.tm_mday)) {
03325 return (time_t)0;
03326 }
03327 if (!mime_parse_month(buf, end, &tp.tm_mon)) {
03328 return (time_t)0;
03329 }
03330 if (!mime_parse_year(buf, end, &tp.tm_year)) {
03331 return (time_t)0;
03332 }
03333 if (!mime_parse_time(buf, end, &tp.tm_hour, &tp.tm_min, &tp.tm_sec)) {
03334 return (time_t)0;
03335 }
03336 } else if (end && (end - buf >= 29) && (buf[3] == ',')) {
03337 if (!mime_parse_rfc822_date_fastcase(buf, end - buf, &tp))
03338 return (time_t)0;
03339 } else {
03340 if (!mime_parse_day(buf, end, &tp.tm_wday)) {
03341 return (time_t)0;
03342 }
03343
03344 while ((buf != end) && is_ws(*buf)) {
03345 buf += 1;
03346 }
03347
03348 if ((buf != end) && ((*buf == ',') || is_digit(*buf))) {
03349
03350 if (!mime_parse_mday(buf, end, &tp.tm_mday)) {
03351 return (time_t)0;
03352 }
03353 if (!mime_parse_month(buf, end, &tp.tm_mon)) {
03354 return (time_t)0;
03355 }
03356 if (!mime_parse_year(buf, end, &tp.tm_year)) {
03357 return (time_t)0;
03358 }
03359 if (!mime_parse_time(buf, end, &tp.tm_hour, &tp.tm_min, &tp.tm_sec)) {
03360 return (time_t)0;
03361 }
03362
03363 } else {
03364
03365 if (!mime_parse_month(buf, end, &tp.tm_mon)) {
03366 return (time_t)0;
03367 }
03368 if (!mime_parse_mday(buf, end, &tp.tm_mday)) {
03369 return (time_t)0;
03370 }
03371 if (!mime_parse_time(buf, end, &tp.tm_hour, &tp.tm_min, &tp.tm_sec)) {
03372 return (time_t)0;
03373 }
03374 if (!mime_parse_year(buf, end, &tp.tm_year)) {
03375 return (time_t)0;
03376 }
03377 }
03378 }
03379
03380 year = tp.tm_year;
03381 month = tp.tm_mon;
03382 mday = tp.tm_mday;
03383
03384
03385 if (year > 137) {
03386 return (time_t)INT_MAX;
03387 }
03388 if (year < 70) {
03389 return (time_t)0;
03390 }
03391
03392 mday += days[month];
03393
03394 if (month < 2) {
03395 year -= 1;
03396 }
03397 mday += (year * 365) + (year / 4) - (year / 100) + (year / 100 + 3) / 4;
03398 mday -= DAYS_OFFSET;
03399
03400 t = ((mday * 24 + tp.tm_hour) * 60 + tp.tm_min) * 60 + tp.tm_sec;
03401
03402 return t;
03403 }
03404
03405 int
03406 mime_parse_day(const char *&buf, const char *end, int *day)
03407 {
03408 const char *e;
03409
03410 while ((buf != end) && *buf && !ParseRules::is_alpha(*buf)) {
03411 buf += 1;
03412 }
03413
03414 e = buf;
03415 while ((e != end) && *e && ParseRules::is_alpha(*e)) {
03416 e += 1;
03417 }
03418
03419 *day = day_names_dfa->match(buf, e - buf);
03420 if (*day < 0) {
03421 return 0;
03422 } else {
03423 buf = e;
03424 return 1;
03425 }
03426 }
03427
03428 int
03429 mime_parse_month(const char *&buf, const char *end, int *month)
03430 {
03431 const char *e;
03432
03433 while ((buf != end) && *buf && !ParseRules::is_alpha(*buf)) {
03434 buf += 1;
03435 }
03436
03437 e = buf;
03438 while ((e != end) && *e && ParseRules::is_alpha(*e)) {
03439 e += 1;
03440 }
03441
03442 *month = month_names_dfa->match(buf, e - buf);
03443 if (*month < 0) {
03444 return 0;
03445 } else {
03446 buf = e;
03447 return 1;
03448 }
03449 }
03450
03451 int
03452 mime_parse_mday(const char *&buf, const char *end, int *mday)
03453 {
03454 return mime_parse_integer(buf, end, mday);
03455 }
03456
03457 int
03458 mime_parse_year(const char *&buf, const char *end, int *year)
03459 {
03460 int val;
03461
03462 while ((buf != end) && *buf && !is_digit(*buf)) {
03463 buf += 1;
03464 }
03465
03466 if ((buf == end) || (*buf == '\0')) {
03467 return 0;
03468 }
03469
03470 val = 0;
03471
03472 while ((buf != end) && *buf && is_digit(*buf)) {
03473 val = (val * 10) + (*buf++ - '0');
03474 }
03475
03476 if (val >= 1900) {
03477 val -= 1900;
03478 } else if (val < 70) {
03479 val += 100;
03480 }
03481
03482 *year = val;
03483
03484 return 1;
03485 }
03486
03487 int
03488 mime_parse_time(const char *&buf, const char *end, int *hour, int *min, int *sec)
03489 {
03490 if (!mime_parse_integer(buf, end, hour)) {
03491 return 0;
03492 }
03493 if (!mime_parse_integer(buf, end, min)) {
03494 return 0;
03495 }
03496 if (!mime_parse_integer(buf, end, sec)) {
03497 return 0;
03498 }
03499 return 1;
03500 }
03501
03502
03503
03504 int
03505 mime_parse_integer(const char *&buf, const char *end, int *integer)
03506 {
03507 int val;
03508 bool negative;
03509
03510 negative = false;
03511
03512 while ((buf != end) && *buf && !is_digit(*buf) && (*buf != '-')) {
03513 buf += 1;
03514 }
03515
03516 if ((buf == end) || (*buf == '\0')) {
03517 return 0;
03518 }
03519
03520 if (*buf == '-') {
03521 negative = true;
03522 buf += 1;
03523 }
03524
03525 val = 0;
03526 while ((buf != end) && is_digit(*buf)) {
03527 val = (val * 10) + (*buf++ - '0');
03528 }
03529
03530 if (negative) {
03531 *integer = -val;
03532 } else {
03533 *integer = val;
03534 }
03535
03536 return 1;
03537 }
03538
03539
03540
03541
03542
03543
03544
03545 int
03546 MIMEFieldBlockImpl::marshal(MarshalXlate *ptr_xlate, int num_ptr, MarshalXlate *str_xlate, int num_str)
03547 {
03548
03549 HDR_MARSHAL_PTR(m_next, MIMEFieldBlockImpl, ptr_xlate, num_ptr);
03550
03551 if ((num_str == 1) && (num_ptr == 1)) {
03552 for (uint32_t index = 0; index < m_freetop; index++) {
03553 MIMEField *field = &(m_field_slots[index]);
03554
03555 if (field->is_live()) {
03556 HDR_MARSHAL_STR_1(field->m_ptr_name, str_xlate);
03557 HDR_MARSHAL_STR_1(field->m_ptr_value, str_xlate);
03558 if (field->m_next_dup) {
03559 HDR_MARSHAL_PTR_1(field->m_next_dup, MIMEField, ptr_xlate);
03560 }
03561 }
03562 }
03563 } else {
03564 for (uint32_t index = 0; index < m_freetop; index++) {
03565 MIMEField *field = &(m_field_slots[index]);
03566
03567 if (field->is_live()) {
03568 HDR_MARSHAL_STR(field->m_ptr_name, str_xlate, num_str);
03569 HDR_MARSHAL_STR(field->m_ptr_value, str_xlate, num_str);
03570 if (field->m_next_dup) {
03571 HDR_MARSHAL_PTR(field->m_next_dup, MIMEField, ptr_xlate, num_ptr);
03572 }
03573 }
03574 }
03575 }
03576 return 0;
03577 }
03578
03579 void
03580 MIMEFieldBlockImpl::unmarshal(intptr_t offset)
03581 {
03582 HDR_UNMARSHAL_PTR(m_next, MIMEFieldBlockImpl, offset);
03583
03584
03585 for (uint32_t index = 0; index < m_freetop; index++) {
03586 MIMEField *field = &(m_field_slots[index]);
03587
03588
03589 if (field->is_live()) {
03590 HDR_UNMARSHAL_STR(field->m_ptr_name, offset);
03591 HDR_UNMARSHAL_STR(field->m_ptr_value, offset);
03592 if (field->m_next_dup) {
03593 HDR_UNMARSHAL_PTR(field->m_next_dup, MIMEField, offset);
03594 }
03595 }
03596
03597 }
03598 }
03599
03600 void
03601 MIMEFieldBlockImpl::move_strings(HdrStrHeap *new_heap)
03602 {
03603 for (uint32_t index = 0; index < m_freetop; index++) {
03604 MIMEField *field = &(m_field_slots[index]);
03605
03606 if (field->is_live() || field->is_detached()) {
03607
03608
03609 field->m_n_v_raw_printable = 0;
03610
03611 HDR_MOVE_STR(field->m_ptr_name, field->m_len_name);
03612 HDR_MOVE_STR(field->m_ptr_value, field->m_len_value);
03613 }
03614 }
03615 }
03616
03617 size_t
03618 MIMEFieldBlockImpl::strings_length()
03619 {
03620 size_t ret = 0;
03621
03622 for (uint32_t index = 0; index < m_freetop; index++) {
03623 MIMEField *field = &(m_field_slots[index]);
03624
03625 if (field->m_readiness == MIME_FIELD_SLOT_READINESS_LIVE ||
03626 field->m_readiness == MIME_FIELD_SLOT_READINESS_DETACHED) {
03627 ret += field->m_len_name;
03628 ret += field->m_len_value;
03629 }
03630 }
03631 return ret;
03632 }
03633
03634 void
03635 MIMEFieldBlockImpl::check_strings(HeapCheck *heaps, int num_heaps)
03636 {
03637 for (uint32_t index = 0; index < m_freetop; index++) {
03638 MIMEField *field = &(m_field_slots[index]);
03639
03640 if (field->is_live() || field->is_detached()) {
03641
03642 CHECK_STR(field->m_ptr_name, field->m_len_name, heaps, num_heaps);
03643 CHECK_STR(field->m_ptr_value, field->m_len_value, heaps, num_heaps);
03644 }
03645 }
03646 }
03647
03648 int
03649 MIMEHdrImpl::marshal(MarshalXlate *ptr_xlate, int num_ptr, MarshalXlate *str_xlate, int num_str)
03650 {
03651
03652 HDR_MARSHAL_PTR(m_fblock_list_tail, MIMEFieldBlockImpl, ptr_xlate, num_ptr);
03653 return m_first_fblock.marshal(ptr_xlate, num_ptr, str_xlate, num_str);
03654 }
03655
03656 void
03657 MIMEHdrImpl::unmarshal(intptr_t offset)
03658 {
03659 HDR_UNMARSHAL_PTR(m_fblock_list_tail, MIMEFieldBlockImpl, offset);
03660 m_first_fblock.unmarshal(offset);
03661 }
03662
03663 void
03664 MIMEHdrImpl::move_strings(HdrStrHeap *new_heap)
03665 {
03666 m_first_fblock.move_strings(new_heap);
03667 }
03668
03669 size_t
03670 MIMEHdrImpl::strings_length()
03671 {
03672 return m_first_fblock.strings_length();
03673 }
03674
03675 void
03676 MIMEHdrImpl::check_strings(HeapCheck *heaps, int num_heaps)
03677 {
03678 m_first_fblock.check_strings(heaps, num_heaps);
03679 }
03680
03681 void
03682 MIMEHdrImpl::recompute_accelerators_and_presence_bits() {
03683 mime_hdr_reset_accelerators_and_presence_bits(this);
03684 }
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702 void
03703 MIMEHdrImpl::recompute_cooked_stuff(MIMEField *changing_field_or_null)
03704 {
03705 int len, tlen;
03706 const char *s;
03707 const char *c;
03708 const char *e;
03709 const char *token_wks;
03710 MIMEField *field;
03711 uint32_t mask = 0;
03712
03713 mime_hdr_cooked_stuff_init(this, changing_field_or_null);
03714
03715
03716
03717
03718
03719
03720 if ((changing_field_or_null == NULL) || (changing_field_or_null->m_wks_idx != MIME_WKSIDX_PRAGMA)) {
03721
03722 field = mime_hdr_field_find(this, MIME_FIELD_CACHE_CONTROL, MIME_LEN_CACHE_CONTROL);
03723
03724 if (field) {
03725
03726
03727 if (!field->has_dups()) {
03728 s = field->value_get(&len);
03729 if (ptr_len_casecmp(s, len, "public", 6) == 0) {
03730 mask = MIME_COOKED_MASK_CC_PUBLIC;
03731 m_cooked_stuff.m_cache_control.m_mask |= mask;
03732 } else if (ptr_len_casecmp(s, len, "private,no-cache", 16) == 0) {
03733 mask = MIME_COOKED_MASK_CC_PRIVATE | MIME_COOKED_MASK_CC_NO_CACHE;
03734 m_cooked_stuff.m_cache_control.m_mask |= mask;
03735 }
03736 }
03737
03738 if (mask == 0) {
03739 HdrCsvIter csv_iter;
03740
03741 for (s = csv_iter.get_first(field, &len); s != NULL; s = csv_iter.get_next(&len)) {
03742 e = s + len;
03743 for (c = s; (c < e) && (ParseRules::is_token(*c)); c++);
03744 tlen = c - s;
03745
03746
03747 if (hdrtoken_tokenize(s, tlen, &token_wks) >= 0) {
03748 #if TRACK_COOKING
03749 Debug("http", "recompute_cooked_stuff: got field '%s'\n", token_wks);
03750 #endif
03751
03752 HdrTokenHeapPrefix *p = hdrtoken_wks_to_prefix(token_wks);
03753 mask = p->wks_type_specific.u.cache_control.cc_mask;
03754 m_cooked_stuff.m_cache_control.m_mask |= mask;
03755
03756 #if TRACK_COOKING
03757 Debug("http", " set mask 0x%0X\n", mask);
03758 #endif
03759
03760 if (mask & (MIME_COOKED_MASK_CC_MAX_AGE |
03761 MIME_COOKED_MASK_CC_S_MAXAGE | MIME_COOKED_MASK_CC_MAX_STALE | MIME_COOKED_MASK_CC_MIN_FRESH)) {
03762 int value;
03763
03764 if (mime_parse_integer(c, e, &value)) {
03765 #if TRACK_COOKING
03766 Debug("http", " set integer value %d\n", value);
03767 #endif
03768 if (token_wks == MIME_VALUE_MAX_AGE)
03769 m_cooked_stuff.m_cache_control.m_secs_max_age = value;
03770 else if (token_wks == MIME_VALUE_MIN_FRESH)
03771 m_cooked_stuff.m_cache_control.m_secs_min_fresh = value;
03772 else if (token_wks == MIME_VALUE_MAX_STALE)
03773 m_cooked_stuff.m_cache_control.m_secs_max_stale = value;
03774 else if (token_wks == MIME_VALUE_S_MAXAGE)
03775 m_cooked_stuff.m_cache_control.m_secs_s_maxage = value;
03776 } else {
03777 #if TRACK_COOKING
03778 Debug("http", " set integer value %d\n", INT_MAX);
03779 #endif
03780 if (token_wks == MIME_VALUE_MAX_STALE)
03781 m_cooked_stuff.m_cache_control.m_secs_max_stale = INT_MAX;
03782 }
03783 }
03784 }
03785 }
03786 }
03787 }
03788 }
03789
03790
03791
03792
03793 if ((changing_field_or_null == NULL) || (changing_field_or_null->m_wks_idx != MIME_WKSIDX_CACHE_CONTROL)) {
03794
03795 field = mime_hdr_field_find(this, MIME_FIELD_PRAGMA, MIME_LEN_PRAGMA);
03796 if (field) {
03797 if (!field->has_dups()) {
03798 s = field->value_get(&len);
03799 if (ptr_len_casecmp(s, len, "no-cache", 8) == 0) {
03800 m_cooked_stuff.m_pragma.m_no_cache = 1;
03801 return;
03802 }
03803 }
03804
03805 {
03806 HdrCsvIter csv_iter;
03807
03808 for (s = csv_iter.get_first(field, &len); s != NULL; s = csv_iter.get_next(&len)) {
03809 e = s + len;
03810 for (c = s; (c < e) && (ParseRules::is_token(*c)); c++);
03811 tlen = c - s;
03812
03813 if (hdrtoken_tokenize(s, tlen, &token_wks) >= 0) {
03814 if (token_wks == MIME_VALUE_NO_CACHE)
03815 m_cooked_stuff.m_pragma.m_no_cache = 1;
03816 }
03817 }
03818 }
03819 }
03820 }
03821 }