dtcm: Resolve CID 87822
[oweals/cde.git] / cde / programs / dtcm / server / cmsconvert.c
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 librararies 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 /* $XConsortium: cmsconvert.c /main/5 1996/10/03 10:38:06 drk $ */
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
31 #include <EUSCompat.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include "cmsconvert.h"
36 #include "convert5-4.h"
37 #include "convert4-5.h"
38 #include "attr.h"
39 #include "appt4.h"
40 #include "iso8601.h"
41 #include "lutil.h"
42 #include "cmsdata.h"
43
44 /*
45  * Routines to convert data types used in version 5 to version 4.
46  */
47
48 /*
49  * forward declaration of functions used in the file
50  */
51 static Abb_Appt_4 * _MakeAbbrAppt();
52
53 static CSA_return_code _AttrsToAbbrAppt(uint size, cms_attribute *attrs,
54                                         Abb_Appt_4 *appt);
55
56 static uint _ConvertV5Access(uint v5rights, boolean_t strictmode);
57
58 static uint _ConvertV4Access(uint v4rights);
59
60 static char * _ConvertReminderName(char *rname);
61
62 static CSA_return_code _Appt4ToCmsentryAttrs(char *calname, Appt_4 *a4,
63                                 uint *num_attrs, cms_attribute **attrs_r);
64 /*****************************************************************************
65  * extern functions
66  *****************************************************************************/
67
68 extern CSA_return_code
69 _DtCmsCmsentriesToAppt4ForClient(cms_entry *entries, Appt_4 **appt)
70 {
71         CSA_return_code stat;
72         Appt_4  *newappt, *prev, *head;
73
74         if (appt == NULL)
75                 return (CSA_E_INVALID_PARAMETER);
76
77         head = prev = NULL;
78         while (entries != NULL) {
79                 if ((newappt = _DtCm_make_appt4(B_TRUE)) == NULL)
80                         break;
81
82                 if ((stat = _DtCmsAttrsToAppt4(entries->num_attrs + 1,
83                     entries->attrs, newappt, B_FALSE)) != CSA_SUCCESS) {
84                         _DtCm_free_appt4(newappt);
85                         break;
86                 } else
87                         newappt->appt_id.key = entries->key.id;
88
89                 if (head == NULL)
90                         head = newappt;
91                 else
92                         prev->next = newappt;
93
94                 prev = newappt;
95                 entries = entries->next;
96         }
97
98         if (stat != CSA_SUCCESS) {
99                 _DtCm_free_appt4(head);
100                 head = NULL;
101         }
102
103         *appt = head;
104         return (stat);
105 }
106
107 extern CSA_return_code
108 _DtCmsCmsentriesToAbbrAppt4ForClient(cms_entry *entries, Abb_Appt_4 **abbr)
109 {
110         CSA_return_code stat;
111         Abb_Appt_4      *newabbr, *prev, *head;
112
113         if (abbr == NULL)
114                 return (CSA_E_INVALID_PARAMETER);
115
116         head = prev = NULL;
117         while (entries != NULL) {
118                 if ((newabbr = _MakeAbbrAppt()) == NULL)
119                         break;
120
121                 if ((stat = _AttrsToAbbrAppt(entries->num_attrs, entries->attrs,
122                     newabbr)) != CSA_SUCCESS) {
123                         _DtCm_free_abbrev_appt4(newabbr);
124                         break;
125                 } else
126                         newabbr->appt_id.key = entries->key.id;
127
128                 if (head == NULL)
129                         head = newabbr;
130                 else
131                         prev->next = newabbr;
132
133                 prev = newabbr;
134                 entries = entries->next;
135         }
136
137         if (stat != CSA_SUCCESS) {
138                 _DtCm_free_abbrev_appt4(head);
139                 head = NULL;
140         }
141
142         *abbr = head;
143         return (stat);
144 }
145
146 extern Access_Entry_4 *
147 _DtCmsConvertV5AccessList(cms_access_entry *cmslist, boolean_t strictmode)
148 {
149         Access_Entry_4  *l, *head, *prev;
150         boolean_t       cleanup = B_FALSE;
151
152         prev = head = NULL;
153         while (cmslist != NULL) {
154                 if ((l = (Access_Entry_4 *)calloc(1, sizeof(Access_Entry_4)))
155                     == NULL) {
156                         cleanup = B_TRUE;
157                         break;
158                 }
159
160                 if ((l->who = strdup(cmslist->user)) == NULL) {
161                         free(l);
162                         cleanup = B_TRUE;
163                         break;
164                 }
165                 l->access_type = _ConvertV5Access(cmslist->rights, strictmode);
166
167                 if (head == NULL)
168                         head = l;
169                 else
170                         prev->next = l;
171                 prev = l;
172
173                 cmslist = cmslist->next;
174         }
175
176         if (cleanup == B_TRUE) {
177                 _DtCm_free_access_list4(head);
178                 head = NULL;
179         }
180         return (head);
181 }
182
183 extern cms_access_entry *
184 _DtCmsConvertV4AccessList(Access_Entry_4 *alist)
185 {
186         cms_access_entry        *l, *head, *prev;
187         boolean_t               cleanup = B_FALSE;
188
189         prev = head = NULL;
190         while (alist != NULL) {
191                 if ((l = (cms_access_entry *)calloc(1,
192                     sizeof(cms_access_entry))) == NULL) {
193                         cleanup = B_TRUE;
194                         break;
195                 }
196
197                 if ((l->user = strdup(alist->who)) == NULL) {
198                         free(l);
199                         cleanup = B_TRUE;
200                         break;
201                 }
202                 l->rights = _ConvertV4Access(alist->access_type);
203
204                 if (head == NULL)
205                         head = l;
206                 else
207                         prev->next = l;
208                 prev = l;
209
210                 alist = alist->next;
211         }
212
213         if (cleanup == B_TRUE) {
214                 _DtCm_free_cms_access_entry(head);
215                 head = NULL;
216         }
217         return (head);
218 }
219
220 extern CSA_return_code
221 _DtCmsReminderRefToReminder(
222         cms_reminder_ref        *rems,
223         Reminder_4              **r4)
224 {
225         CSA_return_code stat = CSA_SUCCESS;
226         Reminder_4      *head, *prev, *rptr;
227         char            buf[30];
228
229         prev = head = NULL;
230         while (rems != NULL) {
231
232                 if ((rptr = (Reminder_4 *)calloc(1, sizeof(Reminder_4)))
233                     == NULL) {
234                         stat = CSA_E_INSUFFICIENT_MEMORY;
235                         break;
236                 }
237
238                 rptr->appt_id.tick = rems->key.time;
239                 rptr->appt_id.key = rems->key.id;
240                 rptr->tick = rems->runtime;
241
242                 if ((rptr->attr.attr=_ConvertReminderName(rems->reminder_name))
243                     == NULL) {
244                         free(rptr);
245                         stat = CSA_E_INSUFFICIENT_MEMORY;
246                         break;
247                 }
248
249                 if ((rptr->attr.value = calloc(1,1)) == NULL) {
250                         free(rptr->attr.attr);
251                         free(rptr);
252                         stat = CSA_E_INSUFFICIENT_MEMORY;
253                         break;
254                 }
255
256                 if ((rptr->attr.clientdata = calloc(1,1)) == NULL) {
257                         free(rptr->attr.value);
258                         free(rptr->attr.attr);
259                         free(rptr);
260                         stat = CSA_E_INSUFFICIENT_MEMORY;
261                         break;
262                 }
263
264                 if (head == NULL)
265                         head = rptr;
266                 else
267                         prev->next = rptr;
268                 prev = rptr;
269
270                 rems = rems->next;
271         }
272
273         if (stat != CSA_SUCCESS) {
274                 _DtCm_free_reminder4(head);
275                 head = NULL;
276         }
277
278         *r4 = head;
279
280         return(stat);
281 }
282
283 extern CSA_return_code
284 _DtCmsV4ReminderToReminderRef(
285         char                    *calname,
286         Reminder_4              *r4,
287         _DtCmsEntryId           *ids,
288         cms_reminder_ref        **rems)
289 {
290         CSA_return_code         stat = CSA_SUCCESS;
291         cms_reminder_ref        *head, *prev, *rptr;
292         char                    buf[BUFSIZ];
293
294         prev = head = NULL;
295         while (r4 != NULL) {
296
297                 if ((rptr = (cms_reminder_ref *)calloc(1,
298                     sizeof(cms_reminder_ref))) == NULL) {
299                         stat = CSA_E_INSUFFICIENT_MEMORY;
300                         break;
301                 }
302
303                 rptr->key.time = r4->appt_id.tick;
304                 rptr->key.id = r4->appt_id.key;
305                 rptr->runtime = r4->tick;
306
307                 if ((rptr->reminder_name = strdup(
308                     _DtCm_old_reminder_name_to_name(r4->attr.attr)))
309                     == NULL) {
310                         free(rptr);
311                         stat = CSA_E_INSUFFICIENT_MEMORY;
312                         break;
313                 }
314
315                 sprintf(buf, "%ld:%s@%s", ids->id, calname,
316                         _DtCmGetHostAtDomain());
317
318                 if ((rptr->entryid = strdup(buf)) == NULL) {
319                         free(rptr->reminder_name);
320                         free(rptr);
321                         stat = CSA_E_INSUFFICIENT_MEMORY;
322                         break;
323                 }
324
325                 if (head == NULL)
326                         head = rptr;
327                 else
328                         prev->next = rptr;
329                 prev = rptr;
330
331                 r4 = r4->next;
332                 ids = ids->next;
333         }
334
335         if (stat != CSA_SUCCESS) {
336                 _DtCmsFreeReminderRef(head);
337                 head = NULL;
338         }
339
340         *rems = head;
341
342         return(stat);
343 }
344
345 extern CSA_return_code
346 _DtCmsCmsAccessToV4Access(cms_access_entry *alist, Access_Entry_4 **a4)
347 {
348         CSA_return_code stat = CSA_SUCCESS;
349         Access_Entry_4  *to, *prev, *head;
350
351         head = prev = NULL;
352         while (alist != NULL) {
353                 if ((to = (Access_Entry_4 *)calloc(1, sizeof(Access_Entry_4)))
354                     == NULL) {
355                         stat = CSA_E_INSUFFICIENT_MEMORY;
356                         break;
357                 }
358
359                 if ((to->access_type = _DtCmAccessRightToV4AccessType(
360                     alist->rights)) < 0) {
361                         stat = CSA_E_INVALID_FLAG;
362                         break;
363                 }
364
365                 if (alist->user == NULL) {
366                         stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
367                         break;
368                 }
369
370                 if ((to->who = strdup(alist->user)) == NULL) {
371                         free(to);
372                         stat = CSA_E_INSUFFICIENT_MEMORY;
373                         break;
374                 }
375
376                 if (head == NULL)
377                         head = to;
378                 else
379                         prev->next = to;
380
381                 prev = to;
382
383                 alist = alist->next;
384         }
385
386         if (stat != CSA_SUCCESS) {
387                 _DtCm_free_access_list4(head);
388                 head = NULL;
389         }
390
391         *a4 = head;
392         return (stat);
393 }
394
395 extern CSA_return_code
396 _DtCmsAppt4ToCmsentriesForClient(
397         char            *calname,
398         Appt_4          *appt,
399         cms_entry       **e_r)
400 {
401         CSA_return_code stat = CSA_SUCCESS;
402         cms_entry       *entry, *head, *prev;
403
404         if (e_r == NULL)
405                 return(CSA_E_INVALID_PARAMETER);
406
407         prev = head = NULL;
408         while (appt != NULL) {
409
410                 if ((entry = (cms_entry *)calloc(1, sizeof(cms_entry))) == NULL)
411                         break;
412
413                 if ((stat = _Appt4ToCmsentryAttrs(calname, appt,
414                     &entry->num_attrs, &entry->attrs)) == CSA_SUCCESS) {
415                         entry->key.time = appt->appt_id.tick;
416                         entry->key.id = appt->appt_id.key;
417                 } else {
418                         free(entry);
419                         break;
420                 }
421
422                 if (head == NULL)
423                         head = entry;
424                 else
425                         prev->next = entry;
426
427                 prev = entry;
428
429                 appt = appt->next;
430         }
431
432         if (stat != CSA_SUCCESS) {
433                 _DtCm_free_cms_entries(head);
434                 head = NULL;
435         }
436
437         *e_r = head;
438         return(stat);
439 }
440
441 extern CSA_return_code
442 _DtCmsAppt4ToCmsentry(
443         char            *calname,
444         Appt_4          *a4,
445         cms_entry       **entry_r,
446         boolean_t       rerule)
447 {
448         CSA_return_code stat;
449         cms_entry       *entry;
450
451         if (a4 == NULL)
452                 return(CSA_E_INVALID_PARAMETER);
453
454         if ((entry = _DtCm_make_cms_entry(_DtCm_entry_name_tbl)) == NULL)
455                 return (CSA_E_INSUFFICIENT_MEMORY);
456
457         entry->key.time = a4->appt_id.tick;
458         entry->key.id = a4->appt_id.key;
459
460         if ((stat = _DtCm_appt4_to_attrs(calname, a4, entry->num_attrs,
461             entry->attrs, rerule)) != CSA_SUCCESS) {
462                 _DtCm_free_cms_entry(entry);
463                 return (stat);
464         }
465
466         *entry_r = entry;
467         return (CSA_SUCCESS);
468 }
469
470 /*
471  * This routine is used either to convert attrs from clients for insert
472  * or update; or to convert appts for sending to clients
473  * Note: the reference id is not converted
474  */
475 extern CSA_return_code
476 _DtCmsAttrsToAppt4(
477         uint            size,
478         cms_attribute   *attrs,
479         Appt_4          *appt,
480         boolean_t       check)
481 {
482         CSA_return_code stat = CSA_SUCCESS;
483         char            *string;
484         time_t          endtick;
485         int             i, enddateindex = -1, interval = -1, wknum;
486         int             typeindex = -1, stypeindex = -1;
487         boolean_t       set_wknum = B_FALSE;
488
489         /*
490          * this routine is called to convert valid v2 to v4 attributes
491          * so no checking of CSA_E_INVALID_ATTRIBUTE and
492          * CSA_E_UNSUPPORTED_ATTRIBUTE is necessary
493          */
494
495         for (i = 0; i < size && stat == CSA_SUCCESS; i++) {
496                 switch (attrs[i].name.num) {
497                 case CSA_ENTRY_ATTR_START_DATE_I:
498                         if (check == B_TRUE && attrs[i].value == NULL)
499                                 stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
500                         else if (_csa_iso8601_to_tick(attrs[i].value->\
501                             item.date_time_value, &appt->appt_id.tick))
502                                 stat = CSA_E_INVALID_DATE_TIME;
503                         break;
504
505                 case CSA_ENTRY_ATTR_END_DATE_I: 
506                         enddateindex = i;
507                         break;
508
509                 case CSA_ENTRY_ATTR_TYPE_I:
510                         typeindex = i;
511                         break;
512
513                 case CSA_ENTRY_ATTR_SUBTYPE_I:
514                         stypeindex = i;
515                         break;
516
517                 case CSA_ENTRY_ATTR_SUMMARY_I:
518
519                         if (attrs[i].value->item.string_value) {
520                                 if ((string = strdup(attrs[i].value->item.\
521                                     string_value)) == NULL)
522                                         stat = CSA_E_INSUFFICIENT_MEMORY;
523                                 else {
524                                         if (appt->what)
525                                                 free(appt->what);
526                                         appt->what = string;
527                                 }
528                         }
529                         break;
530
531                 case CSA_ENTRY_ATTR_ORGANIZER_I:
532                         free(appt->author);
533                         if ((appt->author = strdup(attrs[i].value->\
534                             item.calendar_user_value)) == NULL)
535                                 stat = CSA_E_INSUFFICIENT_MEMORY;
536                         break;
537
538                 case CSA_ENTRY_ATTR_AUDIO_REMINDER_I:
539
540                         if (attrs[i].value == NULL)
541                                 stat = _DtCm_remove_reminder(
542                                         _DtCM_OLD_ATTR_BEEP_REMINDER, appt);
543                         else if (attrs[i].value->item.reminder_value == NULL)
544                                 stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
545                         else
546                                 stat = _DtCm_add_reminder(
547                                         _DtCM_OLD_ATTR_BEEP_REMINDER,
548                                         attrs[i].value->item.reminder_value,
549                                         appt);
550                         break;
551
552                 case CSA_ENTRY_ATTR_FLASHING_REMINDER_I:
553
554                         if (attrs[i].value == NULL)
555                                 stat = _DtCm_remove_reminder(
556                                         _DtCM_OLD_ATTR_FLASH_REMINDER, appt);
557                         else if (attrs[i].value->item.reminder_value == NULL)
558                                 stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
559                         else
560                                 stat = _DtCm_add_reminder(
561                                         _DtCM_OLD_ATTR_FLASH_REMINDER,
562                                         attrs[i].value->item.reminder_value,
563                                         appt);
564                         break;
565
566                 case CSA_ENTRY_ATTR_MAIL_REMINDER_I:
567
568                         if (attrs[i].value == NULL)
569                                 stat = _DtCm_remove_reminder(
570                                         _DtCM_OLD_ATTR_MAIL_REMINDER, appt);
571                         else if (attrs[i].value->item.reminder_value == NULL)
572                                 stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
573                         else
574                                 stat = _DtCm_add_reminder(
575                                         _DtCM_OLD_ATTR_MAIL_REMINDER,
576                                         attrs[i].value->item.reminder_value,
577                                         appt);
578                         break;
579
580                 case CSA_ENTRY_ATTR_POPUP_REMINDER_I:
581
582                         if (attrs[i].value == NULL)
583                                 stat = _DtCm_remove_reminder(
584                                         _DtCM_OLD_ATTR_POPUP_REMINDER, appt);
585                         else if (attrs[i].value->item.reminder_value == NULL)
586                                 stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
587                         else
588                                 stat = _DtCm_add_reminder(
589                                         _DtCM_OLD_ATTR_POPUP_REMINDER,
590                                         attrs[i].value->item.reminder_value,
591                                         appt);
592                         break;
593
594                 case CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I:
595
596                         if (_DtCm_rtype_to_interval4(
597                             attrs[i].value->item.sint32_value,
598                             &appt->period.period)) {
599                                 if (check == B_TRUE)
600                                         stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
601                                 else
602                                         appt->period.period = otherPeriod_4;
603                         }
604                         break;
605
606                 case CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I:
607
608                         if (attrs[i].value) {
609                                 appt->ntimes =
610                                         attrs[i].value->item.uint32_value;
611                                 if (appt->ntimes == CSA_X_DT_DT_REPEAT_FOREVER)
612                                         appt->ntimes = _DtCM_OLD_REPEAT_FOREVER;
613                         }
614                         break;
615
616                 case CSA_X_DT_ENTRY_ATTR_SHOWTIME_I:
617
618                         if (attrs[i].value)
619                                 appt->tag->showtime =
620                                         attrs[i].value->item.sint32_value;
621                         break;
622
623                 case CSA_ENTRY_ATTR_STATUS_I:
624
625                         if (_DtCm_status_to_apptstatus4(
626                             attrs[i].value->item.uint32_value,
627                             &appt->appt_status)) {
628                                 if (check == B_TRUE)
629                                         stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
630                                 else
631                                         appt->appt_status = active_4;
632                         }
633                         break;
634
635                 case CSA_ENTRY_ATTR_CLASSIFICATION_I:
636
637                         if (_DtCm_classification_to_privacy4(
638                             attrs[i].value->item.uint32_value, &appt->privacy))
639                         {
640                                 if (check == B_TRUE)
641                                         stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
642                                 else
643                                         appt->privacy = public_4;
644                         }
645                         break;
646
647                 case CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I:
648
649                         if (attrs[i].value &&
650                             attrs[i].value->item.date_time_value &&
651                             *(attrs[i].value->item.date_time_value))
652                         {
653                                 if (_csa_iso8601_to_tick(
654                                     attrs[i].value->item.date_time_value,
655                                     &appt->period.enddate))
656                                         stat = CSA_E_INVALID_DATE_TIME;
657                         }
658                         break;
659
660                 case CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I:
661                         if (attrs[i].value)
662                                 interval = attrs[i].value->item.uint32_value;
663                         break;
664
665                 case CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I:
666                         if (attrs[i].value) {
667                                 set_wknum = B_TRUE;
668                                 wknum = attrs[i].value->item.sint32_value;
669                         }
670                         break;
671                 }
672         }
673
674         if (stat == CSA_SUCCESS && enddateindex >= 0) {
675                 if (attrs[enddateindex].value == NULL ||
676                     attrs[enddateindex].value->item.date_time_value == NULL) {
677                         appt->duration = 0;
678                 } else if (_csa_iso8601_to_tick(attrs[enddateindex].value->\
679                     item.date_time_value, &endtick)) {
680                         stat = CSA_E_INVALID_DATE_TIME;
681                 } else {
682                         appt->duration = endtick - appt->appt_id.tick;
683                 }
684         }
685
686         if (stat == CSA_SUCCESS && (typeindex >= 0 || typeindex >= 0)) {
687                 if (typeindex >= 0) {
688                         if (stat = _DtCm_attrs_to_eventtype4(
689                             attrs[typeindex].value,
690                             (stypeindex >= 0 ? attrs[stypeindex].value : NULL),
691                             appt->tag)) {
692                                 if (check == B_FALSE) {
693                                         /* this is the case where we are
694                                          * converting appt for clients
695                                          */
696                                         appt->tag->tag = otherTag_4;
697                                         stat = CSA_SUCCESS;
698                                 }
699                         }
700                 } else if (stypeindex >= 0) {
701                         if (attrs[stypeindex].value &&
702                             attrs[stypeindex].value->item.string_value)
703                         {
704                                 if (strcmp(attrs[stypeindex].value->item.\
705                                     string_value, CSA_SUBTYPE_APPOINTMENT) == 0)
706                                         appt->tag->tag = appointment_4;
707                                 else if (strcmp(attrs[stypeindex].value->item.\
708                                     string_value, CSA_SUBTYPE_HOLIDAY) == 0)
709                                         appt->tag->tag = holiday_4;
710                                 else
711                                         stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
712                         } else
713                                 stat = CSA_E_INVALID_ATTRIBUTE_VALUE;
714                 }
715         }
716
717         if (stat == CSA_SUCCESS) {
718                 switch (appt->period.period) {
719                 case nthWeekday_4:
720                         if (set_wknum == B_TRUE)
721                                 appt->period.nth = wknum;
722                         break;
723                 case everyNthDay_4:
724                 case everyNthWeek_4:
725                 case everyNthMonth_4:
726                         if (interval >= 0)
727                                 appt->period.nth = interval;
728                         break;
729                 default:
730                         appt->period.nth = 0;
731                 }
732
733                 if (appt->period.period == single_4)
734                         appt->ntimes = 0;
735         }
736         return (stat);
737 }
738
739
740 /******************************************************************************
741  * static functions used within the file
742  ******************************************************************************/
743
744 /*
745  * attributes are hashed
746  * we are converting v4 events to v3 appts, so attributes are
747  * assumed to be good and all mandatory ones are present
748  */
749 static CSA_return_code
750 _AttrsToAbbrAppt(uint size, cms_attribute *attrs, Abb_Appt_4 *appt)
751 {
752         CSA_return_code stat = CSA_SUCCESS;
753         char            *ptr;
754         time_t          endtick;
755         int             i, typeindex, stypeindex = -1, enddateindex = -1;
756         char            buf[BUFSIZ];
757
758         for (i = 0; i < size && stat == CSA_SUCCESS; i++) {
759                 switch (attrs[i].name.num) {
760                 case CSA_ENTRY_ATTR_START_DATE_I:
761                         _csa_iso8601_to_tick(attrs[i].value->\
762                             item.date_time_value, &appt->appt_id.tick);
763                         break;
764
765                 case CSA_ENTRY_ATTR_END_DATE_I:
766                         enddateindex = i;
767                         break;
768
769                 case CSA_ENTRY_ATTR_TYPE_I:
770                         typeindex = i;
771                         break;
772
773                 case CSA_ENTRY_ATTR_SUBTYPE_I:
774                         stypeindex = i;
775                         break;
776
777                 case CSA_X_DT_ENTRY_ATTR_SHOWTIME_I:
778                         appt->tag->showtime = attrs[i].value->item.sint32_value;
779                         break;
780
781                 case CSA_ENTRY_ATTR_SUMMARY_I:
782                         if (attrs[i].value && attrs[i].value->item.string_value)
783                         {
784                                 free(appt->what);
785                                 if ((appt->what = strdup(attrs[i].value->\
786                                     item.string_value)) == NULL)
787                                         stat = CSA_E_INSUFFICIENT_MEMORY;
788                         }
789                         break;
790
791                 case CSA_ENTRY_ATTR_STATUS_I:
792                         if (_DtCm_status_to_apptstatus4(attrs[i].value->item.\
793                             uint32_value, &appt->appt_status))
794                                 appt->appt_status = active_4;
795                         break;
796
797                 case CSA_ENTRY_ATTR_CLASSIFICATION_I:
798                         if (_DtCm_classification_to_privacy4(attrs[i].value->\
799                             item.uint32_value, &appt->privacy))
800                                 appt->privacy = public_4;
801                         break;
802
803                 case CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I:
804                         if (_DtCm_rtype_to_interval4(attrs[i].value->\
805                             item.sint32_value, &appt->period.period))
806                                 appt->period.period = otherPeriod_4;
807                         break;
808
809                 case CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I:
810                         appt->period.nth = attrs[i].value->item.sint32_value;
811                         break;
812
813                 case CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I:
814                         appt->period.nth = attrs[i].value->item.uint32_value;
815                         break;
816
817                 case CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I:
818                         _csa_iso8601_to_tick(attrs[i].value->item.\
819                                 date_time_value, &appt->period.enddate);
820                         break;
821                 }
822         }
823
824         if (stat != CSA_SUCCESS)
825                 return (stat);
826
827         if (enddateindex >= 0) {
828                 _csa_iso8601_to_tick(attrs[enddateindex].value->item.\
829                         date_time_value, &endtick);
830                 appt->duration = endtick - appt->appt_id.tick;
831         } else
832                 appt->duration = 0;
833
834         if (_DtCm_attrs_to_eventtype4(attrs[typeindex].value,
835             (stypeindex >= 0 ? attrs[stypeindex].value : NULL), appt->tag))
836                 appt->tag->tag = otherTag_4;
837
838         return (CSA_SUCCESS);
839 }
840
841 static Abb_Appt_4 *
842 _MakeAbbrAppt()
843 {
844         Abb_Appt_4 *a;
845
846         if ((a = (Abb_Appt_4 *)calloc(1, sizeof(Abb_Appt_4))) == NULL)
847                 return NULL;
848
849         if ((a->tag = (Tag_4 *)calloc(1, sizeof(Tag_4))) == NULL) {
850                 free(a);
851                 return NULL;
852         }
853
854         a->tag->tag = appointment_4;
855         a->tag->showtime =  B_TRUE;
856
857         return(a);
858 }
859
860 static uint
861 _ConvertV5Access(uint v5rights, boolean_t strictmode)
862 {
863         uint    access = 0;
864
865         if (v5rights & CSA_OWNER_RIGHTS)
866                 return (access_read_4 | access_write_4 | access_delete_4);
867
868         if (v5rights & (CSA_VIEW_PUBLIC_ENTRIES|CSA_VIEW_CONFIDENTIAL_ENTRIES|
869             CSA_VIEW_PRIVATE_ENTRIES))
870                 access = access_read_4;
871
872         if ((strictmode == B_TRUE &&
873             (v5rights & CSA_INSERT_PUBLIC_ENTRIES) &&
874             (v5rights & CSA_INSERT_PRIVATE_ENTRIES) &&
875             (v5rights & CSA_INSERT_CONFIDENTIAL_ENTRIES)) ||
876             (strictmode == B_FALSE &&
877             (v5rights & (CSA_INSERT_PUBLIC_ENTRIES |
878             CSA_INSERT_PRIVATE_ENTRIES | CSA_INSERT_CONFIDENTIAL_ENTRIES))))
879                 access |= access_write_4;
880
881         if ((strictmode == B_TRUE &&
882             (v5rights & CSA_CHANGE_PUBLIC_ENTRIES) &&
883             (v5rights & CSA_CHANGE_PRIVATE_ENTRIES) &&
884             (v5rights & CSA_CHANGE_CONFIDENTIAL_ENTRIES)) ||
885             (strictmode == B_FALSE &&
886             (v5rights & (CSA_CHANGE_PUBLIC_ENTRIES |
887             CSA_CHANGE_PRIVATE_ENTRIES | CSA_CHANGE_CONFIDENTIAL_ENTRIES))))
888                 access |= access_delete_4;
889
890         return (access);
891 }
892
893 static uint
894 _ConvertV4Access(uint v4rights)
895 {
896         uint    access = 0;
897
898         if (v4rights & access_read_4)
899                 access = CSA_VIEW_PUBLIC_ENTRIES;
900
901         if (v4rights & access_write_4)
902                 access |= CSA_INSERT_PUBLIC_ENTRIES;
903
904         if (v4rights & (access_write_4 | access_delete_4))
905                 access |= CSA_CHANGE_PUBLIC_ENTRIES;
906
907         return (access);
908 }
909
910 static char *
911 _ConvertReminderName(char *rname)
912 {
913         if (!strcmp(rname, CSA_ENTRY_ATTR_AUDIO_REMINDER))
914                 return (strdup(_DtCM_OLD_ATTR_BEEP_REMINDER));
915         else if (!strcmp(rname, CSA_ENTRY_ATTR_FLASHING_REMINDER))
916                 return (strdup(_DtCM_OLD_ATTR_FLASH_REMINDER));
917         else if (!strcmp(rname, CSA_ENTRY_ATTR_MAIL_REMINDER))
918                 return (strdup(_DtCM_OLD_ATTR_MAIL_REMINDER));
919         else if (!strcmp(rname, CSA_ENTRY_ATTR_POPUP_REMINDER))
920                 return (strdup(_DtCM_OLD_ATTR_POPUP_REMINDER));
921         else
922                 return (strdup(rname));
923 }
924
925 static CSA_return_code
926 _Appt4ToCmsentryAttrs(
927         char            *calname,
928         Appt_4          *a4,
929         uint            *num_attrs,
930         cms_attribute   **attrs_r)
931 {
932         CSA_return_code         stat = CSA_SUCCESS;
933         cms_attribute           *attrs;
934         cms_attribute           tmpattr;
935         cms_attribute_value     tmpval;
936         Attribute_4             *reminders = a4->attr;
937         char                    buf[BUFSIZ];
938         CSA_opaque_data         opq;
939         int                     index, ntimes, count = 0;
940         char                    *ptr1, *ptr2;
941
942         if (num_attrs == NULL || attrs_r == NULL)
943                 return (CSA_E_INVALID_PARAMETER);
944
945         if ((attrs = (cms_attribute *)calloc(1,
946             sizeof(cms_attribute) * (_DtCM_OLD_ENTRY_ATTR_SIZE+ 1))) == NULL)
947                 return (CSA_E_INSUFFICIENT_MEMORY);
948
949         if (a4->period.period != single_4 &&
950             a4->ntimes == _DtCM_OLD_REPEAT_FOREVER)
951                 ntimes = CSA_X_DT_DT_REPEAT_FOREVER;
952         else
953                 ntimes = a4->ntimes;
954
955         tmpattr.value = &tmpval;
956
957         /* reference id */
958         tmpattr.name.name = CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER;
959         tmpattr.name.num = CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I;
960         tmpval.type = CSA_VALUE_OPAQUE_DATA;
961         tmpval.item.opaque_data_value = &opq;
962         ptr1 = strchr(calname, '@');
963         ptr2 = (ptr1 ? strchr(ptr1, '.') : NULL);
964         if (ptr1) {
965                 sprintf(buf, "%ld:%s%s%s", a4->appt_id.key, calname,
966                         (ptr2 == NULL ? "." : ""),
967                         (ptr2 == NULL ? _DtCmGetLocalDomain(ptr1+1) : ""));
968         } else {
969                 sprintf(buf, "%ld:%s@%s", a4->appt_id.key, calname,
970                         _DtCmGetHostAtDomain());
971         }
972         opq.size = strlen(buf);
973         opq.data = (unsigned char *)buf;
974
975         if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
976             != CSA_SUCCESS) {
977                 free(attrs);
978                 return (stat);
979         }
980
981         /* start date */
982         tmpattr.name.name = CSA_ENTRY_ATTR_START_DATE;
983         tmpattr.name.num = CSA_ENTRY_ATTR_START_DATE_I;
984         tmpval.type = CSA_VALUE_DATE_TIME;
985         tmpval.item.date_time_value = buf;
986         if ((stat = _csa_tick_to_iso8601(a4->appt_id.tick, buf) ?
987             CSA_E_INVALID_DATE_TIME : CSA_SUCCESS) ||
988             (stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
989             != CSA_SUCCESS) {
990                 goto error;
991         }
992
993         /* type */
994         tmpattr.name.name = CSA_ENTRY_ATTR_TYPE;
995         tmpattr.name.num = CSA_ENTRY_ATTR_TYPE_I;
996         tmpval.type = CSA_VALUE_UINT32;
997         tmpval.item.uint32_value = _DtCm_eventtype4_to_type(a4->tag->tag);
998         if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
999             != CSA_SUCCESS) {
1000                 goto error;
1001         }
1002
1003         /* subtype */
1004         tmpattr.name.name = CSA_ENTRY_ATTR_SUBTYPE;
1005         tmpattr.name.num = CSA_ENTRY_ATTR_SUBTYPE_I;
1006         tmpval.type = CSA_VALUE_STRING;
1007         tmpval.item.string_value = _DtCm_eventtype4_to_subtype(a4->tag->tag);
1008         if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
1009             != CSA_SUCCESS) {
1010                 goto error;
1011         }
1012
1013         /* showtime */
1014         tmpattr.name.name = CSA_X_DT_ENTRY_ATTR_SHOWTIME;
1015         tmpattr.name.num = CSA_X_DT_ENTRY_ATTR_SHOWTIME_I;
1016         tmpval.type = CSA_VALUE_SINT32;
1017         tmpval.item.sint32_value = a4->tag->showtime;
1018         if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
1019             != CSA_SUCCESS) {
1020                 goto error;
1021         }
1022
1023         /* end date */
1024         tmpattr.name.name = CSA_ENTRY_ATTR_END_DATE;
1025         tmpattr.name.num = CSA_ENTRY_ATTR_END_DATE_I;
1026         tmpval.type = CSA_VALUE_DATE_TIME;
1027         tmpval.item.date_time_value = buf;
1028         if ((stat = _csa_tick_to_iso8601(a4->appt_id.tick + a4->duration,
1029             buf) ? CSA_E_INVALID_DATE_TIME : CSA_SUCCESS) != CSA_SUCCESS ||
1030             (stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
1031             != CSA_SUCCESS) {
1032                 goto error;
1033         }
1034
1035         /* summary */
1036         tmpattr.name.name = CSA_ENTRY_ATTR_SUMMARY;
1037         tmpattr.name.num = CSA_ENTRY_ATTR_SUMMARY_I;
1038         tmpval.type = CSA_VALUE_STRING;
1039         tmpval.item.string_value = a4->what;
1040         if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
1041             != CSA_SUCCESS) {
1042                 goto error;
1043         }
1044
1045         /* organizer */
1046         tmpattr.name.name = CSA_ENTRY_ATTR_ORGANIZER;
1047         tmpattr.name.num = CSA_ENTRY_ATTR_ORGANIZER_I;
1048         tmpval.type = CSA_VALUE_CALENDAR_USER;
1049         tmpval.item.calendar_user_value = a4->author;
1050         if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
1051             != CSA_SUCCESS) {
1052                 goto error;
1053         }
1054
1055         /* status */
1056         tmpattr.name.name = CSA_ENTRY_ATTR_STATUS;
1057         tmpattr.name.num = CSA_ENTRY_ATTR_STATUS_I;
1058         tmpval.type = CSA_VALUE_UINT32;
1059         tmpval.item.uint32_value = _DtCm_apptstatus4_to_status(a4->appt_status);
1060         if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
1061             != CSA_SUCCESS) {
1062                 goto error;
1063         }
1064
1065         /* classification */
1066         tmpattr.name.name = CSA_ENTRY_ATTR_CLASSIFICATION;
1067         tmpattr.name.num = CSA_ENTRY_ATTR_CLASSIFICATION_I;
1068         tmpval.type = CSA_VALUE_UINT32;
1069         tmpval.item.uint32_value = _DtCm_privacy4_to_classification(a4->privacy);
1070         if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
1071             != CSA_SUCCESS) {
1072                 goto error;
1073         }
1074
1075         /* repeat type */
1076         tmpattr.name.name = CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE;
1077         tmpattr.name.num = CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I;
1078         tmpval.type = CSA_VALUE_SINT32;
1079         tmpval.item.sint32_value = _DtCm_interval4_to_rtype(a4->period.period);
1080         if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr, B_TRUE))
1081             != CSA_SUCCESS) {
1082                 goto error;
1083         }
1084
1085         /* repeat times */
1086         if (a4->period.period != single_4) {
1087                 tmpattr.name.name = CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES;
1088                 tmpattr.name.num = CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I;
1089                 tmpval.type = CSA_VALUE_UINT32;
1090                 tmpval.item.uint32_value = ntimes;
1091                 if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr,
1092                     B_TRUE)) != CSA_SUCCESS) {
1093                         goto error;
1094                 }
1095         }
1096
1097         /* occurrence number */
1098         if (a4->period.period == nthWeekday_4) {
1099                 tmpattr.name.name = CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM;
1100                 tmpattr.name.num = CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I;
1101                 tmpval.type = CSA_VALUE_SINT32;
1102                 tmpval.item.sint32_value = a4->period.nth;
1103                 if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr,
1104                     B_TRUE)) != CSA_SUCCESS) {
1105                         goto error;
1106                 }
1107         }
1108
1109         /* repeat interval */
1110         if (a4->period.period >= everyNthDay_4 &&
1111             a4->period.period <= everyNthMonth_4) {
1112                 tmpattr.name.name = CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL;
1113                 tmpattr.name.num = CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I;
1114                 tmpval.type = CSA_VALUE_UINT32;
1115                 tmpval.item.uint32_value = a4->period.nth;
1116                 if ((stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr,
1117                     B_TRUE)) != CSA_SUCCESS) {
1118                         goto error;
1119                 }
1120         }
1121
1122         if (a4->period.enddate != 0) {
1123                 tmpattr.name.name = CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE;
1124                 tmpattr.name.num = CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I;
1125                 tmpval.type = CSA_VALUE_DATE_TIME;
1126                 tmpval.item.date_time_value = buf;
1127                 if ((stat = _csa_tick_to_iso8601(a4->period.enddate, buf) ?
1128                     CSA_E_INVALID_DATE_TIME : CSA_SUCCESS) != CSA_SUCCESS ||
1129                     (stat = _DtCm_copy_cms_attribute(&attrs[count++], &tmpattr,
1130                     B_TRUE)) != CSA_SUCCESS) {
1131                         goto error;
1132                 }
1133         }
1134
1135         while (reminders != NULL) {
1136                 if ((attrs[count].name.num = _DtCm_old_reminder_name_to_index(
1137                     reminders->attr)) >= 0) {
1138                         if ((attrs[count].name.name =
1139                             strdup(_DtCm_old_reminder_name_to_name(
1140                             reminders->attr))) == NULL) {
1141                                 count++;
1142                                 goto error;
1143                         }
1144                         if ((stat = _DtCmAttr4ToReminderValue(reminders,
1145                             &attrs[count++].value)) != CSA_SUCCESS) {
1146                                 count++;
1147                                 goto error;
1148                         }
1149
1150                 }
1151                 reminders = reminders->next;
1152         }
1153
1154         *num_attrs = count;
1155         *attrs_r = attrs;
1156         return (CSA_SUCCESS);
1157
1158 error:
1159         _DtCm_free_cms_attributes(count--, attrs);
1160         free(attrs);
1161         return (stat);
1162 }
1163