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