Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / csa / attr.c
1 /* $XConsortium: attr.c /main/1 1996/04/21 19:21:41 drk $ */
2 /*
3  *  (c) Copyright 1993, 1994 Hewlett-Packard Company
4  *  (c) Copyright 1993, 1994 International Business Machines Corp.
5  *  (c) Copyright 1993, 1994 Novell, Inc.
6  *  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
7  */
8
9 #include <EUSCompat.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 #include "attr.h"
16 #include "cmsdata.h"
17 #include "nametbl.h"
18 #include "free.h"
19 #include "misc.h"
20 #include "iso8601.h"
21 #include "lutil.h"
22
23 /*
24  * calendar attributes defined by the library
25  * Note: index zero is not used
26  */
27 char *_CSA_calendar_attribute_names[] = {
28         NULL,
29         "-//XAPIA/CSA/CALATTR//NONSGML Access List//EN",
30         "-//XAPIA/CSA/CALATTR//NONSGML Calendar Name//EN",
31         "-//XAPIA/CSA/CALATTR//NONSGML Calendar Owner//EN",
32         "-//XAPIA/CSA/CALATTR//NONSGML Calendar Size//EN",
33         "-//XAPIA/CSA/CALATTR//NONSGML Character Set//EN",
34         "-//XAPIA/CSA/CALATTR//NONSGML Country//EN",
35         "-//XAPIA/CSA/CALATTR//NONSGML Date Created//EN",
36         "-//XAPIA/CSA/CALATTR//NONSGML Language//EN",
37         "-//XAPIA/CSA/CALATTR//NONSGML Number Entries//EN",
38         "-//XAPIA/CSA/CALATTR//NONSGML Product Identifier//EN",
39         "-//XAPIA/CSA/CALATTR//NONSGML Time Zone//EN",
40         "-//XAPIA/CSA/CALATTR//NONSGML Version//EN",
41         "-//XAPIA/CSA/CALATTR//NONSGML Work Schedule//EN",
42         "-//CDE_XAPIA_PRIVATE/CSA/CALATTR//NONSGML Server Version//EN",
43         "-//CDE_XAPIA_PRIVATE/CSA/CALATTR//NONSGML Data Version//EN",
44         "-//CDE_XAPIA_PRIVATE/CSA/CALATTR//NONSGML Calendar Delimiter//EN"
45 };
46
47 /*
48  * entry attributes defined by the library
49  * Note: index zero is not used
50  */
51 char *_CSA_entry_attribute_names[] = {
52         NULL,
53         "-//XAPIA/CSA/ENTRYATTR//NONSGML Attendee List//EN",
54         "-//XAPIA/CSA/ENTRYATTR//NONSGML Audio Reminder//EN",
55         "-//XAPIA/CSA/ENTRYATTR//NONSGML Classification//EN",
56         "-//XAPIA/CSA/ENTRYATTR//NONSGML Date Completed//EN",
57         "-//XAPIA/CSA/ENTRYATTR//NONSGML Date Created//EN",
58         "-//XAPIA/CSA/ENTRYATTR//NONSGML Description//EN",
59         "-//XAPIA/CSA/ENTRYATTR//NONSGML Due Date//EN",
60         "-//XAPIA/CSA/ENTRYATTR//NONSGML End Date//EN",
61         "-//XAPIA/CSA/ENTRYATTR//NONSGML Exception Dates//EN",
62         "-//XAPIA/CSA/ENTRYATTR//NONSGML Exception Rule//EN",
63         "-//XAPIA/CSA/ENTRYATTR//NONSGML Flashing Reminder//EN",
64         "-//XAPIA/CSA/ENTRYATTR//NONSGML Last Update//EN",
65         "-//XAPIA/CSA/ENTRYATTR//NONSGML Mail Reminder//EN",
66         "-//XAPIA/CSA/ENTRYATTR//NONSGML Number Recurrences//EN",
67         "-//XAPIA/CSA/ENTRYATTR//NONSGML Organizer//EN",
68         "-//XAPIA/CSA/ENTRYATTR//NONSGML Popup Reminder//EN",
69         "-//XAPIA/CSA/ENTRYATTR//NONSGML Priority//EN",
70         "-//XAPIA/CSA/ENTRYATTR//NONSGML Recurrence Rule//EN",
71         "-//XAPIA/CSA/ENTRYATTR//NONSGML Recurring Dates//EN",
72         "-//XAPIA/CSA/ENTRYATTR//NONSGML Reference Identifier//EN",
73         "-//XAPIA/CSA/ENTRYATTR//NONSGML Sequence Number//EN",
74         "-//XAPIA/CSA/ENTRYATTR//NONSGML Sponsor//EN",
75         "-//XAPIA/CSA/ENTRYATTR//NONSGML Start Date//EN",
76         "-//XAPIA/CSA/ENTRYATTR//NONSGML Status//EN",
77         "-//XAPIA/CSA/ENTRYATTR//NONSGML Subtype//EN",
78         "-//XAPIA/CSA/ENTRYATTR//NONSGML Summary//EN",
79         "-//XAPIA/CSA/ENTRYATTR//NONSGML Time Transparency//EN",
80         "-//XAPIA/CSA/ENTRYATTR//NONSGML Type//EN",
81         "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Show Time//EN",
82         "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat Type//EN",
83         "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat Times//EN",
84         "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat Interval//EN",
85         "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Repeat Occurrence Number//EN",
86         "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Sequence End Date//EN",
87         "-//CDE_XAPIA_PRIVATE/CSA/ENTRYATTR//NONSGML Entry Delimiter//EN"
88 };
89
90 /*
91  * Values for entry attribute CSA_ENTRY_ATTR_SUBTYPE
92  */
93 char *_CSA_entry_subtype_values[] = {
94         "-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Appointment//EN",
95         "-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Class//EN",
96         "-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Holiday//EN",
97         "-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Meeting//EN",
98         "-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Miscellaneous//EN",
99         "-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Phone Call//EN",
100         "-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Sick Day//EN",
101         "-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Special Occasion//EN",
102         "-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Travel//EN",
103         "-//XAPIA/CSA/SUBTYPE//NONSGML Subtype Vacation//EN",
104 };
105
106 /* list of calendar attributes and value type */
107 _DtCmAttrInfo _CSA_cal_attr_info[] =
108 {
109         /* first element is not used */
110         { 0, -1, 0, _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
111         { CSA_CAL_ATTR_ACCESS_LIST_I, CSA_VALUE_ACCESS_LIST,    1,
112                 _DtCm_old_attr_unknown, B_FALSE, B_FALSE },
113         { CSA_CAL_ATTR_CALENDAR_NAME_I, CSA_VALUE_STRING,       1,
114                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
115         { CSA_CAL_ATTR_CALENDAR_OWNER_I, CSA_VALUE_CALENDAR_USER,       1,
116                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
117         { CSA_CAL_ATTR_CALENDAR_SIZE_I, CSA_VALUE_UINT32,       4,
118                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
119         { CSA_CAL_ATTR_CHARACTER_SET_I, CSA_VALUE_STRING,       4,
120                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
121         { CSA_CAL_ATTR_COUNTRY_I,       CSA_VALUE_STRING,       0,
122                 _DtCm_old_attr_unknown, B_FALSE, B_FALSE },
123         { CSA_CAL_ATTR_DATE_CREATED_I,  CSA_VALUE_DATE_TIME,    4,
124                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
125         { CSA_CAL_ATTR_LANGUAGE_I,      CSA_VALUE_STRING,       0,
126                 _DtCm_old_attr_unknown, B_FALSE, B_FALSE },
127         { CSA_CAL_ATTR_NUMBER_ENTRIES_I, CSA_VALUE_UINT32,      1,
128                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
129         { CSA_CAL_ATTR_PRODUCT_IDENTIFIER_I, CSA_VALUE_STRING,  1,
130                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
131         { CSA_CAL_ATTR_TIME_ZONE_I,     CSA_VALUE_STRING,       4,
132                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
133         { CSA_CAL_ATTR_VERSION_I,       CSA_VALUE_STRING,       1,
134                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
135         { CSA_CAL_ATTR_WORK_SCHEDULE_I, CSA_VALUE_OPAQUE_DATA,  0,
136                 _DtCm_old_attr_unknown, B_FALSE, B_FALSE },
137         { CSA_X_DT_CAL_ATTR_SERVER_VERSION_I, CSA_VALUE_UINT32, 1,
138                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
139         { CSA_X_DT_CAL_ATTR_DATA_VERSION_I, CSA_VALUE_UINT32,   1,
140                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
141         { CSA_X_DT_CAL_ATTR_CAL_DELIMITER_I, CSA_VALUE_STRING,  -1,
142                 _DtCm_old_attr_unknown, B_TRUE, B_TRUE }
143 };
144
145 /* list of entry attributes and value type */
146 _DtCmAttrInfo _CSA_entry_attr_info[] =
147 {
148         /* first element is not used */
149         { 0, -1, 0, _DtCm_old_attr_unknown, B_TRUE, B_TRUE },
150         { CSA_ENTRY_ATTR_ATTENDEE_LIST_I,       CSA_VALUE_ATTENDEE_LIST,
151           0,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
152         { CSA_ENTRY_ATTR_AUDIO_REMINDER_I,      CSA_VALUE_REMINDER,
153           1,    _DtCm_old_attr_beep_reminder,   B_FALSE, B_FALSE },
154         { CSA_ENTRY_ATTR_CLASSIFICATION_I,      CSA_VALUE_UINT32,
155           2,    _DtCm_old_attr_privacy,         B_FALSE, B_FALSE },
156         { CSA_ENTRY_ATTR_DATE_COMPLETED_I,      CSA_VALUE_DATE_TIME,
157           4,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
158         { CSA_ENTRY_ATTR_DATE_CREATED_I,        CSA_VALUE_DATE_TIME,
159           4,    _DtCm_old_attr_unknown,         B_TRUE, B_TRUE },
160         { CSA_ENTRY_ATTR_DESCRIPTION_I,         CSA_VALUE_STRING,
161           4,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
162         { CSA_ENTRY_ATTR_DUE_DATE_I,            CSA_VALUE_DATE_TIME,
163           4,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
164         { CSA_ENTRY_ATTR_END_DATE_I,            CSA_VALUE_DATE_TIME,
165           1,    _DtCm_old_attr_duration,        B_FALSE, B_FALSE },
166         { CSA_ENTRY_ATTR_EXCEPTION_DATES_I,     CSA_VALUE_DATE_TIME_LIST,
167           4,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
168         { CSA_ENTRY_ATTR_EXCEPTION_RULE_I,      CSA_VALUE_STRING,
169           0,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
170         { CSA_ENTRY_ATTR_FLASHING_REMINDER_I,   CSA_VALUE_REMINDER,
171           1,    _DtCm_old_attr_flash_reminder,  B_FALSE, B_FALSE },
172         { CSA_ENTRY_ATTR_LAST_UPDATE_I,         CSA_VALUE_DATE_TIME,
173           4,    _DtCm_old_attr_unknown,         B_TRUE, B_TRUE },
174         { CSA_ENTRY_ATTR_MAIL_REMINDER_I,       CSA_VALUE_REMINDER,
175           1,    _DtCm_old_attr_mail_reminder,   B_FALSE, B_FALSE },
176         { CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I,  CSA_VALUE_UINT32,
177           4,    _DtCm_old_attr_unknown,         B_TRUE, B_TRUE },
178         { CSA_ENTRY_ATTR_ORGANIZER_I,           CSA_VALUE_CALENDAR_USER,
179           1,    _DtCm_old_attr_author,          B_TRUE, B_TRUE },
180         { CSA_ENTRY_ATTR_POPUP_REMINDER_I,      CSA_VALUE_REMINDER,
181           1,    _DtCm_old_attr_popup_reminder,  B_FALSE, B_FALSE },
182         { CSA_ENTRY_ATTR_PRIORITY_I,            CSA_VALUE_UINT32,
183           4,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
184         { CSA_ENTRY_ATTR_RECURRENCE_RULE_I,     CSA_VALUE_STRING,
185           4,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
186         { CSA_ENTRY_ATTR_RECURRING_DATES_I,     CSA_VALUE_DATE_TIME_LIST,
187           0,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
188         { CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I, CSA_VALUE_OPAQUE_DATA, 
189           1,    _DtCm_old_attr_id,              B_TRUE, B_TRUE },
190         { CSA_ENTRY_ATTR_SEQUENCE_NUMBER_I,     CSA_VALUE_UINT32,
191           0,    _DtCm_old_attr_unknown,         B_TRUE, B_TRUE },
192         { CSA_ENTRY_ATTR_SPONSOR_I,             CSA_VALUE_CALENDAR_USER,
193           4,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
194         { CSA_ENTRY_ATTR_START_DATE_I,          CSA_VALUE_DATE_TIME,
195           1,    _DtCm_old_attr_time,            B_FALSE, B_FALSE },
196         { CSA_ENTRY_ATTR_STATUS_I,              CSA_VALUE_UINT32,
197           2,    _DtCm_old_attr_status,          B_FALSE, B_FALSE },
198         { CSA_ENTRY_ATTR_SUBTYPE_I,             CSA_VALUE_STRING,
199           1,    _DtCm_old_attr_type2,           B_FALSE, B_FALSE },
200         { CSA_ENTRY_ATTR_SUMMARY_I,             CSA_VALUE_STRING,
201           1,    _DtCm_old_attr_what,            B_FALSE, B_FALSE },
202         { CSA_ENTRY_ATTR_TIME_TRANSPARENCY_I,   CSA_VALUE_SINT32,
203           4,    _DtCm_old_attr_unknown,         B_FALSE, B_FALSE },
204         { CSA_ENTRY_ATTR_TYPE_I,                CSA_VALUE_UINT32,
205           1,    _DtCm_old_attr_type,            B_FALSE, B_FALSE },
206         { CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,       CSA_VALUE_SINT32,
207           2,    _DtCm_old_attr_showtime,        B_FALSE, B_FALSE },
208         { CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I,    CSA_VALUE_SINT32,
209           1,    _DtCm_old_attr_repeat_type,     B_FALSE, B_TRUE },
210         { CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I,   CSA_VALUE_UINT32,
211           1,    _DtCm_old_attr_repeat_times,    B_FALSE, B_TRUE },
212         { CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I, CSA_VALUE_UINT32,
213           3,    _DtCm_old_attr_repeat_nth_interval, B_FALSE, B_TRUE },
214         { CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I, CSA_VALUE_SINT32,
215           3,    _DtCm_old_attr_repeat_nth_weeknum, B_FALSE, B_TRUE },
216         { CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I, CSA_VALUE_DATE_TIME,
217           3,    _DtCm_old_attr_end_date,        B_FALSE, B_TRUE },
218         { CSA_X_DT_ENTRY_ATTR_ENTRY_DELIMITER_I, CSA_VALUE_STRING,
219           -1,   _DtCm_old_attr_unknown,         B_TRUE, B_TRUE }
220 };
221
222 /*****************************************************************************
223  * forward declaration of static functions used within the file
224  *****************************************************************************/
225 static CSA_return_code check_predefined_attrs(
226         int                     fversion,
227         uint                    num_attrs,
228         cms_attribute           *attrs,
229         boolean_t               checkreadonly,
230         _DtCmNameTable          *tbl,
231         uint                    num_defined,
232         _DtCmAttrInfo           *our_attrs);
233
234 static CSA_return_code convert_cms_user_to_csa_user(char *from,
235         CSA_calendar_user **to);
236
237 static CSA_return_code hash_entry_attrs(uint num_attrs, CSA_attribute *csaattrs,
238         cms_attribute *cmsattrs, uint *hnum, cms_attribute **hattrs, uint *num);
239
240 static CSA_return_code hash_cal_attrs(uint num_attrs, CSA_attribute *csaattrs,
241         cms_attribute *cmsattrs, uint *hnum, cms_attribute **hattrs, uint *num);
242
243 static CSA_return_code _DtCm_check_hashed_entry_attributes(
244         int             fvers,
245         uint            num_attrs,
246         cms_attribute   *attrs,
247         CSA_flags       utype);
248
249 static CSA_return_code _DtCm_check_hashed_cal_attributes(
250         int             fvers,
251         uint            num_attrs,
252         cms_attribute   *attrs,
253         char            *owner,
254         char            *cname,
255         boolean_t       checkreadonly,
256         boolean_t       firsttime,
257         boolean_t       csatype);
258
259 static CSA_return_code _CheckNameAtHost(char *owner, char *value);
260
261 static CSA_return_code _CheckCalendarOwner(char *owner, int type, char *name);
262
263 static CSA_return_code _CheckCalendarName(char *owner, char *cname,
264                                         cms_attribute_value *val);
265
266 /*****************************************************************************
267  * extern functions used in the library
268  *****************************************************************************/
269
270 /*
271  * For each calendar attribute, if it is a predefined attribute,
272  * check that the data type is correct.
273  * If checkreadonly is B_TRUE, also check that it's not readonly.
274  */
275 extern CSA_return_code
276 _DtCm_check_cal_csa_attributes(
277         int             fvers,
278         uint            num_attrs,
279         CSA_attribute   *attrs,
280         char            *cname,
281         boolean_t       checkreadonly,
282         boolean_t       firsttime,
283         boolean_t       checkattrnum)
284 {
285         CSA_return_code stat;
286         uint            hnum;
287         cms_attribute   *hattrs;
288         uint            realnum;
289
290         if ((stat = hash_cal_attrs(num_attrs, attrs, NULL, &hnum, &hattrs,
291             &realnum)) != CSA_SUCCESS)
292                 return (stat);
293
294         if (checkattrnum == B_TRUE && realnum == 0)
295                 return (CSA_E_INVALID_PARAMETER);
296
297         stat = _DtCm_check_hashed_cal_attributes(fvers, hnum, hattrs,
298                 NULL, cname, checkreadonly, firsttime, B_TRUE);
299
300         free(hattrs);
301
302         return (stat);
303 }
304
305 extern CSA_return_code
306 _DtCm_check_cal_cms_attributes(
307         int             fvers,
308         uint            num_attrs,
309         cms_attribute   *attrs,
310         char            *owner,
311         char            *cname,
312         boolean_t       checkreadonly,
313         boolean_t       firsttime,
314         boolean_t       checkattrnum)
315 {
316         CSA_return_code stat;
317         uint            hnum;
318         cms_attribute   *hattrs;
319         uint            realnum;
320
321         if ((stat = hash_cal_attrs(num_attrs, NULL, attrs, &hnum, &hattrs,
322             &realnum)) != CSA_SUCCESS)
323                 return (stat);
324
325         if (checkattrnum == B_TRUE && realnum == 0)
326                 return (CSA_E_INVALID_PARAMETER);
327
328         stat = _DtCm_check_hashed_cal_attributes(fvers, hnum, hattrs,
329                 owner, cname, checkreadonly, firsttime, B_FALSE);
330
331         free(hattrs);
332
333         return (stat);
334 }
335
336 extern CSA_return_code
337 _DtCm_check_entry_attributes(
338         int             fvers,
339         uint            num_attrs,
340         CSA_attribute   *attrs,
341         CSA_flags       utype,
342         boolean_t       checkattrnum)
343 {
344         CSA_return_code stat;
345         uint            hnum;
346         cms_attribute   *hattrs;
347         uint            realnum;
348
349         if ((stat = hash_entry_attrs(num_attrs, attrs, NULL, &hnum, &hattrs,
350             &realnum)) != CSA_SUCCESS)
351                 return (stat);
352
353         if (checkattrnum == B_TRUE && realnum == 0)
354                 return (CSA_E_INVALID_PARAMETER);
355
356         stat = _DtCm_check_hashed_entry_attributes(fvers, hnum, hattrs,
357                 utype);
358
359         free(hattrs);
360
361         return (stat);
362 }
363
364 extern CSA_return_code
365 _DtCm_check_entry_cms_attributes(
366         int             fvers,
367         uint            num_attrs,
368         cms_attribute   *attrs,
369         CSA_flags       utype,
370         boolean_t       checkattrnum)
371 {
372         CSA_return_code stat;
373         uint            hnum;
374         cms_attribute   *hattrs;
375         uint            realnum;
376
377         if ((stat = hash_entry_attrs(num_attrs, NULL, attrs, &hnum, &hattrs,
378             &realnum)) != CSA_SUCCESS)
379                 return (stat);
380
381         if (checkattrnum == B_TRUE && realnum == 0)
382                 return (CSA_E_INVALID_PARAMETER);
383
384         stat = _DtCm_check_hashed_entry_attributes(fvers, hnum, hattrs,
385                 utype);
386
387         free(hattrs);
388
389         return (stat);
390 }
391
392 /*
393  * copy attributes
394  * attributes with a name but NULL value is allowed
395  * attributes with null names are ignored
396  * validity of attributes should be checked before calling this routine
397  *
398  * Note: the first entry is not used
399  */
400 extern CSA_return_code
401 _DtCm_copy_cms_attributes(
402         uint srcsize,
403         cms_attribute *srcattrs,
404         uint *dstsize,
405         cms_attribute **dstattrs)
406 {
407         int     i, j;
408         CSA_return_code stat = CSA_SUCCESS;
409         cms_attribute   *attrs;
410
411         if (dstsize == NULL || dstattrs == NULL)
412                 return (CSA_E_INVALID_PARAMETER);
413
414         *dstsize = 0;
415         *dstattrs = NULL;
416
417         if (srcsize == 0)
418                 return (CSA_SUCCESS);
419
420         if ((attrs = calloc(1, sizeof(cms_attribute) * (srcsize + 1))) == NULL)
421                 return (CSA_E_INSUFFICIENT_MEMORY);
422
423         /* firstr element is not used */
424         for (i = 1, j = 1; i <= srcsize; i++) {
425                 if (srcattrs[i].name.name != NULL) {
426                         if ((stat = _DtCm_copy_cms_attribute(&attrs[j],
427                             &srcattrs[i], B_TRUE)) != CSA_SUCCESS)
428                                 break;
429                         else
430                                 j++;
431                 }
432         }
433
434         if (stat != CSA_SUCCESS && j > 1) {
435                 _DtCm_free_cms_attributes(j, attrs);
436                 free(attrs);
437         } else {
438                 *dstsize = j - 1;
439                 *dstattrs = attrs;
440         }
441
442         return(stat);
443 }
444
445 /*
446  * Frees the name and value field of the array, but not
447  * array itself.
448  * note: element 0 is not used
449  */
450 extern void
451 _DtCm_free_cms_attributes(uint size, cms_attribute *attrs)
452 {
453         int i;
454
455         for (i = 0; i < size; i++) {
456                 if (attrs[i].name.name) {
457                         free(attrs[i].name.name);
458                         attrs[i].name.name = NULL;
459
460                         if (attrs[i].value) {
461                                 _DtCm_free_cms_attribute_value(attrs[i].value);
462                                 attrs[i].value = NULL;
463                         }
464                 }
465         }
466 }
467
468 /*
469  * Frees the name and value field of the array, but not
470  * array itself.
471  */
472 extern void
473 _DtCm_free_attributes(uint size, CSA_attribute * attrs)
474 {
475         int i;
476
477         for (i = 0; i < size; i++) {
478                 if (attrs[i].name) {
479                         free(attrs[i].name);
480                         attrs[i].name = NULL;
481
482                         if (attrs[i].value) {
483                                 _DtCm_free_attribute_value(attrs[i].value);
484                                 attrs[i].value = NULL;
485                         }
486                 }
487         }
488 }
489
490 /*
491  * Free the value part of the cms_attribute structure.
492  * note: element 0 is not used
493  */
494 extern void
495 _DtCm_free_cms_attribute_values(uint size, cms_attribute *attrs)
496 {
497         int     i;
498
499         for (i = 1; i <= size; i++) {
500                 if (attrs[i].value) {
501                         _DtCm_free_cms_attribute_value(attrs[i].value);
502                         attrs[i].value = NULL;
503                 }
504         }
505 }
506
507 /*
508  * Free the value part of the the attribute structure.
509  */
510 extern void
511 _DtCm_free_attribute_values(uint size, CSA_attribute * attrs)
512 {
513         int     i;
514
515         for (i = 0; i < size; i++) {
516                 if (attrs[i].value) {
517                         _DtCm_free_attribute_value(attrs[i].value);
518                         attrs[i].value = NULL;
519                 }
520         }
521 }
522
523 extern char *
524 _DtCm_old_reminder_name_to_name(char *oldname)
525 {
526         if (strcmp(oldname, _DtCM_OLD_ATTR_BEEP_REMINDER) == 0)
527                 return (CSA_ENTRY_ATTR_AUDIO_REMINDER);
528         else if (strcmp(oldname, _DtCM_OLD_ATTR_FLASH_REMINDER) == 0)
529                 return (CSA_ENTRY_ATTR_FLASHING_REMINDER);
530         else if (strcmp(oldname, _DtCM_OLD_ATTR_MAIL_REMINDER) == 0)
531                 return (CSA_ENTRY_ATTR_MAIL_REMINDER);
532         else if (strcmp(oldname, _DtCM_OLD_ATTR_POPUP_REMINDER) == 0)
533                 return (CSA_ENTRY_ATTR_POPUP_REMINDER);
534         else
535                 return (oldname);
536 }
537
538 extern int
539 _DtCm_old_reminder_name_to_index(char *oldname)
540 {
541         char    *name;
542
543         name = _DtCm_old_reminder_name_to_name(oldname);
544
545         return (_DtCm_get_index_from_table(_DtCm_entry_name_tbl, name));
546 }
547
548 /*
549  * Given an attribute name, return the corresponding
550  * attribute number that's supported by old backends (v4 and before).
551  */
552 extern CSA_return_code
553 _DtCm_get_old_attr_by_name(char *name, _DtCm_old_attrs *attr)
554 {
555         int     index;
556
557         index = _DtCm_get_index_from_table(_DtCm_entry_name_tbl, name);
558         if (index > 0 && index <= _DtCM_DEFINED_ENTRY_ATTR_SIZE) {
559
560                 if (_CSA_entry_attr_info[index].oldattr
561                     != _DtCm_old_attr_unknown) {
562                         *attr = _CSA_entry_attr_info[index].oldattr;
563                         return (CSA_SUCCESS);
564                 } else
565                         return (CSA_E_UNSUPPORTED_ATTRIBUTE);
566         } else
567                 return (CSA_E_INVALID_ATTRIBUTE);
568 }
569
570 /*
571  * Given an attribute index, return the corresponding
572  * attribute number that's supported by old backends (v4 and before).
573  */
574 extern CSA_return_code
575 _DtCm_get_old_attr_by_index(int index, _DtCm_old_attrs *attr)
576 {
577         if (index <= _DtCM_DEFINED_ENTRY_ATTR_SIZE) {
578                 if (_CSA_entry_attr_info[index].oldattr
579                     != _DtCm_old_attr_unknown) {
580                         *attr = _CSA_entry_attr_info[index].oldattr;
581                         return (CSA_SUCCESS);
582                 } else
583                         return (CSA_E_UNSUPPORTED_ATTRIBUTE);
584         } else
585                 return (CSA_E_INVALID_ATTRIBUTE);
586 }
587
588 /*
589  * copy attribute
590  * the attribute structure should contain valid value
591  * a NULL attribute value is valid
592  */
593 extern CSA_return_code
594 _DtCm_copy_cms_attribute(
595         cms_attribute *to,
596         cms_attribute *from,
597         boolean_t copyname)
598 {
599         CSA_return_code stat = CSA_SUCCESS;
600         char            *name;
601
602         if (to == NULL)
603                 return (CSA_E_INVALID_PARAMETER);
604
605         /* copy the attribute name */
606         if (copyname) {
607                 if ((name = strdup(from->name.name)) == NULL)
608                         return(CSA_E_INSUFFICIENT_MEMORY);
609         }
610
611         if ((stat = _DtCm_copy_cms_attr_val(from->value, &to->value))
612             == CSA_SUCCESS) {
613                 if (copyname) {
614                         to->name.name = name;
615                         to->name.num = from->name.num;
616                 }
617         } else if (copyname)
618                 free (name);
619
620         return(stat);
621 }
622
623 extern CSA_return_code
624 _DtCm_copy_cms_attr_val(cms_attribute_value *from, cms_attribute_value **to)
625 {
626         CSA_return_code stat = CSA_SUCCESS;
627         cms_attribute_value     *val;
628
629         if (to == NULL)
630                 return (CSA_E_INVALID_PARAMETER);
631
632         /* copy the attribute value */
633         if (from == NULL)
634                 val = NULL;
635         else {
636                 if ((val = (cms_attribute_value *)calloc(1,
637                     sizeof(cms_attribute_value))) == NULL)
638                         return (CSA_E_INSUFFICIENT_MEMORY);
639
640                 switch (from->type) {
641                 case CSA_VALUE_BOOLEAN:
642                 case CSA_VALUE_ENUMERATED:
643                 case CSA_VALUE_FLAGS:
644                 case CSA_VALUE_UINT32:
645                 case CSA_VALUE_SINT32:
646                         val->item.uint32_value = from->item.uint32_value;
647                         break;
648
649                 case CSA_VALUE_STRING:
650                 case CSA_VALUE_DATE_TIME:
651                 case CSA_VALUE_DATE_TIME_RANGE:
652                 case CSA_VALUE_TIME_DURATION:
653                 case CSA_VALUE_CALENDAR_USER:
654                         if (from->item.string_value)
655                                 val->item.string_value =
656                                         strdup(from->item.string_value);
657                         else
658                                 val->item.string_value = calloc(1, 1);
659                         if (val->item.string_value == NULL)
660                                 stat = CSA_E_INSUFFICIENT_MEMORY;
661                         break;
662
663                 case CSA_VALUE_REMINDER:
664                         if (from->item.reminder_value == NULL)
665                                 stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
666                         else
667                                 stat = _DtCm_copy_reminder(
668                                         from->item.reminder_value,
669                                         &val->item.reminder_value);
670                         break;
671                 case CSA_VALUE_ATTENDEE_LIST:
672                         stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
673                         break;
674                 case CSA_VALUE_ACCESS_LIST:
675                         if (from->item.access_list_value &&
676                             (val->item.access_list_value =
677                             _DtCm_copy_cms_access_list(
678                             from->item.access_list_value)) == NULL) {
679
680                                 stat = CSA_E_INSUFFICIENT_MEMORY;
681                         }
682                         break;
683                 case CSA_VALUE_DATE_TIME_LIST:
684                         if (from->item.date_time_list_value &&
685                             (val->item.date_time_list_value =
686                             _DtCm_copy_date_time_list(
687                             from->item.date_time_list_value)) == NULL) {
688
689                                 stat = CSA_E_INSUFFICIENT_MEMORY;
690                         }
691                         break;
692                 case CSA_VALUE_OPAQUE_DATA:
693                         if (from->item.opaque_data_value) {
694                                 stat = _DtCm_copy_opaque_data(
695                                         from->item.opaque_data_value,
696                                         &val->item.opaque_data_value);
697                         }
698                         break;
699                 default:
700                         stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
701                         break;
702                 }
703
704                 if (stat != CSA_SUCCESS)
705                         free(val);
706                 else
707                         val->type = from->type;
708         }
709
710         if (stat == CSA_SUCCESS) {
711                 *to = val;
712         }
713
714         return(stat);
715 }
716
717 /*
718  * copy the attribute name, and convert the attribute value
719  */
720 extern CSA_return_code
721 _DtCm_cms2csa_attribute(cms_attribute from, CSA_attribute *to)
722 {
723         CSA_return_code         stat;
724         char                    *name;
725         CSA_attribute_value     *val;
726
727         if ((name = strdup(from.name.name)) == NULL)
728                 return (CSA_E_INSUFFICIENT_MEMORY);
729
730         if ((stat = _DtCm_cms2csa_attrval(from.value, &val)) == CSA_SUCCESS) {
731                 to->name = name;
732                 to->value = val;
733         } else
734                 free(name);
735
736         return (stat);
737 }
738
739 extern CSA_return_code
740 _DtCm_cms2csa_attrval(cms_attribute_value *from, CSA_attribute_value **to)
741 {
742         CSA_return_code stat = CSA_SUCCESS;
743         CSA_attribute_value     *val;
744
745         if (to == NULL)
746                 return (CSA_E_INVALID_PARAMETER);
747
748         /* copy the attribute value */
749         if (from == NULL)
750                 val = NULL;
751         else {
752                 if ((val = (CSA_attribute_value *)calloc(1,
753                     sizeof(CSA_attribute_value))) == NULL)
754                         return (CSA_E_INSUFFICIENT_MEMORY);
755
756                 switch (from->type) {
757                 case CSA_VALUE_BOOLEAN:
758                 case CSA_VALUE_ENUMERATED:
759                 case CSA_VALUE_FLAGS:
760                 case CSA_VALUE_UINT32:
761                 case CSA_VALUE_SINT32:
762                         val->item.uint32_value = from->item.uint32_value;
763                         break;
764
765                 case CSA_VALUE_STRING:
766                 case CSA_VALUE_DATE_TIME:
767                 case CSA_VALUE_DATE_TIME_RANGE:
768                 case CSA_VALUE_TIME_DURATION:
769                         if (from->item.string_value)
770                                 val->item.string_value =
771                                         strdup(from->item.string_value);
772                         else
773                                 val->item.string_value = calloc(1, 1);
774                         if (val->item.string_value == NULL)
775                                 stat = CSA_E_INSUFFICIENT_MEMORY;
776                         break;
777
778                 case CSA_VALUE_REMINDER:
779                         if (from->item.reminder_value == NULL)
780                                 stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
781                         else
782                                 stat = _DtCm_copy_reminder(
783                                         from->item.reminder_value,
784                                         &val->item.reminder_value);
785                         break;
786                 case CSA_VALUE_CALENDAR_USER:
787                         if (from->item.calendar_user_value == NULL)
788                                 stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
789                         else
790                                 stat = convert_cms_user_to_csa_user(
791                                         from->item.calendar_user_value,
792                                         &val->item.calendar_user_value);
793                         break;
794                 case CSA_VALUE_ACCESS_LIST:
795                         stat = _DtCm_cms2csa_access_list(
796                                 from->item.access_list_value,
797                                 &val->item.access_list_value);
798                         break;
799                 case CSA_VALUE_ATTENDEE_LIST:
800                         stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
801                         break;
802                 case CSA_VALUE_DATE_TIME_LIST:
803                         if (from->item.date_time_list_value &&
804                             (val->item.date_time_list_value =
805                             _DtCm_copy_date_time_list(
806                             from->item.date_time_list_value)) == NULL) {
807                                 stat = CSA_E_INSUFFICIENT_MEMORY;
808                         }
809                         break;
810                 case CSA_VALUE_OPAQUE_DATA:
811                         if (from->item.opaque_data_value) {
812                                 stat = _DtCm_copy_opaque_data(
813                                         from->item.opaque_data_value,
814                                         &val->item.opaque_data_value);
815                         } else
816                                 val->item.opaque_data_value = NULL;
817                         break;
818                 default:
819                         stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
820                         break;
821                 }
822
823                 if (stat != CSA_SUCCESS)
824                         free(val);
825                 else
826                         val->type = from->type;
827         }
828
829         if (stat == CSA_SUCCESS) {
830                 *to = val;
831         }
832
833         return(stat);
834 }
835
836 extern void
837 _DtCm_free_cms_attribute_value(cms_attribute_value *val)
838 {
839         if (val == NULL)
840                 return;
841
842         switch (val->type) {
843         case CSA_VALUE_STRING:
844         case CSA_VALUE_DATE_TIME:
845         case CSA_VALUE_DATE_TIME_RANGE:
846         case CSA_VALUE_TIME_DURATION:
847         case CSA_VALUE_CALENDAR_USER:
848                 if (val->item.string_value)
849                         free(val->item.string_value);
850                 break;
851
852         case CSA_VALUE_REMINDER:
853                 if (val->item.reminder_value)
854                         _DtCm_free_reminder(val->item.reminder_value);
855                 break;
856         case CSA_VALUE_ACCESS_LIST:
857                 if (val->item.access_list_value)
858                         _DtCm_free_cms_access_entry(val->item.access_list_value);
859                 break;
860         case CSA_VALUE_DATE_TIME_LIST:
861                 if (val->item.date_time_list_value)
862                         _DtCm_free_date_time_list(
863                                 val->item.date_time_list_value);
864                 break;
865         case CSA_VALUE_OPAQUE_DATA:
866                 if (val->item.opaque_data_value) {
867                         _DtCm_free_opaque_data(val->item.opaque_data_value);
868                 }
869                 break;
870         }
871         free(val);
872 }
873
874 extern void
875 _DtCm_free_attribute_value(CSA_attribute_value *val)
876 {
877         if (val == NULL)
878                 return;
879
880         switch (val->type) {
881         case CSA_VALUE_STRING:
882         case CSA_VALUE_DATE_TIME:
883         case CSA_VALUE_DATE_TIME_RANGE:
884         case CSA_VALUE_TIME_DURATION:
885                 if (val->item.string_value)
886                         free(val->item.string_value);
887                 break;
888
889         case CSA_VALUE_REMINDER:
890                 if (val->item.reminder_value)
891                         _DtCm_free_reminder(val->item.reminder_value);
892                 break;
893         case CSA_VALUE_ACCESS_LIST:
894                 if (val->item.access_list_value)
895                         _DtCm_free_csa_access_list(val->item.access_list_value);
896                 break;
897         case CSA_VALUE_CALENDAR_USER:
898                 if (val->item.calendar_user_value) {
899                         if (val->item.calendar_user_value->user_name)
900                                 free(val->item.calendar_user_value->user_name);
901                         if (val->item.calendar_user_value->calendar_address)
902                                 free(val->item.calendar_user_value->user_name);
903                         free(val->item.calendar_user_value);
904                 }
905                 break;
906         case CSA_VALUE_DATE_TIME_LIST:
907                 if (val->item.date_time_list_value)
908                         _DtCm_free_date_time_list(
909                                 val->item.date_time_list_value);
910                 break;
911         case CSA_VALUE_OPAQUE_DATA:
912                 if (val->item.opaque_data_value) {
913                         _DtCm_free_opaque_data(val->item.opaque_data_value);
914                 }
915                 break;
916         }
917         free(val);
918 }
919
920 extern CSA_return_code
921 _DtCm_set_uint32_attrval(uint numval, cms_attribute_value **attrval)
922 {
923         cms_attribute_value     *val;
924
925         if ((val = (cms_attribute_value *)malloc(sizeof(cms_attribute_value)))
926             == NULL) {
927                 return (CSA_E_INSUFFICIENT_MEMORY);
928         }
929
930         val->type = CSA_VALUE_UINT32;
931         val->item.uint32_value = numval;
932
933         *attrval = val;
934
935         return (CSA_SUCCESS);
936 }
937
938 extern CSA_return_code
939 _DtCm_set_sint32_attrval(int numval, cms_attribute_value **attrval)
940 {
941         cms_attribute_value     *val;
942
943         if ((val = (cms_attribute_value *)malloc(sizeof(cms_attribute_value)))
944             == NULL) {
945                 return (CSA_E_INSUFFICIENT_MEMORY);
946         }
947
948         val->type = CSA_VALUE_SINT32;
949         val->item.sint32_value = numval;
950
951         *attrval = val;
952
953         return (CSA_SUCCESS);
954 }
955
956 extern CSA_return_code
957 _DtCm_set_string_attrval(
958         char *strval,
959         cms_attribute_value **attrval,
960         CSA_enum type)
961 {
962         cms_attribute_value     *val;
963
964         if (type != CSA_VALUE_STRING && type != CSA_VALUE_DATE_TIME &&
965             type != CSA_VALUE_DATE_TIME_RANGE &&
966             type != CSA_VALUE_TIME_DURATION && type != CSA_VALUE_CALENDAR_USER)
967                 return (CSA_E_INVALID_PARAMETER);
968
969         if ((val = (cms_attribute_value *)malloc(sizeof(cms_attribute_value)))
970             == NULL) {
971                 return (CSA_E_INSUFFICIENT_MEMORY);
972         }
973
974         val->type = type;
975
976         if (strval == NULL) {
977                 val->item.string_value = NULL;
978         } else if ((val->item.string_value = strdup(strval)) == NULL) {
979                 free(val);
980                 return (CSA_E_INSUFFICIENT_MEMORY);
981         }
982
983         *attrval = val;
984
985         return (CSA_SUCCESS);
986 }
987
988 extern CSA_return_code
989 _DtCm_set_user_attrval(
990         char *user,
991         cms_attribute_value **attrval)
992 {
993         cms_attribute_value     *val;
994
995         if (user == NULL) {
996                 *attrval = NULL;
997                 return (CSA_SUCCESS);
998         }
999
1000         if ((val = (cms_attribute_value *)malloc(sizeof(cms_attribute_value)))
1001             == NULL) {
1002                 return (CSA_E_INSUFFICIENT_MEMORY);
1003         }
1004
1005         val->type = CSA_VALUE_CALENDAR_USER;
1006
1007         if ((val->item.calendar_user_value = strdup(user)) == NULL) {
1008                 free(val);
1009                 return (CSA_E_INSUFFICIENT_MEMORY);
1010         }
1011
1012         *attrval = val;
1013
1014         return (CSA_SUCCESS);
1015 }
1016
1017 extern CSA_return_code
1018 _DtCm_set_reminder_attrval(CSA_reminder *remval, cms_attribute_value **attrval)
1019 {
1020         cms_attribute_value *val;
1021         CSA_return_code stat;
1022
1023         if (remval == NULL)
1024                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1025
1026         if ((val = (cms_attribute_value *)malloc(sizeof(cms_attribute_value)))
1027             == NULL) {
1028                 return (CSA_E_INSUFFICIENT_MEMORY);
1029         }
1030
1031         val->type = CSA_VALUE_REMINDER;
1032
1033         if ((stat = _DtCm_copy_reminder(remval, &val->item.reminder_value))
1034             != CSA_SUCCESS) {
1035                 free(val);
1036                 return (stat);
1037         } else {
1038
1039                 *attrval = val;
1040
1041                 return (CSA_SUCCESS);
1042         }
1043 }
1044
1045 extern CSA_return_code
1046 _DtCm_set_csa_access_attrval(
1047         cms_access_entry *aval,
1048         CSA_attribute_value **attrval)
1049 {
1050         CSA_attribute_value *val;
1051         CSA_return_code stat = CSA_SUCCESS;
1052
1053         if ((val = (CSA_attribute_value *)malloc(sizeof(CSA_attribute_value)))
1054             == NULL) {
1055                 return (CSA_E_INSUFFICIENT_MEMORY);
1056         }
1057
1058         val->type = CSA_VALUE_ACCESS_LIST;
1059
1060         if (aval == NULL) {
1061
1062                 val->item.access_list_value = NULL;
1063
1064         } else {
1065         
1066                 stat = _DtCm_cms2csa_access_list(aval,
1067                         &val->item.access_list_value);
1068
1069         }
1070
1071         if (stat == CSA_SUCCESS)
1072                 *attrval = val;
1073         else
1074                 free(val);
1075
1076         return (stat);
1077 }
1078
1079 extern CSA_return_code
1080 _DtCm_set_opaque_attrval(CSA_opaque_data *data, cms_attribute_value **attrval)
1081 {
1082         CSA_return_code stat;
1083         cms_attribute_value     *val;
1084
1085         if (data == NULL)
1086                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1087
1088         if ((val = (cms_attribute_value *)malloc(sizeof(cms_attribute_value)))
1089             == NULL) {
1090                 return (CSA_E_INSUFFICIENT_MEMORY);
1091         }
1092
1093         val->type = CSA_VALUE_OPAQUE_DATA;
1094
1095         if ((stat = _DtCm_copy_opaque_data(data, &val->item.opaque_data_value))
1096             != CSA_SUCCESS) {
1097                 free(val);
1098                 return (stat);
1099         } else {
1100
1101                 *attrval = val;
1102                 return (CSA_SUCCESS);
1103         }
1104 }
1105
1106 extern CSA_return_code
1107 _DtCm_set_csa_uint32_attrval(uint numval, CSA_attribute_value **attrval)
1108 {
1109         CSA_attribute_value     *val;
1110
1111         if ((val = (CSA_attribute_value *)malloc(sizeof(CSA_attribute_value)))
1112             == NULL) {
1113                 return (CSA_E_INSUFFICIENT_MEMORY);
1114         }
1115
1116         val->type = CSA_VALUE_UINT32;
1117         val->item.uint32_value = numval;
1118
1119         *attrval = val;
1120
1121         return (CSA_SUCCESS);
1122 }
1123
1124 extern CSA_return_code
1125 _DtCm_set_csa_string_attrval(
1126         char *strval,
1127         CSA_attribute_value **attrval,
1128         CSA_enum type)
1129 {
1130         CSA_attribute_value     *val;
1131
1132         if (type != CSA_VALUE_STRING && type != CSA_VALUE_DATE_TIME &&
1133             type != CSA_VALUE_DATE_TIME_RANGE &&
1134             type != CSA_VALUE_TIME_DURATION && type != CSA_VALUE_CALENDAR_USER)
1135                 return (CSA_E_INVALID_PARAMETER);
1136
1137         if ((val = (CSA_attribute_value *)malloc(sizeof(CSA_attribute_value)))
1138             == NULL) {
1139                 return (CSA_E_INSUFFICIENT_MEMORY);
1140         }
1141
1142         val->type = type;
1143
1144         if (strval == NULL) {
1145                 val->item.string_value = NULL;
1146         } else if ((val->item.string_value = strdup(strval)) == NULL) {
1147                 free(val);
1148                 return (CSA_E_INSUFFICIENT_MEMORY);
1149         }
1150
1151         *attrval = val;
1152
1153         return (CSA_SUCCESS);
1154 }
1155
1156 extern void
1157 _DtCm_free_csa_access_list(CSA_access_list alist)
1158 {
1159         CSA_access_list nptr;
1160
1161         while (alist != NULL) {
1162                 nptr = alist->next;
1163
1164                 if (alist->user) {
1165                         if (alist->user->user_name)
1166                                 free(alist->user->user_name);
1167                         if (alist->user->calendar_address);
1168                                 free(alist->user->calendar_address);
1169                         free(alist->user);
1170                 }
1171
1172                 free(alist);
1173
1174                 alist = nptr;
1175         }
1176 }
1177
1178 extern void
1179 _DtCm_free_date_time_list(CSA_date_time_list list)
1180 {
1181         CSA_date_time_entry *nptr;
1182
1183         while (list != NULL) {
1184                 nptr = list->next;
1185
1186                 if (list->date_time) {
1187                         free(list->date_time);
1188                 }
1189
1190                 free(list);
1191
1192                 list = nptr;
1193         }
1194 }
1195
1196 extern void
1197 _DtCm_free_cms_access_entry(cms_access_entry *list)
1198 {
1199         cms_access_entry *nptr;
1200
1201         while (list != NULL) {
1202                 nptr = list->next;
1203
1204                 if (list->user) {
1205                         free(list->user);
1206                 }
1207
1208                 free(list);
1209
1210                 list = nptr;
1211         }
1212 }
1213
1214 extern cms_access_entry *
1215 _DtCm_copy_cms_access_list(cms_access_entry *alist)
1216 {
1217         cms_access_entry        *l, *head, *prev;
1218         boolean_t       cleanup = B_FALSE;
1219
1220         prev = head = NULL;
1221         while (alist != NULL) {
1222                 if ((l = (cms_access_entry *)calloc(1, sizeof(cms_access_entry)))
1223                     == NULL) {
1224                         cleanup = B_TRUE;
1225                         break;
1226                 }
1227
1228                 if ((l->user = strdup(alist->user)) == NULL) {
1229                         free(l);
1230                         cleanup = B_TRUE;
1231                         break;
1232                 }
1233
1234                 l->rights = alist->rights;
1235                 l->next = NULL;
1236
1237                 if (head == NULL)
1238                         head = l;
1239                 else
1240                         prev->next = l;
1241                 prev = l;
1242
1243                 alist = alist->next;
1244         }
1245
1246         if (cleanup == B_TRUE) {
1247                 _DtCm_free_cms_access_entry(head);
1248                 head = NULL;
1249         }
1250         return(head);
1251 }
1252
1253 extern CSA_return_code
1254 _DtCm_cms2csa_access_list(
1255         cms_access_entry *cmslist,
1256         CSA_access_rights **csalist)
1257 {
1258         CSA_return_code stat = CSA_SUCCESS;
1259         CSA_access_rights *to, *head, *prev;
1260
1261         head = prev = NULL;
1262         while (cmslist != NULL) {
1263                 if ((to = (CSA_access_rights *)calloc(1,
1264                     sizeof(CSA_access_rights))) == NULL) {
1265                         stat = CSA_E_INSUFFICIENT_MEMORY;
1266                         break;
1267                 }
1268
1269                 if ((to->user = (CSA_calendar_user *)calloc(1,
1270                     sizeof(CSA_calendar_user))) == NULL) {
1271                         free(to);
1272                         stat = CSA_E_INSUFFICIENT_MEMORY;
1273                         break;
1274                 }
1275
1276                 if ((to->user->user_name = strdup(cmslist->user)) == NULL) {
1277                         free(to->user);
1278                         free(to);
1279                         stat = CSA_E_INSUFFICIENT_MEMORY;
1280                         break;
1281                 }
1282
1283                 to->rights = cmslist->rights;
1284                 to->next = NULL;
1285
1286                 if (head == NULL)
1287                         head = to;
1288                 else
1289                         prev->next = to;
1290
1291                 prev = to;
1292
1293                 cmslist = cmslist->next;
1294         }
1295
1296         if (stat != CSA_SUCCESS) {
1297                 _DtCm_free_csa_access_list(head);
1298                 head = NULL;
1299         }
1300
1301         *csalist = head;
1302         return (stat);
1303 }
1304
1305 extern CSA_return_code
1306 _DtCm_csa2cms_access_list(
1307         CSA_access_rights *csalist,
1308         cms_access_entry **cmslist)
1309 {
1310         CSA_return_code stat = CSA_SUCCESS;
1311         cms_access_entry *to, *head, *prev;
1312
1313         head = prev = NULL;
1314         while (csalist != NULL) {
1315                 if ((to = (cms_access_entry *)calloc(1,
1316                     sizeof(cms_access_entry))) == NULL) {
1317                         stat = CSA_E_INSUFFICIENT_MEMORY;
1318                         break;
1319                 }
1320
1321                 if (csalist->user->user_name) {
1322                         if ((to->user = strdup(csalist->user->user_name))
1323                             == NULL) {
1324                                 stat = CSA_E_INSUFFICIENT_MEMORY;
1325                                 free(to);
1326                                 break;
1327                         }
1328                 } else {
1329                         stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
1330                         free(to);
1331                         break;
1332                 }
1333
1334                 to->rights = csalist->rights;
1335                 to->next = NULL;
1336
1337                 if (head == NULL)
1338                         head = to;
1339                 else
1340                         prev->next = to;
1341
1342                 prev = to;
1343
1344                 csalist = csalist->next;
1345         }
1346
1347         if (stat != CSA_SUCCESS) {
1348                 _DtCm_free_cms_access_entry(head);
1349                 head = NULL;
1350         }
1351
1352         *cmslist = head;
1353         return (stat);
1354 }
1355
1356 extern CSA_date_time_list
1357 _DtCm_copy_date_time_list(CSA_date_time_list dlist)
1358 {
1359         CSA_date_time_entry     *l, *head, *prev;
1360         boolean_t       cleanup = B_FALSE;
1361
1362         prev = head = NULL;
1363         while (dlist != NULL) {
1364                 if ((l = (CSA_date_time_entry *)calloc(1,
1365                     sizeof(CSA_date_time_entry))) == NULL) {
1366                         cleanup = B_TRUE;
1367                         break;
1368                 }
1369
1370                 if ((l->date_time = strdup(dlist->date_time)) == NULL) {
1371                         free(l);
1372                         cleanup = B_TRUE;
1373                         break;
1374                 }
1375
1376                 l->next = NULL;
1377
1378                 if (head == NULL)
1379                         head = l;
1380                 else
1381                         prev->next = l;
1382                 prev = l;
1383
1384                 dlist = dlist->next;
1385         }
1386
1387         if (cleanup == B_TRUE) {
1388                 _DtCm_free_date_time_list(head);
1389                 head = NULL;
1390         }
1391         return(head);
1392 }
1393
1394 extern CSA_return_code
1395 _DtCm_copy_reminder(CSA_reminder *from, CSA_reminder **to)
1396 {
1397         CSA_reminder *newval;
1398
1399         if ((newval = (CSA_reminder *)calloc(1, sizeof(CSA_reminder))) == NULL)
1400                 return (CSA_E_INSUFFICIENT_MEMORY);
1401
1402         if (from->lead_time) {
1403                 if ((newval->lead_time = strdup(from->lead_time)) == NULL) {
1404                         free(newval);
1405                         return (CSA_E_INSUFFICIENT_MEMORY);
1406                 }
1407         } else {
1408                 free(newval);
1409                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1410         }
1411
1412         if (from->snooze_time)
1413                 newval->snooze_time = strdup(from->snooze_time);
1414         else
1415                 newval->snooze_time = calloc(1, 1);
1416
1417         if (newval->snooze_time == NULL) {
1418                 _DtCm_free_reminder(newval);
1419                 return (CSA_E_INSUFFICIENT_MEMORY);
1420         }
1421
1422         newval->repeat_count = from->repeat_count;
1423
1424         if (from->reminder_data.size > 0) {
1425                 newval->reminder_data.size = from->reminder_data.size;
1426                 if ((newval->reminder_data.data = malloc(
1427                     newval->reminder_data.size)) == NULL) {
1428                         _DtCm_free_reminder(newval);
1429                         return (CSA_E_INSUFFICIENT_MEMORY);
1430                 }
1431                 memcpy(newval->reminder_data.data, from->reminder_data.data,
1432                         from->reminder_data.size);
1433         }
1434
1435         *to = newval;
1436         return (CSA_SUCCESS);
1437 }
1438
1439 extern void
1440 _DtCm_free_reminder(CSA_reminder *val)
1441 {
1442         if (val == NULL) return;
1443
1444         if (val->lead_time)
1445                 free(val->lead_time);
1446
1447         if (val->snooze_time)
1448                 free(val->snooze_time);
1449
1450         if (val->reminder_data.size > 0)
1451                 free(val->reminder_data.data);
1452
1453         free(val);
1454 }
1455
1456 extern CSA_return_code
1457 _DtCm_copy_opaque_data(CSA_opaque_data *from, CSA_opaque_data **to)
1458 {
1459         CSA_opaque_data *val;
1460
1461         if ((val = (CSA_opaque_data *)calloc(1, sizeof(CSA_opaque_data)))
1462             == NULL) {
1463                 return (CSA_E_INSUFFICIENT_MEMORY);
1464         }
1465
1466         if (from->size > 0) {
1467                 val->size = from->size;
1468                 if ((val->data = malloc(from->size)) == NULL) {
1469                         free(val);
1470                         return (CSA_E_INSUFFICIENT_MEMORY);
1471                 }
1472                 memcpy(val->data, from->data, from->size);
1473         } else {
1474                 val->size = 0;
1475                 val->data = NULL;
1476         }
1477
1478         *to = val;
1479
1480         return (CSA_SUCCESS);
1481 }
1482
1483 extern void
1484 _DtCm_free_opaque_data(CSA_opaque_data *val)
1485 {
1486         if (val == NULL) return;
1487
1488         if (val->data)
1489                 free(val->data);
1490         free(val);
1491 }
1492
1493 extern void
1494 _DtCm_get_attribute_types(uint size, int *types)
1495 {
1496         int     i;
1497
1498         for (i = 1; i <= size; i++) {
1499                 types[i] = _CSA_entry_attr_info[i].type;
1500         }
1501 }
1502
1503 /******************************************************************************
1504  * static functions used within the file
1505  ******************************************************************************/
1506
1507 /*
1508  * The passed in attributes are hashed.
1509  * For each attribute, check
1510  * 1. type is valid and supported
1511  * 2. if it's a date time value type, check validity of date time.
1512  * 3. if it's a reminder value type, check validity of lead time.
1513  * 4. if it is a defined attribute, check that the data type is correct.
1514  * 5. if it is a defined attribute and checkreadonly is set, check
1515  *      that it's not readonly.
1516  */
1517 static CSA_return_code
1518 check_predefined_attrs(
1519         int                     fver,
1520         uint                    num_attrs,
1521         cms_attribute           *attrs,
1522         boolean_t               checkreadonly,
1523         _DtCmNameTable          *tbl,
1524         uint                    num_defined,
1525         _DtCmAttrInfo           *our_attrs)
1526 {
1527         int             i, index, cl;
1528         CSA_reminder    *rptr;
1529         time_t          tick;
1530
1531         for (i = 0; i < num_attrs; i++) {
1532
1533                 if (attrs[i].name.name == NULL)
1534                         continue;
1535
1536                 if (tbl == NULL)
1537                         index = i;
1538                 else
1539                         index = _DtCm_get_index_from_table(tbl,
1540                                         attrs[i].name.name); 
1541
1542                 if (index > 0 && index <= num_defined) {
1543
1544                         /* check whether the attribute is supported
1545                          * in this version
1546                          */
1547                         if (our_attrs[index].fst_vers == 0 ||
1548                             (fver < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
1549                             fver < our_attrs[index].fst_vers))
1550                                 return (CSA_E_UNSUPPORTED_ATTRIBUTE);
1551                         else if (our_attrs[index].fst_vers == -1)
1552                                 return (CSA_E_INVALID_ATTRIBUTE);
1553
1554                         /* check whether the attribute is readonly */
1555                         if (checkreadonly &&
1556                             ((fver < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
1557                             our_attrs[index].nex_ro) ||
1558                             (fver >= _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
1559                             our_attrs[index].ex_ro)))
1560                                 return (CSA_E_READONLY);
1561
1562                         /* check data type */
1563                         if (attrs[i].value &&
1564                             attrs[i].value->type != our_attrs[index].type)
1565                                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1566
1567                         if (index == CSA_ENTRY_ATTR_CLASSIFICATION_I) {
1568                                 cl = attrs[i].value->item.uint32_value;
1569                                 if (cl < CSA_CLASS_PUBLIC ||
1570                                     cl > CSA_CLASS_CONFIDENTIAL)
1571                                         return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1572                         }
1573
1574                         if (index == CSA_ENTRY_ATTR_TYPE_I) {
1575                                 cl = attrs[i].value->item.uint32_value;
1576                                 if (cl < CSA_TYPE_EVENT ||
1577                                     cl > CSA_X_DT_TYPE_OTHER)
1578                                         return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1579                         }
1580
1581                 } else if (fver < _DtCM_FIRST_EXTENSIBLE_DATA_VERSION) {
1582                         return (CSA_E_INVALID_ATTRIBUTE);
1583                 }
1584
1585                 /* check validity of value type */
1586                 if (attrs[i].value) {
1587                         if (attrs[i].value->type < CSA_VALUE_BOOLEAN ||
1588                             attrs[i].value->type > CSA_VALUE_OPAQUE_DATA)
1589                                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1590
1591                         /* cast the sint32_value element to the desired
1592                          * type to be safe since the value part could
1593                          * actually be a pointer to a CSA_attribute_value
1594                          */
1595                         switch (attrs[i].value->type) {
1596                         case CSA_VALUE_DATE_TIME:
1597                                 if (attrs[i].value->item.sint32_value == 0
1598                                     || _csa_iso8601_to_tick(
1599                                     (char *)attrs[i].value->item.sint32_value,
1600                                     &tick))
1601                                         return (CSA_E_INVALID_DATE_TIME);
1602                                 break;
1603                         case CSA_VALUE_REMINDER:
1604                                 rptr = (CSA_reminder *)
1605                                         attrs[i].value->item.sint32_value;
1606                                 if (rptr == NULL || rptr->lead_time == NULL ||
1607                                     _csa_iso8601_to_duration(rptr->lead_time,
1608                                                              &tick))
1609                                         return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1610                                 break;
1611                         case CSA_VALUE_ATTENDEE_LIST:
1612                                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1613                         }
1614                 }
1615         }
1616
1617         return (CSA_SUCCESS);
1618 }
1619
1620 static CSA_return_code
1621 convert_cms_user_to_csa_user(char *from, CSA_calendar_user **to)
1622 {
1623         CSA_calendar_user *newval;
1624
1625         if ((newval = (CSA_calendar_user *)calloc(1,
1626             sizeof(CSA_calendar_user))) == NULL)
1627                 return (CSA_E_INSUFFICIENT_MEMORY);
1628
1629         if (from) {
1630                 if ((newval->user_name = strdup(from)) == NULL) {
1631                         free(newval);
1632                         return (CSA_E_INSUFFICIENT_MEMORY);
1633                 }
1634         }
1635
1636         *to = newval;
1637         return (CSA_SUCCESS);
1638 }
1639
1640 static CSA_return_code
1641 hash_entry_attrs(
1642         uint            num_attrs,
1643         CSA_attribute   *csaattrs,
1644         cms_attribute   *cmsattrs,
1645         uint            *hnum,
1646         cms_attribute   **hattrs,
1647         uint            *num)
1648 {
1649         CSA_return_code         stat;
1650         int                     i, j, index, count = 0;
1651         cms_attribute           *nattrs;
1652         char                    *name;
1653         cms_attribute_value     *val;
1654
1655         if ((nattrs = (cms_attribute *)calloc(1,
1656             sizeof(cms_attribute)*(num_attrs+_DtCM_DEFINED_ENTRY_ATTR_SIZE+1)))
1657             == NULL)
1658                 return (CSA_E_INSUFFICIENT_MEMORY);
1659
1660         for (i = 0, j = _DtCM_DEFINED_ENTRY_ATTR_SIZE + 1; i < num_attrs; i++) {
1661                 name = (csaattrs ? csaattrs[i].name : cmsattrs[i].name.name);
1662                 if (name == NULL)
1663                         continue;
1664                 else {
1665                         count++;
1666                         val = (csaattrs ?
1667                                 ((cms_attribute_value *)csaattrs[i].value) :
1668                                 cmsattrs[i].value);
1669                 }
1670
1671                 index = _DtCm_get_index_from_table(_DtCm_entry_name_tbl, name);
1672
1673                 if (index > 0) {
1674                         if (cmsattrs) cmsattrs[i].name.num = index;
1675
1676                         nattrs[index].name.name = name;
1677                         nattrs[index].value = val;
1678                 } else {
1679                         nattrs[j].name.name = name;
1680                         nattrs[j++].value = val;
1681                 }
1682         }
1683
1684         if (num) *num = count;
1685         *hnum = j - 1;
1686         *hattrs = nattrs;
1687         return (CSA_SUCCESS);
1688 }
1689
1690 static CSA_return_code
1691 hash_cal_attrs(
1692         uint            num_attrs,
1693         CSA_attribute   *csaattrs,
1694         cms_attribute   *cmsattrs,
1695         uint            *hnum,
1696         cms_attribute   **hattrs,
1697         uint            *num)
1698 {
1699         CSA_return_code         stat;
1700         int                     i, j, index, count = 0;
1701         cms_attribute           *nattrs;
1702         char                    *name;
1703         cms_attribute_value     *val;
1704
1705         if ((nattrs = (cms_attribute *)calloc(1,
1706             sizeof(cms_attribute)*(num_attrs+_DtCM_DEFINED_CAL_ATTR_SIZE+1)))
1707             == NULL)
1708                 return (CSA_E_INSUFFICIENT_MEMORY);
1709
1710         for (i = 0, j = _DtCM_DEFINED_CAL_ATTR_SIZE + 1; i < num_attrs; i++) {
1711                 name = (csaattrs ? csaattrs[i].name : cmsattrs[i].name.name);
1712                 if (name == NULL)
1713                         continue;
1714                 else {
1715                         count++;
1716                         val = (csaattrs ?
1717                                 ((cms_attribute_value *)csaattrs[i].value) :
1718                                 cmsattrs[i].value);
1719                 }
1720
1721                 index = _DtCm_get_index_from_table(_DtCm_cal_name_tbl, name);
1722
1723                 if (index > 0) {
1724                         if (cmsattrs) cmsattrs[i].name.num = index;
1725
1726                         nattrs[index].name.name = name;
1727                         nattrs[index].value = val;
1728                 } else {
1729                         nattrs[j].name.name = name;
1730                         nattrs[j++].value = val;
1731                 }
1732         }
1733
1734         if (num) *num = count;
1735         *hnum = j - 1;
1736         *hattrs = nattrs;
1737         return (CSA_SUCCESS);
1738 }
1739
1740 static CSA_return_code
1741 _DtCm_check_hashed_cal_attributes(
1742         int             fvers,
1743         uint            num_attrs,
1744         cms_attribute   *attrs,
1745         char            *owner,
1746         char            *cname,
1747         boolean_t       checkreadonly,
1748         boolean_t       firsttime,
1749         boolean_t       csatype)
1750 {
1751         CSA_return_code stat;
1752         CSA_attribute_value     *csaval;
1753         cms_attribute_value     *cmsval;
1754         char                    *nattr = NULL; /* calendar name */
1755         char                    *oattr = NULL; /* calendar owner */
1756         char                    *cattr = NULL; /* character set */
1757         char                    *tattr = NULL; /* time zone */
1758
1759         if (firsttime) {
1760                 if (attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].name.name) {
1761                         if (attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].value == NULL
1762                             || attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].value->\
1763                             item.calendar_user_value == NULL)
1764                                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1765
1766                         if (csatype) {
1767                                 csaval = (CSA_attribute_value *)attrs[\
1768                                         CSA_CAL_ATTR_CALENDAR_OWNER_I].value;
1769                                 stat = _CheckCalendarOwner(owner, csaval->type,
1770                                     (csaval && csaval->item.calendar_user_value?
1771                                     csaval->item.calendar_user_value->user_name:
1772                                     NULL));
1773                         } else {
1774                                 cmsval = attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].\
1775                                         value;
1776                                 stat = _CheckCalendarOwner(owner, cmsval->type,
1777                                         cmsval ?
1778                                         cmsval->item.calendar_user_value:NULL);
1779                         }
1780
1781                         if (stat != CSA_SUCCESS)
1782                                 return (stat);
1783
1784                         oattr = attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].name.name;
1785                         attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].name.name = NULL;
1786                 }
1787
1788                 if (attrs[CSA_CAL_ATTR_CALENDAR_NAME_I].name.name) {
1789                         if (attrs[CSA_CAL_ATTR_CALENDAR_NAME_I].value == NULL ||
1790                             attrs[CSA_CAL_ATTR_CALENDAR_NAME_I].value->\
1791                             item.string_value == NULL) {
1792                                 if (oattr)
1793                                         attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].\
1794                                                 name.name = oattr;
1795                                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1796                         }
1797
1798                         if ((stat = _CheckCalendarName(owner, cname,
1799                             attrs[CSA_CAL_ATTR_CALENDAR_NAME_I].value))
1800                             != CSA_SUCCESS) {
1801                                 if (oattr)
1802                                         attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].\
1803                                                 name.name = oattr;
1804                                 return (stat);
1805                         }
1806
1807                         nattr = attrs[CSA_CAL_ATTR_CALENDAR_NAME_I].name.name;
1808                         attrs[CSA_CAL_ATTR_CALENDAR_NAME_I].name.name = NULL;
1809                 }
1810
1811                 if (attrs[CSA_CAL_ATTR_CHARACTER_SET_I].name.name) {
1812                         cattr = attrs[CSA_CAL_ATTR_CHARACTER_SET_I].name.name;
1813                         attrs[CSA_CAL_ATTR_CHARACTER_SET_I].name.name = NULL;
1814                 }
1815
1816                 if (attrs[CSA_CAL_ATTR_TIME_ZONE_I].name.name) {
1817                         tattr = attrs[CSA_CAL_ATTR_TIME_ZONE_I].name.name;
1818                         attrs[CSA_CAL_ATTR_TIME_ZONE_I].name.name = NULL;
1819                 }
1820         }
1821
1822         stat = check_predefined_attrs(fvers, num_attrs+1, attrs,
1823                 checkreadonly, NULL, _DtCM_DEFINED_CAL_ATTR_SIZE,
1824                 _CSA_cal_attr_info);
1825
1826         if (oattr)
1827                 attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].name.name = oattr;
1828
1829         if (nattr)
1830                 attrs[CSA_CAL_ATTR_CALENDAR_NAME_I].name.name = nattr;
1831
1832         if (cattr)
1833                 attrs[CSA_CAL_ATTR_CHARACTER_SET_I].name.name = oattr;
1834
1835         if (tattr)
1836                 attrs[CSA_CAL_ATTR_TIME_ZONE_I].name.name = nattr;
1837
1838         return (stat);
1839 }
1840
1841 static CSA_return_code
1842 _DtCm_check_hashed_entry_attributes(
1843         int             fvers,
1844         uint            num_attrs,
1845         cms_attribute   *attrs,
1846         CSA_flags       utype)
1847 {
1848         CSA_return_code stat;
1849
1850         if ((stat = check_predefined_attrs(fvers, num_attrs+1, attrs,
1851             (utype == 0 ? B_FALSE : B_TRUE), NULL,
1852             _DtCM_DEFINED_ENTRY_ATTR_SIZE, _CSA_entry_attr_info))
1853             != CSA_SUCCESS) {
1854
1855                 return (stat);
1856         }
1857
1858         if (utype == CSA_CB_ENTRY_ADDED) {
1859
1860                 /* make sure the minimum set of attribute is specified */
1861                 if (attrs[CSA_ENTRY_ATTR_START_DATE_I].value == NULL ||
1862                     attrs[CSA_ENTRY_ATTR_TYPE_I].value == NULL)
1863                         return (CSA_E_INVALID_PARAMETER);
1864
1865         } else if (utype == CSA_CB_ENTRY_UPDATED) {
1866
1867                 /* type can only be set at insertion time */
1868                 if (attrs[CSA_ENTRY_ATTR_TYPE_I].name.name)
1869                         return (CSA_E_READONLY);
1870         }
1871
1872         return (CSA_SUCCESS);
1873 }
1874
1875 static CSA_return_code
1876 _CheckNameAtHost(char *owner, char *value)
1877 {
1878         char            *ptr, *optr;
1879         int             res;
1880
1881         /* check name part first */
1882         if (owner == NULL) {
1883                 /* get user name of user running the application */
1884                 if ((owner = _DtCmGetUserName()) == NULL)
1885                         return (CSA_E_FAILURE);
1886         }
1887
1888         if (optr = strchr(owner, '@')) *optr = NULL;
1889         if (ptr = strchr(value, '@')) *ptr = NULL;
1890         res = strcmp(value, owner);
1891         if (optr) *optr = '@';
1892         if (ptr) *ptr = '@';
1893
1894         if (res != 0)
1895                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1896
1897         /* check host too if it's specified */
1898         if (ptr == NULL)
1899                 return (CSA_SUCCESS);
1900
1901         ptr++;
1902         if (strcmp(ptr, (optr ? ++optr : _DtCmGetLocalHost())) == 0)
1903                 return (CSA_SUCCESS);
1904         else
1905                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1906 }
1907
1908 /*
1909  * check the data type and validity of calendar owner attribute
1910  */
1911 static CSA_return_code
1912 _CheckCalendarOwner(char *owner, int type, char *user)
1913 {
1914         if (type != CSA_VALUE_CALENDAR_USER || user == NULL)
1915                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1916
1917         /* make sure user is the same as the one running the application */
1918         return (_CheckNameAtHost(owner, user));
1919 }
1920
1921 /*
1922  * check the data type and validity of calendar name attribute
1923  */
1924 static CSA_return_code
1925 _CheckCalendarName(char *owner, char *cname, cms_attribute_value *val)
1926 {
1927         CSA_return_code stat;
1928         char            *ptr, *optr;
1929         char            user[BUFSIZ];
1930         int             res;
1931         boolean_t       isuser;
1932
1933         if (val->type != CSA_VALUE_STRING)
1934                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1935
1936         /* check that the attribute value is the same as the given
1937          * calendar name
1938          */
1939         if ((stat = _CheckNameAtHost(cname, val->item.string_value))
1940             != CSA_SUCCESS)
1941                 return (stat);
1942
1943         /* now make sure if cal name is a user name, it's
1944          * the same as that of the calling user
1945          */
1946         if (ptr = strchr(val->item.string_value, '@')) *ptr = NULL;
1947         isuser = _DtCmIsUserName(val->item.string_value);
1948         if (ptr) *ptr = '@';
1949
1950         /* make sure it's the same as the user running the application */
1951         if (isuser == B_TRUE) {
1952                 sprintf(user, "%s%s", val->item.string_value, (ptr ? ptr : ""));
1953                 return (_CheckNameAtHost(owner, user));
1954         }
1955
1956         /* check the host part */
1957         if (ptr == NULL)
1958                 return (CSA_SUCCESS);
1959         else
1960                 ptr++;
1961
1962         if (owner && (optr = strchr(owner, '@')))
1963                 optr++;
1964         else
1965                 optr = _DtCmGetLocalHost();
1966
1967         if (strcmp(ptr, optr) == 0)
1968                 return (CSA_SUCCESS);
1969         else
1970                 return (CSA_E_INVALID_ATTRIBUTE_VALUE);
1971 }
1972