Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / csa / entry.c
1 /* $XConsortium: entry.c /main/1 1996/04/21 19:23:10 drk $ */
2 /*
3  *  (c) Copyright 1993, 1994 Hewlett-Packard Company
4  *  (c) Copyright 1993, 1994 International Business Machines Corp.
5  *  (c) Copyright 1993, 1994 Novell, Inc.
6  *  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
7  */
8
9 /*
10  * Functions that manage the entry data structures.
11  */
12
13 #include <EUSCompat.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "appt4.h"
18 #include "attr.h"
19 #include "calendar.h"
20 #include "cmsdata.h"
21 #include "convert4-5.h"
22 #include "convert5-4.h"
23 #include "debug.h"
24 #include "entry.h"
25 #include "free.h"
26 #include "nametbl.h"
27 #include "rpccalls.h"
28 #include "iso8601.h"
29 #include "updateattrs.h"
30
31 /******************************************************************************
32  * forward declaration of static functions used within the file
33  ******************************************************************************/
34 static CSA_return_code _CmsentryToLibentry(_DtCmNameTable **tbl, cms_entry *e,
35                         _DtCm_libentry  **entry_r);
36
37 /*****************************************************************************
38  * extern functions used in the library
39  *****************************************************************************/
40
41 /*
42  * Given the entry handle, return the internal entry data structure.
43  */
44 extern _DtCm_libentry *
45 _DtCm_get_libentry(CSA_entry_handle entryhandle)
46 {
47         _DtCm_libentry *entry = (_DtCm_libentry *)entryhandle;
48
49         if (entry == NULL || entry->handle != (void *)entry)
50                 return (NULL);
51         else
52                 return(entry);
53 }
54
55 extern CSA_return_code
56 _DtCm_make_libentry(cms_entry *e, _DtCm_libentry **entry_r)
57 {
58         _DtCm_libentry  *ptr;
59         CSA_return_code stat = CSA_SUCCESS;
60
61         if (entry_r == NULL)
62                 return (CSA_E_INVALID_PARAMETER);
63
64         if ((ptr = (_DtCm_libentry *)calloc(1, sizeof(_DtCm_libentry)))
65             == NULL)
66                 return (CSA_E_INSUFFICIENT_MEMORY);
67
68         if (e == NULL) {
69                 if ((ptr->e = _DtCm_make_cms_entry(_DtCm_entry_name_tbl))
70                     == NULL)
71                         stat = CSA_E_INSUFFICIENT_MEMORY;
72         } else
73                 stat = _DtCm_copy_cms_entry(e, &ptr->e);
74
75         if (stat == CSA_SUCCESS) {
76                 ptr->handle = (void *)ptr;
77                 *entry_r = ptr;
78         } else
79                 free(ptr);
80
81         return (stat);
82 }
83
84 /*
85  * Get entry data from the server.
86  */
87 extern CSA_return_code
88 _DtCm_get_entry_detail(_DtCm_libentry *entry)
89 {
90         CSA_return_code stat = CSA_SUCCESS;
91
92         if (entry->filled == B_FALSE)
93                 return (_DtCm_rpc_lookup_entry_by_id(entry->cal, entry));
94         else
95                 return (stat);
96 }
97
98 /*
99  * return attribute names of all attributes.
100  * ** how to deal with
101  *      - predefined attributes with null values
102  *      - custom attributes
103  */
104 extern CSA_return_code
105 _DtCm_get_entry_attr_names(
106         _DtCm_libentry *entry,
107         CSA_uint32 *num_names_r,
108         char **names_r[])
109 {
110         char    **names;
111         int     i, j;
112
113         *names_r = NULL;
114         *num_names_r = 0;
115
116         if ((names = _DtCm_alloc_character_pointers(entry->e->num_attrs))
117             == NULL)
118                 return (CSA_E_INSUFFICIENT_MEMORY);
119
120         /* first element in attr array is not used */
121         for (i = 1, j = 0; i <= entry->e->num_attrs; i++) {
122                 /* there should not be any NULL names in the attr array */
123                 if (entry->e->attrs[i].value != NULL) {
124                         if ((names[j] = strdup(entry->e->attrs[i].name.name))
125                             == NULL) {
126                                 _DtCm_free(names);
127                                 return (CSA_E_INSUFFICIENT_MEMORY);
128                         } else
129                                 j++;
130                 }
131         }
132
133         *names_r = names;
134         *num_names_r = j;
135
136         return (CSA_SUCCESS);
137 }
138
139 extern CSA_return_code
140 _DtCm_get_all_entry_attrs(
141         _DtCm_libentry *entry,
142         CSA_uint32 *num_attrs,
143         CSA_attribute **attrs)
144 {
145         int             i, j;
146         CSA_return_code stat = CSA_SUCCESS;
147         CSA_attribute   *attrs_r;
148
149         if (num_attrs == NULL || attrs == NULL)
150                 return (CSA_E_INVALID_PARAMETER);
151
152         if ((attrs_r = _DtCm_alloc_attributes(entry->e->num_attrs)) == NULL)
153                 return (CSA_E_INSUFFICIENT_MEMORY);
154
155         /* first element in attr array is not used */
156         for (i = 1, j = 0; i <= entry->e->num_attrs; i++) {
157                 if (entry->e->attrs[i].value != NULL) {
158
159                         if ((stat = _DtCm_cms2csa_attribute(entry->e->attrs[i],
160                             &attrs_r[j])) != CSA_SUCCESS) {
161                                 _DtCm_free(attrs_r);
162                                 return (stat);
163                         } else
164                                 j++;
165                 }
166         }
167
168         *num_attrs = j;
169         *attrs = attrs_r;
170
171         return (CSA_SUCCESS);
172 }
173
174 /*
175  * Search the attribute list for the given attribute names.
176  * If it's not found, the attribute value
177  * is set to NULL.
178  */
179 extern CSA_return_code
180 _DtCm_get_entry_attrs_by_name(
181         _DtCm_libentry *entry,
182         CSA_uint32 num_names,
183         CSA_attribute_reference *names,
184         CSA_uint32 *num_attrs,
185         CSA_attribute **attrs)
186 {
187         int             i, j, index;
188         CSA_return_code stat = CSA_SUCCESS;
189         CSA_attribute   *attrs_r;
190
191         if (num_attrs == NULL || attrs == NULL)
192                 return (CSA_E_INVALID_PARAMETER);
193
194         if ((attrs_r = _DtCm_alloc_attributes(num_names)) == NULL)
195                 return (CSA_E_INSUFFICIENT_MEMORY);
196
197         /* get attributes */
198         for (i = 0, j = 0; i < num_names; i++) {
199                 if (names[i] != NULL) {
200                         index = _DtCm_get_index_from_table(
201                                 entry->cal->entry_tbl, names[i]);
202
203                         if (index >= 0 && entry->e->attrs[index].value) {
204                                 if (attrs_r[j].name =
205                                     strdup(entry->e->attrs[index].name.name))
206                                 {
207                                         stat = _DtCm_cms2csa_attrval(
208                                                 entry->e->attrs[index].value,
209                                                 &attrs_r[j].value);
210                                 } else
211                                         stat = CSA_E_INSUFFICIENT_MEMORY;
212
213                                 if (stat != CSA_SUCCESS) {
214                                         _DtCm_free(attrs_r);
215                                         return (stat);
216                                 } else
217                                         j++;
218                         }
219                 }
220         }
221
222         *num_attrs = j;
223         *attrs = attrs_r;
224
225         return (CSA_SUCCESS);
226 }
227
228 /*
229  * convert the linked list of entry structures to
230  * an array of entry handles.
231  */
232 extern CSA_return_code
233 _DtCm_libentry_to_entryh(
234         _DtCm_libentry *elist,
235         CSA_uint32 *size,
236         CSA_entry_handle **entries_r)
237 {
238         CSA_return_code stat = CSA_SUCCESS;
239         CSA_entry_handle        *eh;
240         _DtCm_libentry  *ptr;
241         int             i, j;
242
243         if (elist == NULL || size == NULL || entries_r == NULL)
244                 return (CSA_E_INVALID_PARAMETER);
245
246         for (i = 0, ptr = elist; ptr != NULL; ptr = ptr->next)
247                 i++;
248
249         if ((eh = _DtCm_alloc_entry_handles(i)) == NULL)
250                 return (CSA_E_INSUFFICIENT_MEMORY);
251
252         for (j = 0; j < i; j++, elist = elist->next)
253                 eh[j] = (CSA_entry_handle)elist;
254
255         *size = i;
256         *entries_r = eh;
257
258         return (CSA_SUCCESS);
259 }
260
261 extern CSA_return_code
262 _DtCmCmsentriesToLibentries(
263         _DtCmNameTable  **tbl,
264         cms_entry       *entries,
265         _DtCm_libentry  **libentries)
266 {
267         CSA_return_code stat = CSA_SUCCESS;
268         _DtCm_libentry  *entry, *head, *prev;
269
270         if (libentries == NULL)
271                 return(CSA_E_INVALID_PARAMETER);
272
273         prev = head = NULL;
274         while (entries != NULL) {
275
276                 if ((stat = _CmsentryToLibentry(tbl, entries, &entry))
277                     != CSA_SUCCESS)
278                         break;
279
280                 if (head == NULL)
281                         head = entry;
282                 else {
283                         prev->next = entry;
284                         entry->prev = prev;
285                 }
286
287                 prev = entry;
288
289                 entries = entries->next;
290         }
291
292         if (stat != CSA_SUCCESS) {
293                 _DtCm_free_libentries(head);
294                 head = NULL;
295         }
296
297         *libentries = head;
298         return(stat);
299 }
300
301 extern CSA_return_code
302 _DtCm_appt4_to_libentries(
303         char            *calname,
304         Appt_4          *appt4,
305         _DtCm_libentry  **libentries)
306 {
307         CSA_return_code stat = CSA_SUCCESS;
308         _DtCm_libentry  *entry, *head, *prev;
309
310         if (libentries == NULL)
311                 return(CSA_E_INVALID_PARAMETER);
312
313         prev = head = NULL;
314         while (appt4 != NULL) {
315
316                 if ((stat = _DtCm_make_libentry(NULL, &entry)) != CSA_SUCCESS)
317                         break;
318
319                 if ((stat = _DtCm_appt4_to_attrs(calname, appt4,
320                     entry->e->num_attrs, entry->e->attrs, B_FALSE))
321                     != CSA_SUCCESS)
322                         break;
323
324                 entry->e->key.time = appt4->appt_id.tick;
325                 entry->e->key.id = appt4->appt_id.key;
326                 entry->filled = B_TRUE;
327
328                 if (head == NULL)
329                         head = entry;
330                 else {
331                         prev->next = entry;
332                         entry->prev = prev;
333                 }
334
335                 prev = entry;
336
337                 appt4 = appt4->next;
338         }
339
340         if (stat != CSA_SUCCESS) {
341                 _DtCm_free_libentries(head);
342                 head = NULL;
343         }
344
345         *libentries = head;
346         return(stat);
347 }
348
349 extern CSA_return_code
350 _DtCm_libentries_to_appt4(_DtCm_libentry *entries, Appt_4 **appt4)
351 {
352         CSA_return_code stat = CSA_SUCCESS;
353         Appt_4          *a4, *head, *prev;
354
355         if (appt4 == NULL)
356                 return(CSA_E_INVALID_PARAMETER);
357
358         prev = head = NULL;
359         while (entries != NULL) {
360
361                 if ((stat = _DtCm_cms_entry_to_appt4(entries->e, &a4)) != CSA_SUCCESS)
362                         break;
363
364                 if (head == NULL)
365                         head = a4;
366                 else {
367                         prev->next = a4;
368                 }
369
370                 prev = a4;
371
372                 entries = entries->next;
373         }
374
375         if (stat != CSA_SUCCESS) {
376                 _DtCm_free_appt4(head);
377                 head = NULL;
378         }
379
380         *appt4 = head;
381         return(stat);
382 }
383
384 extern CSA_return_code
385 _DtCm_reminder4_to_csareminder(
386         Reminder_4 *r4,
387         CSA_uint32 *num_rems,
388         CSA_reminder_reference **rems)
389 {
390         CSA_return_code stat = CSA_SUCCESS;
391         _DtCm_libentry  *entry;
392         CSA_reminder_reference *rem_r;
393         int     i, count;
394         Reminder_4 *rptr = r4;
395         char    isotime[BUFSIZ];
396
397         if (num_rems == NULL || rems == NULL)
398                 return(CSA_E_INVALID_PARAMETER);
399
400         if (r4 == NULL) {
401                 *num_rems = 0;
402                 *rems = NULL;
403                 return (CSA_SUCCESS);
404         }
405
406         for (count = 0, rptr = r4; rptr != NULL; count++, rptr = rptr->next)
407                 ;
408
409         if ((rem_r = _DtCm_alloc_reminder_references(count)) == NULL) {
410                 return (CSA_E_INSUFFICIENT_MEMORY);
411         }
412
413         i = 0;
414         while (r4 != NULL && r4->attr.attr != NULL) {
415
416                 (void)_csa_tick_to_iso8601(r4->tick, isotime);
417                 if ((rem_r[i].run_time = strdup(isotime)) == NULL) {
418                         stat = CSA_E_INSUFFICIENT_MEMORY;
419                         break;
420                 }
421
422                 if ((rem_r[i].attribute_name = strdup(
423                     _DtCm_old_reminder_name_to_name(r4->attr.attr))) == NULL) {
424                         stat = CSA_E_INSUFFICIENT_MEMORY;
425                         break;
426                 }
427
428                 if ((stat = _DtCm_make_libentry(NULL, &entry)) == CSA_SUCCESS) {
429                         entry->e->key.id = r4->appt_id.key;
430                         entry->e->key.time = r4->appt_id.tick;
431                         rem_r[i].entry = (CSA_entry_handle)entry;
432                 } else
433                         break;
434
435                 r4 = r4->next;
436                 i++;
437         }
438
439         if (stat == CSA_SUCCESS) {
440                 *num_rems = i;
441                 *rems = rem_r;
442         } else {
443                 _DtCm_free(rem_r);
444         }
445
446         return(stat);
447 }
448
449 extern CSA_return_code
450 _DtCm_cms2csa_reminder_ref(
451         cms_reminder_ref        *cmsrems,
452         CSA_uint32              *num_rems,
453         CSA_reminder_reference  **csarems)
454 {
455         CSA_return_code         stat = CSA_SUCCESS;
456         _DtCm_libentry          *entry;
457         CSA_reminder_reference  *rem_r;
458         cms_reminder_ref        *rptr;
459         int                     i, count;
460         char                    isotime[BUFSIZ];
461         char                    *ptr;
462         CSA_opaque_data         opq;
463
464         if (num_rems == NULL || csarems == NULL)
465                 return(CSA_E_INVALID_PARAMETER);
466
467         if (cmsrems == NULL) {
468                 *num_rems = 0;
469                 *csarems = NULL;
470                 return (CSA_SUCCESS);
471         }
472
473         for (count = 0, rptr = cmsrems; rptr != NULL; rptr = rptr->next)
474                 count++;
475
476         if ((rem_r = _DtCm_alloc_reminder_references(count)) == NULL) {
477                 return (CSA_E_INSUFFICIENT_MEMORY);
478         }
479
480         i = 0;
481         while (cmsrems != NULL && stat == CSA_SUCCESS) {
482
483                 (void)_csa_tick_to_iso8601(cmsrems->runtime, isotime);
484                 if ((rem_r[i].run_time = strdup(isotime)) == NULL) {
485                         stat = CSA_E_INSUFFICIENT_MEMORY;
486                         break;
487                 }
488
489                 if ((rem_r[i].attribute_name = strdup(cmsrems->reminder_name))
490                     == NULL) {
491                         stat = CSA_E_INSUFFICIENT_MEMORY;
492                         break;
493                 }
494
495                 if ((stat = _DtCm_make_libentry(NULL, &entry)) == CSA_SUCCESS) {
496                         opq.size = strlen(cmsrems->entryid);
497                         opq.data = (unsigned char *)cmsrems->entryid;
498
499                         /* put reference id in entry */
500                         stat = _DtCm_set_opaque_attrval(&opq,
501                                 &entry->e->attrs\
502                                 [CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I].value);
503
504                         entry->e->key.id = cmsrems->key.id;
505                         entry->e->key.time = cmsrems->key.time;
506
507                         rem_r[i].entry = (CSA_entry_handle)entry;
508                 } else
509                         break;
510
511                 cmsrems = cmsrems->next;
512                 i++;
513         }
514
515         if (stat == CSA_SUCCESS) {
516                 *num_rems = i;
517                 *csarems = rem_r;
518         } else {
519                 _DtCm_free(rem_r);
520         }
521
522         return(stat);
523 }
524
525 /*
526  * This routine convert the entry to an entry structure with
527  * a header so that it can be freed with csa_free
528  * Memory occupied by the orginal entry will be destroyed.
529  */
530 extern _DtCm_libentry *
531 _DtCm_convert_entry_wheader(_DtCm_libentry *entry)
532 {
533         _DtCm_libentry *pentry;
534
535         if ((pentry = (_DtCm_libentry *)_DtCm_alloc_entry(
536             sizeof(_DtCm_libentry))) == NULL) {
537                 _DtCm_free_libentries(entry);
538                 return (NULL);
539         }
540
541         pentry->handle = (void *)pentry;
542         pentry->filled = entry->filled;
543         pentry->e = entry->e;
544
545         free(entry);
546
547         return(pentry);
548 }
549
550 /*
551  * this is invoked from csa_free indirectly
552  * to free one entry.
553  */
554 extern void
555 _DtCm_free_entry_content(uint dummy, _DtCm_libentry *entry)
556 {
557         _DtCm_remove_from_entry_list(entry->cal, (caddr_t)entry, (caddr_t)entry);
558         if (entry->e) _DtCm_free_cms_entry(entry->e);
559         memset((void *)entry, NULL, sizeof(_DtCm_libentry));
560 }
561
562 /*
563  * free a linked list of entries
564  * It is first removed from the list and then freed.
565  */
566 extern void
567 _DtCm_free_libentries_from_list(_DtCm_libentry *head, _DtCm_libentry *tail)
568 {
569         if (head == NULL || tail == NULL)
570                 return;
571
572         _DtCm_remove_from_entry_list(head->cal, (caddr_t)head, (caddr_t)tail);
573
574         _DtCm_free_libentries(head);
575 }
576
577 /*
578  * free a linked list of appointments
579  * All the memory pointed to by the entry are freed,
580  * except for the attribute array.
581  * The entry structures are returned to the free list.
582  */
583 extern void
584 _DtCm_free_libentries(_DtCm_libentry *entry)
585 {
586         _DtCm_libentry *nptr;
587
588         while (entry != NULL) {
589                 nptr = entry->next;
590
591                 if (entry->e) _DtCm_free_cms_entry(entry->e);
592                 memset((void *)entry, NULL, sizeof(_DtCm_libentry));
593
594                 free(entry);
595
596                 entry = nptr;
597         }
598 }
599
600 /*
601  * Free the reminder linked list.
602  * The entry objects pointed to by the list are freed as well.
603  */
604 extern void
605 _DtCm_free_reminder_references(uint num_rems, CSA_reminder_reference *rems)
606 {
607         CSA_reminder_reference *nptr;
608         _DtCm_libentry  *entry, *head, *cptr;
609         int i;
610
611         head = cptr = NULL;
612         for (i = 0; i < num_rems; i++) {
613
614                 entry = (_DtCm_libentry *)rems[i].entry;
615                 if (entry && entry->handle == (void *)entry) {
616                         if (head == NULL) {
617                                 head = cptr = entry;
618                         } else if (cptr->next == entry) {
619                                 cptr = cptr->next;
620                         } else {
621                                 _DtCm_free_libentries_from_list(head, cptr);
622                                 head = cptr = entry;
623                         }
624                 }
625
626                 if (rems[i].run_time)
627                         free(rems[i].run_time);
628
629                 if (rems[i].snooze_time)
630                         free(rems[i].snooze_time);
631
632                 if (rems[i].attribute_name)
633                         free(rems[i].attribute_name);
634
635         }
636
637         _DtCm_free_libentries_from_list(head, cptr);
638 }
639
640 extern void
641 _DtCm_free_entry_handles(uint num_entries, CSA_entry_handle *entries)
642 {
643         int i;
644         _DtCm_libentry *entry, *head, *cptr;
645
646         DP(("api.c: _DtCm_free_entry_handles\n"));
647
648         head = cptr = NULL;
649         for (i = 0, head = cptr = NULL; i < num_entries; i++) {
650
651                 /* in case it is a bad appointment handle */
652                 if ((entry = _DtCm_get_libentry(entries[i])) != NULL) {
653                         /*
654                          * rather than freeing one appointment at a time,
655                          * check to see if the appointments are linked to
656                          * each other and free each consecutive chunk together
657                          */
658
659                         if (head == NULL) {
660                                 head = cptr = entry;
661                         } else if (cptr->next == entry) {
662                                 cptr = cptr->next;
663                         } else {
664                                 _DtCm_free_libentries_from_list(head, cptr);
665                                 head = cptr = entry;
666                         }
667                 }
668         }
669
670         _DtCm_free_libentries_from_list(head, cptr);
671 }
672
673 /******************************************************************************
674  * static functions used within in the file
675  ******************************************************************************/
676
677 static CSA_return_code
678 _CmsentryToLibentry(
679         _DtCmNameTable  **tbl,
680         cms_entry       *e,
681         _DtCm_libentry  **entry_r)
682 {
683         _DtCm_libentry *entry;
684         CSA_return_code stat;
685
686         if ((stat = _DtCm_make_libentry(NULL, &entry)) != CSA_SUCCESS)
687                 return (stat); 
688
689         if ((stat = _DtCmUpdateAttributes(e->num_attrs, e->attrs,
690             &entry->e->num_attrs, &entry->e->attrs, tbl, B_FALSE,
691             NULL, B_FALSE)) != CSA_SUCCESS) {
692                 _DtCm_free_libentries(entry);
693         } else {
694                 entry->e->key = e->key;
695                 entry->filled = B_TRUE;
696                 *entry_r = entry;
697         }
698
699         return (stat);
700 }
701
702