Coverage Report

Created: 2026-04-11 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/trafficserver/include/proxy/hdrs/MIME.h
Line
Count
Source
1
/** @file
2
3
  A brief file description
4
5
  @section license License
6
7
  Licensed to the Apache Software Foundation (ASF) under one
8
  or more contributor license agreements.  See the NOTICE file
9
  distributed with this work for additional information
10
  regarding copyright ownership.  The ASF licenses this file
11
  to you under the Apache License, Version 2.0 (the
12
  "License"); you may not use this file except in compliance
13
  with the License.  You may obtain a copy of the License at
14
15
      http://www.apache.org/licenses/LICENSE-2.0
16
17
  Unless required by applicable law or agreed to in writing, software
18
  distributed under the License is distributed on an "AS IS" BASIS,
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
  See the License for the specific language governing permissions and
21
  limitations under the License.
22
 */
23
24
#pragma once
25
26
#include <sys/time.h>
27
#include <string_view>
28
#include <string>
29
30
using namespace std::literals;
31
32
#include "tscore/ink_assert.h"
33
#include "tscore/ink_apidefs.h"
34
#include "tscore/ink_string++.h"
35
#include "tscore/ParseRules.h"
36
#include "proxy/hdrs/HdrHeap.h"
37
#include "proxy/hdrs/HdrToken.h"
38
39
#include "swoc/TextView.h"
40
41
/***********************************************************************
42
 *                                                                     *
43
 *                              Defines                                *
44
 *                                                                     *
45
 ***********************************************************************/
46
47
enum class ParseResult {
48
  ERROR = -1,
49
  DONE  = 0,
50
  CONT  = 1,
51
  OK    = 3, // This is only used internally in mime_parser_parse and not returned to the user
52
};
53
54
enum {
55
  UNDEFINED_COUNT = -1,
56
};
57
58
/// Parsing state.
59
enum class MimeParseState {
60
  BEFORE,   ///< Before a field.
61
  FOUND_CR, ///< Before a field, found a CR.
62
  INSIDE,   ///< Inside a field.
63
  AFTER,    ///< After a field.
64
};
65
66
/***********************************************************************
67
 *                                                                     *
68
 *                              Assertions                             *
69
 *                                                                     *
70
 ***********************************************************************/
71
72
#ifdef ENABLE_MIME_SANITY_CHECK
73
#define MIME_HDR_SANITY_CHECK mime_hdr_sanity_check
74
#else
75
126k
#define MIME_HDR_SANITY_CHECK (void)
76
#endif
77
78
0
#define MIME_FIELD_SLOT_READINESS_EMPTY    0
79
104k
#define MIME_FIELD_SLOT_READINESS_DETACHED 1
80
401k
#define MIME_FIELD_SLOT_READINESS_LIVE     2
81
5.69k
#define MIME_FIELD_SLOT_READINESS_DELETED  3
82
83
68.4k
#define MIME_FIELD_SLOT_FLAGS_DUP_HEAD (1 << 0)
84
22.4k
#define MIME_FIELD_SLOT_FLAGS_COOKED   (1 << 1)
85
86
255k
#define MIME_FIELD_BLOCK_SLOTS 16
87
88
8.46k
#define MIME_FIELD_SLOTNUM_BITS    4
89
8.46k
#define MIME_FIELD_SLOTNUM_MASK    ((1 << MIME_FIELD_SLOTNUM_BITS) - 1)
90
6.31k
#define MIME_FIELD_SLOTNUM_MAX     (MIME_FIELD_SLOTNUM_MASK - 1)
91
6.20k
#define MIME_FIELD_SLOTNUM_UNKNOWN MIME_FIELD_SLOTNUM_MAX
92
93
/***********************************************************************
94
 *                                                                     *
95
 *                    MIMEField & MIMEFieldBlockImpl                   *
96
 *                                                                     *
97
 ***********************************************************************/
98
99
struct MIMEHdrImpl;
100
101
struct MIMEField {
102
  const char *m_ptr_name;                   // 4
103
  const char *m_ptr_value;                  // 4
104
  MIMEField  *m_next_dup;                   // 4
105
  int16_t     m_wks_idx;                    // 2
106
  uint16_t    m_len_name;                   // 2
107
  uint32_t    m_len_value             : 24; // 3
108
  uint8_t     m_n_v_raw_printable     : 1;  // 1/8
109
  uint8_t     m_n_v_raw_printable_pad : 3;  // 3/8
110
  uint8_t     m_readiness             : 2;  // 2/8
111
  uint8_t     m_flags                 : 2;  // 2/8
112
113
  bool
114
  is_dup_head() const
115
15.3k
  {
116
15.3k
    return (m_flags & MIME_FIELD_SLOT_FLAGS_DUP_HEAD);
117
15.3k
  }
118
119
  bool
120
  is_cooked() const
121
21.0k
  {
122
21.0k
    return (m_flags & MIME_FIELD_SLOT_FLAGS_COOKED) ? true : false;
123
21.0k
  }
124
125
  bool
126
  is_live() const
127
350k
  {
128
350k
    return (m_readiness == MIME_FIELD_SLOT_READINESS_LIVE);
129
350k
  }
130
131
  bool
132
  is_detached() const
133
52.2k
  {
134
52.2k
    return (m_readiness == MIME_FIELD_SLOT_READINESS_DETACHED);
135
52.2k
  }
136
137
  bool
138
  supports_commas() const
139
0
  {
140
0
    if (m_wks_idx >= 0) {
141
0
      return (hdrtoken_index_to_flags(m_wks_idx) & HdrTokenInfoFlags::COMMAS) != HdrTokenInfoFlags::NONE;
142
0
    }
143
0
    return true; // by default, assume supports commas
144
0
  }
145
146
  /// @return The name of @a this field.
147
  std::string_view name_get() const;
148
149
  /** Find the index of the value in the multi-value field.
150
151
     If @a value is one of the values in this field return the
152
     0 based index of it in the list of values. If the field is
153
     not multivalued the index will always be zero if found.
154
     Otherwise return -1 if the @a value is not found.
155
156
     @note The most common use of this is to check for the presence of a specific
157
     value in a comma enabled field.
158
159
     @return The index of @a value.
160
  */
161
  int value_get_index(std::string_view value) const;
162
163
  /// @return The value of @a this field.
164
  std::string_view value_get() const;
165
166
  int32_t  value_get_int() const;
167
  uint32_t value_get_uint() const;
168
  int64_t  value_get_int64() const;
169
  time_t   value_get_date() const;
170
  int      value_get_comma_list(StrList *list) const;
171
172
  void name_set(HdrHeap *heap, MIMEHdrImpl *mh, std::string_view name);
173
  bool name_is_valid(uint32_t invalid_char_bits = is_control_BIT) const;
174
175
  void value_set(HdrHeap *heap, MIMEHdrImpl *mh, std::string_view value);
176
  void value_set_int(HdrHeap *heap, MIMEHdrImpl *mh, int32_t value);
177
  void value_set_uint(HdrHeap *heap, MIMEHdrImpl *mh, uint32_t value);
178
  void value_set_int64(HdrHeap *heap, MIMEHdrImpl *mh, int64_t value);
179
  void value_set_date(HdrHeap *heap, MIMEHdrImpl *mh, time_t value);
180
  void value_clear(HdrHeap *heap, MIMEHdrImpl *mh);
181
  // MIME standard separator ',' is used as the default value
182
  // Other separators (e.g. ';' in Set-cookie/Cookie) are also possible
183
  void value_append(HdrHeap *heap, MIMEHdrImpl *mh, std::string_view value, bool prepend_comma = false, const char separator = ',');
184
  bool value_is_valid(uint32_t invalid_char_bits = is_control_BIT) const;
185
  int  has_dups() const;
186
};
187
188
struct MIMEFieldBlockImpl : public HdrHeapObjImpl {
189
  // HdrHeapObjImpl is 4 bytes
190
  uint32_t            m_freetop;
191
  MIMEFieldBlockImpl *m_next;
192
  MIMEField           m_field_slots[MIME_FIELD_BLOCK_SLOTS];
193
  // mime_hdr_copy_onto assumes that m_field_slots is last --
194
  // don't add any new fields after it.
195
196
  // Marshaling Functions
197
  int    marshal(MarshalXlate *ptr_xlate, int num_ptr, MarshalXlate *str_xlate, int num_str);
198
  void   unmarshal(intptr_t offset);
199
  void   move_strings(HdrStrHeap *new_heap);
200
  size_t strings_length();
201
  bool   contains(const MIMEField *field);
202
203
  // Sanity Check Functions
204
  void check_strings(HeapCheck *heaps, int num_heaps);
205
};
206
207
/***********************************************************************
208
 *                                                                     *
209
 *                              MIMECooked                             *
210
 *                                                                     *
211
 ***********************************************************************/
212
213
enum MIMECookedMask {
214
  MIME_COOKED_MASK_CC_MAX_AGE              = (1 << 0),
215
  MIME_COOKED_MASK_CC_NO_CACHE             = (1 << 1),
216
  MIME_COOKED_MASK_CC_NO_STORE             = (1 << 2),
217
  MIME_COOKED_MASK_CC_NO_TRANSFORM         = (1 << 3),
218
  MIME_COOKED_MASK_CC_MAX_STALE            = (1 << 4),
219
  MIME_COOKED_MASK_CC_MIN_FRESH            = (1 << 5),
220
  MIME_COOKED_MASK_CC_ONLY_IF_CACHED       = (1 << 6),
221
  MIME_COOKED_MASK_CC_PUBLIC               = (1 << 7),
222
  MIME_COOKED_MASK_CC_PRIVATE              = (1 << 8),
223
  MIME_COOKED_MASK_CC_MUST_REVALIDATE      = (1 << 9),
224
  MIME_COOKED_MASK_CC_PROXY_REVALIDATE     = (1 << 10),
225
  MIME_COOKED_MASK_CC_S_MAXAGE             = (1 << 11),
226
  MIME_COOKED_MASK_CC_NEED_REVALIDATE_ONCE = (1 << 12),
227
  MIME_COOKED_MASK_CC_EXTENSION            = (1 << 13)
228
};
229
230
struct MIMECookedCacheControl {
231
  uint32_t m_mask;
232
  int32_t  m_secs_max_age;
233
  int32_t  m_secs_s_maxage;
234
  int32_t  m_secs_max_stale;
235
  int32_t  m_secs_min_fresh;
236
};
237
238
struct MIMECookedPragma {
239
  bool m_no_cache;
240
};
241
242
struct MIMECooked {
243
  MIMECookedCacheControl m_cache_control;
244
  MIMECookedPragma       m_pragma;
245
};
246
247
/***********************************************************************
248
 *                                                                     *
249
 *                                MIMEHdr                              *
250
 *                                                                     *
251
 ***********************************************************************/
252
253
struct MIMEHdrImpl : public HdrHeapObjImpl {
254
  /** Iterator over fields in the header.
255
   * This iterator should be stable over field deletes, but not insertions.
256
   */
257
  class iterator
258
  {
259
    using self_type = iterator; ///< Self reference types.
260
261
  public:
262
0
    iterator() = default;
263
264
    // STL iterator compliance types.
265
    using difference_type   = void;
266
    using value_type        = MIMEField;
267
    using pointer           = value_type *;
268
    using reference         = value_type &;
269
    using iterator_category = std::forward_iterator_tag;
270
271
    pointer   operator->();
272
    reference operator*();
273
274
    self_type &operator++();
275
    self_type  operator++(int);
276
277
    bool operator==(self_type const &that) const;
278
    bool operator!=(self_type const &that) const;
279
280
  protected:
281
    MIMEFieldBlockImpl *_block = nullptr; ///< Current block.
282
    unsigned            _slot  = 0;       ///< Slot in @a _block
283
284
    /** Internal constructor.
285
     *
286
     * @param block Block containing current field.
287
     * @param slot Index of current field.
288
     */
289
0
    iterator(MIMEFieldBlockImpl *block, unsigned slot) : _block(block), _slot(slot) { this->step(); }
290
291
    /** Move to a valid (live) slot.
292
     *
293
     * This enforces the invariant that the iterator is exactly one of
294
     * 1. referencing a valid slot
295
     * 2. equal to the @c end iterator
296
     *
297
     * Therefore if called when the iterator is in state (1) the iterator is unchanged.
298
     *
299
     * @return @a this
300
     */
301
    self_type &step();
302
303
    friend class MIMEHdr;
304
    friend struct MIMEHdrImpl;
305
  };
306
307
  // HdrHeapObjImpl is 4 bytes, so this will result in 4 bytes padding
308
  uint64_t m_presence_bits;
309
  uint32_t m_slot_accelerators[4];
310
311
  MIMECooked m_cooked_stuff;
312
313
  MIMEFieldBlockImpl *m_fblock_list_tail;
314
  MIMEFieldBlockImpl  m_first_fblock; // 1 block inline
315
  // mime_hdr_copy_onto assumes that m_first_fblock is last --
316
  // don't add any new fields after it.
317
318
  // Marshaling Functions
319
  int    marshal(MarshalXlate *ptr_xlate, int num_ptr, MarshalXlate *str_xlate, int num_str);
320
  void   unmarshal(intptr_t offset);
321
  void   move_strings(HdrStrHeap *new_heap);
322
  size_t strings_length();
323
324
  // Sanity Check Functions
325
  void check_strings(HeapCheck *heaps, int num_heaps);
326
327
  // Cooked values
328
  void recompute_cooked_stuff(MIMEField *changing_field_or_null = nullptr, const std::string_view *targeted_headers = nullptr,
329
                              size_t targeted_headers_count = 0);
330
  void recompute_accelerators_and_presence_bits();
331
332
  // Utility
333
  /// Iterator for first field.
334
  iterator begin();
335
  /// Iterator past last field.
336
  iterator end();
337
338
  /** Find a field by address.
339
   *
340
   * @param field Target to find.
341
   * @return An iterator referencing @a field if it is in the header, an empty iterator
342
   * if not.
343
   */
344
  iterator find(MIMEField const *field);
345
};
346
347
inline auto
348
MIMEHdrImpl::begin() -> iterator
349
0
{
350
0
  return iterator(&m_first_fblock, 0);
351
0
}
352
353
inline auto
354
MIMEHdrImpl::end() -> iterator
355
0
{
356
0
  return {}; // default constructed iterator.
357
0
}
358
359
inline auto
360
MIMEHdrImpl::iterator::step() -> self_type &
361
0
{
362
0
  while (_block) {
363
0
    for (auto limit = _block->m_freetop; _slot < limit; ++_slot) {
364
0
      if (_block->m_field_slots[_slot].is_live()) {
365
0
        return *this;
366
0
      }
367
0
    }
368
0
    _block = _block->m_next;
369
0
    _slot  = 0;
370
0
  }
371
0
  return *this;
372
0
}
373
374
inline auto
375
MIMEHdrImpl::iterator::operator*() -> reference
376
0
{
377
0
  return _block->m_field_slots[_slot];
378
0
}
379
380
inline auto
381
MIMEHdrImpl::iterator::operator->() -> pointer
382
0
{
383
0
  return &(_block->m_field_slots[_slot]);
384
0
}
385
386
inline bool
387
MIMEHdrImpl::iterator::operator==(const self_type &that) const
388
0
{
389
0
  return _block == that._block && _slot == that._slot;
390
0
}
391
392
inline bool
393
MIMEHdrImpl::iterator::operator!=(const self_type &that) const
394
0
{
395
0
  return _block != that._block || _slot != that._slot;
396
0
}
397
398
inline auto
399
MIMEHdrImpl::iterator::operator++() -> self_type &
400
0
{
401
0
  if (_block) {
402
0
    ++_slot;
403
0
    this->step();
404
0
  }
405
0
  return *this;
406
0
}
407
408
inline auto
409
MIMEHdrImpl::iterator::operator++(int) -> self_type
410
0
{
411
0
  self_type zret{*this};
412
0
  ++*this;
413
0
  return zret;
414
0
}
415
416
/***********************************************************************
417
 *                                                                     *
418
 *                                Parser                               *
419
 *                                                                     *
420
 ***********************************************************************/
421
422
/** A pre-parser used to extract MIME "lines" from raw input for further parsing.
423
 *
424
 * This maintains an internal line buffer which is used to keeping content between calls
425
 * when the parse has not yet completed.
426
 *
427
 */
428
struct MIMEScanner {
429
  using self_type = MIMEScanner; ///< Self reference type.
430
public:
431
  /// Type of input scanning.
432
  enum class ScanType {
433
    LINE  = 0, ///< Scan a single line.
434
    FIELD = 1, ///< Scan with line folding enabled.
435
  };
436
437
  void init();  ///< Pseudo-constructor required by proxy allocation.
438
  void clear(); ///< Pseudo-destructor required by proxy allocation.
439
440
  /// @return The size of the internal line buffer.
441
  size_t get_buffered_line_size() const;
442
443
  /** Scan @a input for MIME data delimited by CR/LF end of line markers.
444
   *
445
   * @param input [in,out] Text to scan.
446
   * @param output [out] Parsed text from @a input, if any.
447
   * @param output_shares_input [out] Whether @a output is in @a input.
448
   * @param eof_p [in] The source for @a input is done, no more data will ever be available.
449
   * @param scan_type [in] Whether to check for line folding.
450
   * @return The result of scanning.
451
   *
452
   * @a input is updated to remove text that was scanned. @a output is updated to be a view of the
453
   * scanned @a input. This is separate because @a output may be a view of @a input or a view of the
454
   * internal line buffer. Which of these cases obtains is returned in @a output_shares_input. This
455
   * is @c true if @a output is a view of @a input, and @c false if @a output is a view of the
456
   * internal buffer, but is only set if the result is not @c ParseResult::CONT (that is, it is not
457
   * set until scanning has completed). If @a scan_type is @c FIELD then folded lines are
458
   * accumulated in to a single line stored in the internal buffer. Otherwise the scanning
459
   * terminates at the first CR/LF.
460
   */
461
  ParseResult get(swoc::TextView &input, swoc::TextView &output, bool &output_shares_input, bool eof_p, ScanType scan_type);
462
463
protected:
464
  /** Append @a text to the internal buffer.
465
   *
466
   * @param text Text to append.
467
   * @return @a this
468
   *
469
   * A copy of @a text is appended to the internal line buffer.
470
   */
471
  self_type &append(swoc::TextView text);
472
473
  static constexpr MimeParseState INITIAL_PARSE_STATE = MimeParseState::BEFORE;
474
  std::string                     m_line;                       ///< Internally buffered line data for field coalescence.
475
  MimeParseState                  m_state{INITIAL_PARSE_STATE}; ///< Parsing machine state.
476
};
477
478
inline size_t
479
MIMEScanner::get_buffered_line_size() const
480
18.7k
{
481
18.7k
  return m_line.size();
482
18.7k
}
483
484
inline void
485
MIMEScanner::clear()
486
18.7k
{
487
18.7k
  std::string empty;        // GAH! @c swap isn't defined to take r-value reference!
488
18.7k
  std::swap(m_line, empty); // make sure the memory is released.
489
18.7k
  m_state = INITIAL_PARSE_STATE;
490
18.7k
}
491
492
struct MIMEParser {
493
  MIMEScanner m_scanner;
494
  int32_t     m_field;
495
  int         m_field_flags;
496
  int         m_value;
497
};
498
499
/***********************************************************************
500
 *                                                                     *
501
 *                                SDK                                  *
502
 *                                                                     *
503
 ***********************************************************************/
504
505
/********************************************/
506
/* SDK Handles to Fields are special structures */
507
/********************************************/
508
struct MIMEFieldSDKHandle : public HdrHeapObjImpl {
509
  MIMEHdrImpl *mh;
510
  MIMEField   *field_ptr;
511
};
512
513
/***********************************************************************
514
 *                                                                     *
515
 *                     Well-Known Field Name Tokens                    *
516
 *                                                                     *
517
 ***********************************************************************/
518
519
extern c_str_view MIME_FIELD_ACCEPT;
520
extern c_str_view MIME_FIELD_ACCEPT_CHARSET;
521
extern c_str_view MIME_FIELD_ACCEPT_ENCODING;
522
extern c_str_view MIME_FIELD_ACCEPT_LANGUAGE;
523
extern c_str_view MIME_FIELD_ACCEPT_RANGES;
524
extern c_str_view MIME_FIELD_AGE;
525
extern c_str_view MIME_FIELD_ALLOW;
526
extern c_str_view MIME_FIELD_APPROVED;
527
extern c_str_view MIME_FIELD_AUTHORIZATION;
528
extern c_str_view MIME_FIELD_BYTES;
529
extern c_str_view MIME_FIELD_CACHE_CONTROL;
530
extern c_str_view MIME_FIELD_CLIENT_IP;
531
extern c_str_view MIME_FIELD_CONNECTION;
532
extern c_str_view MIME_FIELD_CONTENT_BASE;
533
extern c_str_view MIME_FIELD_CONTENT_ENCODING;
534
extern c_str_view MIME_FIELD_CONTENT_LANGUAGE;
535
extern c_str_view MIME_FIELD_CONTENT_LENGTH;
536
extern c_str_view MIME_FIELD_CONTENT_LOCATION;
537
extern c_str_view MIME_FIELD_CONTENT_MD5;
538
extern c_str_view MIME_FIELD_CONTENT_RANGE;
539
extern c_str_view MIME_FIELD_CONTENT_TYPE;
540
extern c_str_view MIME_FIELD_CONTROL;
541
extern c_str_view MIME_FIELD_COOKIE;
542
extern c_str_view MIME_FIELD_DATE;
543
extern c_str_view MIME_FIELD_DISTRIBUTION;
544
extern c_str_view MIME_FIELD_ETAG;
545
extern c_str_view MIME_FIELD_EXPECT;
546
extern c_str_view MIME_FIELD_EXPIRES;
547
extern c_str_view MIME_FIELD_FOLLOWUP_TO;
548
extern c_str_view MIME_FIELD_FROM;
549
extern c_str_view MIME_FIELD_HOST;
550
extern c_str_view MIME_FIELD_IF_MATCH;
551
extern c_str_view MIME_FIELD_IF_MODIFIED_SINCE;
552
extern c_str_view MIME_FIELD_IF_NONE_MATCH;
553
extern c_str_view MIME_FIELD_IF_RANGE;
554
extern c_str_view MIME_FIELD_IF_UNMODIFIED_SINCE;
555
extern c_str_view MIME_FIELD_KEEP_ALIVE;
556
extern c_str_view MIME_FIELD_KEYWORDS;
557
extern c_str_view MIME_FIELD_LAST_MODIFIED;
558
extern c_str_view MIME_FIELD_LINES;
559
extern c_str_view MIME_FIELD_LOCATION;
560
extern c_str_view MIME_FIELD_MAX_FORWARDS;
561
extern c_str_view MIME_FIELD_MESSAGE_ID;
562
extern c_str_view MIME_FIELD_NEWSGROUPS;
563
extern c_str_view MIME_FIELD_ORGANIZATION;
564
extern c_str_view MIME_FIELD_PATH;
565
extern c_str_view MIME_FIELD_PRAGMA;
566
extern c_str_view MIME_FIELD_PROXY_AUTHENTICATE;
567
extern c_str_view MIME_FIELD_PROXY_AUTHORIZATION;
568
extern c_str_view MIME_FIELD_PROXY_CONNECTION;
569
extern c_str_view MIME_FIELD_PUBLIC;
570
extern c_str_view MIME_FIELD_RANGE;
571
extern c_str_view MIME_FIELD_REFERENCES;
572
extern c_str_view MIME_FIELD_REFERER;
573
extern c_str_view MIME_FIELD_REPLY_TO;
574
extern c_str_view MIME_FIELD_RETRY_AFTER;
575
extern c_str_view MIME_FIELD_SENDER;
576
extern c_str_view MIME_FIELD_SERVER;
577
extern c_str_view MIME_FIELD_SET_COOKIE;
578
extern c_str_view MIME_FIELD_STRICT_TRANSPORT_SECURITY;
579
extern c_str_view MIME_FIELD_SUBJECT;
580
extern c_str_view MIME_FIELD_SUMMARY;
581
extern c_str_view MIME_FIELD_TE;
582
extern c_str_view MIME_FIELD_TRANSFER_ENCODING;
583
extern c_str_view MIME_FIELD_UPGRADE;
584
extern c_str_view MIME_FIELD_USER_AGENT;
585
extern c_str_view MIME_FIELD_VARY;
586
extern c_str_view MIME_FIELD_VIA;
587
extern c_str_view MIME_FIELD_WARNING;
588
extern c_str_view MIME_FIELD_WWW_AUTHENTICATE;
589
extern c_str_view MIME_FIELD_XREF;
590
extern c_str_view MIME_FIELD_ATS_INTERNAL;
591
extern c_str_view MIME_FIELD_X_ID;
592
extern c_str_view MIME_FIELD_X_FORWARDED_FOR;
593
extern c_str_view MIME_FIELD_FORWARDED;
594
extern c_str_view MIME_FIELD_SEC_WEBSOCKET_KEY;
595
extern c_str_view MIME_FIELD_SEC_WEBSOCKET_VERSION;
596
extern c_str_view MIME_FIELD_HTTP2_SETTINGS;
597
extern c_str_view MIME_FIELD_EARLY_DATA;
598
599
extern c_str_view MIME_VALUE_BYTES;
600
extern c_str_view MIME_VALUE_CHUNKED;
601
extern c_str_view MIME_VALUE_CLOSE;
602
extern c_str_view MIME_VALUE_COMPRESS;
603
extern c_str_view MIME_VALUE_DEFLATE;
604
extern c_str_view MIME_VALUE_GZIP;
605
extern c_str_view MIME_VALUE_BROTLI;
606
extern c_str_view MIME_VALUE_ZSTD;
607
608
extern c_str_view MIME_VALUE_IDENTITY;
609
extern c_str_view MIME_VALUE_KEEP_ALIVE;
610
extern c_str_view MIME_VALUE_MAX_AGE;
611
extern c_str_view MIME_VALUE_MAX_STALE;
612
extern c_str_view MIME_VALUE_MIN_FRESH;
613
extern c_str_view MIME_VALUE_MUST_REVALIDATE;
614
extern c_str_view MIME_VALUE_NONE;
615
extern c_str_view MIME_VALUE_NO_CACHE;
616
extern c_str_view MIME_VALUE_NO_STORE;
617
extern c_str_view MIME_VALUE_NO_TRANSFORM;
618
extern c_str_view MIME_VALUE_ONLY_IF_CACHED;
619
extern c_str_view MIME_VALUE_PRIVATE;
620
extern c_str_view MIME_VALUE_PROXY_REVALIDATE;
621
extern c_str_view MIME_VALUE_PUBLIC;
622
extern c_str_view MIME_VALUE_S_MAXAGE;
623
extern c_str_view MIME_VALUE_NEED_REVALIDATE_ONCE;
624
extern c_str_view MIME_VALUE_WEBSOCKET;
625
extern c_str_view MIME_VALUE_H2C;
626
627
extern int MIME_WKSIDX_ACCEPT;
628
extern int MIME_WKSIDX_ACCEPT_CHARSET;
629
extern int MIME_WKSIDX_ACCEPT_ENCODING;
630
extern int MIME_WKSIDX_ACCEPT_LANGUAGE;
631
extern int MIME_WKSIDX_ACCEPT_RANGES;
632
extern int MIME_WKSIDX_AGE;
633
extern int MIME_WKSIDX_ALLOW;
634
extern int MIME_WKSIDX_APPROVED;
635
extern int MIME_WKSIDX_AUTHORIZATION;
636
extern int MIME_WKSIDX_BYTES;
637
extern int MIME_WKSIDX_CACHE_CONTROL;
638
extern int MIME_WKSIDX_CLIENT_IP;
639
extern int MIME_WKSIDX_CONNECTION;
640
extern int MIME_WKSIDX_CONTENT_BASE;
641
extern int MIME_WKSIDX_CONTENT_ENCODING;
642
extern int MIME_WKSIDX_CONTENT_LANGUAGE;
643
extern int MIME_WKSIDX_CONTENT_LENGTH;
644
extern int MIME_WKSIDX_CONTENT_LOCATION;
645
extern int MIME_WKSIDX_CONTENT_MD5;
646
extern int MIME_WKSIDX_CONTENT_RANGE;
647
extern int MIME_WKSIDX_CONTENT_TYPE;
648
extern int MIME_WKSIDX_CONTROL;
649
extern int MIME_WKSIDX_COOKIE;
650
extern int MIME_WKSIDX_DATE;
651
extern int MIME_WKSIDX_DISTRIBUTION;
652
extern int MIME_WKSIDX_ETAG;
653
extern int MIME_WKSIDX_EXPECT;
654
extern int MIME_WKSIDX_EXPIRES;
655
extern int MIME_WKSIDX_FOLLOWUP_TO;
656
extern int MIME_WKSIDX_FROM;
657
extern int MIME_WKSIDX_HOST;
658
extern int MIME_WKSIDX_IF_MATCH;
659
extern int MIME_WKSIDX_IF_MODIFIED_SINCE;
660
extern int MIME_WKSIDX_IF_NONE_MATCH;
661
extern int MIME_WKSIDX_IF_RANGE;
662
extern int MIME_WKSIDX_IF_UNMODIFIED_SINCE;
663
extern int MIME_WKSIDX_KEEP_ALIVE;
664
extern int MIME_WKSIDX_KEYWORDS;
665
extern int MIME_WKSIDX_LAST_MODIFIED;
666
extern int MIME_WKSIDX_LINES;
667
extern int MIME_WKSIDX_LOCATION;
668
extern int MIME_WKSIDX_MAX_FORWARDS;
669
extern int MIME_WKSIDX_MESSAGE_ID;
670
extern int MIME_WKSIDX_NEWSGROUPS;
671
extern int MIME_WKSIDX_ORGANIZATION;
672
extern int MIME_WKSIDX_PATH;
673
extern int MIME_WKSIDX_PRAGMA;
674
extern int MIME_WKSIDX_PROXY_AUTHENTICATE;
675
extern int MIME_WKSIDX_PROXY_AUTHORIZATION;
676
extern int MIME_WKSIDX_PROXY_CONNECTION;
677
extern int MIME_WKSIDX_PUBLIC;
678
extern int MIME_WKSIDX_RANGE;
679
extern int MIME_WKSIDX_REFERENCES;
680
extern int MIME_WKSIDX_REFERER;
681
extern int MIME_WKSIDX_REPLY_TO;
682
extern int MIME_WKSIDX_RETRY_AFTER;
683
extern int MIME_WKSIDX_SENDER;
684
extern int MIME_WKSIDX_SERVER;
685
extern int MIME_WKSIDX_SET_COOKIE;
686
extern int MIME_WKSIDX_STRICT_TRANSPORT_SECURITY;
687
extern int MIME_WKSIDX_SUBJECT;
688
extern int MIME_WKSIDX_SUMMARY;
689
extern int MIME_WKSIDX_TE;
690
extern int MIME_WKSIDX_TRANSFER_ENCODING;
691
extern int MIME_WKSIDX_UPGRADE;
692
extern int MIME_WKSIDX_USER_AGENT;
693
extern int MIME_WKSIDX_VARY;
694
extern int MIME_WKSIDX_VIA;
695
extern int MIME_WKSIDX_WARNING;
696
extern int MIME_WKSIDX_WWW_AUTHENTICATE;
697
extern int MIME_WKSIDX_XREF;
698
extern int MIME_WKSIDX_ATS_INTERNAL;
699
extern int MIME_WKSIDX_X_ID;
700
extern int MIME_WKSIDX_SEC_WEBSOCKET_KEY;
701
extern int MIME_WKSIDX_SEC_WEBSOCKET_VERSION;
702
extern int MIME_WKSIDX_HTTP2_SETTINGS;
703
extern int MIME_WKSIDX_EARLY_DATA;
704
705
/***********************************************************************
706
 *                                                                     *
707
 *                           Internal C API                            *
708
 *                                                                     *
709
 ***********************************************************************/
710
711
uint64_t mime_field_presence_mask(const char *well_known_str);
712
uint64_t mime_field_presence_mask(int well_known_str_index);
713
int      mime_field_presence_get(MIMEHdrImpl *h, const char *well_known_str);
714
int      mime_field_presence_get(MIMEHdrImpl *h, int well_known_str_index);
715
void     mime_hdr_presence_set(MIMEHdrImpl *h, const char *well_known_str);
716
void     mime_hdr_presence_set(MIMEHdrImpl *h, int well_known_str_index);
717
void     mime_hdr_presence_unset(MIMEHdrImpl *h, const char *well_known_str);
718
void     mime_hdr_presence_unset(MIMEHdrImpl *h, int well_known_str_index);
719
720
void mime_hdr_sanity_check(MIMEHdrImpl *mh);
721
722
void mime_init();
723
void mime_init_cache_control_cooking_masks();
724
void mime_init_date_format_table();
725
726
MIMEHdrImpl        *mime_hdr_create(HdrHeap *heap);
727
void                _mime_hdr_field_block_init(MIMEFieldBlockImpl *fblock);
728
void                mime_hdr_cooked_stuff_init(MIMEHdrImpl *mh, MIMEField *changing_field_or_null = nullptr);
729
void                mime_hdr_init(MIMEHdrImpl *mh);
730
MIMEFieldBlockImpl *_mime_field_block_copy(MIMEFieldBlockImpl *s_fblock, HdrHeap *s_heap, HdrHeap *d_heap);
731
void                _mime_field_block_destroy(HdrHeap *heap, MIMEFieldBlockImpl *fblock);
732
void                mime_hdr_destroy_field_block_list(HdrHeap *heap, MIMEFieldBlockImpl *head);
733
void                mime_hdr_destroy(HdrHeap *heap, MIMEHdrImpl *mh);
734
void         mime_hdr_copy_onto(MIMEHdrImpl *s_mh, HdrHeap *s_heap, MIMEHdrImpl *d_mh, HdrHeap *d_heap, bool inherit_strs = true);
735
MIMEHdrImpl *mime_hdr_clone(MIMEHdrImpl *s_mh, HdrHeap *s_heap, HdrHeap *d_heap, bool inherit_strs = true);
736
void         mime_hdr_field_block_list_adjust(int block_count, MIMEFieldBlockImpl *old_list, MIMEFieldBlockImpl *new_list);
737
int          mime_hdr_length_get(MIMEHdrImpl *mh);
738
739
void mime_hdr_fields_clear(HdrHeap *heap, MIMEHdrImpl *mh);
740
741
MIMEField *_mime_hdr_field_list_search_by_wks(MIMEHdrImpl *mh, int wks_idx);
742
MIMEField *_mime_hdr_field_list_search_by_string(MIMEHdrImpl *mh, std::string_view field_name);
743
MIMEField *_mime_hdr_field_list_search_by_slotnum(MIMEHdrImpl *mh, int slotnum);
744
MIMEField *mime_hdr_field_find(MIMEHdrImpl *mh, std::string_view field_name);
745
746
MIMEField *mime_hdr_field_get(MIMEHdrImpl *mh, int idx);
747
MIMEField *mime_hdr_field_get_slotnum(MIMEHdrImpl *mh, int slotnum);
748
int        mime_hdr_fields_count(MIMEHdrImpl *mh);
749
750
void       mime_field_init(MIMEField *field);
751
MIMEField *mime_field_create(HdrHeap *heap, MIMEHdrImpl *mh);
752
MIMEField *mime_field_create_named(HdrHeap *heap, MIMEHdrImpl *mh, std::string_view name);
753
754
void mime_hdr_field_attach(MIMEHdrImpl *mh, MIMEField *field, int check_for_dups, MIMEField *prev_dup);
755
void mime_hdr_field_detach(MIMEHdrImpl *mh, MIMEField *field, bool detach_all_dups = false);
756
void mime_hdr_field_delete(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, bool delete_all_dups = false);
757
758
/**
759
 * Returned slotnum is not a persistent value. A slotnum may refer a different field after making changes to a mime header.
760
 */
761
int        mime_hdr_field_slotnum(MIMEHdrImpl *mh, MIMEField *field);
762
MIMEField *mime_hdr_prepare_for_value_set(HdrHeap *heap, MIMEHdrImpl *mh, std::string_view name);
763
764
void mime_field_destroy(MIMEHdrImpl *mh, MIMEField *field);
765
766
void mime_field_name_set(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int16_t name_wks_idx_or_neg1, std::string_view name,
767
                         bool must_copy_string);
768
769
int32_t     mime_field_value_get_int(const MIMEField *field);
770
uint32_t    mime_field_value_get_uint(const MIMEField *field);
771
int64_t     mime_field_value_get_int64(const MIMEField *field);
772
time_t      mime_field_value_get_date(const MIMEField *field);
773
const char *mime_field_value_get_comma_val(const MIMEField *field, int *length, int idx);
774
int         mime_field_value_get_comma_val_count(const MIMEField *field);
775
int         mime_field_value_get_comma_list(const MIMEField *field, StrList *list);
776
777
void mime_field_value_set_comma_val(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int idx, std::string_view new_piece);
778
void mime_field_value_delete_comma_val(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int idx);
779
void mime_field_value_extend_comma_val(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int idx, std::string_view new_piece);
780
void mime_field_value_insert_comma_val(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int idx, std::string_view new_piece);
781
782
void mime_field_value_set(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, std::string_view value, bool must_copy_string);
783
void mime_field_value_set_int(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int32_t value);
784
void mime_field_value_set_uint(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, uint32_t value);
785
void mime_field_value_set_int64(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int64_t value);
786
void mime_field_value_set_date(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, time_t value);
787
void mime_field_name_value_set(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, int16_t name_wks_idx_or_neg1,
788
                               std::string_view name, std::string_view value, int n_v_raw_printable, int n_v_raw_length,
789
                               bool must_copy_strings);
790
791
void mime_field_value_append(HdrHeap *heap, MIMEHdrImpl *mh, MIMEField *field, std::string_view value, bool prepend_comma,
792
                             const char separator);
793
794
void        mime_parser_init(MIMEParser *parser);
795
void        mime_parser_clear(MIMEParser *parser);
796
ParseResult mime_parser_parse(MIMEParser *parser, HdrHeap *heap, MIMEHdrImpl *mh, const char **real_s, const char *real_e,
797
                              bool must_copy_strings, bool eof, bool remove_ws_from_field_name, size_t max_hdr_field_size = 131070);
798
799
void mime_hdr_describe(HdrHeapObjImpl *raw, bool recurse);
800
void mime_field_block_describe(HdrHeapObjImpl *raw, bool recurse);
801
802
int mime_hdr_print(MIMEHdrImpl const *mh, char *buf_start, int buf_length, int *buf_index_inout, int *buf_chars_to_skip_inout);
803
int mime_mem_print(std::string_view src, char *buf_start, int buf_length, int *buf_index_inout, int *buf_chars_to_skip_inout);
804
int mime_mem_print_lc(std::string_view src, char *buf_start, int buf_length, int *buf_index_inout, int *buf_chars_to_skip_inout);
805
int mime_field_print(MIMEField const *field, char *buf_start, int buf_length, int *buf_index_inout, int *buf_chars_to_skip_inout);
806
807
const char *mime_str_u16_set(HdrHeap *heap, std::string_view src, const char **d_str, uint16_t *d_len, bool must_copy);
808
809
int mime_field_length_get(MIMEField *field);
810
int mime_format_int(char *buf, int32_t val, size_t buf_len);
811
int mime_format_uint(char *buf, uint32_t val, size_t buf_len);
812
int mime_format_int64(char *buf, int64_t val, size_t buf_len);
813
int mime_format_uint64(char *buf, uint64_t val, size_t buf_len);
814
815
void mime_days_since_epoch_to_mdy_slowcase(time_t days_since_jan_1_1970, int *m_return, int *d_return, int *y_return);
816
void mime_days_since_epoch_to_mdy(time_t days_since_jan_1_1970, int *m_return, int *d_return, int *y_return);
817
int  mime_format_date(char *buffer, time_t value);
818
819
int32_t  mime_parse_int(const char *buf, const char *end = nullptr);
820
uint32_t mime_parse_uint(const char *buf, const char *end = nullptr);
821
int64_t  mime_parse_int64(const char *buf, const char *end = nullptr);
822
int      mime_parse_rfc822_date_fastcase(const char *buf, int length, struct tm *tp);
823
time_t   mime_parse_date(const char *buf, const char *end = nullptr);
824
bool     mime_parse_day(const char *&buf, const char *end, int *day);
825
bool     mime_parse_month(const char *&buf, const char *end, int *month);
826
bool     mime_parse_mday(const char *&buf, const char *end, int *mday);
827
bool     mime_parse_year(const char *&buf, const char *end, int *year);
828
bool     mime_parse_time(const char *&buf, const char *end, int *hour, int *min, int *sec);
829
bool     mime_parse_integer(const char *&buf, const char *end, int *integer);
830
831
/***********************************************************************
832
 *                                                                     *
833
 *                          MIMEField Methods                          *
834
 *                                                                     *
835
 ***********************************************************************/
836
837
/*-------------------------------------------------------------------------
838
  -------------------------------------------------------------------------*/
839
840
inline void
841
MIMEField::name_set(HdrHeap *heap, MIMEHdrImpl *mh, std::string_view name)
842
0
{
843
0
  const char *name_wks;
844
845
0
  if (hdrtoken_is_wks(name.data())) {
846
0
    int16_t name_wks_idx = hdrtoken_wks_to_index(name.data());
847
0
    mime_field_name_set(heap, mh, this, name_wks_idx, name, true);
848
0
  } else {
849
0
    int field_name_wks_idx = hdrtoken_tokenize(name.data(), static_cast<int>(name.length()), &name_wks);
850
0
    mime_field_name_set(heap, mh, this, field_name_wks_idx,
851
0
                        field_name_wks_idx == -1 ? name : std::string_view{name_wks, name.length()}, true);
852
0
  }
853
0
}
854
855
/*-------------------------------------------------------------------------
856
  -------------------------------------------------------------------------*/
857
858
inline bool
859
MIMEField::name_is_valid(uint32_t invalid_char_bits) const
860
0
{
861
0
  auto name{name_get()};
862
0
  for (auto c : name) {
863
0
    if (ParseRules::is_type(c, invalid_char_bits)) {
864
0
      return false;
865
0
    }
866
0
  }
867
0
  return true;
868
0
}
869
870
/*-------------------------------------------------------------------------
871
  -------------------------------------------------------------------------*/
872
873
inline int32_t
874
MIMEField::value_get_int() const
875
0
{
876
0
  return mime_field_value_get_int(this);
877
0
}
878
879
inline uint32_t
880
MIMEField::value_get_uint() const
881
0
{
882
0
  return mime_field_value_get_uint(this);
883
0
}
884
885
inline int64_t
886
MIMEField::value_get_int64() const
887
0
{
888
0
  return mime_field_value_get_int64(this);
889
0
}
890
891
inline time_t
892
MIMEField::value_get_date() const
893
0
{
894
0
  return mime_field_value_get_date(this);
895
0
}
896
897
inline int
898
MIMEField::value_get_comma_list(StrList *list) const
899
0
{
900
0
  return mime_field_value_get_comma_list(this, list);
901
0
}
902
903
/*-------------------------------------------------------------------------
904
  -------------------------------------------------------------------------*/
905
906
inline void
907
MIMEField::value_set(HdrHeap *heap, MIMEHdrImpl *mh, std::string_view value)
908
0
{
909
0
  mime_field_value_set(heap, mh, this, value, true);
910
0
}
911
912
inline void
913
MIMEField::value_set_int(HdrHeap *heap, MIMEHdrImpl *mh, int32_t value)
914
0
{
915
0
  mime_field_value_set_int(heap, mh, this, value);
916
0
}
917
918
inline void
919
MIMEField::value_set_uint(HdrHeap *heap, MIMEHdrImpl *mh, uint32_t value)
920
0
{
921
0
  mime_field_value_set_uint(heap, mh, this, value);
922
0
}
923
924
inline void
925
MIMEField::value_set_int64(HdrHeap *heap, MIMEHdrImpl *mh, int64_t value)
926
0
{
927
0
  mime_field_value_set_int64(heap, mh, this, value);
928
0
}
929
930
inline void
931
MIMEField::value_set_date(HdrHeap *heap, MIMEHdrImpl *mh, time_t value)
932
0
{
933
0
  mime_field_value_set_date(heap, mh, this, value);
934
0
}
935
936
/*-------------------------------------------------------------------------
937
  -------------------------------------------------------------------------*/
938
939
inline void
940
MIMEField::value_clear(HdrHeap *heap, MIMEHdrImpl *mh)
941
0
{
942
0
  value_set(heap, mh, ""sv);
943
0
}
944
945
/*-------------------------------------------------------------------------
946
  -------------------------------------------------------------------------*/
947
948
inline void
949
MIMEField::value_append(HdrHeap *heap, MIMEHdrImpl *mh, std::string_view value, bool prepend_comma, const char separator)
950
0
{
951
0
  mime_field_value_append(heap, mh, this, value, prepend_comma, separator);
952
0
}
953
954
/*-------------------------------------------------------------------------
955
  -------------------------------------------------------------------------*/
956
957
inline bool
958
MIMEField::value_is_valid(uint32_t invalid_char_bits) const
959
0
{
960
0
  auto value{value_get()};
961
0
  for (auto c : value) {
962
0
    if (ParseRules::is_type(c, invalid_char_bits)) {
963
0
      return false;
964
0
    }
965
0
  }
966
0
  return true;
967
0
}
968
969
inline int
970
MIMEField::has_dups() const
971
2.08k
{
972
2.08k
  return (m_next_dup != nullptr);
973
2.08k
}
974
975
/***********************************************************************
976
 *                                                                     *
977
 *                           MIMEFieldIter                             *
978
 *                                                                     *
979
 ***********************************************************************/
980
981
struct MIMEFieldIter {
982
0
  MIMEFieldIter() {}
983
  uint32_t            m_slot  = 0;
984
  MIMEFieldBlockImpl *m_block = nullptr;
985
};
986
987
/*-------------------------------------------------------------------------
988
  -------------------------------------------------------------------------*/
989
990
/***********************************************************************
991
 *                                                                     *
992
 *                            MIMEHdr Class                            *
993
 *                                                                     *
994
 ***********************************************************************/
995
996
class MIMEHdr : public HdrHeapSDKHandle
997
{
998
public:
999
  using iterator = MIMEHdrImpl::iterator;
1000
1001
  MIMEHdrImpl *m_mime = nullptr;
1002
1003
18.7k
  MIMEHdr() = default; // Force the creation of the default constructor
1004
1005
  int valid() const;
1006
1007
  void create(HdrHeap *heap = nullptr);
1008
  void copy(const MIMEHdr *hdr);
1009
1010
  int length_get() const;
1011
1012
  void fields_clear();
1013
  int  fields_count() const;
1014
1015
  MIMEField       *field_create(std::string_view name = ""sv);
1016
  MIMEField       *field_find(std::string_view name);
1017
  const MIMEField *field_find(std::string_view name) const;
1018
  void             field_attach(MIMEField *field);
1019
  void             field_detach(MIMEField *field, bool detach_all_dups = true);
1020
  void             field_delete(MIMEField *field, bool delete_all_dups = true);
1021
  void             field_delete(std::string_view name);
1022
1023
  iterator begin() const;
1024
  iterator end() const;
1025
1026
  /*
1027
  MIMEField *iter_get_first(MIMEFieldIter *iter);
1028
  MIMEField *iter_get(MIMEFieldIter *iter);
1029
  MIMEField *iter_get_next(MIMEFieldIter *iter);
1030
   */
1031
1032
  uint64_t presence(uint64_t mask) const;
1033
1034
  int print(char *buf, int bufsize, int *bufindex, int *chars_to_skip);
1035
1036
  ParseResult parse(MIMEParser *parser, const char **start, const char *end, bool must_copy_strs, bool eof,
1037
                    bool remove_ws_from_field_name, size_t max_hdr_field_size = UINT16_MAX);
1038
1039
  int              value_get_index(std::string_view name, std::string_view value) const;
1040
  std::string_view value_get(std::string_view name) const;
1041
  int32_t          value_get_int(std::string_view name) const;
1042
  uint32_t         value_get_uint(std::string_view name) const;
1043
  int64_t          value_get_int64(std::string_view name) const;
1044
  time_t           value_get_date(std::string_view name) const;
1045
  int              value_get_comma_list(std::string_view name, StrList *list) const;
1046
1047
  void value_set(std::string_view name, std::string_view value);
1048
  void value_set_int(std::string_view name, int32_t value);
1049
  void value_set_uint(std::string_view name, uint32_t value);
1050
  void value_set_int64(std::string_view name, int64_t value);
1051
  void value_set_date(std::string_view name, time_t value);
1052
  // MIME standard separator ',' is used as the default value
1053
  // Other separators (e.g. ';' in Set-cookie/Cookie) are also possible
1054
  void value_append(std::string_view name, std::string_view value, bool prepend_comma = false, const char separator = ',');
1055
1056
  void field_value_set(MIMEField *field, std::string_view value, bool reuse_heaps = false);
1057
  void field_value_set_int(MIMEField *field, int32_t value);
1058
  void field_value_set_uint(MIMEField *field, uint32_t value);
1059
  void field_value_set_int64(MIMEField *field, int64_t value);
1060
  void field_value_set_date(MIMEField *field, time_t value);
1061
  // MIME standard separator ',' is used as the default value
1062
  // Other separators (e.g. ';' in Set-cookie/Cookie) are also possible
1063
  void    field_value_append(MIMEField *field, std::string_view value, bool prepend_comma = false, const char separator = ',');
1064
  void    value_append_or_set(std::string_view name, std::string_view value);
1065
  void    field_combine_dups(MIMEField *field, bool prepend_comma = false, const char separator = ',');
1066
  time_t  get_age() const;
1067
  int64_t get_content_length() const;
1068
  time_t  get_date() const;
1069
  time_t  get_expires() const;
1070
  time_t  get_if_modified_since() const;
1071
  time_t  get_if_unmodified_since() const;
1072
  time_t  get_last_modified() const;
1073
  time_t  get_if_range_date() const;
1074
  int32_t get_max_forwards() const;
1075
  int32_t get_warning(int idx = 0);
1076
1077
  uint32_t get_cooked_cc_mask() const;
1078
  int32_t  get_cooked_cc_max_age() const;
1079
  int32_t  get_cooked_cc_s_maxage() const;
1080
  int32_t  get_cooked_cc_max_stale() const;
1081
  int32_t  get_cooked_cc_min_fresh() const;
1082
  bool     get_cooked_pragma_no_cache() const;
1083
1084
  /** Get the value of the host field.
1085
      This parses the host field for brackets and port value.
1086
      @return The tuple of mime HOST field, host, and port if it has a value,
1087
              or the tuple of @c NULL and two empty string views. otherwise.
1088
  */
1089
  std::tuple<MIMEField *, std::string_view, std::string_view> get_host_port_values();
1090
1091
  void set_cooked_cc_need_revalidate_once();
1092
  void unset_cooked_cc_need_revalidate_once();
1093
1094
  void set_age(time_t value);
1095
  void set_content_length(int64_t value);
1096
  void set_date(time_t value);
1097
  void set_expires(time_t value);
1098
  void set_if_modified_since(time_t value);
1099
  void set_if_unmodified_since(time_t value);
1100
  void set_last_modified(time_t value);
1101
  void set_max_forwards(int32_t value);
1102
  void set_warning(int32_t value);
1103
  void set_server(std::string_view server_id_tag);
1104
1105
  // No gratuitous copies & refcounts!
1106
  MIMEHdr(const MIMEHdr &m)            = delete;
1107
  MIMEHdr &operator=(const MIMEHdr &m) = delete;
1108
1109
private:
1110
  // Interface to replace (overwrite) field value without
1111
  // changing the heap as long as the new value is not longer
1112
  // than the current value
1113
  bool field_value_replace(MIMEField *field, std::string_view value);
1114
};
1115
1116
/*-------------------------------------------------------------------------
1117
  -------------------------------------------------------------------------*/
1118
1119
inline int
1120
MIMEHdr::valid() const
1121
0
{
1122
0
  return (m_mime && m_heap);
1123
0
}
1124
1125
/*-------------------------------------------------------------------------
1126
  -------------------------------------------------------------------------*/
1127
1128
inline void
1129
MIMEHdr::create(HdrHeap *heap)
1130
0
{
1131
0
  if (heap) {
1132
0
    m_heap = heap;
1133
0
  } else if (!m_heap) {
1134
0
    m_heap = new_HdrHeap();
1135
0
  }
1136
0
1137
0
  m_mime = mime_hdr_create(m_heap);
1138
0
}
1139
1140
/*-------------------------------------------------------------------------
1141
  -------------------------------------------------------------------------*/
1142
1143
inline void
1144
MIMEHdr::copy(const MIMEHdr *src_hdr)
1145
0
{
1146
0
  if (valid()) {
1147
0
    mime_hdr_copy_onto(src_hdr->m_mime, src_hdr->m_heap, m_mime, m_heap, (m_heap != src_hdr->m_heap) ? true : false);
1148
0
  } else {
1149
0
    m_heap = new_HdrHeap();
1150
0
    m_mime = mime_hdr_clone(src_hdr->m_mime, src_hdr->m_heap, m_heap);
1151
0
  }
1152
0
}
1153
1154
/*-------------------------------------------------------------------------
1155
  -------------------------------------------------------------------------*/
1156
1157
inline int
1158
MIMEHdr::length_get() const
1159
0
{
1160
0
  return mime_hdr_length_get(m_mime);
1161
0
}
1162
1163
/*-------------------------------------------------------------------------
1164
  -------------------------------------------------------------------------*/
1165
1166
inline void
1167
MIMEHdr::fields_clear()
1168
0
{
1169
0
  mime_hdr_fields_clear(m_heap, m_mime);
1170
0
}
1171
1172
/*-------------------------------------------------------------------------
1173
  -------------------------------------------------------------------------*/
1174
1175
inline int
1176
MIMEHdr::fields_count() const
1177
0
{
1178
0
  return mime_hdr_fields_count(m_mime);
1179
0
}
1180
1181
/*-------------------------------------------------------------------------
1182
  -------------------------------------------------------------------------*/
1183
1184
inline MIMEField *
1185
MIMEHdr::field_create(std::string_view name)
1186
0
{
1187
0
  MIMEField *field = mime_field_create(m_heap, m_mime);
1188
0
1189
0
  if (!name.empty()) {
1190
0
    auto length{static_cast<int>(name.length())};
1191
0
    int  field_name_wks_idx = hdrtoken_tokenize(name.data(), length);
1192
0
    mime_field_name_set(m_heap, m_mime, field, field_name_wks_idx, name, true);
1193
0
  }
1194
0
1195
0
  return field;
1196
0
}
1197
1198
/*-------------------------------------------------------------------------
1199
  -------------------------------------------------------------------------*/
1200
1201
inline MIMEField *
1202
MIMEHdr::field_find(std::string_view name) // NOLINT(readability-make-member-function-const)
1203
0
{
1204
  //    ink_assert(valid());
1205
0
  return mime_hdr_field_find(m_mime, name);
1206
0
}
1207
1208
inline const MIMEField *
1209
MIMEHdr::field_find(std::string_view name) const
1210
0
{
1211
  //    ink_assert(valid());
1212
0
  MIMEField *retval = mime_hdr_field_find(const_cast<MIMEHdr *>(this)->m_mime, name);
1213
0
  return retval;
1214
0
}
1215
1216
/*-------------------------------------------------------------------------
1217
  -------------------------------------------------------------------------*/
1218
1219
inline void
1220
MIMEHdr::field_attach(MIMEField *field) // NOLINT(readability-make-member-function-const)
1221
0
{
1222
0
  mime_hdr_field_attach(m_mime, field, 1, nullptr);
1223
0
}
1224
1225
/*-------------------------------------------------------------------------
1226
  -------------------------------------------------------------------------*/
1227
1228
inline void
1229
MIMEHdr::field_detach(MIMEField *field, bool detach_all_dups) // NOLINT(readability-make-member-function-const)
1230
0
{
1231
0
  mime_hdr_field_detach(m_mime, field, detach_all_dups);
1232
0
}
1233
1234
/*-------------------------------------------------------------------------
1235
  -------------------------------------------------------------------------*/
1236
1237
inline void
1238
MIMEHdr::field_delete(MIMEField *field, bool delete_all_dups)
1239
0
{
1240
0
  mime_hdr_field_delete(m_heap, m_mime, field, delete_all_dups);
1241
0
}
1242
1243
inline auto
1244
MIMEHdr::begin() const -> iterator
1245
0
{
1246
0
  return m_mime ? m_mime->begin() : iterator();
1247
0
}
1248
1249
inline auto
1250
MIMEHdr::end() const -> iterator
1251
0
{
1252
0
  return {}; // default constructed iterator.
1253
0
}
1254
1255
inline void
1256
MIMEHdr::field_delete(std::string_view name)
1257
0
{
1258
0
  MIMEField *field = field_find(name);
1259
0
  if (field)
1260
0
    field_delete(field);
1261
0
}
1262
1263
/*-------------------------------------------------------------------------
1264
  -------------------------------------------------------------------------*/
1265
1266
inline uint64_t
1267
MIMEHdr::presence(uint64_t mask) const
1268
0
{
1269
0
  return (m_mime->m_presence_bits & mask);
1270
0
}
1271
1272
/*-------------------------------------------------------------------------
1273
  -------------------------------------------------------------------------*/
1274
1275
inline int
1276
MIMEHdr::print(char *buf, int bufsize, int *bufindex, int *chars_to_skip)
1277
0
{
1278
0
  return mime_hdr_print(m_mime, buf, bufsize, bufindex, chars_to_skip);
1279
0
}
1280
1281
/*-------------------------------------------------------------------------
1282
  -------------------------------------------------------------------------*/
1283
1284
inline ParseResult
1285
MIMEHdr::parse(MIMEParser *parser, const char **start, const char *end, bool must_copy_strs, bool eof,
1286
               bool remove_ws_from_field_name, size_t max_hdr_field_size)
1287
0
{
1288
0
  if (!m_heap)
1289
0
    m_heap = new_HdrHeap();
1290
0
1291
0
  if (!m_mime)
1292
0
    m_mime = mime_hdr_create(m_heap);
1293
0
1294
0
  return mime_parser_parse(parser, m_heap, m_mime, start, end, must_copy_strs, eof, remove_ws_from_field_name, max_hdr_field_size);
1295
0
}
1296
1297
/*-------------------------------------------------------------------------
1298
  -------------------------------------------------------------------------*/
1299
inline int
1300
MIMEHdr::value_get_index(std::string_view name, std::string_view value) const
1301
0
{
1302
0
  const MIMEField *field = field_find(name);
1303
0
1304
0
  if (field) {
1305
0
    return field->value_get_index(value);
1306
0
  }
1307
0
  return -1;
1308
0
}
1309
1310
/*-------------------------------------------------------------------------
1311
  -------------------------------------------------------------------------*/
1312
1313
inline std::string_view
1314
MIMEHdr::value_get(std::string_view name) const
1315
0
{
1316
0
  MIMEField const *field = field_find(name);
1317
0
1318
0
  if (field) {
1319
0
    return field->value_get();
1320
0
  }
1321
0
  return {};
1322
0
}
1323
1324
inline int32_t
1325
MIMEHdr::value_get_int(std::string_view name) const
1326
0
{
1327
0
  const MIMEField *field = field_find(name);
1328
0
1329
0
  if (field) {
1330
0
    return mime_field_value_get_int(field);
1331
0
  }
1332
0
  return 0;
1333
0
}
1334
1335
inline uint32_t
1336
MIMEHdr::value_get_uint(std::string_view name) const
1337
0
{
1338
0
  const MIMEField *field = field_find(name);
1339
0
1340
0
  if (field) {
1341
0
    return mime_field_value_get_uint(field);
1342
0
  }
1343
0
  return 0;
1344
0
}
1345
1346
inline int64_t
1347
MIMEHdr::value_get_int64(std::string_view name) const
1348
0
{
1349
0
  const MIMEField *field = field_find(name);
1350
0
1351
0
  if (field) {
1352
0
    return mime_field_value_get_int64(field);
1353
0
  }
1354
0
  return 0;
1355
0
}
1356
1357
inline time_t
1358
MIMEHdr::value_get_date(std::string_view name) const
1359
0
{
1360
0
  const MIMEField *field = field_find(name);
1361
0
1362
0
  if (field) {
1363
0
    return mime_field_value_get_date(field);
1364
0
  }
1365
0
  return 0;
1366
0
}
1367
1368
inline int
1369
MIMEHdr::value_get_comma_list(std::string_view name, StrList *list) const
1370
0
{
1371
0
  const MIMEField *field = field_find(name);
1372
0
1373
0
  if (field) {
1374
0
    return field->value_get_comma_list(list);
1375
0
  }
1376
0
  return 0;
1377
0
}
1378
1379
/*-------------------------------------------------------------------------
1380
  -------------------------------------------------------------------------*/
1381
1382
inline bool
1383
MIMEHdr::field_value_replace(MIMEField *field, std::string_view value)
1384
0
{
1385
0
  auto value_length{static_cast<uint32_t>(value.length())};
1386
0
  if (field->m_len_value >= value_length) {
1387
0
    memcpy((char *)field->m_ptr_value, value.data(), value_length);
1388
0
    field->m_len_value = value_length;
1389
0
    return true;
1390
0
  }
1391
0
  return false;
1392
0
}
1393
1394
inline void
1395
MIMEHdr::field_value_set(MIMEField *field, std::string_view value, bool reuse_heaps)
1396
0
{
1397
0
  if (!reuse_heaps || !field_value_replace(field, value)) {
1398
0
    field->value_set(m_heap, m_mime, value);
1399
0
  }
1400
0
}
1401
1402
inline void
1403
MIMEHdr::field_value_set_int(MIMEField *field, int32_t value)
1404
0
{
1405
0
  field->value_set_int(m_heap, m_mime, value);
1406
0
}
1407
1408
inline void
1409
MIMEHdr::field_value_set_uint(MIMEField *field, uint32_t value)
1410
0
{
1411
0
  field->value_set_uint(m_heap, m_mime, value);
1412
0
}
1413
1414
inline void
1415
MIMEHdr::field_value_set_int64(MIMEField *field, int64_t value)
1416
0
{
1417
0
  field->value_set_int64(m_heap, m_mime, value);
1418
0
}
1419
1420
inline void
1421
MIMEHdr::field_value_set_date(MIMEField *field, time_t value)
1422
0
{
1423
0
  field->value_set_date(m_heap, m_mime, value);
1424
0
}
1425
1426
/*-------------------------------------------------------------------------
1427
  -------------------------------------------------------------------------*/
1428
1429
inline void
1430
MIMEHdr::field_value_append(MIMEField *field, std::string_view value, bool prepend_comma, const char separator)
1431
0
{
1432
0
  field->value_append(m_heap, m_mime, value, prepend_comma, separator);
1433
0
}
1434
1435
inline void
1436
MIMEHdr::field_combine_dups(MIMEField *field, bool prepend_comma, const char separator)
1437
0
{
1438
0
  MIMEField *current = field->m_next_dup;
1439
1440
0
  while (current) {
1441
0
    auto value{current->value_get()};
1442
0
    if (value.length() > 0) {
1443
0
      HdrHeap::HeapGuard guard(m_heap, value.data()); // reference count the source string so it doesn't get moved
1444
0
      field->value_append(m_heap, m_mime, value, prepend_comma, separator);
1445
0
    }
1446
0
    field_delete(current, false); // don't delete duplicates
1447
0
    current = field->m_next_dup;
1448
0
  }
1449
0
}
1450
1451
inline void
1452
MIMEHdr::value_append_or_set(std::string_view name, std::string_view value)
1453
0
{
1454
0
  MIMEField *field = nullptr;
1455
0
1456
0
  if ((field = field_find(name)) != nullptr) {
1457
0
    while (field->m_next_dup) {
1458
0
      field = field->m_next_dup;
1459
0
    }
1460
0
    field_value_append(field, value, true);
1461
0
  } else {
1462
0
    value_set(name, value);
1463
0
  }
1464
0
}
1465
1466
/*-------------------------------------------------------------------------
1467
  -------------------------------------------------------------------------*/
1468
1469
inline void
1470
MIMEHdr::value_set(std::string_view name, std::string_view value)
1471
0
{
1472
0
  MIMEField *field;
1473
0
  field = mime_hdr_prepare_for_value_set(m_heap, m_mime, name);
1474
0
  field->value_set(m_heap, m_mime, value);
1475
0
}
1476
1477
inline void
1478
MIMEHdr::value_set_int(std::string_view name, int32_t value)
1479
0
{
1480
0
  MIMEField *field;
1481
0
  field = mime_hdr_prepare_for_value_set(m_heap, m_mime, name);
1482
0
  field->value_set_int(m_heap, m_mime, value);
1483
0
}
1484
1485
inline void
1486
MIMEHdr::value_set_uint(std::string_view name, uint32_t value)
1487
0
{
1488
0
  MIMEField *field;
1489
0
  field = mime_hdr_prepare_for_value_set(m_heap, m_mime, name);
1490
0
  field->value_set_uint(m_heap, m_mime, value);
1491
0
}
1492
1493
inline void
1494
MIMEHdr::value_set_int64(std::string_view name, int64_t value)
1495
0
{
1496
0
  MIMEField *field;
1497
0
  field = mime_hdr_prepare_for_value_set(m_heap, m_mime, name);
1498
0
  field->value_set_int64(m_heap, m_mime, value);
1499
0
}
1500
1501
inline void
1502
MIMEHdr::value_set_date(std::string_view name, time_t value)
1503
0
{
1504
0
  MIMEField *field;
1505
0
  field = mime_hdr_prepare_for_value_set(m_heap, m_mime, name);
1506
0
  field->value_set_date(m_heap, m_mime, value);
1507
0
}
1508
1509
/*-------------------------------------------------------------------------
1510
  -------------------------------------------------------------------------*/
1511
1512
inline void
1513
MIMEHdr::value_append(std::string_view name, std::string_view value, bool prepend_comma, const char separator)
1514
0
{
1515
0
  MIMEField *field;
1516
0
1517
0
  field = field_find(name);
1518
0
  if (field) {
1519
0
    while (field->m_next_dup)
1520
0
      field = field->m_next_dup;
1521
0
    field->value_append(m_heap, m_mime, value, prepend_comma, separator);
1522
0
  } else {
1523
0
    field = field_create(name.empty() ? ""sv : name);
1524
0
    field_attach(field);
1525
0
    field->value_set(m_heap, m_mime, value);
1526
0
  }
1527
0
}
1528
1529
/*-------------------------------------------------------------------------
1530
  -------------------------------------------------------------------------*/
1531
inline time_t
1532
MIMEHdr::get_age() const
1533
0
{
1534
0
  int64_t age = value_get_int64(static_cast<std::string_view>(MIME_FIELD_AGE));
1535
0
1536
0
  if (age < 0) // We should ignore negative Age: values
1537
0
    return 0;
1538
0
1539
0
  if ((4 == sizeof(time_t)) && (age > INT_MAX)) // Overflow
1540
0
    return -1;
1541
0
1542
0
  return age;
1543
0
}
1544
1545
/*-------------------------------------------------------------------------
1546
  -------------------------------------------------------------------------*/
1547
1548
inline int64_t
1549
MIMEHdr::get_content_length() const
1550
0
{
1551
0
  return value_get_int64(static_cast<std::string_view>(MIME_FIELD_CONTENT_LENGTH));
1552
0
}
1553
1554
/*-------------------------------------------------------------------------
1555
  -------------------------------------------------------------------------*/
1556
1557
inline time_t
1558
MIMEHdr::get_date() const
1559
0
{
1560
0
  return value_get_date(static_cast<std::string_view>(MIME_FIELD_DATE));
1561
0
}
1562
1563
/*-------------------------------------------------------------------------
1564
  -------------------------------------------------------------------------*/
1565
1566
inline time_t
1567
MIMEHdr::get_expires() const
1568
0
{
1569
0
  return value_get_date(static_cast<std::string_view>(MIME_FIELD_EXPIRES));
1570
0
}
1571
1572
/*-------------------------------------------------------------------------
1573
  -------------------------------------------------------------------------*/
1574
1575
inline time_t
1576
MIMEHdr::get_if_modified_since() const
1577
0
{
1578
0
  return value_get_date(static_cast<std::string_view>(MIME_FIELD_IF_MODIFIED_SINCE));
1579
0
}
1580
1581
/*-------------------------------------------------------------------------
1582
  -------------------------------------------------------------------------*/
1583
1584
inline time_t
1585
MIMEHdr::get_if_unmodified_since() const
1586
0
{
1587
0
  return value_get_date(static_cast<std::string_view>(MIME_FIELD_IF_UNMODIFIED_SINCE));
1588
0
}
1589
1590
/*-------------------------------------------------------------------------
1591
  -------------------------------------------------------------------------*/
1592
1593
inline time_t
1594
MIMEHdr::get_last_modified() const
1595
0
{
1596
0
  return value_get_date(static_cast<std::string_view>(MIME_FIELD_LAST_MODIFIED));
1597
0
}
1598
1599
/*-------------------------------------------------------------------------
1600
  -------------------------------------------------------------------------*/
1601
1602
inline time_t
1603
MIMEHdr::get_if_range_date() const
1604
0
{
1605
0
  return value_get_date(static_cast<std::string_view>(MIME_FIELD_IF_RANGE));
1606
0
}
1607
1608
/*-------------------------------------------------------------------------
1609
  -------------------------------------------------------------------------*/
1610
1611
inline int32_t
1612
MIMEHdr::get_max_forwards() const
1613
0
{
1614
0
  return value_get_int(static_cast<std::string_view>(MIME_FIELD_MAX_FORWARDS));
1615
0
}
1616
1617
/*-------------------------------------------------------------------------
1618
  -------------------------------------------------------------------------*/
1619
1620
inline int32_t
1621
MIMEHdr::get_warning(int idx)
1622
0
{
1623
0
  (void)idx;
1624
0
  // FIXME: what do we do here?
1625
0
  ink_release_assert(!"unimplemented");
1626
0
  return 0;
1627
0
}
1628
1629
/*-------------------------------------------------------------------------
1630
  -------------------------------------------------------------------------*/
1631
1632
inline uint32_t
1633
MIMEHdr::get_cooked_cc_mask() const
1634
0
{
1635
0
  return m_mime->m_cooked_stuff.m_cache_control.m_mask;
1636
0
}
1637
1638
/*-------------------------------------------------------------------------
1639
  -------------------------------------------------------------------------*/
1640
1641
inline int32_t
1642
MIMEHdr::get_cooked_cc_max_age() const
1643
0
{
1644
0
  return m_mime->m_cooked_stuff.m_cache_control.m_secs_max_age;
1645
0
}
1646
1647
/*-------------------------------------------------------------------------
1648
  -------------------------------------------------------------------------*/
1649
1650
inline int32_t
1651
MIMEHdr::get_cooked_cc_s_maxage() const
1652
0
{
1653
0
  return m_mime->m_cooked_stuff.m_cache_control.m_secs_s_maxage;
1654
0
}
1655
1656
/*-------------------------------------------------------------------------
1657
  -------------------------------------------------------------------------*/
1658
1659
inline int32_t
1660
MIMEHdr::get_cooked_cc_max_stale() const
1661
0
{
1662
0
  return m_mime->m_cooked_stuff.m_cache_control.m_secs_max_stale;
1663
0
}
1664
1665
/*-------------------------------------------------------------------------
1666
  -------------------------------------------------------------------------*/
1667
1668
inline int32_t
1669
MIMEHdr::get_cooked_cc_min_fresh() const
1670
0
{
1671
0
  return m_mime->m_cooked_stuff.m_cache_control.m_secs_min_fresh;
1672
0
}
1673
1674
/*-------------------------------------------------------------------------
1675
  -------------------------------------------------------------------------*/
1676
1677
inline bool
1678
MIMEHdr::get_cooked_pragma_no_cache() const
1679
0
{
1680
0
  return m_mime->m_cooked_stuff.m_pragma.m_no_cache;
1681
0
}
1682
1683
/*-------------------------------------------------------------------------
1684
  -------------------------------------------------------------------------*/
1685
1686
inline void
1687
MIMEHdr::set_cooked_cc_need_revalidate_once() // NOLINT(readability-make-member-function-const)
1688
0
{
1689
0
  m_mime->m_cooked_stuff.m_cache_control.m_mask |= MIME_COOKED_MASK_CC_NEED_REVALIDATE_ONCE;
1690
0
}
1691
1692
/*-------------------------------------------------------------------------
1693
  -------------------------------------------------------------------------*/
1694
1695
inline void
1696
MIMEHdr::unset_cooked_cc_need_revalidate_once() // NOLINT(readability-make-member-function-const)
1697
0
{
1698
0
  m_mime->m_cooked_stuff.m_cache_control.m_mask &= ~((uint32_t)MIME_COOKED_MASK_CC_NEED_REVALIDATE_ONCE);
1699
0
}
1700
1701
/*-------------------------------------------------------------------------
1702
  -------------------------------------------------------------------------*/
1703
1704
inline void
1705
MIMEHdr::set_age(time_t value)
1706
0
{
1707
0
  if (value < 0)
1708
0
    value_set_uint(static_cast<std::string_view>(MIME_FIELD_AGE), (uint32_t)INT_MAX + 1);
1709
0
  else {
1710
0
    if (sizeof(time_t) > 4) {
1711
0
      value_set_int64(static_cast<std::string_view>(MIME_FIELD_AGE), value);
1712
0
    } else {
1713
0
      // Only on systems where time_t is 32 bits
1714
0
      // coverity[Y2K38_SAFETY]
1715
0
      value_set_uint(static_cast<std::string_view>(MIME_FIELD_AGE), value);
1716
0
    }
1717
0
  }
1718
0
}
1719
1720
/*-------------------------------------------------------------------------
1721
  -------------------------------------------------------------------------*/
1722
1723
inline void
1724
MIMEHdr::set_content_length(int64_t value)
1725
0
{
1726
0
  value_set_int64(static_cast<std::string_view>(MIME_FIELD_CONTENT_LENGTH), value);
1727
0
}
1728
1729
/*-------------------------------------------------------------------------
1730
  -------------------------------------------------------------------------*/
1731
1732
inline void
1733
MIMEHdr::set_date(time_t value)
1734
0
{
1735
0
  value_set_date(static_cast<std::string_view>(MIME_FIELD_DATE), value);
1736
0
}
1737
1738
/*-------------------------------------------------------------------------
1739
  -------------------------------------------------------------------------*/
1740
1741
inline void
1742
MIMEHdr::set_expires(time_t value)
1743
0
{
1744
0
  value_set_date(static_cast<std::string_view>(MIME_FIELD_EXPIRES), value);
1745
0
}
1746
1747
/*-------------------------------------------------------------------------
1748
  -------------------------------------------------------------------------*/
1749
1750
inline void
1751
MIMEHdr::set_if_modified_since(time_t value)
1752
0
{
1753
0
  value_set_date(static_cast<std::string_view>(MIME_FIELD_IF_MODIFIED_SINCE), value);
1754
0
}
1755
1756
/*-------------------------------------------------------------------------
1757
  -------------------------------------------------------------------------*/
1758
1759
inline void
1760
MIMEHdr::set_if_unmodified_since(time_t value)
1761
0
{
1762
0
  value_set_date(static_cast<std::string_view>(MIME_FIELD_IF_UNMODIFIED_SINCE), value);
1763
0
}
1764
1765
/*-------------------------------------------------------------------------
1766
  -------------------------------------------------------------------------*/
1767
1768
inline void
1769
MIMEHdr::set_last_modified(time_t value)
1770
0
{
1771
0
  value_set_date(static_cast<std::string_view>(MIME_FIELD_LAST_MODIFIED), value);
1772
0
}
1773
1774
/*-------------------------------------------------------------------------
1775
  -------------------------------------------------------------------------*/
1776
1777
inline void
1778
MIMEHdr::set_max_forwards(int32_t value)
1779
0
{
1780
0
  value_set_int(static_cast<std::string_view>(MIME_FIELD_MAX_FORWARDS), value);
1781
0
}
1782
1783
/*-------------------------------------------------------------------------
1784
  -------------------------------------------------------------------------*/
1785
1786
inline void
1787
MIMEHdr::set_warning(int32_t value)
1788
0
{
1789
0
  value_set_int(static_cast<std::string_view>(MIME_FIELD_WARNING), value);
1790
0
}
1791
1792
/*-------------------------------------------------------------------------
1793
  -------------------------------------------------------------------------*/
1794
1795
inline void
1796
MIMEHdr::set_server(std::string_view server_id_tag)
1797
0
{
1798
0
  value_set(static_cast<std::string_view>(MIME_FIELD_SERVER), server_id_tag);
1799
0
}