Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtcm / server / v5ops.c
1 /* $XConsortium: v5ops.c /main/4 1995/11/09 12:55:44 rswiston $ */
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 <time.h>
14 #include "v5ops.h"
15 #include "iso8601.h"
16 #include "attr.h"
17 #include "updateattrs.h"
18 #include "rerule.h"
19 #include "repeat.h"
20 #include "reutil.h"
21
22 /*****************************************************************************
23  * extern functions used in the library
24  *****************************************************************************/
25
26 extern _DtCmsComparisonResult
27 _DtCmsCompareEntry(cms_key *key, caddr_t data)
28 {
29         cms_entry *entry = (cms_entry *)data;
30
31         /* check the time only if it's not zero */
32         if (key->time < entry->key.time)
33                 return (_DtCmsIsLess);
34         if (key->time > entry->key.time)
35                 return (_DtCmsIsGreater);
36
37         /* tick's are _DtCmsIsEqual */
38         if (key->id < entry->key.id)
39                 return (_DtCmsIsLess);
40         if (key->id > entry->key.id)
41                 return (_DtCmsIsGreater);
42
43         return (_DtCmsIsEqual);
44 }
45
46 extern _DtCmsComparisonResult
47 _DtCmsCompareRptEntry(cms_key *key, caddr_t data)
48 {
49         cms_entry *entry = (cms_entry *)data;
50
51         if (key->id < entry->key.id)
52                 return (_DtCmsIsLess);
53         if (key->id > entry->key.id)
54                 return (_DtCmsIsGreater);
55         return (_DtCmsIsEqual);
56 }
57
58 extern caddr_t
59 _DtCmsGetEntryKey(caddr_t data)
60 {
61         return ((caddr_t) &(((cms_entry *)data)->key));
62 }
63
64 extern CSA_return_code
65 _DtCmsSetLastUpdate(cms_entry *entry)
66 {
67         char                    datestr[20];
68         cms_attribute_value     val;
69
70         _csa_tick_to_iso8601(time(0), datestr);
71
72         val.type = CSA_VALUE_DATE_TIME;
73         val.item.date_time_value = datestr;
74
75         /* CSA_ENTRY_ATTR_LAST_UPDATE_I */
76         return (_DtCmUpdateStringAttrVal(&val,
77                 &entry->attrs[CSA_ENTRY_ATTR_LAST_UPDATE_I].value));
78 }
79
80 extern void
81 _DtCmsConvertToOnetime(cms_entry *entry, RepeatEvent *re)
82 {
83         time_t                  ctick, lasttick, diff = 0;
84         RepeatEventState        *res;
85
86         lasttick = LastTick(entry->key.time, re);
87         for (ctick = ClosestTick(entry->key.time, entry->key.time, re, &res);
88             ctick <= lasttick;
89             ctick = NextTick(ctick, entry->key.time, re, res))
90         {
91                 if (ctick <= 0 || !_DtCmsInExceptionList(entry, ctick))
92                         break;
93         }
94
95         if (ctick != entry->key.time) {
96                 if (entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value) {
97                         _csa_iso8601_to_tick(entry->attrs\
98                                 [CSA_ENTRY_ATTR_END_DATE_I].value->item.\
99                                 date_time_value, &diff);
100                         diff = diff - entry->key.time;
101                 }
102
103                 entry->key.time = ctick;
104                 _csa_tick_to_iso8601(ctick, entry->attrs\
105                         [CSA_ENTRY_ATTR_START_DATE_I].value->item.\
106                         date_time_value);
107
108                 if (entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value)
109                         _csa_tick_to_iso8601(ctick+diff, entry->attrs\
110                                 [CSA_ENTRY_ATTR_END_DATE_I].value->item.\
111                                 date_time_value);
112         }
113
114         if (entry->attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I].value)
115                 entry->attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I].value->item.\
116                         sint32_value = CSA_X_DT_REPEAT_ONETIME;
117         else
118                 _DtCm_set_sint32_attrval(CSA_X_DT_REPEAT_ONETIME,
119                         &entry->attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I].value); 
120
121         _DtCmUpdateDateTimeListAttrVal(NULL, &entry->attrs\
122                 [CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value);
123
124         _DtCmUpdateSint32AttrVal(NULL, &entry->attrs\
125                 [CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I].value);
126
127         _DtCmUpdateStringAttrVal(NULL, &entry->attrs\
128                 [CSA_ENTRY_ATTR_RECURRENCE_RULE_I].value);
129
130         _DtCmUpdateSint32AttrVal(NULL, &entry->attrs\
131                 [CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I].value);
132
133         _DtCmUpdateSint32AttrVal(NULL, &entry->attrs\
134                 [CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I].value);
135
136         _DtCmUpdateSint32AttrVal(NULL, &entry->attrs\
137                 [CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I].value);
138
139         _DtCmUpdateStringAttrVal(NULL, &entry->attrs\
140                 [CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I].value);
141 }
142
143 extern int
144 _DtCmsGetDuration(cms_entry *eptr)
145 {
146         time_t  stime, etime;
147
148         if (eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].value) {
149                 _csa_iso8601_to_tick(eptr->attrs[CSA_ENTRY_ATTR_END_DATE_I].\
150                         value->item.date_time_value, &etime);
151
152                 _csa_iso8601_to_tick(eptr->attrs[CSA_ENTRY_ATTR_START_DATE_I].\
153                         value->item.date_time_value, &stime);
154
155                 return (etime - stime);
156         } else
157                 return (0);
158 }
159
160 extern CSA_return_code
161 _DtCmsCheckInitialAttributes(cms_entry *entry)
162 {
163         CSA_return_code stat;
164         cms_attribute   *attrs;
165         char            datestr[80];
166
167         if (entry == NULL)
168                 return (CSA_E_INVALID_PARAMETER);
169
170         attrs = entry->attrs;
171
172         /* fill in server generated value */
173
174         /* CSA_ENTRY_ATTR_DATE_CREATED_I */
175         _csa_tick_to_iso8601(time(0), datestr);
176         if ((stat = _DtCm_set_string_attrval(datestr,
177             &attrs[CSA_ENTRY_ATTR_DATE_CREATED_I].value, CSA_VALUE_DATE_TIME))
178             != CSA_SUCCESS)
179                 return (stat);
180
181         /* CSA_ENTRY_ATTR_LAST_UPDATE_I */
182         if ((stat = _DtCm_set_string_attrval(datestr,
183             &attrs[CSA_ENTRY_ATTR_LAST_UPDATE_I].value, CSA_VALUE_DATE_TIME))
184             != CSA_SUCCESS)
185                 return (stat);
186
187         /* fill in default values when not specified */
188         if (attrs[CSA_ENTRY_ATTR_SUMMARY_I].value == NULL &&
189             (stat = _DtCm_set_string_attrval("",
190             &attrs[CSA_ENTRY_ATTR_SUMMARY_I].value, CSA_VALUE_STRING))
191             != CSA_SUCCESS)
192                 return (stat);
193
194         if (attrs[CSA_X_DT_ENTRY_ATTR_SHOWTIME_I].value == NULL &&
195             (stat = _DtCm_set_sint32_attrval(1,
196             &attrs[CSA_X_DT_ENTRY_ATTR_SHOWTIME_I].value)) != CSA_SUCCESS)
197                 return (stat);
198
199         if (attrs[CSA_ENTRY_ATTR_CLASSIFICATION_I].value == NULL &&
200             (stat = _DtCm_set_uint32_attrval(CSA_CLASS_PUBLIC,
201             &attrs[CSA_ENTRY_ATTR_CLASSIFICATION_I].value)) != CSA_SUCCESS)
202                 return (stat);
203
204         if (attrs[CSA_ENTRY_ATTR_STATUS_I].value == NULL &&
205             (stat = _DtCm_set_uint32_attrval(CSA_X_DT_STATUS_ACTIVE,
206             &attrs[CSA_ENTRY_ATTR_STATUS_I].value)) != CSA_SUCCESS)
207                 return (stat);
208
209         if (attrs[CSA_ENTRY_ATTR_SUBTYPE_I].value == NULL &&
210             attrs[CSA_ENTRY_ATTR_TYPE_I].value->item.uint32_value ==
211             CSA_TYPE_EVENT &&
212             (stat = _DtCm_set_string_attrval(CSA_SUBTYPE_APPOINTMENT,
213             &attrs[CSA_ENTRY_ATTR_SUBTYPE_I].value, CSA_VALUE_STRING))
214             != CSA_SUCCESS)
215                 return (stat);
216
217         return (CSA_SUCCESS);
218 }
219
220 extern CSA_return_code
221 _DtCmsCheckStartEndTime(cms_entry *entry)
222 {
223         time_t  endtime;
224
225         if (entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].value) {
226                 _csa_iso8601_to_tick(entry->attrs[CSA_ENTRY_ATTR_END_DATE_I].\
227                         value->item.date_time_value, &endtime);
228                 if (endtime < entry->key.time)
229                         return (CSA_E_INVALID_ATTRIBUTE_VALUE);
230                 else
231                         return (CSA_SUCCESS);
232         }
233         return (CSA_SUCCESS);
234 }
235
236 extern void
237 _DtCmsCleanupExceptionDates(cms_entry *entry, long ftick)
238 {
239         time_t                  tick;
240         CSA_date_time_list      dt, prev, head;
241
242         if (entry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value == NULL ||
243             entry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value->item.\
244             date_time_list_value == NULL)
245                 return;
246
247         head = entry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value->item.\
248                 date_time_list_value;
249
250         for (dt = head, prev = NULL; dt != NULL; prev = dt, dt = dt->next) {
251                 _csa_iso8601_to_tick(dt->date_time, &tick);
252                 if (ftick <= tick) {
253                         if (prev) {
254                                 prev->next = NULL;
255                                 _DtCm_free_date_time_list(head);
256                         }
257                         break;
258                 }
259         }
260
261         if (dt == NULL) {
262                 free(entry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value);
263                 entry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value = NULL;
264         } else
265                 entry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value->item.\
266                         date_time_list_value = dt;
267 }
268
269 extern int
270 _DtCmsNumberExceptionDates(cms_entry *entry)
271 {
272         cms_attribute_value     *vptr;
273         CSA_date_time_list      dt;
274         int                     count;
275
276         if ((vptr = entry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I].value)
277             == NULL)
278                 return (0);
279
280         count = 0;
281         for (dt = vptr->item.date_time_list_value; dt != NULL; dt = dt->next)
282                 count++;
283
284         return (count);
285 }
286
287 extern CSA_return_code
288 _DtCmsUpdateDurationInRule(cms_entry *entry, uint remain)
289 {
290         char                    *newrule, *ptr;
291         char                    buf[BUFSIZ];
292         cms_attribute_value     *vptr;
293
294         vptr = entry->attrs[CSA_ENTRY_ATTR_RECURRENCE_RULE_I].value;
295         if ((newrule = malloc(strlen(vptr->item.string_value) + 20)) == NULL)
296                 return (CSA_E_INSUFFICIENT_MEMORY);
297
298         sprintf(buf, "#%d", remain);
299         if (ptr = strchr(vptr->item.string_value, '#')) {
300                 *ptr = NULL;
301                 strcpy(newrule, vptr->item.string_value);
302                 strcat(newrule, buf);
303                 if (ptr = strchr(ptr + 1, ' '))
304                         strcat(newrule, ptr);
305         } else {
306                 if (ptr = strchr(vptr->item.string_value, ' ')) {
307                         *ptr = NULL;
308                         sprintf(newrule, "%s %s %s", vptr->item.string_value,
309                                 buf, ptr+1);
310                 } else
311                         sprintf(newrule, "%s %s", vptr->item.string_value, buf);
312         }
313
314         free (vptr->item.string_value);
315         entry->attrs[CSA_ENTRY_ATTR_RECURRENCE_RULE_I].value->item.string_value
316                 = newrule;
317
318         entry->attrs[CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I].value->\
319                 item.uint32_value = remain;
320
321         return (CSA_SUCCESS);
322 }
323
324 extern CSA_return_code
325 _DtCmsAddEndDateToRule(cms_attribute *attr, RepeatEvent *re, long time)
326 {
327         char    *newrule, *ptr;
328         char    buf[20];
329
330         if (_csa_tick_to_iso8601(time, buf))
331                 return (CSA_E_INVALID_DATE_TIME);
332
333         if ((newrule = malloc(strlen(attr->value->item.string_value)+20))
334             == NULL)
335                 return (CSA_E_INSUFFICIENT_MEMORY);
336
337         if (re->re_end_date == 0) {
338                 sprintf(newrule, "%s %s", attr->value->item.string_value, buf);
339         } else {
340                 /* end date is always at the end of the rule */
341                 strcpy(newrule, attr->value->item.string_value);
342                 ptr = strrchr(newrule, ' ');
343                 sprintf(ptr, " %s", buf);
344         }
345
346         free(attr->value->item.string_value);
347         attr->value->item.string_value = newrule;
348
349         return (CSA_SUCCESS);
350 }
351
352