tmrec.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. */
  23. /**
  24. * Time Recurence Library according to iCalendar (RFC 2445)
  25. * - implemented at FhG Fokus, 2003 - external link:
  26. * https://github.com/miconda/tmrec
  27. * - this is a clone adapted for kamailio/ser
  28. */
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <time.h>
  32. #include "../../mem/mem.h"
  33. #include "tmrec.h"
  34. /**
  35. * ===== imported from "utils.h"
  36. */
  37. static inline int tr_strz_to_int(char *_bp)
  38. {
  39. int _v;
  40. char *_p;
  41. if(!_bp)
  42. return 0;
  43. _v = 0;
  44. _p = _bp;
  45. while(*_p && *_p>='0' && *_p<='9')
  46. {
  47. _v += *_p - '0';
  48. _p++;
  49. }
  50. return _v;
  51. }
  52. static inline char* tr_trim(char* _s)
  53. {
  54. int len;
  55. char* end;
  56. /* Null pointer, there is nothing to do */
  57. if (!_s) return _s;
  58. /* Remove spaces and tabs from the beginning of string */
  59. while ((*_s == ' ') || (*_s == '\t')) _s++;
  60. len = strlen(_s);
  61. end = _s + len - 1;
  62. /* Remove trailing spaces and tabs */
  63. while ((*end == ' ') || (*end == '\t')) end--;
  64. if (end != (_s + len - 1)) {
  65. *(end+1) = '\0';
  66. }
  67. return _s;
  68. }
  69. /**
  70. * ===== imported from "ac_tm.c"
  71. */
  72. /* #define USE_YWEEK_U // Sunday system
  73. * #define USE_YWEEK_V // ISO 8601
  74. */
  75. #ifndef USE_YWEEK_U
  76. #ifndef USE_YWEEK_V
  77. #ifndef USE_YWEEK_W
  78. #define USE_YWEEK_W /* Monday system */.
  79. #endif
  80. #endif
  81. #endif
  82. #ifdef USE_YWEEK_U
  83. #define SUN_WEEK(t) (int)(((t)->tm_yday + 7 - \
  84. ((t)->tm_wday)) / 7)
  85. #else
  86. #define MON_WEEK(t) (int)(((t)->tm_yday + 7 - \
  87. ((t)->tm_wday ? (t)->tm_wday - 1 : 6)) / 7)
  88. #endif
  89. #define ac_get_wday_yr(t) (int)((t)->tm_yday/7)
  90. #define ac_get_wday_mr(t) (int)(((t)->tm_mday-1)/7)
  91. ac_tm_t *ac_tm_new(void)
  92. {
  93. ac_tm_t *_atp = NULL;
  94. _atp = (ac_tm_t*)pkg_malloc(sizeof(ac_tm_t));
  95. if(!_atp)
  96. return NULL;
  97. memset(_atp, 0, sizeof(ac_tm_t));
  98. return _atp;
  99. }
  100. int ac_tm_fill(ac_tm_t *_atp, struct tm* _tm)
  101. {
  102. if(!_atp || !_tm)
  103. return -1;
  104. _atp->t.tm_sec = _tm->tm_sec; /* seconds */
  105. _atp->t.tm_min = _tm->tm_min; /* minutes */
  106. _atp->t.tm_hour = _tm->tm_hour; /* hours */
  107. _atp->t.tm_mday = _tm->tm_mday; /* day of the month */
  108. _atp->t.tm_mon = _tm->tm_mon; /* month */
  109. _atp->t.tm_year = _tm->tm_year; /* year */
  110. _atp->t.tm_wday = _tm->tm_wday; /* day of the week */
  111. _atp->t.tm_yday = _tm->tm_yday; /* day in the year */
  112. _atp->t.tm_isdst = _tm->tm_isdst; /* daylight saving time */
  113. _atp->mweek = ac_get_mweek(_tm);
  114. _atp->yweek = ac_get_yweek(_tm);
  115. _atp->ywday = ac_get_wday_yr(_tm);
  116. _atp->mwday = ac_get_wday_mr(_tm);
  117. return 0;
  118. }
  119. int ac_tm_set_time(ac_tm_t *_atp, time_t _t)
  120. {
  121. if(!_atp)
  122. return -1;
  123. _atp->time = _t;
  124. return ac_tm_fill(_atp, localtime(&_t));
  125. }
  126. int ac_get_mweek(struct tm* _tm)
  127. {
  128. if(!_tm)
  129. return -1;
  130. #ifdef USE_YWEEK_U
  131. return ((_tm->tm_mday-1)/7 + (7-_tm->tm_wday+(_tm->tm_mday-1)%7)/7);
  132. #else
  133. return ((_tm->tm_mday-1)/7 + (7-(6+_tm->tm_wday)%7+(_tm->tm_mday-1)%7)/7);
  134. #endif
  135. }
  136. int ac_get_yweek(struct tm* _tm)
  137. {
  138. int week = -1;
  139. #ifdef USE_YWEEK_V
  140. int days;
  141. #endif
  142. if(!_tm)
  143. return -1;
  144. #ifdef USE_YWEEK_U
  145. week = SUN_WEEK(_tm);
  146. #else
  147. week = MON_WEEK(_tm);
  148. #endif
  149. #ifdef USE_YWEEK_V
  150. days = ((_tm->tm_yday + 7 - (_tm->tm_wday ? _tm->tm_wday-1 : 6)) % 7);
  151. if(days >= 4)
  152. week++;
  153. else
  154. if(week == 0)
  155. week = 53;
  156. #endif
  157. return week;
  158. }
  159. int ac_get_wkst(void)
  160. {
  161. #ifdef USE_YWEEK_U
  162. return 0;
  163. #else
  164. return 1;
  165. #endif
  166. }
  167. int ac_tm_reset(ac_tm_t *_atp)
  168. {
  169. if(!_atp)
  170. return -1;
  171. memset(_atp, 0, sizeof(ac_tm_t));
  172. return 0;
  173. }
  174. int ac_tm_free(ac_tm_t *_atp)
  175. {
  176. if(!_atp)
  177. return -1;
  178. if(_atp->mv)
  179. pkg_free(_atp->mv);
  180. pkg_free(_atp);
  181. return 0;
  182. }
  183. int ac_tm_destroy(ac_tm_t *_atp)
  184. {
  185. if(!_atp)
  186. return -1;
  187. if(_atp->mv)
  188. pkg_free(_atp->mv);
  189. return 0;
  190. }
  191. ac_maxval_t *ac_get_maxval(ac_tm_t *_atp)
  192. {
  193. struct tm _tm;
  194. int _v;
  195. ac_maxval_t *_amp = NULL;
  196. if(!_atp)
  197. return NULL;
  198. _amp = (ac_maxval_t*)pkg_malloc(sizeof(ac_maxval_t));
  199. if(!_amp)
  200. return NULL;
  201. /* the number of the days in the year */
  202. _amp->yday = 365 + tr_is_leap_year(_atp->t.tm_year+1900);
  203. /* the number of the days in the month */
  204. switch(_atp->t.tm_mon)
  205. {
  206. case 1:
  207. if(_amp->yday == 366)
  208. _amp->mday = 29;
  209. else
  210. _amp->mday = 28;
  211. break;
  212. case 3: case 5: case 8: case 10:
  213. _amp->mday = 30;
  214. break;
  215. default:
  216. _amp->mday = 31;
  217. }
  218. /* maximum occurrences of a week day in the year */
  219. memset(&_tm, 0, sizeof(struct tm));
  220. _tm.tm_year = _atp->t.tm_year;
  221. _tm.tm_mon = 11;
  222. _tm.tm_mday = 31;
  223. mktime(&_tm);
  224. _v = 0;
  225. if(_atp->t.tm_wday > _tm.tm_wday)
  226. _v = _atp->t.tm_wday - _tm.tm_wday + 1;
  227. else
  228. _v = _tm.tm_wday - _atp->t.tm_wday;
  229. _amp->ywday = (int)((_tm.tm_yday-_v)/7) + 1;
  230. /* maximum number of weeks in the year */
  231. _amp->yweek = ac_get_yweek(&_tm) + 1;
  232. /* maximum number of the week day in the month */
  233. _amp->mwday=(int)((_amp->mday-1-(_amp->mday-_atp->t.tm_mday)%7)/7)+1;
  234. /* maximum number of weeks in the month */
  235. _v = (_atp->t.tm_wday + (_amp->mday - _atp->t.tm_mday)%7)%7;
  236. #ifdef USE_YWEEK_U
  237. _amp->mweek = (int)((_amp->mday-1)/7+(7-_v+(_amp->mday-1)%7)/7)+1;
  238. #else
  239. _amp->mweek = (int)((_amp->mday-1)/7+(7-(6+_v)%7+(_amp->mday-1)%7)/7)+1;
  240. #endif
  241. _atp->mv = _amp;
  242. return _amp;
  243. }
  244. int ac_print(ac_tm_t *_atp)
  245. {
  246. static char *_wdays[] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
  247. if(!_atp)
  248. {
  249. printf("\n(null)\n");
  250. return -1;
  251. }
  252. printf("\nSys time: %d\nTime: %02d:%02d:%02d\n", (int)_atp->time,
  253. _atp->t.tm_hour, _atp->t.tm_min, _atp->t.tm_sec);
  254. printf("Date: %s, %04d-%02d-%02d\n", _wdays[_atp->t.tm_wday],
  255. _atp->t.tm_year+1900, _atp->t.tm_mon+1, _atp->t.tm_mday);
  256. printf("Year day: %d\nYear week-day: %d\nYear week: %d\n", _atp->t.tm_yday,
  257. _atp->ywday, _atp->yweek);
  258. printf("Month week: %d\nMonth week-day: %d\n", _atp->mweek, _atp->mwday);
  259. if(_atp->mv)
  260. {
  261. printf("Max ydays: %d\nMax yweeks: %d\nMax yweekday: %d\n",
  262. _atp->mv->yday, _atp->mv->yweek, _atp->mv->ywday);;
  263. printf("Max mdays: %d\nMax mweeks: %d\nMax mweekday: %d\n",
  264. _atp->mv->mday, _atp->mv->mweek, _atp->mv->mwday);;
  265. }
  266. return 0;
  267. }
  268. /************************ imported from "tmrec.c" ***************************/
  269. #define _D(c) ((c) -'0')
  270. tr_byxxx_t *tr_byxxx_new(void)
  271. {
  272. tr_byxxx_t *_bxp = NULL;
  273. _bxp = (tr_byxxx_t*)pkg_malloc(sizeof(tr_byxxx_t));
  274. if(!_bxp)
  275. return NULL;
  276. memset(_bxp, 0, sizeof(tr_byxxx_t));
  277. return _bxp;
  278. }
  279. int tr_byxxx_init(tr_byxxx_t *_bxp, int _nr)
  280. {
  281. if(!_bxp)
  282. return -1;
  283. _bxp->nr = _nr;
  284. _bxp->xxx = (int*)pkg_malloc(_nr*sizeof(int));
  285. if(!_bxp->xxx)
  286. return -1;
  287. _bxp->req = (int*)pkg_malloc(_nr*sizeof(int));
  288. if(!_bxp->req)
  289. {
  290. pkg_free(_bxp->xxx);
  291. _bxp->xxx = NULL;
  292. return -1;
  293. }
  294. memset(_bxp->xxx, 0, _nr*sizeof(int));
  295. memset(_bxp->req, 0, _nr*sizeof(int));
  296. return 0;
  297. }
  298. int tr_byxxx_free(tr_byxxx_t *_bxp)
  299. {
  300. if(!_bxp)
  301. return -1;
  302. if(_bxp->xxx)
  303. pkg_free(_bxp->xxx);
  304. if(_bxp->req)
  305. pkg_free(_bxp->req);
  306. pkg_free(_bxp);
  307. return 0;
  308. }
  309. tmrec_t *tmrec_new(void)
  310. {
  311. tmrec_t *_trp = NULL;
  312. _trp = (tmrec_t*)pkg_malloc(sizeof(tmrec_t));
  313. if(!_trp)
  314. return NULL;
  315. memset(_trp, 0, sizeof(tmrec_t));
  316. localtime_r(&_trp->dtstart,&(_trp->ts));
  317. return _trp;
  318. }
  319. int tmrec_free(tmrec_t *_trp)
  320. {
  321. if(!_trp)
  322. return -1;
  323. tr_byxxx_free(_trp->byday);
  324. tr_byxxx_free(_trp->bymday);
  325. tr_byxxx_free(_trp->byyday);
  326. tr_byxxx_free(_trp->bymonth);
  327. tr_byxxx_free(_trp->byweekno);
  328. pkg_free(_trp);
  329. return 0;
  330. }
  331. int tmrec_destroy(tmrec_t *_trp)
  332. {
  333. if(!_trp)
  334. return -1;
  335. tr_byxxx_free(_trp->byday);
  336. tr_byxxx_free(_trp->bymday);
  337. tr_byxxx_free(_trp->byyday);
  338. tr_byxxx_free(_trp->bymonth);
  339. tr_byxxx_free(_trp->byweekno);
  340. return 0;
  341. }
  342. int tr_parse_dtstart(tmrec_t *_trp, char *_in)
  343. {
  344. if(!_trp || !_in)
  345. return -1;
  346. _trp->dtstart = ic_parse_datetime(_in, &(_trp->ts));
  347. return (_trp->dtstart==0)?-1:0;
  348. }
  349. int tr_parse_dtend(tmrec_t *_trp, char *_in)
  350. {
  351. struct tm _tm;
  352. if(!_trp || !_in)
  353. return -1;
  354. _trp->dtend = ic_parse_datetime(_in,&_tm);
  355. return (_trp->dtend==0)?-1:0;
  356. }
  357. int tr_parse_duration(tmrec_t *_trp, char *_in)
  358. {
  359. if(!_trp || !_in)
  360. return -1;
  361. _trp->duration = ic_parse_duration(_in);
  362. return (_trp->duration==0)?-1:0;
  363. }
  364. int tr_parse_until(tmrec_t *_trp, char *_in)
  365. {
  366. struct tm _tm;
  367. if(!_trp || !_in)
  368. return -1;
  369. _trp->until = ic_parse_datetime(_in, &_tm);
  370. return (_trp->until==0)?-1:0;
  371. }
  372. int tr_parse_freq(tmrec_t *_trp, char *_in)
  373. {
  374. if(!_trp || !_in)
  375. return -1;
  376. if(!strcasecmp(_in, "daily"))
  377. {
  378. _trp->freq = FREQ_DAILY;
  379. return 0;
  380. }
  381. if(!strcasecmp(_in, "weekly"))
  382. {
  383. _trp->freq = FREQ_WEEKLY;
  384. return 0;
  385. }
  386. if(!strcasecmp(_in, "monthly"))
  387. {
  388. _trp->freq = FREQ_MONTHLY;
  389. return 0;
  390. }
  391. if(!strcasecmp(_in, "yearly"))
  392. {
  393. _trp->freq = FREQ_YEARLY;
  394. return 0;
  395. }
  396. _trp->freq = FREQ_NOFREQ;
  397. return 0;
  398. }
  399. int tr_parse_interval(tmrec_t *_trp, char *_in)
  400. {
  401. if(!_trp || !_in)
  402. return -1;
  403. _trp->interval = tr_strz_to_int(_in);
  404. return 0;
  405. }
  406. int tr_parse_byday(tmrec_t *_trp, char *_in)
  407. {
  408. if(!_trp || !_in)
  409. return -1;
  410. _trp->byday = ic_parse_byday(_in);
  411. return 0;
  412. }
  413. int tr_parse_bymday(tmrec_t *_trp, char *_in)
  414. {
  415. if(!_trp || !_in)
  416. return -1;
  417. _trp->bymday = ic_parse_byxxx(_in);
  418. return 0;
  419. }
  420. int tr_parse_byyday(tmrec_t *_trp, char *_in)
  421. {
  422. if(!_trp || !_in)
  423. return -1;
  424. _trp->byyday = ic_parse_byxxx(_in);
  425. return 0;
  426. }
  427. int tr_parse_bymonth(tmrec_t *_trp, char *_in)
  428. {
  429. if(!_trp || !_in)
  430. return -1;
  431. _trp->bymonth = ic_parse_byxxx(_in);
  432. return 0;
  433. }
  434. int tr_parse_byweekno(tmrec_t *_trp, char *_in)
  435. {
  436. if(!_trp || !_in)
  437. return -1;
  438. _trp->byweekno = ic_parse_byxxx(_in);
  439. return 0;
  440. }
  441. int tr_parse_wkst(tmrec_t *_trp, char *_in)
  442. {
  443. if(!_trp || !_in)
  444. return -1;
  445. _trp->wkst = ic_parse_wkst(_in);
  446. return 0;
  447. }
  448. int tr_print(tmrec_t *_trp)
  449. {
  450. static char *_wdays[] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
  451. int i;
  452. if(!_trp)
  453. {
  454. printf("\n(null)\n");
  455. return -1;
  456. }
  457. printf("Recurrence definition\n-- start time ---\n");
  458. printf("Sys time: %d\n", (int)_trp->dtstart);
  459. printf("Time: %02d:%02d:%02d\n", _trp->ts.tm_hour,
  460. _trp->ts.tm_min, _trp->ts.tm_sec);
  461. printf("Date: %s, %04d-%02d-%02d\n", _wdays[_trp->ts.tm_wday],
  462. _trp->ts.tm_year+1900, _trp->ts.tm_mon+1, _trp->ts.tm_mday);
  463. printf("---\n");
  464. printf("End time: %d\n", (int)_trp->dtend);
  465. printf("Duration: %d\n", (int)_trp->duration);
  466. printf("Until: %d\n", (int)_trp->until);
  467. printf("Freq: %d\n", (int)_trp->freq);
  468. printf("Interval: %d\n", (int)_trp->interval);
  469. if(_trp->byday)
  470. {
  471. printf("Byday: ");
  472. for(i=0; i<_trp->byday->nr; i++)
  473. printf(" %d%s", _trp->byday->req[i], _wdays[_trp->byday->xxx[i]]);
  474. printf("\n");
  475. }
  476. if(_trp->bymday)
  477. {
  478. printf("Bymday: %d:", _trp->bymday->nr);
  479. for(i=0; i<_trp->bymday->nr; i++)
  480. printf(" %d", _trp->bymday->xxx[i]*_trp->bymday->req[i]);
  481. printf("\n");
  482. }
  483. if(_trp->byyday)
  484. {
  485. printf("Byyday:");
  486. for(i=0; i<_trp->byyday->nr; i++)
  487. printf(" %d", _trp->byyday->xxx[i]*_trp->byyday->req[i]);
  488. printf("\n");
  489. }
  490. if(_trp->bymonth)
  491. {
  492. printf("Bymonth: %d:", _trp->bymonth->nr);
  493. for(i=0; i< _trp->bymonth->nr; i++)
  494. printf(" %d", _trp->bymonth->xxx[i]*_trp->bymonth->req[i]);
  495. printf("\n");
  496. }
  497. if(_trp->byweekno)
  498. {
  499. printf("Byweekno: ");
  500. for(i=0; i<_trp->byweekno->nr; i++)
  501. printf(" %d", _trp->byweekno->xxx[i]*_trp->byweekno->req[i]);
  502. printf("\n");
  503. }
  504. printf("Weekstart: %d\n", _trp->wkst);
  505. return 0;
  506. }
  507. time_t ic_parse_datetime(char *_in, struct tm *_tm)
  508. {
  509. if(!_in || !_tm || strlen(_in)!=15)
  510. return 0;
  511. memset(_tm, 0, sizeof(struct tm));
  512. _tm->tm_year = _D(_in[0])*1000 + _D(_in[1])*100
  513. + _D(_in[2])*10 + _D(_in[3]) - 1900;
  514. _tm->tm_mon = _D(_in[4])*10 + _D(_in[5]) - 1;
  515. _tm->tm_mday = _D(_in[6])*10 + _D(_in[7]);
  516. _tm->tm_hour = _D(_in[9])*10 + _D(_in[10]);
  517. _tm->tm_min = _D(_in[11])*10 + _D(_in[12]);
  518. _tm->tm_sec = _D(_in[13])*10 + _D(_in[14]);
  519. _tm->tm_isdst = -1 /*daylight*/;
  520. return mktime(_tm);
  521. }
  522. time_t ic_parse_duration(char *_in)
  523. {
  524. time_t _t, _ft;
  525. char *_p;
  526. int _fl;
  527. if(!_in || (*_in!='+' && *_in!='-' && *_in!='P' && *_in!='p'))
  528. return 0;
  529. if(*_in == 'P' || *_in=='p')
  530. _p = _in+1;
  531. else
  532. {
  533. if(strlen(_in)<2 || (_in[1]!='P' && _in[1]!='p'))
  534. return 0;
  535. _p = _in+2;
  536. }
  537. _t = _ft = 0;
  538. _fl = 1;
  539. while(*_p)
  540. {
  541. switch(*_p)
  542. {
  543. case '0': case '1': case '2':
  544. case '3': case '4': case '5':
  545. case '6': case '7': case '8':
  546. case '9':
  547. _t = _t*10 + *_p - '0';
  548. break;
  549. case 'w':
  550. case 'W':
  551. if(!_fl)
  552. return 0;
  553. _ft += _t*7*24*3600;
  554. _t = 0;
  555. break;
  556. case 'd':
  557. case 'D':
  558. if(!_fl)
  559. return 0;
  560. _ft += _t*24*3600;
  561. _t = 0;
  562. break;
  563. case 'h':
  564. case 'H':
  565. if(_fl)
  566. return 0;
  567. _ft += _t*3600;
  568. _t = 0;
  569. break;
  570. case 'm':
  571. case 'M':
  572. if(_fl)
  573. return 0;
  574. _ft += _t*60;
  575. _t = 0;
  576. break;
  577. case 's':
  578. case 'S':
  579. if(_fl)
  580. return 0;
  581. _ft += _t;
  582. _t = 0;
  583. break;
  584. case 't':
  585. case 'T':
  586. if(!_fl)
  587. return 0;
  588. _fl = 0;
  589. break;
  590. default:
  591. return 0;
  592. }
  593. _p++;
  594. }
  595. return _ft;
  596. }
  597. tr_byxxx_t *ic_parse_byday(char *_in)
  598. {
  599. tr_byxxx_t *_bxp = NULL;
  600. int _nr, _s, _v;
  601. char *_p;
  602. if(!_in)
  603. return NULL;
  604. _bxp = tr_byxxx_new();
  605. if(!_bxp)
  606. return NULL;
  607. _p = _in;
  608. _nr = 1;
  609. while(*_p)
  610. {
  611. if(*_p == ',')
  612. _nr++;
  613. _p++;
  614. }
  615. if(tr_byxxx_init(_bxp, _nr) < 0)
  616. {
  617. tr_byxxx_free(_bxp);
  618. return NULL;
  619. }
  620. _p = _in;
  621. _nr = _v = 0;
  622. _s = 1;
  623. while(*_p && _nr < _bxp->nr)
  624. {
  625. switch(*_p)
  626. {
  627. case '0': case '1': case '2':
  628. case '3': case '4': case '5':
  629. case '6': case '7': case '8':
  630. case '9':
  631. _v = _v*10 + *_p - '0';
  632. break;
  633. case 's':
  634. case 'S':
  635. _p++;
  636. switch(*_p)
  637. {
  638. case 'a':
  639. case 'A':
  640. _bxp->xxx[_nr] = WDAY_SA;
  641. _bxp->req[_nr] = _s*_v;
  642. break;
  643. case 'u':
  644. case 'U':
  645. _bxp->xxx[_nr] = WDAY_SU;
  646. _bxp->req[_nr] = _s*_v;
  647. break;
  648. default:
  649. goto error;
  650. }
  651. _s = 1;
  652. _v = 0;
  653. break;
  654. case 'm':
  655. case 'M':
  656. _p++;
  657. if(*_p!='o' && *_p!='O')
  658. goto error;
  659. _bxp->xxx[_nr] = WDAY_MO;
  660. _bxp->req[_nr] = _s*_v;
  661. _s = 1;
  662. _v = 0;
  663. break;
  664. case 't':
  665. case 'T':
  666. _p++;
  667. switch(*_p)
  668. {
  669. case 'h':
  670. case 'H':
  671. _bxp->xxx[_nr] = WDAY_TH;
  672. _bxp->req[_nr] = _s*_v;
  673. break;
  674. case 'u':
  675. case 'U':
  676. _bxp->xxx[_nr] = WDAY_TU;
  677. _bxp->req[_nr] = _s*_v;
  678. break;
  679. default:
  680. goto error;
  681. }
  682. _s = 1;
  683. _v = 0;
  684. break;
  685. case 'w':
  686. case 'W':
  687. _p++;
  688. if(*_p!='e' && *_p!='E')
  689. goto error;
  690. _bxp->xxx[_nr] = WDAY_WE;
  691. _bxp->req[_nr] = _s*_v;
  692. _s = 1;
  693. _v = 0;
  694. break;
  695. case 'f':
  696. case 'F':
  697. _p++;
  698. if(*_p!='r' && *_p!='R')
  699. goto error;
  700. _bxp->xxx[_nr] = WDAY_FR;
  701. _bxp->req[_nr] = _s*_v;
  702. _s = 1;
  703. _v = 0;
  704. break;
  705. case '-':
  706. _s = -1;
  707. break;
  708. case '+':
  709. case ' ':
  710. case '\t':
  711. break;
  712. case ',':
  713. _nr++;
  714. break;
  715. default:
  716. goto error;
  717. }
  718. _p++;
  719. }
  720. return _bxp;
  721. error:
  722. tr_byxxx_free(_bxp);
  723. return NULL;
  724. }
  725. tr_byxxx_t *ic_parse_byxxx(char *_in)
  726. {
  727. tr_byxxx_t *_bxp = NULL;
  728. int _nr, _s, _v;
  729. char *_p;
  730. if(!_in)
  731. return NULL;
  732. _bxp = tr_byxxx_new();
  733. if(!_bxp)
  734. return NULL;
  735. _p = _in;
  736. _nr = 1;
  737. while(*_p)
  738. {
  739. if(*_p == ',')
  740. _nr++;
  741. _p++;
  742. }
  743. if(tr_byxxx_init(_bxp, _nr) < 0)
  744. {
  745. tr_byxxx_free(_bxp);
  746. return NULL;
  747. }
  748. _p = _in;
  749. _nr = _v = 0;
  750. _s = 1;
  751. while(*_p && _nr < _bxp->nr)
  752. {
  753. switch(*_p)
  754. {
  755. case '0': case '1': case '2':
  756. case '3': case '4': case '5':
  757. case '6': case '7': case '8':
  758. case '9':
  759. _v = _v*10 + *_p - '0';
  760. break;
  761. case '-':
  762. _s = -1;
  763. break;
  764. case '+':
  765. case ' ':
  766. case '\t':
  767. break;
  768. case ',':
  769. _bxp->xxx[_nr] = _v;
  770. _bxp->req[_nr] = _s;
  771. _s = 1;
  772. _v = 0;
  773. _nr++;
  774. break;
  775. default:
  776. goto error;
  777. }
  778. _p++;
  779. }
  780. if(_nr < _bxp->nr)
  781. {
  782. _bxp->xxx[_nr] = _v;
  783. _bxp->req[_nr] = _s;
  784. }
  785. return _bxp;
  786. error:
  787. tr_byxxx_free(_bxp);
  788. return NULL;
  789. }
  790. int ic_parse_wkst(char *_in)
  791. {
  792. if(!_in || strlen(_in)!=2)
  793. goto error;
  794. switch(_in[0])
  795. {
  796. case 's':
  797. case 'S':
  798. switch(_in[1])
  799. {
  800. case 'a':
  801. case 'A':
  802. return WDAY_SA;
  803. case 'u':
  804. case 'U':
  805. return WDAY_SU;
  806. default:
  807. goto error;
  808. }
  809. case 'm':
  810. case 'M':
  811. if(_in[1]!='o' && _in[1]!='O')
  812. goto error;
  813. return WDAY_MO;
  814. case 't':
  815. case 'T':
  816. switch(_in[1])
  817. {
  818. case 'h':
  819. case 'H':
  820. return WDAY_TH;
  821. case 'u':
  822. case 'U':
  823. return WDAY_TU;
  824. default:
  825. goto error;
  826. }
  827. case 'w':
  828. case 'W':
  829. if(_in[1]!='e' && _in[1]!='E')
  830. goto error;
  831. return WDAY_WE;
  832. case 'f':
  833. case 'F':
  834. if(_in[1]!='r' && _in[1]!='R')
  835. goto error;
  836. return WDAY_FR;
  837. break;
  838. default:
  839. goto error;
  840. }
  841. error:
  842. #ifdef USE_YWEEK_U
  843. return WDAY_SU;
  844. #else
  845. return WDAY_MO;
  846. #endif
  847. }
  848. /**
  849. * =====imported from "checktr.c"
  850. */
  851. #define REC_ERR -1
  852. #define REC_MATCH 0
  853. #define REC_NOMATCH 1
  854. #define _IS_SET(x) (((x)>0)?1:0)
  855. /*** local headers ***/
  856. int get_min_interval(tmrec_t*);
  857. int check_min_unit(tmrec_t*, ac_tm_t*, tr_res_t*);
  858. int check_freq_interval(tmrec_t *_trp, ac_tm_t *_atp);
  859. int check_byxxx(tmrec_t*, ac_tm_t*);
  860. /**
  861. *
  862. * return 0/REC_MATCH - the time falls in
  863. * -1/REC_ERR - error
  864. * 1/REC_NOMATCH - the time falls out
  865. */
  866. int tr_check_recurrence(tmrec_t *_trp, ac_tm_t *_atp, tr_res_t *_tsw)
  867. {
  868. if(!_trp || !_atp || (!_IS_SET(_trp->duration) && !_IS_SET(_trp->dtend)))
  869. return REC_ERR;
  870. /* it is before start date */
  871. if(_atp->time < _trp->dtstart)
  872. return REC_NOMATCH;
  873. /* compute the duration of the recurrence interval */
  874. if(!_IS_SET(_trp->duration))
  875. _trp->duration = _trp->dtend - _trp->dtstart;
  876. if(_atp->time <= _trp->dtstart+_trp->duration)
  877. {
  878. if(_tsw)
  879. {
  880. if(_tsw->flag & TSW_RSET)
  881. {
  882. if(_tsw->rest>_trp->dtstart+_trp->duration-_atp->time)
  883. _tsw->rest = _trp->dtstart+_trp->duration - _atp->time;
  884. }
  885. else
  886. {
  887. _tsw->flag |= TSW_RSET;
  888. _tsw->rest = _trp->dtstart+_trp->duration - _atp->time;
  889. }
  890. }
  891. return REC_MATCH;
  892. }
  893. /* after the bound of recurrence */
  894. if(_IS_SET(_trp->until) && _atp->time >= _trp->until + _trp->duration)
  895. return REC_NOMATCH;
  896. /* check if the instance of recurrence matches the 'interval' */
  897. if(check_freq_interval(_trp, _atp)!=REC_MATCH)
  898. return REC_NOMATCH;
  899. if(check_min_unit(_trp, _atp, _tsw)!=REC_MATCH)
  900. return REC_NOMATCH;
  901. if(check_byxxx(_trp, _atp)!=REC_MATCH)
  902. return REC_NOMATCH;
  903. return REC_MATCH;
  904. }
  905. int check_freq_interval(tmrec_t *_trp, ac_tm_t *_atp)
  906. {
  907. int _t0, _t1;
  908. struct tm _tm;
  909. if(!_trp || !_atp)
  910. return REC_ERR;
  911. if(!_IS_SET(_trp->freq))
  912. return REC_NOMATCH;
  913. if(!_IS_SET(_trp->interval) || _trp->interval==1)
  914. return REC_MATCH;
  915. switch(_trp->freq)
  916. {
  917. case FREQ_DAILY:
  918. case FREQ_WEEKLY:
  919. memset(&_tm, 0, sizeof(struct tm));
  920. _tm.tm_year = _trp->ts.tm_year;
  921. _tm.tm_mon = _trp->ts.tm_mon;
  922. _tm.tm_mday = _trp->ts.tm_mday;
  923. _t0 = (int)mktime(&_tm);
  924. memset(&_tm, 0, sizeof(struct tm));
  925. _tm.tm_year = _atp->t.tm_year;
  926. _tm.tm_mon = _atp->t.tm_mon;
  927. _tm.tm_mday = _atp->t.tm_mday;
  928. _t1 = (int)mktime(&_tm);
  929. if(_trp->freq == FREQ_DAILY)
  930. return (((_t1-_t0)/(24*3600))%_trp->interval==0)?
  931. REC_MATCH:REC_NOMATCH;
  932. #ifdef USE_YWEEK_U
  933. _t0 -= _trp->ts.tm_wday*24*3600;
  934. _t1 -= _atp->t.tm_wday*24*3600;
  935. #else
  936. _t0 -= ((_trp->ts.tm_wday+6)%7)*24*3600;
  937. _t1 -= ((_atp->t.tm_wday+6)%7)*24*3600;
  938. #endif
  939. return (((_t1-_t0)/(7*24*3600))%_trp->interval==0)?
  940. REC_MATCH:REC_NOMATCH;
  941. case FREQ_MONTHLY:
  942. _t0 = (_atp->t.tm_year-_trp->ts.tm_year)*12
  943. + _atp->t.tm_mon-_trp->ts.tm_mon;
  944. return (_t0%_trp->interval==0)?REC_MATCH:REC_NOMATCH;
  945. case FREQ_YEARLY:
  946. return ((_atp->t.tm_year-_trp->ts.tm_year)%_trp->interval==0)?
  947. REC_MATCH:REC_NOMATCH;
  948. }
  949. return REC_NOMATCH;
  950. }
  951. int get_min_interval(tmrec_t *_trp)
  952. {
  953. if(!_trp)
  954. return FREQ_NOFREQ;
  955. if(_trp->freq == FREQ_DAILY || _trp->byday || _trp->bymday || _trp->byyday)
  956. return FREQ_DAILY;
  957. if(_trp->freq == FREQ_WEEKLY || _trp->byweekno)
  958. return FREQ_WEEKLY;
  959. if(_trp->freq == FREQ_MONTHLY || _trp->bymonth)
  960. return FREQ_MONTHLY;
  961. if(_trp->freq == FREQ_YEARLY)
  962. return FREQ_YEARLY;
  963. return FREQ_NOFREQ;
  964. }
  965. int check_min_unit(tmrec_t *_trp, ac_tm_t *_atp, tr_res_t *_tsw)
  966. {
  967. int _v0, _v1;
  968. if(!_trp || !_atp)
  969. return REC_ERR;
  970. switch(get_min_interval(_trp))
  971. {
  972. case FREQ_DAILY:
  973. break;
  974. case FREQ_WEEKLY:
  975. if(_trp->ts.tm_wday != _atp->t.tm_wday)
  976. return REC_NOMATCH;
  977. break;
  978. case FREQ_MONTHLY:
  979. if(_trp->ts.tm_mday != _atp->t.tm_mday)
  980. return REC_NOMATCH;
  981. break;
  982. case FREQ_YEARLY:
  983. if(_trp->ts.tm_mon != _atp->t.tm_mon
  984. || _trp->ts.tm_mday != _atp->t.tm_mday)
  985. return REC_NOMATCH;
  986. break;
  987. default:
  988. return REC_NOMATCH;
  989. }
  990. _v0 = _trp->ts.tm_hour*3600 + _trp->ts.tm_min*60 + _trp->ts.tm_sec;
  991. _v1 = _atp->t.tm_hour*3600 + _atp->t.tm_min*60 + _atp->t.tm_sec;
  992. if(_v1 >= _v0 && _v1 < _v0 + _trp->duration)
  993. {
  994. if(_tsw)
  995. {
  996. if(_tsw->flag & TSW_RSET)
  997. {
  998. if(_tsw->rest>_v0+_trp->duration-_v1)
  999. _tsw->rest = _v0 + _trp->duration - _v1;
  1000. }
  1001. else
  1002. {
  1003. _tsw->flag |= TSW_RSET;
  1004. _tsw->rest = _v0 + _trp->duration - _v1;
  1005. }
  1006. }
  1007. return REC_MATCH;
  1008. }
  1009. return REC_NOMATCH;
  1010. }
  1011. int check_byxxx(tmrec_t *_trp, ac_tm_t *_atp)
  1012. {
  1013. int i;
  1014. ac_maxval_t *_amp = NULL;
  1015. if(!_trp || !_atp)
  1016. return REC_ERR;
  1017. if(!_trp->byday && !_trp->bymday && !_trp->byyday && !_trp->bymonth
  1018. && !_trp->byweekno)
  1019. return REC_MATCH;
  1020. _amp = ac_get_maxval(_atp);
  1021. if(!_amp)
  1022. return REC_NOMATCH;
  1023. if(_trp->bymonth)
  1024. {
  1025. for(i=0; i<_trp->bymonth->nr; i++)
  1026. {
  1027. if(_atp->t.tm_mon ==
  1028. (_trp->bymonth->xxx[i]*_trp->bymonth->req[i]+12)%12)
  1029. break;
  1030. }
  1031. if(i>=_trp->bymonth->nr)
  1032. return REC_NOMATCH;
  1033. }
  1034. if(_trp->freq==FREQ_YEARLY && _trp->byweekno)
  1035. {
  1036. for(i=0; i<_trp->byweekno->nr; i++)
  1037. {
  1038. if(_atp->yweek == (_trp->byweekno->xxx[i]*_trp->byweekno->req[i]+
  1039. _amp->yweek)%_amp->yweek)
  1040. break;
  1041. }
  1042. if(i>=_trp->byweekno->nr)
  1043. return REC_NOMATCH;
  1044. }
  1045. if(_trp->byyday)
  1046. {
  1047. for(i=0; i<_trp->byyday->nr; i++)
  1048. {
  1049. if(_atp->t.tm_yday == (_trp->byyday->xxx[i]*_trp->byyday->req[i]+
  1050. _amp->yday)%_amp->yday)
  1051. break;
  1052. }
  1053. if(i>=_trp->byyday->nr)
  1054. return REC_NOMATCH;
  1055. }
  1056. if(_trp->bymday)
  1057. {
  1058. for(i=0; i<_trp->bymday->nr; i++)
  1059. {
  1060. #ifdef EXTRA_DEBUG
  1061. DBG("Req:bymday: %d == %d\n", _atp->t.tm_mday,
  1062. (_trp->bymday->xxx[i]*_trp->bymday->req[i]+
  1063. _amp->mday)%_amp->mday + ((_trp->bymday->req[i]<0)?1:0));
  1064. #endif
  1065. if(_atp->t.tm_mday == (_trp->bymday->xxx[i]*_trp->bymday->req[i]+
  1066. _amp->mday)%_amp->mday + (_trp->bymday->req[i]<0)?1:0)
  1067. break;
  1068. }
  1069. if(i>=_trp->bymday->nr)
  1070. return REC_NOMATCH;
  1071. }
  1072. if(_trp->byday)
  1073. {
  1074. for(i=0; i<_trp->byday->nr; i++)
  1075. {
  1076. if(_trp->freq==FREQ_YEARLY)
  1077. {
  1078. #ifdef EXTRA_DEBUG
  1079. DBG("Req:byday:y: %d==%d && %d==%d\n", _atp->t.tm_wday,
  1080. _trp->byday->xxx[i], _atp->ywday+1,
  1081. (_trp->byday->req[i]+_amp->ywday)%_amp->ywday);
  1082. #endif
  1083. if(_atp->t.tm_wday == _trp->byday->xxx[i] &&
  1084. _atp->ywday+1 == (_trp->byday->req[i]+_amp->ywday)%
  1085. _amp->ywday)
  1086. break;
  1087. }
  1088. else
  1089. {
  1090. if(_trp->freq==FREQ_MONTHLY)
  1091. {
  1092. #ifdef EXTRA_DEBUG
  1093. DBG("Req:byday:m: %d==%d && %d==%d\n", _atp->t.tm_wday,
  1094. _trp->byday->xxx[i], _atp->mwday+1,
  1095. (_trp->byday->req[i]+_amp->mwday)%_amp->mwday);
  1096. #endif
  1097. if(_atp->t.tm_wday == _trp->byday->xxx[i] &&
  1098. _atp->mwday+1==(_trp->byday->req[i]+
  1099. _amp->mwday)%_amp->mwday)
  1100. break;
  1101. }
  1102. else
  1103. {
  1104. if(_atp->t.tm_wday == _trp->byday->xxx[i])
  1105. break;
  1106. }
  1107. }
  1108. }
  1109. if(i>=_trp->byday->nr)
  1110. return REC_NOMATCH;
  1111. }
  1112. return REC_MATCH;
  1113. }
  1114. int tr_parse_recurrence_string(tmrec_t *trp, char *rdef, char sep)
  1115. {
  1116. char *p;
  1117. char *s;
  1118. int type;
  1119. type = 0;
  1120. p = rdef;
  1121. memset(trp, 0, sizeof(tmrec_t));
  1122. do{
  1123. s = strchr(p, (int)sep);
  1124. if (s!=NULL)
  1125. *s = '\0';
  1126. /* LM_DBG("----- parsing tr param <%s>\n", p); */
  1127. if(s != p) {
  1128. switch(type) {
  1129. case 0:
  1130. if(tr_parse_dtstart(trp, p)<0)
  1131. goto error;
  1132. break;
  1133. case 1:
  1134. if(tr_parse_duration(trp, p)<0)
  1135. goto error;
  1136. break;
  1137. case 2:
  1138. if(tr_parse_freq(trp, p)<0)
  1139. goto error;
  1140. break;
  1141. case 3:
  1142. if(tr_parse_until(trp, p)<0)
  1143. goto error;
  1144. break;
  1145. case 4:
  1146. if(tr_parse_interval(trp, p)<0)
  1147. goto error;
  1148. break;
  1149. case 5:
  1150. if(tr_parse_byday(trp, p)<0)
  1151. goto error;
  1152. break;
  1153. case 6:
  1154. if(tr_parse_bymday(trp, p)<0)
  1155. goto error;
  1156. break;
  1157. case 7:
  1158. if(tr_parse_byyday(trp, p)<0)
  1159. goto error;
  1160. break;
  1161. case 8:
  1162. if(tr_parse_byweekno(trp, p)<0)
  1163. goto error;
  1164. break;
  1165. case 9:
  1166. if(tr_parse_bymonth(trp, p)<0)
  1167. goto error;
  1168. break;
  1169. }
  1170. }
  1171. type++;
  1172. if (s!=NULL) {
  1173. *s = sep;
  1174. p = s + 1;
  1175. if(*p==0)
  1176. goto done;
  1177. } else {
  1178. goto done;
  1179. }
  1180. } while(1);
  1181. done:
  1182. return 0;
  1183. error:
  1184. LM_ERR("failed to parse time recurrence [%s]\n", rdef);
  1185. if (s!=NULL)
  1186. *s = sep;
  1187. return -1;
  1188. }