Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / csa / convert4-5.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: convert4-5.c /main/1 1996/04/21 19:22:49 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 /*
32  * Routines to convert data types used in version 4 to version 5.
33  */
34
35 #include <EUSCompat.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include "csa.h"
40 #include "attr.h"
41 #include "cmsdata.h"
42 #include "convert4-5.h"
43 #include "free.h"
44 #include "iso8601.h"
45 #include "lutil.h"
46
47 #define V4_ATTR_NUM     13
48
49 /*
50  * forward declaration of static functions
51  */
52 static unsigned int accesstype4_to_accessright(int access);
53 static CSA_return_code eventtype4_to_attrs(Event_Type_4 tag, uint num_attrs,
54                                 cms_attribute *attrs);
55 static CSA_return_code _RepeatInfoToRule(Appt_4 *a4,
56                                 cms_attribute_value **attrval);
57
58 /*****************************************************************************
59  * extern functions
60  *****************************************************************************/
61
62 extern CSA_return_code
63 _DtCm_accessentry4_to_cmsaccesslist(
64         Access_Entry_4 *a4,
65         cms_access_entry **alist)
66 {
67         CSA_return_code stat = CSA_SUCCESS;
68         cms_access_entry *to, *head, *prev;
69
70         head = prev = NULL;
71         while (a4 != NULL) {
72                 if ((to = (cms_access_entry *)calloc(1,
73                     sizeof(cms_access_entry))) == NULL) {
74                         stat = CSA_E_INSUFFICIENT_MEMORY;
75                         break;
76                 }
77
78                 if (a4->who && (to->user = strdup(a4->who)) == NULL) {
79                         free(to);
80                         stat = CSA_E_INSUFFICIENT_MEMORY;
81                         break;
82                 }
83
84                 to->rights = accesstype4_to_accessright(a4->access_type);
85                 to->next = NULL;
86
87                 if (head == NULL)
88                         head = to;
89                 else
90                         prev->next = to;
91
92                 prev = to;
93
94                 a4 = a4->next;
95         }
96
97         if (stat != CSA_SUCCESS) {
98                 _DtCm_free_cms_access_entry(head);
99                 head = NULL;
100         }
101
102         *alist = head;
103         return (stat);
104 }
105
106 extern CSA_return_code
107 _DtCm_appt4_to_attrs(
108         char            *calname,
109         Appt_4          *a4,
110         uint            num_attrs,
111         cms_attribute   *attrs,
112         boolean_t       rerule)
113 {
114         CSA_return_code stat = CSA_SUCCESS;
115         Attribute_4     *reminders = a4->attr;
116         char            buf[BUFSIZ];
117         CSA_opaque_data opq;
118         int             index, ntimes;
119         char            *ptr1, *ptr2;
120
121         if (a4 == NULL || num_attrs < _DtCM_DEFINED_ENTRY_ATTR_SIZE)
122                 return (CSA_E_INVALID_PARAMETER);
123
124         /* exception info is not converted since it's not used
125          * and we don't have an attribute for it yet
126          */
127
128         while (stat == CSA_SUCCESS && reminders != NULL) {
129                 if ((index =
130                     _DtCm_old_reminder_name_to_index(reminders->attr)) >= 0) {
131                         if ((stat = _DtCmAttr4ToReminderValue(reminders,
132                             &attrs[index].value)) != CSA_SUCCESS) {
133                                 break;
134                         }
135                 }
136                 reminders = reminders->next;
137         }
138
139         /* only contains the id now, need to
140          * add calendar name and location info
141          */
142         if (a4->appt_id.key > 0) {
143                 ptr1 = strchr(calname, '@');
144                 ptr2 = (ptr1 ? strchr(ptr1, '.') : NULL);
145
146                 if (ptr1) {
147                         sprintf(buf, "%d:%s%s%s", a4->appt_id.key, calname,
148                                 (ptr2 == NULL ? "." : ""),
149                                 (ptr2 == NULL ? _DtCmGetLocalDomain(ptr1+1) :
150                                 ""));
151                 } else {
152                         sprintf(buf, "%d:%s@%s", a4->appt_id.key, calname,
153                                 _DtCmGetHostAtDomain());
154                 }
155                 opq.size = strlen(buf);
156                 opq.data = (unsigned char *)buf;
157         }
158
159         if (a4->period.period != single_4 &&
160             a4->ntimes == _DtCM_OLD_REPEAT_FOREVER)
161                 ntimes = CSA_X_DT_DT_REPEAT_FOREVER;
162         else
163                 ntimes = a4->ntimes;
164
165         /* convert tick to iso8601 */
166
167         if (stat != CSA_SUCCESS || (a4->appt_id.key > 0 &&
168                 (stat = _DtCm_set_opaque_attrval(&opq,
169                 &attrs[CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I].value))))
170                         ;
171         else if ((stat = _csa_tick_to_iso8601(a4->appt_id.tick, buf) ?
172                 CSA_E_INVALID_DATE_TIME : CSA_SUCCESS) ||
173                 (stat = _DtCm_set_string_attrval(buf,
174                 &attrs[CSA_ENTRY_ATTR_START_DATE_I].value,CSA_VALUE_DATE_TIME)))
175                         ;
176         else if (stat = eventtype4_to_attrs(a4->tag->tag, num_attrs, attrs))
177                         ;
178         else if (stat = _DtCm_set_sint32_attrval(a4->tag->showtime,
179                 &attrs[CSA_X_DT_ENTRY_ATTR_SHOWTIME_I].value))
180                         ;
181         else if ((stat = _csa_tick_to_iso8601(a4->appt_id.tick + a4->duration,
182                 buf) ? CSA_E_INVALID_DATE_TIME : CSA_SUCCESS) ||
183                 (stat = _DtCm_set_string_attrval(buf,
184                 &attrs[CSA_ENTRY_ATTR_END_DATE_I].value, CSA_VALUE_DATE_TIME)))
185                         ;
186         else if (stat = _DtCm_set_string_attrval(a4->what,
187                 &attrs[CSA_ENTRY_ATTR_SUMMARY_I].value, CSA_VALUE_STRING))
188                         ;
189         else if (stat = _DtCm_set_user_attrval(a4->author,
190                 &attrs[CSA_ENTRY_ATTR_ORGANIZER_I].value))
191                         ;
192         else if (stat = _DtCm_set_uint32_attrval(_DtCm_apptstatus4_to_status(
193                 a4->appt_status), &attrs[CSA_ENTRY_ATTR_STATUS_I].value))
194                         ;
195         else if (stat = _DtCm_set_uint32_attrval(
196                 _DtCm_privacy4_to_classification(a4->privacy),
197                 &attrs[CSA_ENTRY_ATTR_CLASSIFICATION_I].value))
198                         ;
199         else if (rerule && (stat = _RepeatInfoToRule(a4,
200                 &attrs[CSA_ENTRY_ATTR_RECURRENCE_RULE_I].value)))
201                         ;
202         else if (!rerule &&
203                 ((stat = _DtCm_set_uint32_attrval(ntimes,
204                     &attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I].value)) ||
205                 (stat = _DtCm_set_sint32_attrval(_DtCm_interval4_to_rtype(
206                     a4->period.period),
207                     &attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I].value)) ||
208                 (a4->period.period == nthWeekday_4 &&
209                     (stat = _DtCm_set_sint32_attrval(a4->period.nth, &attrs\
210                     [CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I].value))) ||
211                 (a4->period.period >= everyNthDay_4 &&
212                     a4->period.period <= everyNthMonth_4 &&
213                     (stat = _DtCm_set_uint32_attrval(a4->period.nth, &attrs\
214                     [CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I].value))) ||
215                 (a4->period.enddate != 0 &&
216                     ((stat = _csa_tick_to_iso8601(a4->period.enddate, buf) ?
217                     CSA_E_INVALID_DATE_TIME : CSA_SUCCESS) ||
218                     (stat = _DtCm_set_string_attrval(buf, &attrs\
219                     [CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I].value,
220                     CSA_VALUE_DATE_TIME))))))
221                         ;
222         else {
223                 return (CSA_SUCCESS);
224         }
225
226         /* something wrong, need cleanup */
227         /* free up all attribute values set so far */
228
229         return (stat);
230 }
231
232 extern int
233 _DtCm_eventtype4_to_type(Event_Type_4 tag)
234 {
235         switch (tag) {
236         case appointment_4:
237         case holiday_4:
238                 return (CSA_TYPE_EVENT);
239
240         case toDo_4:
241                 return (CSA_TYPE_TODO);
242
243         case reminder_4:
244         case otherTag_4:
245         default:
246                 return (CSA_X_DT_TYPE_OTHER);
247         }
248 }
249
250 extern char *
251 _DtCm_eventtype4_to_subtype(Event_Type_4 tag)
252 {
253         switch (tag) {
254         case appointment_4:
255                 return (CSA_SUBTYPE_APPOINTMENT);
256         case holiday_4:
257                 return (CSA_SUBTYPE_HOLIDAY);
258         case toDo_4:
259         case reminder_4:
260         case otherTag_4:
261         default:
262                 return ("");
263         }
264 }
265
266 extern CSA_sint32
267 _DtCm_interval4_to_rtype(Interval_4 val)
268 {
269         switch (val) {
270         case single_4:
271                 return (CSA_X_DT_REPEAT_ONETIME);
272         case weekly_4:
273                 return (CSA_X_DT_REPEAT_WEEKLY);
274         case daily_4:
275                 return (CSA_X_DT_REPEAT_DAILY);
276         case biweekly_4:
277                 return (CSA_X_DT_REPEAT_BIWEEKLY);
278         case monthly_4:
279                 return (CSA_X_DT_REPEAT_MONTHLY_BY_DATE);
280         case yearly_4:
281                 return (CSA_X_DT_REPEAT_YEARLY);
282         case nthWeekday_4:
283                 return (CSA_X_DT_REPEAT_MONTHLY_BY_WEEKDAY);
284         case everyNthDay_4:
285                 return (CSA_X_DT_REPEAT_EVERY_NDAY);
286         case everyNthWeek_4:
287                 return (CSA_X_DT_REPEAT_EVERY_NWEEK);
288         case everyNthMonth_4:
289                 return (CSA_X_DT_REPEAT_EVERY_NMONTH);
290         case monThruFri_4:
291                 return (CSA_X_DT_REPEAT_MON_TO_FRI);
292         case monWedFri_4:
293                 return (CSA_X_DT_REPEAT_MONWEDFRI);
294         case tueThur_4:
295                 return (CSA_X_DT_REPEAT_TUETHUR);
296         case daysOfWeek_4:
297                 return (CSA_X_DT_REPEAT_WEEKDAYCOMBO);
298         case otherPeriod_4:
299         default:
300                 return (CSA_X_DT_REPEAT_OTHER);
301         }
302 }
303
304 extern CSA_sint32
305 _DtCm_apptstatus4_to_status(Appt_Status_4 stat)
306 {
307         switch (stat) {
308         case active_4:
309                 return (CSA_X_DT_STATUS_ACTIVE);
310         case completed_4:
311                 return (CSA_STATUS_COMPLETED);
312         case pendingAdd_4:
313                 return (CSA_X_DT_STATUS_ADD_PENDING);
314         case pendingDelete_4:
315                 return (CSA_X_DT_STATUS_DELETE_PENDING);
316         case committed_4:
317                 return (CSA_X_DT_STATUS_COMMITTED);
318         case cancelled_4:
319                 return (CSA_X_DT_STATUS_CANCELLED);
320         default:
321                 return (CSA_X_DT_STATUS_ACTIVE);
322         }
323 }
324
325 extern CSA_sint32
326 _DtCm_privacy4_to_classification(Privacy_Level_4 p)
327 {
328         switch (p) {
329         case public_4:
330                 return (CSA_CLASS_PUBLIC);
331         case semiprivate_4:
332                 return (CSA_CLASS_CONFIDENTIAL);
333         case private_4:
334                 return (CSA_CLASS_PRIVATE);
335         default:
336                 return (CSA_CLASS_PUBLIC);
337         }
338 }
339
340 /******************************************************************************
341  * static functions used within the file
342  ******************************************************************************/
343
344 /*
345  * Static functions used within the file.
346  */
347
348 /*
349  * DtCM_PERMIT_ACCESS is added for backward compatibility
350  */
351 static unsigned int
352 accesstype4_to_accessright(int access)
353 {
354         unsigned int    newaccess = 0;
355
356         if (access & access_read_4)
357                 newaccess |= CSA_X_DT_BROWSE_ACCESS;
358         if (access & access_write_4)
359                 newaccess |= CSA_X_DT_INSERT_ACCESS;
360         if (access & access_delete_4)
361                 newaccess |= CSA_X_DT_DELETE_ACCESS;
362
363         return (newaccess);
364 }
365
366 extern CSA_return_code
367 _DtCmAttr4ToReminderValue(
368         Attribute_4 *remval,
369         cms_attribute_value **attrval)
370 {
371         CSA_reminder rval;
372         char timestr[BUFSIZ];
373
374         /*
375          * rval is just a place holder, values will be
376          * copied in _DtCm_set_reminder_attrval
377          */
378         _csa_duration_to_iso8601(atoi(remval->value), timestr);
379         rval.lead_time = timestr;
380
381         if (remval->clientdata && *remval->clientdata != NULL) {
382                 rval.reminder_data.size = strlen(remval->clientdata);
383                 rval.reminder_data.data = (unsigned char *)remval->clientdata;
384         } else {
385                 rval.reminder_data.size = 0;
386                 rval.reminder_data.data = NULL;
387         }
388
389         rval.snooze_time = NULL;
390         rval.repeat_count = 0;
391
392         return (_DtCm_set_reminder_attrval(&rval, attrval));
393 }
394
395 static CSA_return_code
396 eventtype4_to_attrs(Event_Type_4 tag, uint num_attrs, cms_attribute *attrs)
397 {
398         CSA_return_code stat;
399
400         switch (tag) {
401         case appointment_4:
402                 if ((stat = _DtCm_set_uint32_attrval(CSA_TYPE_EVENT,
403                     &attrs[CSA_ENTRY_ATTR_TYPE_I].value)) != CSA_SUCCESS)
404                         return (stat);
405
406                 return (_DtCm_set_string_attrval(CSA_SUBTYPE_APPOINTMENT,
407                         &attrs[CSA_ENTRY_ATTR_SUBTYPE_I].value,
408                         CSA_VALUE_STRING));
409
410         case toDo_4:
411                 return (_DtCm_set_uint32_attrval(CSA_TYPE_TODO,
412                         &attrs[CSA_ENTRY_ATTR_TYPE_I].value));
413
414         case holiday_4:
415                 if ((stat = _DtCm_set_uint32_attrval(CSA_TYPE_EVENT,
416                     &attrs[CSA_ENTRY_ATTR_TYPE_I].value)) != CSA_SUCCESS)
417                         return (stat);
418
419                 return (_DtCm_set_string_attrval(CSA_SUBTYPE_HOLIDAY,
420                         &attrs[CSA_ENTRY_ATTR_SUBTYPE_I].value,
421                         CSA_VALUE_STRING));
422
423         case reminder_4:
424         case otherTag_4:
425         default:
426                 return (_DtCm_set_uint32_attrval(CSA_X_DT_TYPE_OTHER,
427                         &attrs[CSA_ENTRY_ATTR_TYPE_I].value));
428         }
429 }
430
431 static CSA_return_code
432 _RepeatInfoToRule(Appt_4 *a4, cms_attribute_value **attrval)
433 {
434         char    buf[BUFSIZ], datestr[25];
435         uint    duration;
436
437         if (a4->period.period == single_4 || a4->period.period == otherPeriod_4)        {
438                 *attrval = NULL;
439                 return (CSA_SUCCESS);
440         }
441
442         if (a4->ntimes == _DtCM_OLD_REPEAT_FOREVER) {
443                 duration = 0;
444         } else if (a4->period.period >= everyNthDay_4 &&
445             a4->period.period <= everyNthMonth_4) {
446                 duration = ((a4->ntimes % a4->period.nth) ? 1 : 0) +
447                                 a4->ntimes/a4->period.nth;
448         } else
449                 duration = a4->ntimes;
450
451         switch (a4->period.period) {
452         case daily_4:
453                 sprintf(buf, "D1 #%d ", duration);
454                 break;
455         case weekly_4:
456                 sprintf(buf, "W1 #%d ", duration);
457                 break;
458         case biweekly_4:
459                 sprintf(buf, "W2 #%d ", duration);
460                 break;
461         case monthly_4:
462                 sprintf(buf, "MD1 #%d ", duration);
463                 break;
464         case yearly_4:
465                 sprintf(buf, "YM1 #%d ", duration);
466                 break;
467         case nthWeekday_4:
468                 sprintf(buf, "MP1 #%d ", duration);
469                 break;
470         case everyNthDay_4:
471                 sprintf(buf, "D%d #%d ", a4->period.nth, duration);
472                 break;
473         case everyNthWeek_4:
474                 sprintf(buf, "W%d #%d ", a4->period.nth, duration);
475                 break;
476         case everyNthMonth_4:
477                 sprintf(buf, "MD%d #%d ", a4->period.nth, duration);
478                 break;
479         case monThruFri_4:
480                 sprintf(buf, "W1 MO TU WE TH FR #%d ", duration);
481                 break;
482         case monWedFri_4:
483                 sprintf(buf, "W1 MO WE FR #%d ", duration);
484                 break;
485         case tueThur_4:
486                 sprintf(buf, "W1 TU TH #%d ", duration);
487                 break;
488         case daysOfWeek_4:
489                 sprintf(buf, "W1 #%d ", duration);
490                 if (a4->period.nth & 0x1) strcat(buf, "SU ");
491                 if (a4->period.nth & 0x2) strcat(buf, "MO ");
492                 if (a4->period.nth & 0x4) strcat(buf, "TU ");
493                 if (a4->period.nth & 0x8) strcat(buf, "WE ");
494                 if (a4->period.nth & 0x10) strcat(buf, "TH ");
495                 if (a4->period.nth & 0x20) strcat(buf, "FR ");
496                 if (a4->period.nth & 0x40) strcat(buf, "SA ");
497                 break;
498         }
499
500         if (a4->period.enddate) {
501                 if (_csa_tick_to_iso8601(a4->period.enddate, datestr))
502                         return (CSA_E_INVALID_DATE_TIME);
503                 strcat(buf, datestr);
504         }
505
506         return (_DtCm_set_string_attrval(buf, attrval, CSA_VALUE_STRING));
507 }
508