match.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $TOG: match.c /main/2 1999/10/14 17:15:21 mgreess $ */
  24. /*
  25. * (c) Copyright 1993, 1994 Hewlett-Packard Company
  26. * (c) Copyright 1993, 1994 International Business Machines Corp.
  27. * (c) Copyright 1993, 1994 Novell, Inc.
  28. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  29. */
  30. #include <EUSCompat.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include "nametbl.h"
  35. #include "match.h"
  36. #include "cm.h"
  37. #include "appt4.h"
  38. #include "attr.h"
  39. #include "convert4-5.h"
  40. #include "iso8601.h"
  41. #include "misc.h"
  42. /*****************************************************************************
  43. * forward declaration of static functions
  44. *****************************************************************************/
  45. static boolean_t match_this_attribute(
  46. Appt_4 *appt,
  47. cms_attribute attr,
  48. CSA_enum op);
  49. static Attribute_4 *get_appt_reminder(Attribute_4 *attr, char *oldattr);
  50. static boolean_t match_names(char *target, uint num_names, char **names);
  51. static boolean_t match_old_reminder_attribute(
  52. Attribute_4 *rem4,
  53. cms_attribute_value *val,
  54. CSA_enum op);
  55. static boolean_t is_same_string(char *str1, char *str2);
  56. static boolean_t contain_substr(char *str1, char *str2);
  57. static boolean_t is_same_opaque_data(CSA_opaque_data *d1, CSA_opaque_data *d2);
  58. /*****************************************************************************
  59. * extern functions used in the library
  60. *****************************************************************************/
  61. /*
  62. * new array of cms_attribute type is allocated.
  63. * and CSA_attribute_value is converted to cms_attribtue_value type
  64. * If conflicts in the search criteria that lead to a no
  65. * match situation is detected, no_match will be set to B_TRUE and the
  66. * function return CSA_SUCCESS right away. The calling
  67. * function should always check the return status and the no_match
  68. * parameter first before using any of the other output parameters.
  69. * If CSA_E_INVALID_ATTRIBUTE is returned, the caller should treat
  70. * it as a no_match case.
  71. */
  72. extern CSA_return_code
  73. _DtCmHashCriteria(
  74. _DtCmNameTable *tbl,
  75. CSA_uint32 num_attrs,
  76. CSA_attribute *csaattrs,
  77. cms_attribute *cmsattrs,
  78. CSA_enum *ops,
  79. boolean_t *no_match,
  80. boolean_t *no_start_time_range,
  81. boolean_t *no_end_time_range,
  82. time_t *start1,
  83. time_t *start2,
  84. time_t *end1,
  85. time_t *end2,
  86. long *id,
  87. CSA_uint32 *hnum,
  88. cms_attribute **hattrs,
  89. CSA_enum **hops)
  90. {
  91. int i, j, index, starti = -1, endi = -1;
  92. time_t tstart1, tstart2, tend1, tend2;
  93. time_t tick;
  94. char *name;
  95. cms_attribute_value *val, *hval;
  96. boolean_t keep;
  97. *hnum = 0;
  98. *hattrs = NULL;
  99. *hops = NULL;
  100. *no_match = B_FALSE;
  101. /*
  102. * Find time range.
  103. */
  104. tstart1 = _DtCM_BOT;
  105. tstart2 = _DtCM_EOT;
  106. tend1 = _DtCM_BOT;
  107. tend2 = _DtCM_EOT;
  108. *id = 0;
  109. for (i = 0, j = 0; i < num_attrs; i++) {
  110. keep = B_TRUE;
  111. name = (csaattrs ? csaattrs[i].name : cmsattrs[i].name.name);
  112. if ((index = _DtCm_get_index_from_table(tbl, name)) == -1)
  113. return (CSA_E_INVALID_ATTRIBUTE);
  114. val = (csaattrs ? ((cms_attribute_value *)csaattrs[i].value) :
  115. cmsattrs[i].value);
  116. if (index == CSA_ENTRY_ATTR_START_DATE_I && val == NULL) {
  117. if (ops == NULL || ops[i] == CSA_MATCH_EQUAL_TO) {
  118. *no_match = B_TRUE;
  119. return (CSA_SUCCESS);
  120. } else if (ops && (ops[i] == CSA_MATCH_ANY ||
  121. ops[i] == CSA_MATCH_NOT_EQUAL_TO)) {
  122. /* match any start date, no need to set
  123. * the range since the range is default to
  124. * the largest range already
  125. */
  126. starti = i;
  127. keep = B_FALSE;
  128. }
  129. } else if (index == CSA_ENTRY_ATTR_START_DATE_I && val) {
  130. starti = i;
  131. keep = B_FALSE;
  132. if (_csa_iso8601_to_tick(val->item.date_time_value,
  133. &tick))
  134. return (CSA_E_INVALID_DATE_TIME);
  135. if (ops == NULL || ops[i] == CSA_MATCH_EQUAL_TO) {
  136. tstart1 = tick - 1;
  137. tstart2 = tick + 1;
  138. } else switch (ops[i]) {
  139. /*
  140. *case CSA_MATCH_ANY:
  141. *case CSA_MATCH_NOT_EQUAL_TO:
  142. * this will be really expensive
  143. * tstart1 = _DtCM_BOT;
  144. * tstart2 = _DtCM_EOT;
  145. * break;
  146. */
  147. case CSA_MATCH_NOT_EQUAL_TO:
  148. keep = B_TRUE;
  149. break;
  150. case CSA_MATCH_LESS_THAN:
  151. tstart2 = tick;
  152. break;
  153. case CSA_MATCH_LESS_THAN_OR_EQUAL_TO:
  154. tstart2 = tick + 1;
  155. break;
  156. case CSA_MATCH_GREATER_THAN:
  157. tstart1 = tick;
  158. break;
  159. case CSA_MATCH_GREATER_THAN_OR_EQUAL_TO:
  160. tstart1 = tick - 1;
  161. break;
  162. }
  163. } else if (index == CSA_ENTRY_ATTR_END_DATE_I && val) {
  164. endi = i;
  165. keep = B_FALSE;
  166. if (_csa_iso8601_to_tick(val->item.date_time_value,
  167. &tick))
  168. return (CSA_E_INVALID_DATE_TIME);
  169. if (ops == NULL || ops[i] == CSA_MATCH_EQUAL_TO) {
  170. tend1 = tick - 1;
  171. tend2 = tick + 1;
  172. } else switch (ops[i]) {
  173. /*
  174. *case CSA_MATCH_ANY:
  175. *case CSA_MATCH_NOT_EQUAL_TO:
  176. * this will be really expensive
  177. * old_range.key1 = _DtCM_BOT;
  178. * old_range.key2 = _DtCM_EOT;
  179. * break;
  180. */
  181. case CSA_MATCH_NOT_EQUAL_TO:
  182. keep = B_TRUE;
  183. break;
  184. case CSA_MATCH_LESS_THAN:
  185. tend2 = tick;
  186. break;
  187. case CSA_MATCH_LESS_THAN_OR_EQUAL_TO:
  188. tend2 = tick + 1;
  189. break;
  190. case CSA_MATCH_GREATER_THAN:
  191. tend1 = tick;
  192. break;
  193. case CSA_MATCH_GREATER_THAN_OR_EQUAL_TO:
  194. tend1 = tick - 1;
  195. break;
  196. }
  197. } else if (index == CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I) {
  198. keep = B_FALSE;
  199. if (val && val->item.opaque_data_value &&
  200. val->item.opaque_data_value->data) {
  201. *id = atoi((char *)val->\
  202. item.opaque_data_value->data);
  203. }
  204. }
  205. if (keep == B_TRUE) {
  206. void *savedHattrs = NULL;
  207. if (*hattrs == NULL) {
  208. if ((*hattrs = (cms_attribute *)calloc(1,
  209. sizeof(cms_attribute)*(num_attrs-i)+
  210. sizeof(char *))) == NULL)
  211. return (CSA_E_INSUFFICIENT_MEMORY);
  212. if ((hval = (cms_attribute_value *)calloc(1,
  213. sizeof(cms_attribute_value)*(num_attrs-i)))
  214. == NULL) {
  215. free(*hattrs);
  216. return (CSA_E_INSUFFICIENT_MEMORY);
  217. } else {
  218. savedHattrs = (void *)*hattrs;
  219. *((char**)(*hattrs)) = (char *)&hval[0];
  220. *hattrs = (cms_attribute *)\
  221. ((char *)(*hattrs)+sizeof(char*));
  222. }
  223. if (ops && (*hops = (CSA_enum *)calloc(1,
  224. sizeof(CSA_enum)*(num_attrs-i))) == NULL) {
  225. free(hval);
  226. free(savedHattrs);
  227. return (CSA_E_INSUFFICIENT_MEMORY);
  228. }
  229. }
  230. (*hattrs)[j].name.name = name;
  231. (*hattrs)[j].name.num = index;
  232. if (val) {
  233. (*hattrs)[j].value = &hval[j];
  234. (*hattrs)[j].value->type = val->type;
  235. if (csaattrs &&
  236. val->type == CSA_VALUE_CALENDAR_USER) {
  237. if (csaattrs[i].value->item.calendar_user_value)
  238. (*hattrs)[j].value->item.\
  239. calendar_user_value =
  240. csaattrs[i].value->item.\
  241. calendar_user_value->\
  242. user_name;
  243. } else
  244. (*hattrs)[j].value->item.sint32_value =
  245. val->item.sint32_value;
  246. }
  247. if (ops != NULL)
  248. (*hops)[j] = ops[i];
  249. j++;
  250. }
  251. }
  252. if (j == 0) {
  253. if (*hattrs) _DtCmFreeHashedArrays(*hnum, *hattrs, *hops);
  254. *hnum = 0;
  255. *hattrs = NULL;
  256. *hops = NULL;
  257. } else {
  258. *hnum = j;
  259. }
  260. if (starti == -1)
  261. *no_start_time_range = B_TRUE;
  262. else
  263. *no_start_time_range = B_FALSE;
  264. if (endi == -1)
  265. *no_end_time_range = B_TRUE;
  266. else
  267. *no_end_time_range = B_FALSE;
  268. /* do some optimization here: if an end time range is
  269. * specified, since start time cannot be > end time,
  270. * set end of start time range to end of end time range
  271. * if the original end of start time range is > the
  272. * end of end time range
  273. */
  274. if (endi != -1 && start2 > end2)
  275. tstart2 = tend2;
  276. *start1 = tstart1;
  277. *start2 = tstart2;
  278. *end1 = tend1;
  279. *end2 = tend2;
  280. return (CSA_SUCCESS);
  281. }
  282. extern void _DtCmFreeHashedArrays(
  283. CSA_uint32 hnum,
  284. cms_attribute *hattrs,
  285. CSA_enum *hops)
  286. {
  287. char *ptr, *ptr1;
  288. if (hattrs) {
  289. ptr = ((char *)hattrs - sizeof(char *));
  290. ptr1 = *((char **)ptr);
  291. free(ptr1);
  292. free(ptr);
  293. }
  294. if (hops) free(hops);
  295. }
  296. /*
  297. * The algorithm used now simply goes through each criterion.
  298. * Probably need to optimize this.
  299. */
  300. extern Appt_4 *
  301. _DtCm_match_appts(
  302. Appt_4 *appts,
  303. long id,
  304. boolean_t no_end_time_range,
  305. time_t end1,
  306. time_t end2,
  307. CSA_uint32 num_attrs,
  308. cms_attribute *attrs,
  309. CSA_enum *ops)
  310. {
  311. Appt_4 *head = NULL;
  312. Appt_4 *freelist = NULL;
  313. Appt_4 *last, *nptr;
  314. time_t endtick;
  315. if (id == 0 && num_attrs == 0 && no_end_time_range)
  316. return (appts);
  317. while (appts != NULL) {
  318. nptr = appts->next;
  319. endtick = appts->appt_id.tick + appts->duration;
  320. if ((id > 0 && id != appts->appt_id.key) ||
  321. (!no_end_time_range && (appts->duration == 0 ||
  322. endtick < end1 || endtick >= end2)) ||
  323. (num_attrs > 0 && !_DtCm_match_one_appt(appts, num_attrs,
  324. attrs, ops)))
  325. {
  326. /* not match */
  327. appts->next = freelist;
  328. freelist = appts;
  329. } else {
  330. /* match */
  331. appts->next = NULL;
  332. if (head == NULL) {
  333. head = appts;
  334. last = appts;
  335. } else {
  336. last->next = appts;
  337. last = appts;
  338. }
  339. }
  340. appts = nptr;
  341. }
  342. _DtCm_free_appt4(freelist);
  343. return (head);
  344. }
  345. extern boolean_t
  346. _DtCm_match_one_appt(
  347. Appt_4 *appt,
  348. uint num_attrs,
  349. cms_attribute *attrs,
  350. CSA_enum *ops)
  351. {
  352. int i;
  353. for (i = 0; i < num_attrs; i++) {
  354. if (match_this_attribute(appt, attrs[i],
  355. (ops ? ops[i] : CSA_MATCH_EQUAL_TO)) == B_FALSE)
  356. return (B_FALSE);
  357. }
  358. /* match all given attributes */
  359. return (B_TRUE);
  360. }
  361. extern Reminder_4 *
  362. _DtCm_match_reminders(Reminder_4 *rems, uint num_names, char **names)
  363. {
  364. Reminder_4 *head = NULL;
  365. Reminder_4 *freelist = NULL;
  366. Reminder_4 *nptr;
  367. if (rems == NULL)
  368. return (NULL);
  369. if (names == NULL || num_names == 0) {
  370. return (rems);
  371. }
  372. while (rems != NULL) {
  373. nptr = rems->next;
  374. if (match_names(rems->attr.attr, num_names, names) == B_TRUE) {
  375. rems->next = head;
  376. head = rems;
  377. } else {
  378. rems->next = freelist;
  379. freelist = rems;
  380. }
  381. rems = nptr;
  382. }
  383. _DtCm_free_reminder4(freelist);
  384. return (head);
  385. }
  386. extern CSA_return_code
  387. _DtCm_check_operator(
  388. uint size,
  389. CSA_attribute *csaattrs,
  390. cms_attribute *cmsattrs,
  391. CSA_enum *ops)
  392. {
  393. int i;
  394. char *name;
  395. cms_attribute_value *val;
  396. for (i = 0; i < size; i++) {
  397. if ((name = csaattrs ? csaattrs[i].name : cmsattrs[i].name.name)
  398. == NULL)
  399. continue;
  400. val = (csaattrs ? ((cms_attribute_value *)csaattrs[i].value) :
  401. cmsattrs[i].value);
  402. /* don't support matching on CSA_VALUE_OPAQUE_DATA,
  403. * CSA_VALUE_ACCESS_LIST, CSA_VALUE_ATTENDEE_LIST,
  404. * and CSA_VALUE_DATE_TIME_LIST data type
  405. */
  406. if (val && (val->type == CSA_VALUE_ACCESS_LIST ||
  407. val->type == CSA_VALUE_ATTENDEE_LIST ||
  408. val->type == CSA_VALUE_DATE_TIME_LIST ||
  409. (val->type == CSA_VALUE_OPAQUE_DATA &&
  410. (strcmp(name, CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER) ||
  411. (ops && ops[i] != CSA_MATCH_EQUAL_TO)))))
  412. return (CSA_E_UNSUPPORTED_ENUM);
  413. /* all other test depends on ops being not NULL */
  414. if (ops == NULL)
  415. continue;
  416. /* unknown operator */
  417. if (ops[i] < CSA_MATCH_ANY || ops[i] > CSA_MATCH_CONTAIN)
  418. return (CSA_E_INVALID_ENUM);
  419. /*
  420. * if an operator other than CSA_MATCH_ANY, or
  421. * CSA_MATCH_EQUAL_TO, CSA_MATCH_NOT_EQUAL_TO
  422. * is specified, must specify a value
  423. */
  424. if (val == NULL && (ops[i] != CSA_MATCH_ANY &&
  425. ops[i] != CSA_MATCH_EQUAL_TO &&
  426. ops[i] != CSA_MATCH_NOT_EQUAL_TO))
  427. return (CSA_E_INVALID_ENUM);
  428. /*
  429. * only support CSA_MATCH_ANY and CSA_MATCH_EQUAL_TO
  430. * for CSA_VALUE_REMINDER, CSA_VALUE_CALENDAR_USER,
  431. * and CSA_VALUE_DATE_TIME_RANGE data type
  432. */
  433. if (val && (val->type == CSA_VALUE_REMINDER ||
  434. val->type == CSA_VALUE_CALENDAR_USER ||
  435. val->type == CSA_VALUE_DATE_TIME_RANGE) &&
  436. (ops[i] != CSA_MATCH_ANY &&
  437. ops[i] != CSA_MATCH_EQUAL_TO))
  438. return (CSA_E_UNSUPPORTED_ENUM);
  439. /*
  440. * only support CSA_MATCH_ANY, CSA_MATCH_EQUAL_TO,
  441. * CSA_MATCH_NOT_EQUAL_TO and CSA_MATCH_CONTAIN
  442. * for strings, other op does not make sense
  443. */
  444. if (val && val->type == CSA_VALUE_STRING &&
  445. (ops[i] > CSA_MATCH_NOT_EQUAL_TO &&
  446. ops[i] < CSA_MATCH_CONTAIN))
  447. return (CSA_E_UNSUPPORTED_ENUM);
  448. /* CSA_MATCH_CONTAIN applies to CSA_VALUE_STRING type only */
  449. if (ops[i] == CSA_MATCH_CONTAIN && val &&
  450. val->type != CSA_VALUE_STRING)
  451. return (CSA_E_UNSUPPORTED_ENUM);
  452. }
  453. return (CSA_SUCCESS);
  454. }
  455. extern boolean_t
  456. _DtCm_match_time_attribute(
  457. cms_attribute_value *val1,
  458. cms_attribute_value *val2,
  459. CSA_enum op)
  460. {
  461. cms_attribute_value tval1, tval2;
  462. if ((val1 && val1->type != CSA_VALUE_DATE_TIME) ||
  463. (val2 && val2->type != CSA_VALUE_DATE_TIME))
  464. return (B_FALSE);
  465. if (val1) {
  466. tval1.type = CSA_VALUE_SINT32;
  467. if (_csa_iso8601_to_tick(val1->item.date_time_value,
  468. (time_t *)&tval1.item.sint32_value))
  469. return (B_FALSE);
  470. }
  471. if (val2) {
  472. tval2.type = CSA_VALUE_SINT32;
  473. if (_csa_iso8601_to_tick(val2->item.date_time_value,
  474. (time_t *)&tval2.item.sint32_value))
  475. return (B_FALSE);
  476. }
  477. return (_DtCm_match_sint32_attribute((val1 ? &tval1 : NULL),
  478. (val2 ? &tval2 : NULL), op));
  479. }
  480. extern boolean_t
  481. _DtCm_match_time_duration_attribute(
  482. cms_attribute_value *val1,
  483. cms_attribute_value *val2,
  484. CSA_enum op)
  485. {
  486. cms_attribute_value tval1, tval2;
  487. if ((val1 && val1->type != CSA_VALUE_TIME_DURATION) ||
  488. (val2 && val2->type != CSA_VALUE_TIME_DURATION))
  489. return (B_FALSE);
  490. if (val1) {
  491. tval1.type = CSA_VALUE_SINT32;
  492. if (_csa_iso8601_to_duration(val1->item.time_duration_value,
  493. (time_t *)&tval1.item.sint32_value))
  494. return (B_FALSE);
  495. }
  496. if (val2) {
  497. tval2.type = CSA_VALUE_SINT32;
  498. if (_csa_iso8601_to_duration(val2->item.time_duration_value,
  499. (time_t *)&tval2.item.sint32_value))
  500. return (B_FALSE);
  501. }
  502. return (_DtCm_match_sint32_attribute((val1 ? &tval1 : NULL),
  503. (val2 ? &tval2 : NULL), op));
  504. }
  505. extern boolean_t
  506. _DtCm_match_sint32_attribute(
  507. cms_attribute_value *val1,
  508. cms_attribute_value *val2,
  509. CSA_enum op)
  510. {
  511. if (val1 && val2 && val1->type != val2->type)
  512. return (B_FALSE);
  513. switch (op) {
  514. case CSA_MATCH_ANY:
  515. if (val1 != NULL)
  516. return (B_TRUE);
  517. else
  518. return (B_FALSE);
  519. case CSA_MATCH_EQUAL_TO:
  520. if (val2 == NULL) {
  521. if (val1 == NULL)
  522. return (B_TRUE);
  523. else
  524. return (B_FALSE);
  525. } else {
  526. if (val1 && val1->item.sint32_value
  527. == val2->item.sint32_value)
  528. return (B_TRUE);
  529. else
  530. return (B_FALSE);
  531. }
  532. case CSA_MATCH_NOT_EQUAL_TO:
  533. if (val2 == NULL) {
  534. if (val1 != NULL)
  535. return (B_TRUE);
  536. else
  537. return (B_FALSE);
  538. } else {
  539. if (val1 && val1->item.sint32_value
  540. != val2->item.sint32_value)
  541. return (B_TRUE);
  542. else
  543. return (B_FALSE);
  544. }
  545. case CSA_MATCH_LESS_THAN:
  546. if (val1 == NULL)
  547. return (B_FALSE);
  548. else if (val2 && val1->item.sint32_value < val2->item.sint32_value)
  549. return (B_TRUE);
  550. else
  551. return (B_FALSE);
  552. case CSA_MATCH_LESS_THAN_OR_EQUAL_TO:
  553. if (val1 == NULL)
  554. return (B_FALSE);
  555. else if (val2 && val1->item.sint32_value <= val2->item.sint32_value)
  556. return (B_TRUE);
  557. else
  558. return (B_FALSE);
  559. case CSA_MATCH_GREATER_THAN:
  560. if (val1 == NULL)
  561. return (B_FALSE);
  562. else if (val2 && val1->item.sint32_value > val2->item.sint32_value)
  563. return (B_TRUE);
  564. else
  565. return (B_FALSE);
  566. case CSA_MATCH_GREATER_THAN_OR_EQUAL_TO:
  567. if (val1 == NULL)
  568. return (B_FALSE);
  569. else if (val2 && val1->item.sint32_value >= val2->item.sint32_value)
  570. return (B_TRUE);
  571. else
  572. return (B_FALSE);
  573. case CSA_MATCH_CONTAIN: /* only apply to string type */
  574. default:
  575. return (B_FALSE);
  576. }
  577. }
  578. extern boolean_t
  579. _DtCm_match_uint32_attribute(
  580. cms_attribute_value *val1,
  581. cms_attribute_value *val2,
  582. CSA_enum op)
  583. {
  584. if (val1 && val2 && val1->type != val2->type)
  585. return (B_FALSE);
  586. switch (op) {
  587. case CSA_MATCH_ANY:
  588. if (val1 != NULL)
  589. return (B_TRUE);
  590. else
  591. return (B_FALSE);
  592. case CSA_MATCH_EQUAL_TO:
  593. if (val2 == NULL) {
  594. if (val1 == NULL)
  595. return (B_TRUE);
  596. else
  597. return (B_FALSE);
  598. } else {
  599. if (val1 && val1->item.uint32_value
  600. == val2->item.uint32_value)
  601. return (B_TRUE);
  602. else
  603. return (B_FALSE);
  604. }
  605. case CSA_MATCH_NOT_EQUAL_TO:
  606. if (val2 == NULL) {
  607. if (val1 != NULL)
  608. return (B_TRUE);
  609. else
  610. return (B_FALSE);
  611. } else {
  612. if (val1 && val1->item.uint32_value
  613. != val2->item.uint32_value)
  614. return (B_TRUE);
  615. else
  616. return (B_FALSE);
  617. }
  618. case CSA_MATCH_LESS_THAN:
  619. if (val1 == NULL)
  620. return (B_FALSE);
  621. else if (val2 && val1->item.uint32_value < val2->item.uint32_value)
  622. return (B_TRUE);
  623. else
  624. return (B_FALSE);
  625. case CSA_MATCH_LESS_THAN_OR_EQUAL_TO:
  626. if (val1 == NULL)
  627. return (B_FALSE);
  628. else if (val2 && val1->item.uint32_value <= val2->item.uint32_value)
  629. return (B_TRUE);
  630. else
  631. return (B_FALSE);
  632. case CSA_MATCH_GREATER_THAN:
  633. if (val1 == NULL)
  634. return (B_FALSE);
  635. else if (val2 && val1->item.uint32_value > val2->item.uint32_value)
  636. return (B_TRUE);
  637. else
  638. return (B_FALSE);
  639. case CSA_MATCH_GREATER_THAN_OR_EQUAL_TO:
  640. if (val1 == NULL)
  641. return (B_FALSE);
  642. else if (val2 && val1->item.uint32_value >= val2->item.uint32_value)
  643. return (B_TRUE);
  644. else
  645. return (B_FALSE);
  646. case CSA_MATCH_CONTAIN: /* only apply to string type */
  647. default:
  648. return (B_FALSE);
  649. }
  650. }
  651. /*
  652. * The matching value should have been checked by _DtCm_check_operator()
  653. * already so contains valid value for the corresponding operator.
  654. * Treat NULL string and string with zero length to be equal.
  655. * val1 is the string to be matched
  656. * val2 is the matching string
  657. */
  658. extern boolean_t
  659. _DtCm_match_string_attribute(
  660. cms_attribute_value *val1,
  661. cms_attribute_value *val2,
  662. CSA_enum op)
  663. {
  664. if (val1 && val2 && val1->type != val2->type)
  665. return (B_FALSE);
  666. if (val1 == NULL) {
  667. if ((op == CSA_MATCH_EQUAL_TO && val2 == NULL) ||
  668. (op == CSA_MATCH_NOT_EQUAL_TO && val2))
  669. return (B_TRUE);
  670. else
  671. return (B_FALSE);
  672. }
  673. switch (op) {
  674. case CSA_MATCH_ANY:
  675. return (B_TRUE); /* since val1 != NULL */
  676. case CSA_MATCH_EQUAL_TO:
  677. if (val2 == NULL) {
  678. return (B_FALSE); /* since val1 != NULL */
  679. } else {
  680. return (is_same_string(val1->item.string_value,
  681. val2->item.string_value));
  682. }
  683. case CSA_MATCH_NOT_EQUAL_TO:
  684. if (val2 == NULL) {
  685. return (B_TRUE); /* since val1 != NULL */
  686. } else {
  687. return (!is_same_string(val1->item.string_value,
  688. val2->item.string_value));
  689. }
  690. case CSA_MATCH_CONTAIN:
  691. /* if val2 is null, will be rejected already */
  692. return (contain_substr(val1->item.string_value,
  693. val2->item.string_value));
  694. case CSA_MATCH_LESS_THAN:
  695. case CSA_MATCH_LESS_THAN_OR_EQUAL_TO:
  696. case CSA_MATCH_GREATER_THAN:
  697. case CSA_MATCH_GREATER_THAN_OR_EQUAL_TO:
  698. default:
  699. return (B_FALSE);
  700. }
  701. }
  702. extern boolean_t
  703. _DtCm_match_reminder_attribute(
  704. cms_attribute_value *val1,
  705. cms_attribute_value *val2,
  706. CSA_enum op)
  707. {
  708. CSA_reminder *r1, *r2;
  709. cms_attribute_value tv1, tv2;
  710. if ((val1 && val1->type != CSA_VALUE_REMINDER) ||
  711. (val2 && val2->type != CSA_VALUE_REMINDER))
  712. return (B_FALSE);
  713. switch (op) {
  714. case CSA_MATCH_ANY:
  715. if (val1 != NULL)
  716. return (B_TRUE);
  717. else
  718. return (B_FALSE);
  719. case CSA_MATCH_EQUAL_TO:
  720. if (val2 == NULL || val2->item.reminder_value == NULL) {
  721. if (val1 == NULL || val1->item.reminder_value == NULL)
  722. return (B_TRUE);
  723. else
  724. return (B_FALSE);
  725. } else if (val1 == NULL || val1->item.reminder_value == NULL) {
  726. return (B_FALSE);
  727. } else {
  728. r1 = val1->item.reminder_value;
  729. r2 = val2->item.reminder_value;
  730. if ((r1->repeat_count != r2->repeat_count) ||
  731. !is_same_opaque_data(&r1->reminder_data,
  732. &r2->reminder_data))
  733. return (B_FALSE);
  734. tv1.type = CSA_VALUE_SINT32;
  735. tv2.type = CSA_VALUE_SINT32;
  736. tv1.item.sint32_value = 0;
  737. tv2.item.sint32_value = 0;
  738. if (r1->lead_time && *r1->lead_time &&
  739. _csa_iso8601_to_duration(r1->lead_time,
  740. (time_t *)&tv1.item.sint32_value))
  741. return (B_FALSE);
  742. if (r2->lead_time && *r2->lead_time &&
  743. _csa_iso8601_to_duration(r2->lead_time,
  744. (time_t *)&tv2.item.sint32_value))
  745. return (B_FALSE);
  746. if (_DtCm_match_sint32_attribute(&tv1, &tv2, op)
  747. == B_FALSE)
  748. return (B_FALSE);
  749. tv1.item.sint32_value = 0;
  750. tv2.item.sint32_value = 0;
  751. if (r1->snooze_time && *r1->snooze_time &&
  752. _csa_iso8601_to_duration(r1->snooze_time,
  753. (time_t *)&tv1.item.sint32_value))
  754. return (B_FALSE);
  755. if (r2->snooze_time && *r2->snooze_time &&
  756. _csa_iso8601_to_duration(r2->snooze_time,
  757. (time_t *)&tv2.item.sint32_value))
  758. return (B_FALSE);
  759. return (_DtCm_match_sint32_attribute(&tv1, &tv2, op));
  760. }
  761. /* these are not supported for CSA_VALUE_REMINDER type */
  762. case CSA_MATCH_NOT_EQUAL_TO:
  763. case CSA_MATCH_LESS_THAN:
  764. case CSA_MATCH_LESS_THAN_OR_EQUAL_TO:
  765. case CSA_MATCH_GREATER_THAN:
  766. case CSA_MATCH_GREATER_THAN_OR_EQUAL_TO:
  767. case CSA_MATCH_CONTAIN:
  768. default:
  769. return (B_FALSE);
  770. }
  771. }
  772. /*****************************************************************************
  773. * static functions used within the file
  774. *****************************************************************************/
  775. static boolean_t
  776. match_this_attribute(Appt_4 *appt, cms_attribute attr, CSA_enum op)
  777. {
  778. time_t tick;
  779. _DtCm_old_attrs oldtag;
  780. cms_attribute_value oldattr;
  781. cms_attribute_value matchattr;
  782. if (attr.name.name == NULL || attr.value == NULL)
  783. return (B_FALSE);
  784. if ((attr.name.num > 0 &&
  785. _DtCm_get_old_attr_by_index(attr.name.num, &oldtag)) ||
  786. (attr.name.num == 0 &&
  787. _DtCm_get_old_attr_by_name(attr.name.name, &oldtag)))
  788. return (B_FALSE);
  789. switch (oldtag) {
  790. /* id is matched somewhere else
  791. case _DtCm_old_attr_id:
  792. */
  793. case _DtCm_old_attr_time:
  794. /* the only case is to match a non-NULL start date with
  795. * CSA_MATCH_NOT_EQUAL_TO
  796. */
  797. _csa_iso8601_to_tick(attr.value->item.date_time_value, &tick);
  798. if (appt->appt_id.tick == tick)
  799. return (B_FALSE);
  800. else
  801. return (B_TRUE);
  802. case _DtCm_old_attr_type:
  803. oldattr.type = CSA_VALUE_UINT32;
  804. oldattr.item.uint32_value =
  805. _DtCm_eventtype4_to_type(appt->tag->tag);
  806. return (_DtCm_match_uint32_attribute(&oldattr, attr.value, op));
  807. case _DtCm_old_attr_type2:
  808. oldattr.type = CSA_VALUE_STRING;
  809. oldattr.item.string_value =
  810. _DtCm_eventtype4_to_subtype(appt->tag->tag);
  811. return (_DtCm_match_string_attribute(&oldattr, attr.value, op));
  812. case _DtCm_old_attr_duration:
  813. /* the only possibility is to match a NULL end date value
  814. * or match a non-NULL end date with MATCH_NOT_EQUAL_TO
  815. */
  816. if (op == CSA_MATCH_EQUAL_TO) {
  817. if (appt->duration == 0)
  818. return (B_TRUE);
  819. else
  820. return (B_FALSE);
  821. } else if (op == CSA_MATCH_ANY) {
  822. return (B_TRUE);
  823. } else if (op == CSA_MATCH_NOT_EQUAL_TO && attr.value == NULL) {
  824. if (appt->duration == 0)
  825. return (B_FALSE);
  826. else
  827. return (B_TRUE);
  828. } else if (op == CSA_MATCH_NOT_EQUAL_TO && attr.value) {
  829. _csa_iso8601_to_tick(attr.value->item.date_time_value,
  830. &tick);
  831. if ((appt->appt_id.tick+appt->duration) == tick)
  832. return (B_FALSE);
  833. else
  834. return (B_TRUE);
  835. } else
  836. return (B_FALSE);
  837. case _DtCm_old_attr_repeat_type:
  838. oldattr.type = CSA_VALUE_SINT32;
  839. oldattr.item.sint32_value =
  840. _DtCm_interval4_to_rtype(appt->period.period);
  841. return (_DtCm_match_sint32_attribute(&oldattr, attr.value, op));
  842. case _DtCm_old_attr_what:
  843. oldattr.type = CSA_VALUE_STRING;
  844. oldattr.item.string_value = appt->what;
  845. return (_DtCm_match_string_attribute(&oldattr, attr.value, op));
  846. case _DtCm_old_attr_status:
  847. oldattr.type = CSA_VALUE_UINT32;
  848. oldattr.item.uint32_value =
  849. _DtCm_apptstatus4_to_status(appt->appt_status);
  850. return (_DtCm_match_uint32_attribute(&oldattr, attr.value, op));
  851. case _DtCm_old_attr_author:
  852. oldattr.type = CSA_VALUE_STRING;
  853. oldattr.item.string_value = appt->author;
  854. return (_DtCm_match_string_attribute(&oldattr, attr.value, op));
  855. case _DtCm_old_attr_beep_reminder:
  856. return (match_old_reminder_attribute(
  857. get_appt_reminder(appt->attr,
  858. _DtCM_OLD_ATTR_BEEP_REMINDER), attr.value, op));
  859. case _DtCm_old_attr_flash_reminder:
  860. return (match_old_reminder_attribute(
  861. get_appt_reminder(appt->attr,
  862. _DtCM_OLD_ATTR_FLASH_REMINDER), attr.value, op));
  863. case _DtCm_old_attr_mail_reminder:
  864. return (match_old_reminder_attribute(
  865. get_appt_reminder(appt->attr,
  866. _DtCM_OLD_ATTR_MAIL_REMINDER), attr.value, op));
  867. case _DtCm_old_attr_popup_reminder:
  868. return (match_old_reminder_attribute(
  869. get_appt_reminder(appt->attr,
  870. _DtCM_OLD_ATTR_POPUP_REMINDER), attr.value, op));
  871. case _DtCm_old_attr_repeat_times:
  872. oldattr.type = CSA_VALUE_UINT32;
  873. oldattr.item.uint32_value = appt->ntimes;
  874. return (_DtCm_match_uint32_attribute(&oldattr, attr.value, op));
  875. case _DtCm_old_attr_showtime:
  876. oldattr.type = CSA_VALUE_SINT32;
  877. oldattr.item.sint32_value = appt->tag->showtime;
  878. return (_DtCm_match_sint32_attribute(&oldattr, attr.value, op));
  879. case _DtCm_old_attr_privacy:
  880. oldattr.type = CSA_VALUE_UINT32;
  881. oldattr.item.uint32_value =
  882. _DtCm_privacy4_to_classification(appt->privacy);
  883. return (_DtCm_match_uint32_attribute(&oldattr, attr.value, op));
  884. case _DtCm_old_attr_repeat_nth_interval:
  885. oldattr.type = CSA_VALUE_UINT32;
  886. oldattr.item.uint32_value = appt->period.nth;
  887. return (_DtCm_match_uint32_attribute(&oldattr, attr.value, op));
  888. case _DtCm_old_attr_repeat_nth_weeknum:
  889. oldattr.type = CSA_VALUE_SINT32;
  890. oldattr.item.sint32_value = appt->period.nth;
  891. return (_DtCm_match_sint32_attribute(&oldattr, attr.value, op));
  892. case _DtCm_old_attr_end_date:
  893. oldattr.type = CSA_VALUE_SINT32;
  894. oldattr.item.sint32_value = appt->period.enddate;
  895. if (attr.value) {
  896. matchattr.type = CSA_VALUE_SINT32;
  897. _csa_iso8601_to_tick(attr.value->item.date_time_value,
  898. (time_t *)&matchattr.item.sint32_value);
  899. }
  900. return (_DtCm_match_sint32_attribute(&oldattr,
  901. (attr.value ? &matchattr : NULL), op));
  902. defalut:
  903. return (B_FALSE);
  904. }
  905. }
  906. static Attribute_4 *
  907. get_appt_reminder(Attribute_4 *attr4, char *oldattr)
  908. {
  909. while (attr4 != NULL) {
  910. if (attr4->attr && !strcmp(attr4->attr, oldattr))
  911. return (attr4);
  912. else
  913. attr4 = attr4->next;
  914. }
  915. return (NULL);
  916. }
  917. static boolean_t
  918. match_names(char *oldattr, uint num_names, char **names)
  919. {
  920. int i;
  921. char *attrname;
  922. if (oldattr == NULL)
  923. return (B_FALSE);
  924. attrname = _DtCm_old_reminder_name_to_name(oldattr);
  925. for (i = 0; i < num_names; i++) {
  926. if (names[i] && (strcmp(names[i], attrname) == 0)) {
  927. return (B_TRUE);
  928. }
  929. }
  930. return (B_FALSE);
  931. }
  932. static boolean_t
  933. match_old_reminder_attribute(
  934. Attribute_4 *rem4,
  935. cms_attribute_value *val,
  936. CSA_enum op)
  937. {
  938. cms_attribute_value oldattr;
  939. CSA_reminder rem;
  940. char ltstring[BUFSIZ];
  941. if (rem4 != NULL) {
  942. rem.snooze_time = NULL;
  943. rem.repeat_count = 0;
  944. rem.reminder_data.size = (rem4->clientdata ?
  945. strlen(rem4->clientdata) : 0);
  946. rem.reminder_data.data = (unsigned char *)rem4->clientdata;
  947. _csa_duration_to_iso8601((rem4->value ? atoi(rem4->value) : 0),
  948. ltstring);
  949. rem.lead_time = ltstring;
  950. oldattr.type = CSA_VALUE_REMINDER;
  951. oldattr.item.reminder_value = &rem;
  952. }
  953. return (_DtCm_match_reminder_attribute((rem4 ? &oldattr : NULL),
  954. val, op));
  955. }
  956. static boolean_t
  957. is_same_string(char *str1, char *str2)
  958. {
  959. /* val2 is a NULL string */
  960. if (str2 == NULL || *str2 == 0) {
  961. if (str1 == NULL || *str1 == 0)
  962. return (B_TRUE);
  963. else
  964. return (B_FALSE);
  965. } else {
  966. if (str1 && strcmp(str1, str2) == 0)
  967. return (B_TRUE);
  968. else
  969. return (B_FALSE);
  970. }
  971. }
  972. static boolean_t
  973. contain_substr(char *str1, char *str2)
  974. {
  975. int i, len;
  976. if (str2 == NULL || *str2 == '\0')
  977. return (B_TRUE);
  978. if (str1 == NULL || *str1 == '\0') {
  979. return (B_FALSE);
  980. } else {
  981. len = strlen(str2);
  982. for (i = 0; str1[i] != '\0'; i++) {
  983. if (strncasecmp(&str1[i], str2, len) == 0)
  984. return (B_TRUE);
  985. }
  986. return (B_FALSE);
  987. }
  988. }
  989. static boolean_t
  990. is_same_opaque_data(CSA_opaque_data *d1, CSA_opaque_data *d2)
  991. {
  992. /* val2 is a NULL string */
  993. if (d2 == NULL || d2->size == 0) {
  994. if (d1 == NULL || d1->size == 0)
  995. return (B_TRUE);
  996. else
  997. return (B_FALSE);
  998. } else {
  999. if (d1 && d1->size > 0) {
  1000. if (d1->size == d2->size) {
  1001. if (memcmp(d1->data, d2->data, d1->size) == 0)
  1002. return (B_TRUE);
  1003. else
  1004. return (B_FALSE);
  1005. } else
  1006. return (B_FALSE);
  1007. } else
  1008. return (B_FALSE);
  1009. }
  1010. }