cpl_time.c 24 KB

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