Coverage Report

Created: 2025-11-05 06:27

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.07k
   : ParserCategory(hfv, type, pool),
117
6.07k
     mDayOfWeek(Sun),
118
     mDayOfMonth(),
119
6.07k
     mMonth(Jan),
120
6.07k
     mYear(0),
121
6.07k
     mHour(0),
122
6.07k
     mMin(0),
123
6.07k
     mSec(0)
124
6.07k
{}
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) || defined(__sun)
160
   struct tm *gmtp = gmtime(&datetime);
161
   if (gmtp == 0)
162
   {
163
        int e = getErrno();
164
        DebugLog (<< "Failed to convert to gmt: " << strerror(e));
165
        Transport::error(e);
166
        return false;
167
   }
168
   memcpy(&gmt,gmtp,sizeof(gmt));
169
#else
170
0
  if (gmtime_r(&datetime, &gmt) == 0)
171
0
  {
172
0
     int e = getErrno();
173
0
     DebugLog (<< "Failed to convert to gmt: " << strerror(e));
174
0
     Transport::error(e);
175
0
     return false;
176
0
  }
177
0
#endif
178
179
0
   mDayOfWeek = static_cast<DayOfWeek>(gmt.tm_wday);
180
0
   mDayOfMonth = gmt.tm_mday;
181
0
   mMonth = static_cast<Month>(gmt.tm_mon);
182
0
   mYear = gmt.tm_year + 1900;
183
0
   mHour = gmt.tm_hour;
184
0
   mMin = gmt.tm_min;
185
0
   mSec = gmt.tm_sec;
186
0
   DebugLog (<< "Set date: day=" << mDayOfWeek 
187
0
             << " month=" << mMonth
188
0
             << " year=" << mYear
189
0
             << " " << mHour << ":" << mMin << ":" << mSec);
190
0
   return true;
191
0
}
192
193
DayOfWeek
194
DateCategory::DayOfWeekFromData(const Data& dow)
195
881
{
196
881
   const char *str = dow.data();
197
881
   Data::size_type len = dow.size();
198
199
881
   const struct days* _day = DayOfWeekHash::in_word_set(str, len);
200
881
   if(_day != 0)
201
1
   {
202
1
      return _day->type;
203
1
   }
204
880
   else
205
880
   {
206
880
      return Sun;
207
880
   }
208
881
}
209
210
Month
211
DateCategory::MonthFromData(const Data& mon)
212
339
{
213
339
   const char *str = mon.data();
214
339
   Data::size_type len = mon.size();
215
216
339
   const struct months* _month = MonthHash::in_word_set(str, len);
217
339
   if(_month != 0)
218
1
   {
219
1
      return _month->type;
220
1
   }
221
338
   else
222
338
   {
223
338
      return Jan;
224
338
   }
225
339
}
226
227
const DayOfWeek& 
228
DateCategory::dayOfWeek() const 
229
0
{
230
0
   checkParsed();
231
0
   return mDayOfWeek;
232
0
}
233
234
int&
235
DateCategory::dayOfMonth() 
236
0
{
237
0
   checkParsed();
238
0
   return mDayOfMonth;
239
0
}
240
241
int 
242
DateCategory::dayOfMonth() const 
243
0
{
244
0
   checkParsed();
245
0
   return mDayOfMonth;
246
0
}
247
248
Month& 
249
DateCategory::month() 
250
0
{
251
0
   checkParsed();
252
0
   return mMonth;
253
0
}
254
255
Month
256
DateCategory::month() const
257
0
{
258
0
   checkParsed();
259
0
   return mMonth;
260
0
}
261
262
int& 
263
DateCategory::year() 
264
0
{
265
0
   checkParsed();
266
0
   return mYear;
267
0
}
268
269
int
270
DateCategory::year() const 
271
0
{
272
0
   checkParsed();
273
0
   return mYear;
274
0
}
275
276
int&
277
DateCategory::hour() 
278
0
{
279
0
   checkParsed();
280
0
   return mHour;
281
0
}
282
283
int
284
DateCategory::hour() const 
285
0
{
286
0
   checkParsed();
287
0
   return mHour;
288
0
}
289
290
int&
291
DateCategory::minute() 
292
0
{
293
0
   checkParsed();
294
0
   return mMin;
295
0
}
296
297
int
298
DateCategory::minute() const 
299
0
{
300
0
   checkParsed();
301
0
   return mMin;
302
0
}
303
304
int&
305
DateCategory::second() 
306
0
{
307
0
   checkParsed();
308
0
   return mSec;
309
0
}
310
311
int
312
DateCategory::second() const 
313
0
{
314
0
   checkParsed();
315
0
   return mSec;
316
0
}
317
318
void
319
DateCategory::parse(ParseBuffer& pb)
320
6.07k
{
321
   // Mon, 04 Nov 2002 17:34:15 GMT
322
   // Note: Day of Week is optional, so this is also valid: 04 Nov 2002 17:34:15 GMT
323
324
6.07k
   const char* anchor = pb.skipWhitespace();
325
326
   // If comma is present, then DayOfWeek is present
327
6.07k
   pb.skipToChar(Symbols::COMMA[0]);
328
6.07k
   if (!pb.eof())
329
881
   {
330
881
      Data dayOfWeek;
331
881
      pb.data(dayOfWeek, anchor);
332
881
      mDayOfWeek = DateCategory::DayOfWeekFromData(dayOfWeek);
333
334
881
      pb.skipChar(Symbols::COMMA[0]);
335
881
   }
336
5.19k
   else
337
5.19k
   {
338
5.19k
      pb.reset(pb.start());
339
5.19k
      mDayOfWeek = DayOfWeek::NA;
340
5.19k
   }
341
342
6.07k
   pb.skipWhitespace();
343
344
6.07k
   mDayOfMonth = pb.integer();
345
346
6.07k
   anchor = pb.skipWhitespace();
347
6.07k
   pb.skipNonWhitespace();
348
349
6.07k
   Data month;
350
6.07k
   pb.data(month, anchor);
351
6.07k
   mMonth = DateCategory::MonthFromData(month);
352
353
6.07k
   pb.skipWhitespace();
354
6.07k
   mYear = pb.integer();
355
356
6.07k
   pb.skipWhitespace();
357
358
6.07k
   mHour = pb.integer();
359
6.07k
   pb.skipChar(Symbols::COLON[0]);
360
6.07k
   mMin = pb.integer();
361
6.07k
   pb.skipChar(Symbols::COLON[0]);
362
6.07k
   mSec = pb.integer();
363
364
6.07k
   pb.skipWhitespace();
365
6.07k
   pb.skipChar('G');
366
6.07k
   pb.skipChar('M');
367
6.07k
   pb.skipChar('T');
368
369
6.07k
   pb.skipWhitespace();
370
6.07k
   pb.assertEof();
371
6.07k
}
372
373
ParserCategory* 
374
DateCategory::clone() const
375
0
{
376
0
   return new DateCategory(*this);
377
0
}
378
379
ParserCategory* 
380
DateCategory::clone(void* location) const
381
0
{
382
0
   return new (location) DateCategory(*this);
383
0
}
384
385
ParserCategory* 
386
DateCategory::clone(PoolBase* pool) const
387
0
{
388
0
   return new (pool) DateCategory(*this, pool);
389
0
}
390
391
static void pad2(const int x, EncodeStream& str)
392
0
{
393
0
   if (x < 10)
394
0
   {
395
0
      str << Symbols::ZERO[0];
396
0
   }
397
0
   str << x;
398
0
}
399
400
EncodeStream& 
401
DateCategory::encodeParsed(EncodeStream& str) const
402
0
{
403
0
   if (mDayOfWeek != DayOfWeek::NA)
404
0
   {
405
0
      str << DayOfWeekData[mDayOfWeek] // Mon
406
0
         << Symbols::COMMA[0] << Symbols::SPACE[0];
407
0
   }
408
   
409
0
   pad2(mDayOfMonth, str);  //  04
410
411
0
   str << Symbols::SPACE[0]
412
0
       << MonthData[mMonth] << Symbols::SPACE[0] // Nov
413
0
       << mYear << Symbols::SPACE[0]; // 2002
414
415
0
   pad2(mHour, str);
416
0
   str << Symbols::COLON[0];
417
0
   pad2(mMin, str);
418
0
   str << Symbols::COLON[0];
419
0
   pad2(mSec, str);
420
0
   str << " GMT";
421
422
0
   return str;
423
0
}
424
425
426
/* ====================================================================
427
 * The Vovida Software License, Version 1.0 
428
 * 
429
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
430
 * 
431
 * Redistribution and use in source and binary forms, with or without
432
 * modification, are permitted provided that the following conditions
433
 * are met:
434
 * 
435
 * 1. Redistributions of source code must retain the above copyright
436
 *    notice, this list of conditions and the following disclaimer.
437
 * 
438
 * 2. Redistributions in binary form must reproduce the above copyright
439
 *    notice, this list of conditions and the following disclaimer in
440
 *    the documentation and/or other materials provided with the
441
 *    distribution.
442
 * 
443
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
444
 *    and "Vovida Open Communication Application Library (VOCAL)" must
445
 *    not be used to endorse or promote products derived from this
446
 *    software without prior written permission. For written
447
 *    permission, please contact vocal@vovida.org.
448
 *
449
 * 4. Products derived from this software may not be called "VOCAL", nor
450
 *    may "VOCAL" appear in their name, without prior written
451
 *    permission of Vovida Networks, Inc.
452
 * 
453
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
454
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
455
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
456
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
457
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
458
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
459
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
460
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
461
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
462
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
463
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
464
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
465
 * DAMAGE.
466
 * 
467
 * ====================================================================
468
 * 
469
 * This software consists of voluntary contributions made by Vovida
470
 * Networks, Inc. and many individuals on behalf of Vovida Networks,
471
 * Inc.  For more information on Vovida Networks, Inc., please see
472
 * <http://www.vovida.org/>.
473
 *
474
 */