dr_time.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2005-2009 Voice Sistem SRL
  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. * History:
  23. * ---------
  24. * 2005-02-27 ported to 0.9.0 (bogdan)
  25. */
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <time.h>
  29. #include "../../mem/shm_mem.h"
  30. #include "dr_time.h"
  31. /************************ imported from "utils.h" ***************************/
  32. static inline int strz2int(char *_bp)
  33. {
  34. int _v;
  35. char *_p;
  36. if(!_bp)
  37. return 0;
  38. _v = 0;
  39. _p = _bp;
  40. while(*_p && *_p>='0' && *_p<='9')
  41. {
  42. _v += *_p - '0';
  43. _p++;
  44. }
  45. return _v;
  46. }
  47. static inline char* trim(char* _s)
  48. {
  49. int len;
  50. char* end;
  51. /* Null pointer, there is nothing to do */
  52. if (!_s) return _s;
  53. /* Remove spaces and tabs from the beginning of string */
  54. while ((*_s == ' ') || (*_s == '\t')) _s++;
  55. len = strlen(_s);
  56. end = _s + len - 1;
  57. /* Remove trailing spaces and tabs */
  58. while ((*end == ' ') || (*end == '\t')) end--;
  59. if (end != (_s + len - 1)) {
  60. *(end+1) = '\0';
  61. }
  62. return _s;
  63. }
  64. /************************ imported from "ac_tm.c" ***************************/
  65. /* #define USE_YWEEK_U // Sunday system
  66. * #define USE_YWEEK_V // ISO 8601
  67. */
  68. #ifndef USE_YWEEK_U
  69. #ifndef USE_YWEEK_V
  70. #ifndef USE_YWEEK_W
  71. #define USE_YWEEK_W /* Monday system */
  72. #endif
  73. #endif
  74. #endif
  75. #ifdef USE_YWEEK_U
  76. #define SUN_WEEK(t) (int)(((t)->tm_yday + 7 - \
  77. ((t)->tm_wday)) / 7)
  78. #else
  79. #define MON_WEEK(t) (int)(((t)->tm_yday + 7 - \
  80. ((t)->tm_wday ? (t)->tm_wday - 1 : 6)) / 7)
  81. #endif
  82. #define ac_get_wday_yr(t) (int)((t)->tm_yday/7)
  83. #define ac_get_wday_mr(t) (int)(((t)->tm_mday-1)/7)
  84. ac_tm_p ac_tm_new(void)
  85. {
  86. ac_tm_p _atp = NULL;
  87. _atp = (ac_tm_p)shm_malloc(sizeof(ac_tm_t));
  88. if(!_atp)
  89. return NULL;
  90. memset(_atp, 0, sizeof(ac_tm_t));
  91. return _atp;
  92. }
  93. int ac_tm_fill(ac_tm_p _atp, struct tm* _tm)
  94. {
  95. if(!_atp || !_tm)
  96. return -1;
  97. _atp->t.tm_sec = _tm->tm_sec; /* seconds */
  98. _atp->t.tm_min = _tm->tm_min; /* minutes */
  99. _atp->t.tm_hour = _tm->tm_hour; /* hours */
  100. _atp->t.tm_mday = _tm->tm_mday; /* day of the month */
  101. _atp->t.tm_mon = _tm->tm_mon; /* month */
  102. _atp->t.tm_year = _tm->tm_year; /* year */
  103. _atp->t.tm_wday = _tm->tm_wday; /* day of the week */
  104. _atp->t.tm_yday = _tm->tm_yday; /* day in the year */
  105. _atp->t.tm_isdst = _tm->tm_isdst; /* daylight saving time */
  106. _atp->mweek = ac_get_mweek(_tm);
  107. _atp->yweek = ac_get_yweek(_tm);
  108. _atp->ywday = ac_get_wday_yr(_tm);
  109. _atp->mwday = ac_get_wday_mr(_tm);
  110. return 0;
  111. }
  112. int ac_tm_set_time(ac_tm_p _atp, time_t _t)
  113. {
  114. if(!_atp)
  115. return -1;
  116. _atp->time = _t;
  117. return ac_tm_fill(_atp, localtime(&_t));
  118. }
  119. int ac_get_mweek(struct tm* _tm)
  120. {
  121. if(!_tm)
  122. return -1;
  123. #ifdef USE_YWEEK_U
  124. return ((_tm->tm_mday-1)/7 + (7-_tm->tm_wday+(_tm->tm_mday-1)%7)/7);
  125. #else
  126. return ((_tm->tm_mday-1)/7 + (7-(6+_tm->tm_wday)%7+(_tm->tm_mday-1)%7)/7);
  127. #endif
  128. }
  129. int ac_get_yweek(struct tm* _tm)
  130. {
  131. int week = -1;
  132. #ifdef USE_YWEEK_V
  133. int days;
  134. #endif
  135. if(!_tm)
  136. return -1;
  137. #ifdef USE_YWEEK_U
  138. week = SUN_WEEK(_tm);
  139. #else
  140. week = MON_WEEK(_tm);
  141. #endif
  142. #ifdef USE_YWEEK_V
  143. days = ((_tm->tm_yday + 7 - (_tm->tm_wday ? _tm->tm_wday-1 : 6)) % 7);
  144. if(days >= 4)
  145. week++;
  146. else
  147. if(week == 0)
  148. week = 53;
  149. #endif
  150. return week;
  151. }
  152. int ac_get_wkst(void)
  153. {
  154. #ifdef USE_YWEEK_U
  155. return 0;
  156. #else
  157. return 1;
  158. #endif
  159. }
  160. int ac_tm_reset(ac_tm_p _atp)
  161. {
  162. if(!_atp)
  163. return -1;
  164. memset(_atp, 0, sizeof(ac_tm_t));
  165. return 0;
  166. }
  167. int ac_tm_free(ac_tm_p _atp)
  168. {
  169. if(!_atp)
  170. return -1;
  171. if(_atp->mv)
  172. shm_free(_atp->mv);
  173. shm_free(_atp);
  174. return 0;
  175. }
  176. ac_maxval_p ac_get_maxval(ac_tm_p _atp)
  177. {
  178. struct tm _tm;
  179. int _v;
  180. ac_maxval_p _amp = NULL;
  181. if(!_atp)
  182. return NULL;
  183. _amp = (ac_maxval_p)shm_malloc(sizeof(ac_maxval_t));
  184. if(!_amp)
  185. return NULL;
  186. /* the number of the days in the year */
  187. _amp->yday = 365 + is_leap_year(_atp->t.tm_year+1900);
  188. /* the number of the days in the month */
  189. switch(_atp->t.tm_mon)
  190. {
  191. case 1:
  192. if(_amp->yday == 366)
  193. _amp->mday = 29;
  194. else
  195. _amp->mday = 28;
  196. break;
  197. case 3: case 5: case 8: case 10:
  198. _amp->mday = 30;
  199. break;
  200. default:
  201. _amp->mday = 31;
  202. }
  203. /* maximum occurrences of a week day in the year */
  204. memset(&_tm, 0, sizeof(struct tm));
  205. _tm.tm_year = _atp->t.tm_year;
  206. _tm.tm_mon = 11;
  207. _tm.tm_mday = 31;
  208. mktime(&_tm);
  209. _v = 0;
  210. if(_atp->t.tm_wday > _tm.tm_wday)
  211. _v = _atp->t.tm_wday - _tm.tm_wday + 1;
  212. else
  213. _v = _tm.tm_wday - _atp->t.tm_wday;
  214. _amp->ywday = (int)((_tm.tm_yday-_v)/7) + 1;
  215. /* maximum number of weeks in the year */
  216. _amp->yweek = ac_get_yweek(&_tm) + 1;
  217. /* maximum number of the week day in the month */
  218. _amp->mwday=(int)((_amp->mday-1-(_amp->mday-_atp->t.tm_mday)%7)/7)+1;
  219. /* maximum number of weeks in the month */
  220. _v = (_atp->t.tm_wday + (_amp->mday - _atp->t.tm_mday)%7)%7;
  221. #ifdef USE_YWEEK_U
  222. _amp->mweek = (int)((_amp->mday-1)/7+(7-_v+(_amp->mday-1)%7)/7)+1;
  223. #else
  224. _amp->mweek = (int)((_amp->mday-1)/7+(7-(6+_v)%7+(_amp->mday-1)%7)/7)+1;
  225. #endif
  226. _atp->mv = _amp;
  227. return _amp;
  228. }
  229. /************************ imported from "tmrec.c" ***************************/
  230. #define _D(c) ((c) -'0')
  231. tr_byxxx_p tr_byxxx_new(void)
  232. {
  233. tr_byxxx_p _bxp = NULL;
  234. _bxp = (tr_byxxx_p)shm_malloc(sizeof(tr_byxxx_t));
  235. if(!_bxp)
  236. return NULL;
  237. memset(_bxp, 0, sizeof(tr_byxxx_t));
  238. return _bxp;
  239. }
  240. int tr_byxxx_init(tr_byxxx_p _bxp, int _nr)
  241. {
  242. if(!_bxp)
  243. return -1;
  244. _bxp->nr = _nr;
  245. _bxp->xxx = (int*)shm_malloc(_nr*sizeof(int));
  246. if(!_bxp->xxx)
  247. return -1;
  248. _bxp->req = (int*)shm_malloc(_nr*sizeof(int));
  249. if(!_bxp->req)
  250. {
  251. shm_free(_bxp->xxx);
  252. return -1;
  253. }
  254. memset(_bxp->xxx, 0, _nr*sizeof(int));
  255. memset(_bxp->req, 0, _nr*sizeof(int));
  256. return 0;
  257. }
  258. int tr_byxxx_free(tr_byxxx_p _bxp)
  259. {
  260. if(!_bxp)
  261. return -1;
  262. if(_bxp->xxx)
  263. shm_free(_bxp->xxx);
  264. if(_bxp->req)
  265. shm_free(_bxp->req);
  266. shm_free(_bxp);
  267. return 0;
  268. }
  269. tmrec_p tmrec_new(void)
  270. {
  271. tmrec_p _trp = NULL;
  272. _trp = (tmrec_p)shm_malloc(sizeof(tmrec_t));
  273. if(!_trp)
  274. return NULL;
  275. memset(_trp, 0, sizeof(tmrec_t));
  276. localtime_r(&_trp->dtstart,&(_trp->ts));
  277. return _trp;
  278. }
  279. int tmrec_free(tmrec_p _trp)
  280. {
  281. if(!_trp)
  282. return -1;
  283. tr_byxxx_free(_trp->byday);
  284. tr_byxxx_free(_trp->bymday);
  285. tr_byxxx_free(_trp->byyday);
  286. tr_byxxx_free(_trp->bymonth);
  287. tr_byxxx_free(_trp->byweekno);
  288. shm_free(_trp);
  289. return 0;
  290. }
  291. int tr_parse_dtstart(tmrec_p _trp, char *_in)
  292. {
  293. if(!_trp || !_in)
  294. return -1;
  295. _trp->dtstart = ic_parse_datetime(_in, &(_trp->ts));
  296. return (_trp->dtstart==0)?-1:0;
  297. }
  298. int tr_parse_dtend(tmrec_p _trp, char *_in)
  299. {
  300. struct tm _tm;
  301. if(!_trp || !_in)
  302. return -1;
  303. _trp->dtend = ic_parse_datetime(_in,&_tm);
  304. return (_trp->dtend==0)?-1:0;
  305. }
  306. int tr_parse_duration(tmrec_p _trp, char *_in)
  307. {
  308. if(!_trp || !_in)
  309. return -1;
  310. _trp->duration = ic_parse_duration(_in);
  311. return 0;
  312. }
  313. int tr_parse_until(tmrec_p _trp, char *_in)
  314. {
  315. struct tm _tm;
  316. if(!_trp || !_in)
  317. return -1;
  318. _trp->until = ic_parse_datetime(_in, &_tm);
  319. return 0;
  320. }
  321. int tr_parse_freq(tmrec_p _trp, char *_in)
  322. {
  323. if(!_trp || !_in)
  324. return -1;
  325. if(strlen(_in)<5)
  326. {
  327. _trp->freq = FREQ_NOFREQ;
  328. return 0;
  329. }
  330. if(!strcasecmp(_in, "daily"))
  331. {
  332. _trp->freq = FREQ_DAILY;
  333. return 0;
  334. }
  335. if(!strcasecmp(_in, "weekly"))
  336. {
  337. _trp->freq = FREQ_WEEKLY;
  338. return 0;
  339. }
  340. if(!strcasecmp(_in, "monthly"))
  341. {
  342. _trp->freq = FREQ_MONTHLY;
  343. return 0;
  344. }
  345. if(!strcasecmp(_in, "yearly"))
  346. {
  347. _trp->freq = FREQ_YEARLY;
  348. return 0;
  349. }
  350. _trp->freq = FREQ_NOFREQ;
  351. return 0;
  352. }
  353. int tr_parse_interval(tmrec_p _trp, char *_in)
  354. {
  355. if(!_trp || !_in)
  356. return -1;
  357. _trp->interval = strz2int(_in);
  358. return 0;
  359. }
  360. int tr_parse_byday(tmrec_p _trp, char *_in)
  361. {
  362. if(!_trp || !_in)
  363. return -1;
  364. _trp->byday = ic_parse_byday(_in);
  365. return 0;
  366. }
  367. int tr_parse_bymday(tmrec_p _trp, char *_in)
  368. {
  369. if(!_trp || !_in)
  370. return -1;
  371. _trp->bymday = ic_parse_byxxx(_in);
  372. return 0;
  373. }
  374. int tr_parse_byyday(tmrec_p _trp, char *_in)
  375. {
  376. if(!_trp || !_in)
  377. return -1;
  378. _trp->byyday = ic_parse_byxxx(_in);
  379. return 0;
  380. }
  381. int tr_parse_bymonth(tmrec_p _trp, char *_in)
  382. {
  383. if(!_trp || !_in)
  384. return -1;
  385. _trp->bymonth = ic_parse_byxxx(_in);
  386. return 0;
  387. }
  388. int tr_parse_byweekno(tmrec_p _trp, char *_in)
  389. {
  390. if(!_trp || !_in)
  391. return -1;
  392. _trp->byweekno = ic_parse_byxxx(_in);
  393. return 0;
  394. }
  395. int tr_parse_wkst(tmrec_p _trp, char *_in)
  396. {
  397. if(!_trp || !_in)
  398. return -1;
  399. _trp->wkst = ic_parse_wkst(_in);
  400. return 0;
  401. }
  402. time_t ic_parse_datetime(char *_in, struct tm *_tm)
  403. {
  404. if(!_in || !_tm || strlen(_in)!=15)
  405. return 0;
  406. memset(_tm, 0, sizeof(struct tm));
  407. _tm->tm_year = _D(_in[0])*1000 + _D(_in[1])*100
  408. + _D(_in[2])*10 + _D(_in[3]) - 1900;
  409. _tm->tm_mon = _D(_in[4])*10 + _D(_in[5]) - 1;
  410. _tm->tm_mday = _D(_in[6])*10 + _D(_in[7]);
  411. _tm->tm_hour = _D(_in[9])*10 + _D(_in[10]);
  412. _tm->tm_min = _D(_in[11])*10 + _D(_in[12]);
  413. _tm->tm_sec = _D(_in[13])*10 + _D(_in[14]);
  414. _tm->tm_isdst = -1 /*daylight*/;
  415. return mktime(_tm);
  416. }
  417. time_t ic_parse_duration(char *_in)
  418. {
  419. time_t _t, _ft;
  420. char *_p;
  421. int _fl;
  422. if(!_in || strlen(_in)<2)
  423. return 0;
  424. if(*_in == 'P' || *_in=='p')
  425. {
  426. _p = _in+1;
  427. _fl = 1;
  428. } else {
  429. _p = _in;
  430. _fl = 0;
  431. }
  432. _t = _ft = 0;
  433. while(*_p)
  434. {
  435. switch(*_p)
  436. {
  437. case '0': case '1': case '2':
  438. case '3': case '4': case '5':
  439. case '6': case '7': case '8':
  440. case '9':
  441. _t = _t*10 + *_p - '0';
  442. break;
  443. case 'w':
  444. case 'W':
  445. if(!_fl)
  446. {
  447. LM_ERR("week duration not allowed"
  448. " here (%d) [%s]\n", (int)(_p-_in), _in);
  449. return 0;
  450. }
  451. _ft += _t*7*24*3600;
  452. _t = 0;
  453. break;
  454. case 'd':
  455. case 'D':
  456. if(!_fl)
  457. {
  458. LM_ERR("day duration not allowed"
  459. " here (%d) [%s]\n", (int)(_p-_in), _in);
  460. return 0;
  461. }
  462. _ft += _t*24*3600;
  463. _t = 0;
  464. break;
  465. case 'h':
  466. case 'H':
  467. if(_fl)
  468. {
  469. LM_ERR("hour duration not allowed"
  470. " here (%d) [%s]\n", (int)(_p-_in), _in);
  471. return 0;
  472. }
  473. _ft += _t*3600;
  474. _t = 0;
  475. break;
  476. case 'm':
  477. case 'M':
  478. if(_fl)
  479. {
  480. LM_ERR("minute duration not allowed"
  481. " here (%d) [%s]\n", (int)(_p-_in), _in);
  482. return 0;
  483. }
  484. _ft += _t*60;
  485. _t = 0;
  486. break;
  487. case 's':
  488. case 'S':
  489. if(_fl)
  490. {
  491. LM_ERR("second duration not allowed"
  492. " here (%d) [%s]\n", (int)(_p-_in), _in);
  493. return 0;
  494. }
  495. _ft += _t;
  496. _t = 0;
  497. break;
  498. case 't':
  499. case 'T':
  500. if(!_fl)
  501. {
  502. LM_ERR("'T' not allowed"
  503. " here (%d) [%s]\n", (int)(_p-_in), _in);
  504. return 0;
  505. }
  506. _fl = 0;
  507. break;
  508. default:
  509. LM_ERR("bad character here (%d) [%s]\n",
  510. (int)(_p-_in), _in);
  511. return 0;
  512. }
  513. _p++;
  514. }
  515. return _ft;
  516. }
  517. tr_byxxx_p ic_parse_byday(char *_in)
  518. {
  519. tr_byxxx_p _bxp = NULL;
  520. int _nr, _s, _v;
  521. char *_p;
  522. if(!_in)
  523. return NULL;
  524. _bxp = tr_byxxx_new();
  525. if(!_bxp)
  526. return NULL;
  527. _p = _in;
  528. _nr = 1;
  529. while(*_p)
  530. {
  531. if(*_p == ',')
  532. _nr++;
  533. _p++;
  534. }
  535. if(tr_byxxx_init(_bxp, _nr) < 0)
  536. {
  537. tr_byxxx_free(_bxp);
  538. return NULL;
  539. }
  540. _p = _in;
  541. _nr = _v = 0;
  542. _s = 1;
  543. while(*_p && _nr < _bxp->nr)
  544. {
  545. switch(*_p)
  546. {
  547. case '0': case '1': case '2':
  548. case '3': case '4': case '5':
  549. case '6': case '7': case '8':
  550. case '9':
  551. _v = _v*10 + *_p - '0';
  552. break;
  553. case 's':
  554. case 'S':
  555. _p++;
  556. switch(*_p)
  557. {
  558. case 'a':
  559. case 'A':
  560. _bxp->xxx[_nr] = WDAY_SA;
  561. _bxp->req[_nr] = _s*_v;
  562. break;
  563. case 'u':
  564. case 'U':
  565. _bxp->xxx[_nr] = WDAY_SU;
  566. _bxp->req[_nr] = _s*_v;
  567. break;
  568. default:
  569. goto error;
  570. }
  571. _s = 1;
  572. _v = 0;
  573. break;
  574. case 'm':
  575. case 'M':
  576. _p++;
  577. if(*_p!='o' && *_p!='O')
  578. goto error;
  579. _bxp->xxx[_nr] = WDAY_MO;
  580. _bxp->req[_nr] = _s*_v;
  581. _s = 1;
  582. _v = 0;
  583. break;
  584. case 't':
  585. case 'T':
  586. _p++;
  587. switch(*_p)
  588. {
  589. case 'h':
  590. case 'H':
  591. _bxp->xxx[_nr] = WDAY_TH;
  592. _bxp->req[_nr] = _s*_v;
  593. break;
  594. case 'u':
  595. case 'U':
  596. _bxp->xxx[_nr] = WDAY_TU;
  597. _bxp->req[_nr] = _s*_v;
  598. break;
  599. default:
  600. goto error;
  601. }
  602. _s = 1;
  603. _v = 0;
  604. break;
  605. case 'w':
  606. case 'W':
  607. _p++;
  608. if(*_p!='e' && *_p!='E')
  609. goto error;
  610. _bxp->xxx[_nr] = WDAY_WE;
  611. _bxp->req[_nr] = _s*_v;
  612. _s = 1;
  613. _v = 0;
  614. break;
  615. case 'f':
  616. case 'F':
  617. _p++;
  618. if(*_p!='r' && *_p!='R')
  619. goto error;
  620. _bxp->xxx[_nr] = WDAY_FR;
  621. _bxp->req[_nr] = _s*_v;
  622. _s = 1;
  623. _v = 0;
  624. break;
  625. case '-':
  626. _s = -1;
  627. break;
  628. case '+':
  629. case ' ':
  630. case '\t':
  631. break;
  632. case ',':
  633. _nr++;
  634. break;
  635. default:
  636. goto error;
  637. }
  638. _p++;
  639. }
  640. return _bxp;
  641. error:
  642. tr_byxxx_free(_bxp);
  643. return NULL;
  644. }
  645. tr_byxxx_p ic_parse_byxxx(char *_in)
  646. {
  647. tr_byxxx_p _bxp = NULL;
  648. int _nr, _s, _v;
  649. char *_p;
  650. if(!_in)
  651. return NULL;
  652. _bxp = tr_byxxx_new();
  653. if(!_bxp)
  654. return NULL;
  655. _p = _in;
  656. _nr = 1;
  657. while(*_p)
  658. {
  659. if(*_p == ',')
  660. _nr++;
  661. _p++;
  662. }
  663. if(tr_byxxx_init(_bxp, _nr) < 0)
  664. {
  665. tr_byxxx_free(_bxp);
  666. return NULL;
  667. }
  668. _p = _in;
  669. _nr = _v = 0;
  670. _s = 1;
  671. while(*_p && _nr < _bxp->nr)
  672. {
  673. switch(*_p)
  674. {
  675. case '0': case '1': case '2':
  676. case '3': case '4': case '5':
  677. case '6': case '7': case '8':
  678. case '9':
  679. _v = _v*10 + *_p - '0';
  680. break;
  681. case '-':
  682. _s = -1;
  683. break;
  684. case '+':
  685. case ' ':
  686. case '\t':
  687. break;
  688. case ',':
  689. _bxp->xxx[_nr] = _v;
  690. _bxp->req[_nr] = _s;
  691. _s = 1;
  692. _v = 0;
  693. _nr++;
  694. break;
  695. default:
  696. goto error;
  697. }
  698. _p++;
  699. }
  700. if(_nr < _bxp->nr)
  701. {
  702. _bxp->xxx[_nr] = _v;
  703. _bxp->req[_nr] = _s;
  704. }
  705. return _bxp;
  706. error:
  707. tr_byxxx_free(_bxp);
  708. return NULL;
  709. }
  710. int ic_parse_wkst(char *_in)
  711. {
  712. if(!_in || strlen(_in)!=2)
  713. goto error;
  714. switch(_in[0])
  715. {
  716. case 's':
  717. case 'S':
  718. switch(_in[1])
  719. {
  720. case 'a':
  721. case 'A':
  722. return WDAY_SA;
  723. case 'u':
  724. case 'U':
  725. return WDAY_SU;
  726. default:
  727. goto error;
  728. }
  729. case 'm':
  730. case 'M':
  731. if(_in[1]!='o' && _in[1]!='O')
  732. goto error;
  733. return WDAY_MO;
  734. case 't':
  735. case 'T':
  736. switch(_in[1])
  737. {
  738. case 'h':
  739. case 'H':
  740. return WDAY_TH;
  741. case 'u':
  742. case 'U':
  743. return WDAY_TU;
  744. default:
  745. goto error;
  746. }
  747. case 'w':
  748. case 'W':
  749. if(_in[1]!='e' && _in[1]!='E')
  750. goto error;
  751. return WDAY_WE;
  752. case 'f':
  753. case 'F':
  754. if(_in[1]!='r' && _in[1]!='R')
  755. goto error;
  756. return WDAY_FR;
  757. break;
  758. default:
  759. goto error;
  760. }
  761. error:
  762. #ifdef USE_YWEEK_U
  763. return WDAY_SU;
  764. #else
  765. return WDAY_MO;
  766. #endif
  767. }
  768. /*********************** imported from "checktr.c" **************************/
  769. #define REC_ERR -1
  770. #define REC_MATCH 0
  771. #define REC_NOMATCH 1
  772. #define _IS_SET(x) (((x)>0)?1:0)
  773. /*** local headers ***/
  774. int get_min_interval(tmrec_p);
  775. int check_min_unit(tmrec_p, ac_tm_p, tr_res_p);
  776. int check_freq_interval(tmrec_p _trp, ac_tm_p _atp);
  777. int check_byxxx(tmrec_p, ac_tm_p);
  778. /**
  779. *
  780. * return 0/REC_MATCH - the time falls in
  781. * -1/REC_ERR - error
  782. * 1/REC_NOMATCH - the time falls out
  783. */
  784. int check_tmrec(tmrec_p _trp, ac_tm_p _atp, tr_res_p _tsw)
  785. {
  786. if(!_trp || !_atp)
  787. return REC_ERR;
  788. /* it is before start date */
  789. if(_atp->time < _trp->dtstart)
  790. return REC_NOMATCH;
  791. /* no duration or end -> for ever */
  792. if (!_IS_SET(_trp->duration) && !_IS_SET(_trp->dtend))
  793. return REC_MATCH;
  794. /* compute the duration of the recurrence interval */
  795. if(!_IS_SET(_trp->duration))
  796. _trp->duration = _trp->dtend - _trp->dtstart;
  797. if(_atp->time <= _trp->dtstart+_trp->duration)
  798. {
  799. if(_tsw)
  800. {
  801. if(_tsw->flag & TSW_RSET)
  802. {
  803. if(_tsw->rest>_trp->dtstart+_trp->duration-_atp->time)
  804. _tsw->rest = _trp->dtstart+_trp->duration - _atp->time;
  805. }
  806. else
  807. {
  808. _tsw->flag |= TSW_RSET;
  809. _tsw->rest = _trp->dtstart+_trp->duration - _atp->time;
  810. }
  811. }
  812. return REC_MATCH;
  813. }
  814. /* after the bound of recurrence */
  815. if(_IS_SET(_trp->until) && _atp->time >= _trp->until + _trp->duration)
  816. return REC_NOMATCH;
  817. /* check if the instance of recurrence matches the 'interval' */
  818. if(check_freq_interval(_trp, _atp)!=REC_MATCH)
  819. return REC_NOMATCH;
  820. if(check_min_unit(_trp, _atp, _tsw)!=REC_MATCH)
  821. return REC_NOMATCH;
  822. if(check_byxxx(_trp, _atp)!=REC_MATCH)
  823. return REC_NOMATCH;
  824. return REC_MATCH;
  825. }
  826. int check_freq_interval(tmrec_p _trp, ac_tm_p _atp)
  827. {
  828. int _t0, _t1;
  829. struct tm _tm;
  830. if(!_trp || !_atp)
  831. return REC_ERR;
  832. if(!_IS_SET(_trp->freq))
  833. return REC_NOMATCH;
  834. if(!_IS_SET(_trp->interval) || _trp->interval==1)
  835. return REC_MATCH;
  836. switch(_trp->freq)
  837. {
  838. case FREQ_DAILY:
  839. case FREQ_WEEKLY:
  840. memset(&_tm, 0, sizeof(struct tm));
  841. _tm.tm_year = _trp->ts.tm_year;
  842. _tm.tm_mon = _trp->ts.tm_mon;
  843. _tm.tm_mday = _trp->ts.tm_mday;
  844. _t0 = (int)mktime(&_tm);
  845. memset(&_tm, 0, sizeof(struct tm));
  846. _tm.tm_year = _atp->t.tm_year;
  847. _tm.tm_mon = _atp->t.tm_mon;
  848. _tm.tm_mday = _atp->t.tm_mday;
  849. _t1 = (int)mktime(&_tm);
  850. if(_trp->freq == FREQ_DAILY)
  851. return (((_t1-_t0)/(24*3600))%_trp->interval==0)?
  852. REC_MATCH:REC_NOMATCH;
  853. #ifdef USE_YWEEK_U
  854. _t0 -= _trp->ts.tm_wday*24*3600;
  855. _t1 -= _atp->t.tm_wday*24*3600;
  856. #else
  857. _t0 -= ((_trp->ts.tm_wday+6)%7)*24*3600;
  858. _t1 -= ((_atp->t.tm_wday+6)%7)*24*3600;
  859. #endif
  860. return (((_t1-_t0)/(7*24*3600))%_trp->interval==0)?
  861. REC_MATCH:REC_NOMATCH;
  862. case FREQ_MONTHLY:
  863. _t0 = (_atp->t.tm_year-_trp->ts.tm_year)*12
  864. + _atp->t.tm_mon-_trp->ts.tm_mon;
  865. return (_t0%_trp->interval==0)?REC_MATCH:REC_NOMATCH;
  866. case FREQ_YEARLY:
  867. return ((_atp->t.tm_year-_trp->ts.tm_year)%_trp->interval==0)?
  868. REC_MATCH:REC_NOMATCH;
  869. }
  870. return REC_NOMATCH;
  871. }
  872. int get_min_interval(tmrec_p _trp)
  873. {
  874. if(!_trp)
  875. return FREQ_NOFREQ;
  876. if(_trp->freq == FREQ_DAILY || _trp->byday || _trp->bymday || _trp->byyday)
  877. return FREQ_DAILY;
  878. if(_trp->freq == FREQ_WEEKLY || _trp->byweekno)
  879. return FREQ_WEEKLY;
  880. if(_trp->freq == FREQ_MONTHLY || _trp->bymonth)
  881. return FREQ_MONTHLY;
  882. if(_trp->freq == FREQ_YEARLY)
  883. return FREQ_YEARLY;
  884. return FREQ_NOFREQ;
  885. }
  886. int check_min_unit(tmrec_p _trp, ac_tm_p _atp, tr_res_p _tsw)
  887. {
  888. int _v0, _v1;
  889. if(!_trp || !_atp)
  890. return REC_ERR;
  891. switch(get_min_interval(_trp))
  892. {
  893. case FREQ_DAILY:
  894. break;
  895. case FREQ_WEEKLY:
  896. if(_trp->ts.tm_wday != _atp->t.tm_wday)
  897. return REC_NOMATCH;
  898. break;
  899. case FREQ_MONTHLY:
  900. if(_trp->ts.tm_mday != _atp->t.tm_mday)
  901. return REC_NOMATCH;
  902. break;
  903. case FREQ_YEARLY:
  904. if(_trp->ts.tm_mon != _atp->t.tm_mon
  905. || _trp->ts.tm_mday != _atp->t.tm_mday)
  906. return REC_NOMATCH;
  907. break;
  908. default:
  909. return REC_NOMATCH;
  910. }
  911. _v0 = _trp->ts.tm_hour*3600 + _trp->ts.tm_min*60 + _trp->ts.tm_sec;
  912. _v1 = _atp->t.tm_hour*3600 + _atp->t.tm_min*60 + _atp->t.tm_sec;
  913. if(_v1 >= _v0 && _v1 < _v0 + _trp->duration)
  914. {
  915. if(_tsw)
  916. {
  917. if(_tsw->flag & TSW_RSET)
  918. {
  919. if(_tsw->rest>_v0+_trp->duration-_v1)
  920. _tsw->rest = _v0 + _trp->duration - _v1;
  921. }
  922. else
  923. {
  924. _tsw->flag |= TSW_RSET;
  925. _tsw->rest = _v0 + _trp->duration - _v1;
  926. }
  927. }
  928. return REC_MATCH;
  929. }
  930. return REC_NOMATCH;
  931. }
  932. int check_byxxx(tmrec_p _trp, ac_tm_p _atp)
  933. {
  934. int i;
  935. ac_maxval_p _amp = NULL;
  936. if(!_trp || !_atp)
  937. return REC_ERR;
  938. if(!_trp->byday && !_trp->bymday && !_trp->byyday && !_trp->bymonth
  939. && !_trp->byweekno)
  940. return REC_MATCH;
  941. _amp = ac_get_maxval(_atp);
  942. if(!_amp)
  943. return REC_NOMATCH;
  944. if(_trp->bymonth)
  945. {
  946. for(i=0; i<_trp->bymonth->nr; i++)
  947. {
  948. if(_atp->t.tm_mon ==
  949. (_trp->bymonth->xxx[i]*_trp->bymonth->req[i]+12)%12)
  950. break;
  951. }
  952. if(i>=_trp->bymonth->nr)
  953. return REC_NOMATCH;
  954. }
  955. if(_trp->freq==FREQ_YEARLY && _trp->byweekno)
  956. {
  957. for(i=0; i<_trp->byweekno->nr; i++)
  958. {
  959. if(_atp->yweek == (_trp->byweekno->xxx[i]*_trp->byweekno->req[i]+
  960. _amp->yweek)%_amp->yweek)
  961. break;
  962. }
  963. if(i>=_trp->byweekno->nr)
  964. return REC_NOMATCH;
  965. }
  966. if(_trp->byyday)
  967. {
  968. for(i=0; i<_trp->byyday->nr; i++)
  969. {
  970. if(_atp->t.tm_yday == (_trp->byyday->xxx[i]*_trp->byyday->req[i]+
  971. _amp->yday)%_amp->yday)
  972. break;
  973. }
  974. if(i>=_trp->byyday->nr)
  975. return REC_NOMATCH;
  976. }
  977. if(_trp->bymday)
  978. {
  979. for(i=0; i<_trp->bymday->nr; i++)
  980. {
  981. #ifdef EXTRA_DEBUG
  982. LM_DBG("%d == %d\n", _atp->t.tm_mday,
  983. (_trp->bymday->xxx[i]*_trp->bymday->req[i]+
  984. _amp->mday)%_amp->mday + ((_trp->bymday->req[i]<0)?1:0));
  985. #endif
  986. if(_atp->t.tm_mday == (_trp->bymday->xxx[i]*_trp->bymday->req[i]+
  987. _amp->mday)%_amp->mday + (_trp->bymday->req[i]<0)?1:0)
  988. break;
  989. }
  990. if(i>=_trp->bymday->nr)
  991. return REC_NOMATCH;
  992. }
  993. if(_trp->byday)
  994. {
  995. for(i=0; i<_trp->byday->nr; i++)
  996. {
  997. if(_trp->freq==FREQ_YEARLY)
  998. {
  999. #ifdef EXTRA_DEBUG
  1000. LM_DBG("%d==%d && %d==%d\n", _atp->t.tm_wday,
  1001. _trp->byday->xxx[i], _atp->ywday+1,
  1002. (_trp->byday->req[i]+_amp->ywday)%_amp->ywday);
  1003. #endif
  1004. if(_atp->t.tm_wday == _trp->byday->xxx[i] &&
  1005. _atp->ywday+1 == (_trp->byday->req[i]+_amp->ywday)%
  1006. _amp->ywday)
  1007. break;
  1008. }
  1009. else
  1010. {
  1011. if(_trp->freq==FREQ_MONTHLY)
  1012. {
  1013. #ifdef EXTRA_DEBUG
  1014. LM_DBG("%d==%d && %d==%d\n", _atp->t.tm_wday,
  1015. _trp->byday->xxx[i], _atp->mwday+1,
  1016. (_trp->byday->req[i]+_amp->mwday)%_amp->mwday);
  1017. #endif
  1018. if(_atp->t.tm_wday == _trp->byday->xxx[i] &&
  1019. _atp->mwday+1==(_trp->byday->req[i]+
  1020. _amp->mwday)%_amp->mwday)
  1021. break;
  1022. }
  1023. else
  1024. {
  1025. if(_atp->t.tm_wday == _trp->byday->xxx[i])
  1026. break;
  1027. }
  1028. }
  1029. }
  1030. if(i>=_trp->byday->nr)
  1031. return REC_NOMATCH;
  1032. }
  1033. return REC_MATCH;
  1034. }