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