Coverage Report

Created: 2026-10-31 07:06

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