cpl_time.c 23 KB

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