Coverage Report

Created: 2026-06-07 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/resiprocate/resip/stack/DateCategory.cxx
Line
Count
Source
1
#include "rutil/compat.hxx"
2
3
#include <string.h>
4
#include <ctype.h>
5
#include <time.h>
6
7
#include "resip/stack/DateCategory.hxx"
8
9
#include "resip/stack/Transport.hxx"
10
#include "rutil/Data.hxx"
11
#include "rutil/DnsUtil.hxx"
12
#include "rutil/Logger.hxx"
13
#include "rutil/ParseBuffer.hxx"
14
#include "rutil/Socket.hxx"
15
//#include "rutil/WinLeakCheck.hxx"  // not compatible with placement new used below
16
17
using namespace resip;
18
using namespace std;
19
20
namespace resip
21
{
22
// Implemented in gen/DayOfWeekHash.cxx
23
struct days { const char *name; DayOfWeek type; };
24
class DayOfWeekHash
25
{
26
private:
27
  static inline unsigned int hash (const char *str, GPERF_SIZE_TYPE len);
28
public:
29
  static const struct days *in_word_set (const char *str, GPERF_SIZE_TYPE len);
30
};
31
32
// Implemented in gen/MonthHash.cxx
33
struct months { const char *name; Month type; };
34
class MonthHash
35
{
36
private:
37
  static inline unsigned int hash (const char *str, GPERF_SIZE_TYPE len);
38
public:
39
  static const struct months *in_word_set (const char *str, GPERF_SIZE_TYPE len);
40
};
41
}
42
43
#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
44
45
//====================
46
// Date
47
//====================
48
49
Data resip::DayOfWeekData[] =
50
{
51
   "Sun",
52
   "Mon",
53
   "Tue",
54
   "Wed",
55
   "Thu",
56
   "Fri",
57
   "Sat"
58
};
59
60
Data resip::MonthData[] =
61
{
62
   "Jan",
63
   "Feb",
64
   "Mar",
65
   "Apr",
66
   "May",
67
   "Jun",
68
   "Jul",
69
   "Aug",
70
   "Sep",
71
   "Oct",
72
   "Nov",
73
   "Dec"
74
};
75
76
77
DateCategory::DateCategory()
78
0
   : ParserCategory(),
79
0
     mDayOfWeek(Sun),
80
     mDayOfMonth(),
81
0
     mMonth(Jan),
82
0
     mYear(0),
83
0
     mHour(0),
84
0
     mMin(0),
85
0
     mSec(0)
86
0
{
87
0
   time_t now;
88
0
   time(&now);
89
0
   if (now == ((time_t)-1))
90
0
   {
91
0
      int e = getErrno();
92
0
      DebugLog (<< "Failed to get time: " << strError(e));
93
0
      Transport::error(e);
94
0
      return;
95
0
   }
96
   
97
0
   setDatetime(now);
98
0
}
99
100
DateCategory::DateCategory(time_t datetime)
101
0
   : ParserCategory(),
102
0
     mDayOfWeek(Sun),
103
     mDayOfMonth(),
104
0
     mMonth(Jan),
105
0
     mYear(0),
106
0
     mHour(0),
107
0
     mMin(0),
108
0
     mSec(0)
109
0
{
110
0
   setDatetime(datetime);
111
0
}
112
113
DateCategory::DateCategory(const HeaderFieldValue& hfv, 
114
                           Headers::Type type,
115
                           PoolBase* pool)
116
6.55k
   : ParserCategory(hfv, type, pool),
117
6.55k
     mDayOfWeek(Sun),
118
     mDayOfMonth(),
119
6.55k
     mMonth(Jan),
120
6.55k
     mYear(0),
121
6.55k
     mHour(0),
122
6.55k
     mMin(0),
123
6.55k
     mSec(0)
124
6.55k
{}
125
126
DateCategory::DateCategory(const DateCategory& rhs,
127
                           PoolBase* pool)
128
0
   : ParserCategory(rhs, pool),
129
0
     mDayOfWeek(rhs.mDayOfWeek),
130
0
     mDayOfMonth(rhs.mDayOfMonth),
131
0
     mMonth(rhs.mMonth),
132
0
     mYear(rhs.mYear),
133
0
     mHour(rhs.mHour),
134
0
     mMin(rhs.mMin),
135
0
     mSec(rhs.mSec)
136
0
{}
137
138
DateCategory&
139
DateCategory::operator=(const DateCategory& rhs)
140
0
{
141
0
   if (this != &rhs)
142
0
   {
143
0
      ParserCategory::operator=(rhs);
144
0
      mDayOfWeek = rhs.mDayOfWeek;
145
0
      mDayOfMonth = rhs.mDayOfMonth;
146
0
      mMonth = rhs.mMonth;
147
0
      mYear = rhs.mYear;
148
0
      mHour = rhs.mHour;
149
0
      mMin = rhs.mMin;
150
0
      mSec = rhs.mSec;
151
0
   }
152
0
   return *this;
153
0
}
154
155
bool 
156
DateCategory::setDatetime(time_t datetime)
157
0
{
158
0
   struct tm gmt;
159
#if defined(WIN32)
160
   if (gmtime_s(&gmt, &datetime) != 0)
161
   {
162
      int e = getErrno();
163
      DebugLog(<< "Failed to convert to gmt: " << strError(e));
164
      Transport::error(e);
165
      return false;
166
   }
167
#else
168
   // gmtime_r is available on Linux, Solaris, and other POSIX platforms
169
0
   if (gmtime_r(&datetime, &gmt) == 0)
170
0
   {
171
0
      int e = getErrno();
172
0
      DebugLog(<< "Failed to convert to gmt: " << strError(e));
173
0
      Transport::error(e);
174
0
      return false;
175
0
   }
176
0
#endif
177
178
0
   mDayOfWeek = static_cast<DayOfWeek>(gmt.tm_wday);
179
0
   mDayOfMonth = gmt.tm_mday;
180
0
   mMonth = static_cast<Month>(gmt.tm_mon);
181
0
   mYear = gmt.tm_year + 1900;
182
0
   mHour = gmt.tm_hour;
183
0
   mMin = gmt.tm_min;
184
0
   mSec = gmt.tm_sec;
185
0
   DebugLog (<< "Set date: day=" << mDayOfWeek 
186
0
             << " month=" << mMonth
187
0
             << " year=" << mYear
188
0
             << " " << mHour << ":" << mMin << ":" << mSec);
189
0
   return true;
190
0
}
191
192
DayOfWeek
193
DateCategory::DayOfWeekFromData(const Data& dow)
194
872
{
195
872
   const char *str = dow.data();
196
872
   Data::size_type len = dow.size();
197
198
872
   const struct days* _day = DayOfWeekHash::in_word_set(str, len);
199
872
   if(_day != 0)
200
1
   {
201
1
      return _day->type;
202
1
   }
203
871
   else
204
871
   {
205
871
      return Sun;
206
871
   }
207
872
}
208
209
Month
210
DateCategory::MonthFromData(const Data& mon)
211
374
{
212
374
   const char *str = mon.data();
213
374
   Data::size_type len = mon.size();
214
215
374
   const struct months* _month = MonthHash::in_word_set(str, len);
216
374
   if(_month != 0)
217
1
   {
218
1
      return _month->type;
219
1
   }
220
373
   else
221
373
   {
222
373
      return Jan;
223
373
   }
224
374
}
225
226
const DayOfWeek& 
227
DateCategory::dayOfWeek() const 
228
0
{
229
0
   checkParsed();
230
0
   return mDayOfWeek;
231
0
}
232
233
int&
234
DateCategory::dayOfMonth() 
235
0
{
236
0
   checkParsed();
237
0
   return mDayOfMonth;
238
0
}
239
240
int 
241
DateCategory::dayOfMonth() const 
242
0
{
243
0
   checkParsed();
244
0
   return mDayOfMonth;
245
0
}
246
247
Month& 
248
DateCategory::month() 
249
0
{
250
0
   checkParsed();
251
0
   return mMonth;
252
0
}
253
254
Month
255
DateCategory::month() const
256
0
{
257
0
   checkParsed();
258
0
   return mMonth;
259
0
}
260
261
int& 
262
DateCategory::year() 
263
0
{
264
0
   checkParsed();
265
0
   return mYear;
266
0
}
267
268
int
269
DateCategory::year() const 
270
0
{
271
0
   checkParsed();
272
0
   return mYear;
273
0
}
274
275
int&
276
DateCategory::hour() 
277
0
{
278
0
   checkParsed();
279
0
   return mHour;
280
0
}
281
282
int
283
DateCategory::hour() const 
284
0
{
285
0
   checkParsed();
286
0
   return mHour;
287
0
}
288
289
int&
290
DateCategory::minute() 
291
0
{
292
0
   checkParsed();
293
0
   return mMin;
294
0
}
295
296
int
297
DateCategory::minute() const 
298
0
{
299
0
   checkParsed();
300
0
   return mMin;
301
0
}
302
303
int&
304
DateCategory::second() 
305
0
{
306
0
   checkParsed();
307
0
   return mSec;
308
0
}
309
310
int
311
DateCategory::second() const 
312
0
{
313
0
   checkParsed();
314
0
   return mSec;
315
0
}
316
317
void
318
DateCategory::parse(ParseBuffer& pb)
319
6.55k
{
320
   // Mon, 04 Nov 2002 17:34:15 GMT
321
   // Note: Day of Week is optional, so this is also valid: 04 Nov 2002 17:34:15 GMT
322
323
6.55k
   const char* anchor = pb.skipWhitespace();
324
325
   // If comma is present, then DayOfWeek is present
326
6.55k
   pb.skipToChar(Symbols::COMMA[0]);
327
6.55k
   if (!pb.eof())
328
872
   {
329
872
      Data dayOfWeek;
330
872
      pb.data(dayOfWeek, anchor);
331
872
      mDayOfWeek = DateCategory::DayOfWeekFromData(dayOfWeek);
332
333
872
      pb.skipChar(Symbols::COMMA[0]);
334
872
   }
335
5.67k
   else
336
5.67k
   {
337
5.67k
      pb.reset(pb.start());
338
5.67k
      mDayOfWeek = DayOfWeek::NA;
339
5.67k
   }
340
341
6.55k
   pb.skipWhitespace();
342
343
6.55k
   mDayOfMonth = pb.integer();
344
345
6.55k
   anchor = pb.skipWhitespace();
346
6.55k
   pb.skipNonWhitespace();
347
348
6.55k
   Data month;
349
6.55k
   pb.data(month, anchor);
350
6.55k
   mMonth = DateCategory::MonthFromData(month);
351
352
6.55k
   pb.skipWhitespace();
353
6.55k
   mYear = pb.integer();
354
355
6.55k
   pb.skipWhitespace();
356
357
6.55k
   mHour = pb.integer();
358
6.55k
   pb.skipChar(Symbols::COLON[0]);
359
6.55k
   mMin = pb.integer();
360
6.55k
   pb.skipChar(Symbols::COLON[0]);
361
6.55k
   mSec = pb.integer();
362
363
6.55k
   pb.skipWhitespace();
364
6.55k
   pb.skipChar('G');
365
6.55k
   pb.skipChar('M');
366
6.55k
   pb.skipChar('T');
367
368
6.55k
   pb.skipWhitespace();
369
6.55k
   pb.assertEof();
370
6.55k
}
371
372
ParserCategory* 
373
DateCategory::clone() const
374
0
{
375
0
   return new DateCategory(*this);
376
0
}
377
378
ParserCategory* 
379
DateCategory::clone(void* location) const
380
0
{
381
0
   return new (location) DateCategory(*this);
382
0
}
383
384
ParserCategory* 
385
DateCategory::clone(PoolBase* pool) const
386
0
{
387
0
   return new (pool) DateCategory(*this, pool);
388
0
}
389
390
static void pad2(const int x, EncodeStream& str)
391
0
{
392
0
   if (x < 10)
393
0
   {
394
0
      str << Symbols::ZERO[0];
395
0
   }
396
0
   str << x;
397
0
}
398
399
EncodeStream& 
400
DateCategory::encodeParsed(EncodeStream& str) const
401
0
{
402
0
   if (mDayOfWeek != DayOfWeek::NA)
403
0
   {
404
0
      str << DayOfWeekData[mDayOfWeek] // Mon
405
0
         << Symbols::COMMA[0] << Symbols::SPACE[0];
406
0
   }
407
   
408
0
   pad2(mDayOfMonth, str);  //  04
409
410
0
   str << Symbols::SPACE[0]
411
0
       << MonthData[mMonth] << Symbols::SPACE[0] // Nov
412
0
       << mYear << Symbols::SPACE[0]; // 2002
413
414
0
   pad2(mHour, str);
415
0
   str << Symbols::COLON[0];
416
0
   pad2(mMin, str);
417
0
   str << Symbols::COLON[0];
418
0
   pad2(mSec, str);
419
0
   str << " GMT";
420
421
0
   return str;
422
0
}
423
424
425
/* ====================================================================
426
 * The Vovida Software License, Version 1.0 
427
 * 
428
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
429
 * 
430
 * Redistribution and use in source and binary forms, with or without
431
 * modification, are permitted provided that the following conditions
432
 * are met:
433
 * 
434
 * 1. Redistributions of source code must retain the above copyright
435
 *    notice, this list of conditions and the following disclaimer.
436
 * 
437
 * 2. Redistributions in binary form must reproduce the above copyright
438
 *    notice, this list of conditions and the following disclaimer in
439
 *    the documentation and/or other materials provided with the
440
 *    distribution.
441
 * 
442
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
443
 *    and "Vovida Open Communication Application Library (VOCAL)" must
444
 *    not be used to endorse or promote products derived from this
445
 *    software without prior written permission. For written
446
 *    permission, please contact vocal@vovida.org.
447
 *
448
 * 4. Products derived from this software may not be called "VOCAL", nor
449
 *    may "VOCAL" appear in their name, without prior written
450
 *    permission of Vovida Networks, Inc.
451
 * 
452
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
453
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
454
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
455
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
456
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
457
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
458
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
459
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
460
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
461
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
462
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
463
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
464
 * DAMAGE.
465
 * 
466
 * ====================================================================
467
 * 
468
 * This software consists of voluntary contributions made by Vovida
469
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
470
 * Inc.  For more information on Vovida Networks, Inc., please see
471
 * <http://www.vovida.org/>.
472
 *
473
 */