libDtHelp: Cov 88209
[oweals/cde.git] / cde / lib / csa / calendar.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 libraries 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: calendar.c /main/1 1996/04/21 19:21:47 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 calendar data structures.
33  *****************************************************************************/
34
35 #include <EUSCompat.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <pwd.h>
40 #include "calendar.h"
41 #include "entry.h"
42 #include "cmsdata.h"
43 #include "agent_p.h"
44 #include "rpccalls.h"
45 #include "debug.h"
46 #include "attr.h"
47 #include "xtclient.h"
48 #include "misc.h"
49 #include "free.h"
50 #include "nametbl.h"
51 #include "lutil.h"
52
53 /* linked list of calendar structure representing opened calendars */
54 Calendar *_DtCm_active_cal_list = NULL;
55
56 /******************************************************************************
57  * forward declaration of static functions used within the file
58  ******************************************************************************/
59 static CSA_return_code _get_owner_from_old_cal(Calendar *cal, char *buf);
60 static CSA_return_code _get_calendar_owner(Calendar *cal, uint num_names,
61                                         char **names, CSA_attribute *attr);
62 static CSA_return_code _get_calendar_name(Calendar *cal, CSA_attribute *attr);
63 static CSA_return_code _get_product_identifier(Calendar *cal,
64                                                 CSA_attribute *attr);
65 static CSA_return_code _get_version_supported(Calendar *cal,
66                                                 CSA_attribute *attr);
67 static CSA_return_code _get_server_version(Calendar *cal, CSA_attribute *attr);
68 static CSA_return_code _get_data_version(Calendar *cal, CSA_attribute *attr);
69 static CSA_return_code _get_access_list(Calendar *cal, uint num_names,
70                                         char ** names, CSA_attribute *attr);
71 static CSA_return_code _get_number_entries(Calendar *cal, uint num_names,
72                                         char ** names, CSA_attribute *attr);
73
74 /*****************************************************************************
75  * extern functions used in the library
76  *****************************************************************************/
77
78 /*
79  * Allocate a calendar structure and initialize it with
80  * the location, and name of the calendar.
81  */
82 extern Calendar *
83 _DtCm_new_Calendar(const char *calendar)
84 {
85         Calendar        *cal;
86         int i;
87
88         _DtCm_init_hash();
89
90         if ((cal = (Calendar *)malloc(sizeof(Calendar))) == NULL)
91                 return(NULL);
92
93         memset((void *)cal, 0, sizeof(Calendar));
94
95         if ((cal->name = strdup(calendar)) == NULL) {
96                 free(cal);
97                 return(NULL);
98         }
99
100         cal->location = strchr(cal->name, '@');
101         cal->location++;
102
103         /* set up attribute array */
104         if ((cal->attrs = (cms_attribute *)calloc(1,
105             sizeof(cms_attribute) * (_DtCm_cal_name_tbl->size + 1))) == NULL) {
106                 free(cal->name);
107                 free(cal);
108                 return(NULL);
109         }
110
111         for (i = 1; i <= _DtCm_cal_name_tbl->size; i++) {
112                 if ((cal->attrs[i].name.name =
113                     strdup(_DtCm_cal_name_tbl->names[i])) == NULL) {
114                         /* clean up */
115                         cal->num_attrs = i - 1;
116                         _DtCm_free_Calendar(cal);
117                         return(NULL);
118                 } else
119                         cal->attrs[i].name.num = i;
120         }
121         cal->num_attrs = _DtCm_cal_name_tbl->size;
122
123         if (_DtCm_active_cal_list == NULL) {
124                 _DtCm_active_cal_list = cal;
125                 cal->next = NULL;
126                 cal->prev = NULL;
127         }
128         else {
129                 cal->next = _DtCm_active_cal_list;
130                 _DtCm_active_cal_list->prev = cal;
131                 _DtCm_active_cal_list = cal;
132         }
133
134         cal->cal_tbl = _DtCm_cal_name_tbl;
135         cal->entry_tbl = _DtCm_entry_name_tbl;
136
137         cal->handle = (void *)cal;
138
139         return(cal);
140 }
141
142 /*
143  * After freeing up memory pointed to by cal,
144  * put it in the free list.
145  */
146 extern void
147 _DtCm_free_Calendar(Calendar *cal)
148 {
149         _DtCmCallbackEntry      *cb, *ptr;
150
151         /* remove from active list */
152         if (_DtCm_active_cal_list == cal)
153                 _DtCm_active_cal_list = cal->next;
154
155         if (cal->prev != NULL)
156                 cal->prev->next = cal->next;
157
158         if (cal->next != NULL)
159                 cal->next->prev = cal->prev;
160
161         /* free up resources used by it */
162         if (cal->name) free(cal->name);
163         if (cal->ehead) _DtCm_free_libentries((_DtCm_libentry *)cal->ehead);
164
165         if (cal->cal_tbl != _DtCm_cal_name_tbl)
166                 _DtCm_free_name_table(cal->cal_tbl);
167
168         if (cal->entry_tbl != _DtCm_entry_name_tbl)
169                 _DtCm_free_name_table(cal->entry_tbl);
170
171         cb = cal->cb_list;
172         while (cb) {
173                 ptr = cb->next;
174                 free(cb);
175                 cb = ptr;
176         }
177
178         /*
179          * no need to free attribute values now
180          * since the values are passed to client
181          * directly.
182          * need to free attribute values if they
183          * are cached later
184          */
185         _DtCm_free_cms_attribute_values(cal->num_attrs, cal->attrs);
186         free(cal->attrs);
187
188         memset((void *)cal, '\0', sizeof(Calendar));
189
190         /* if no calendar is open, destroy rpc mapping */
191         if (_DtCm_active_cal_list == NULL)
192                 _DtCm_destroy_agent();
193 }
194
195 /*
196  * Given the calendar handle, return the internal calendar data structure.
197  */
198 extern Calendar *
199 _DtCm_get_Calendar(CSA_session_handle calhandle)
200 {
201         Calendar *cal = (Calendar *)calhandle;
202
203         if (cal == NULL || cal->handle != (void *)cal)
204                 return (NULL);
205         else
206                 return ((Calendar *)calhandle);
207 }
208
209 /*
210  * Add linked list of entry data structures to the calendar.
211  */
212 extern uint
213 _DtCm_add_to_entry_list(Calendar *cal, caddr_t elist)
214 {
215         int i;
216         _DtCm_libentry *entries = (_DtCm_libentry *)elist;
217
218         if (entries == NULL)
219                 return (0);
220
221         if (cal->ehead == NULL)
222                 cal->ehead = elist;
223         else {
224                 ((_DtCm_libentry *)cal->etail)->next = entries;
225                 entries->prev = (_DtCm_libentry *)cal->etail;
226         }
227
228         /* find tail of given entry list */
229         i = 1;
230         entries->cal = cal;
231         while (entries->next != NULL) {
232                 i++;
233                 entries->next->cal = cal;
234                 entries = entries->next;
235         }
236
237         cal->etail = (caddr_t)entries;
238
239 #ifdef CM_DEBUG
240         _DtCm_count_entry_in_list(cal->ehead);
241 #endif
242
243         return (i);
244 }
245
246 extern void
247 _DtCm_remove_from_entry_list(
248         Calendar *cal,
249         caddr_t head,
250         caddr_t tail)
251 {
252         _DtCm_libentry *ehead = (_DtCm_libentry *)head;
253         _DtCm_libentry *etail = (_DtCm_libentry *)tail;
254
255         if (ehead == NULL || tail == NULL)
256                 return;
257
258         if (ehead == (_DtCm_libentry *)cal->ehead)
259                 cal->ehead = (caddr_t)etail->next;
260
261         if (etail == (_DtCm_libentry *)cal->etail)
262                 cal->etail = (caddr_t)ehead->prev;
263
264         /* remove from list */
265         if (ehead->prev != NULL)
266                 ehead->prev->next = etail->next;
267
268         if (etail->next != NULL)
269                 etail->next->prev = ehead->prev;
270
271         etail->next = ehead->prev = NULL;
272
273 #ifdef CM_DEBUG
274         _DtCm_count_entry_in_list(cal->ehead);
275 #endif
276 }
277
278 extern void
279 _DtCm_reset_cal_attrs(Calendar *cal)
280 {
281         cal->got_attrs = B_FALSE;
282 }
283
284 /*
285  * Assume good parameters.  Caller should check before calling this.
286  */
287 extern CSA_return_code
288 _DtCm_list_old_cal_attr_names(
289         Calendar *cal,
290         CSA_uint32 *num_names_r,
291         char **names_r[])
292 {
293         CSA_return_code stat;
294         char            **names, buf[BUFSIZ];
295         int             i, j;
296
297         if ((names = _DtCm_alloc_character_pointers(_DtCM_OLD_CAL_ATTR_SIZE))
298             == NULL)
299                 return (CSA_E_INSUFFICIENT_MEMORY);
300
301         /* find out whether we know the owner of the calendar */
302         if ((stat = _get_owner_from_old_cal(cal, buf)) != CSA_SUCCESS) {
303                 _DtCm_free(names);
304                 return (stat);
305         }
306
307         for (i = 1, j = 0; i <= _DtCM_DEFINED_CAL_ATTR_SIZE; i++) {
308                 if (_CSA_cal_attr_info[i].fst_vers > 0 &&
309                     _CSA_cal_attr_info[i].fst_vers <= cal->file_version) {
310                         if (i == CSA_CAL_ATTR_CALENDAR_OWNER_I && *buf == '\0')
311                                 continue;
312
313                         if ((names[j] =
314                             strdup(_CSA_calendar_attribute_names[i])) == NULL)
315                         {
316                                 _DtCm_free(names);
317                                 return (CSA_E_INSUFFICIENT_MEMORY);
318                         } else
319                                 j++;
320                 }
321         }
322
323         *names_r = names;
324         *num_names_r = j;
325
326         return (CSA_SUCCESS);
327 }
328
329 extern CSA_return_code
330 _DtCm_get_all_cal_attrs(
331         Calendar *cal,
332         CSA_uint32 *num_attrs,
333         CSA_attribute **attrs)
334 {
335         CSA_return_code stat;
336         int             i, j;
337         CSA_attribute   *attrs_r;
338
339         if (num_attrs == NULL || attrs == NULL)
340                 return (CSA_E_INVALID_PARAMETER);
341
342         if (cal->rpc_version >= _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION) {
343                 if ((stat = _DtCm_rpc_get_cal_attrs(cal, 0, 0, NULL))
344                     != CSA_SUCCESS)
345                         return (stat);
346
347                 if ((attrs_r = _DtCm_alloc_attributes(cal->num_attrs)) == NULL)
348                         return (CSA_E_INSUFFICIENT_MEMORY);
349
350                 /* get attributes */
351                 for (i = 1, j = 0; i <= cal->num_attrs; i++) {
352                         if (cal->attrs[i].value != NULL) {
353
354                                 if ((stat = _DtCm_cms2csa_attribute(
355                                     cal->attrs[i], &attrs_r[j])) != CSA_SUCCESS)
356                                 {
357                                         _DtCm_free(attrs_r);
358                                         return (stat);
359                                 } else
360                                         j++;
361                         }
362                 }
363
364                 *num_attrs = j;
365                 *attrs = attrs_r;
366
367                 return (CSA_SUCCESS);
368         } else
369                 return (_DtCm_get_cal_attrs_by_name(cal,
370                         _DtCM_DEFINED_CAL_ATTR_SIZE + 1,
371                         _CSA_calendar_attribute_names, num_attrs, attrs));
372 }
373
374 /*
375  * If it's not found, the attribute value is set to NULL.
376  */
377 extern CSA_return_code
378 _DtCm_get_cal_attrs_by_name(
379         Calendar *cal,
380         CSA_uint32      num_names,
381         CSA_attribute_reference *names,
382         CSA_uint32      *num_attrs,
383         CSA_attribute **attrs)
384 {
385         CSA_return_code stat = CSA_SUCCESS;
386         CSA_attribute *attrs_r;
387         int i, j, index;
388
389         if (num_attrs == 0 || attrs == NULL)
390                 return (CSA_E_INVALID_PARAMETER);
391
392
393         if ((attrs_r = _DtCm_alloc_attributes(num_names)) == NULL)
394                 return (CSA_E_INSUFFICIENT_MEMORY);
395
396         for (i = 0, j = 0; i < num_names; i++) {
397                 if (names[i] == NULL)
398                         continue;
399
400                 index = _DtCm_get_index_from_table(cal->cal_tbl, names[i]);
401
402                 switch (index) {
403                 case CSA_X_DT_CAL_ATTR_SERVER_VERSION_I:
404
405                         stat = _get_server_version(cal, &attrs_r[j]);
406                         break;
407
408                 case CSA_X_DT_CAL_ATTR_DATA_VERSION_I:
409
410                         stat = _get_data_version(cal, &attrs_r[j]);
411                         break;
412
413                 case CSA_CAL_ATTR_ACCESS_LIST_I:
414
415                         stat = _get_access_list(cal, num_names, names,
416                                 &attrs_r[j]);
417                         break;
418
419                 case CSA_CAL_ATTR_NUMBER_ENTRIES_I:
420
421                         stat = _get_number_entries(cal, num_names,
422                                 names, &attrs_r[j]);
423                         break;
424
425                 case CSA_CAL_ATTR_CALENDAR_NAME_I:
426
427                         stat = _get_calendar_name(cal, &attrs_r[j]);
428                         break;
429
430                 case CSA_CAL_ATTR_CALENDAR_OWNER_I:
431
432                         stat = _get_calendar_owner(cal, num_names, names,
433                                 &attrs_r[j]);
434                         break;
435
436                 case CSA_CAL_ATTR_PRODUCT_IDENTIFIER_I:
437
438                         stat = _get_product_identifier(cal, &attrs_r[j]);
439                         break;
440
441                 case CSA_CAL_ATTR_VERSION_I:
442
443                         stat = _get_version_supported(cal, &attrs_r[j]);
444                         break;
445
446                 default:
447                         if (cal->rpc_version >=
448                             _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION)
449                         {
450                                 if (cal->file_version <
451                                     _DtCM_FIRST_EXTENSIBLE_DATA_VERSION &&
452                                     index == -1)
453                                         break;
454
455                                 if (cal->got_attrs == B_FALSE &&
456                                     (stat = _DtCm_rpc_get_cal_attrs(cal, 0,
457                                     num_names, names)) == CSA_SUCCESS) {
458                                         /* there might by new attributes */
459                                         if (index == -1 &&
460                                             (index = _DtCm_get_index_from_table(
461                                             cal->cal_tbl, names[i])) == -1)
462                                                 break;
463                                 }
464
465                                 if (stat == CSA_SUCCESS &&
466                                     cal->attrs[index].value)
467                                         stat = _DtCm_cms2csa_attribute(
468                                                 cal->attrs[index], &attrs_r[j]);
469                         }
470                         break;
471                 }
472
473                 if (stat == CSA_SUCCESS) {
474                         if (attrs_r[j].value != NULL)
475                                 j++;
476                 } else {
477                         _DtCm_free(attrs_r);
478                         return (stat);
479                 }
480         }
481
482         *num_attrs = j;
483
484         if (j > 0) {
485                 *attrs = attrs_r;
486         } else {
487                 *attrs = NULL;
488                 _DtCm_free(attrs_r);
489         }
490
491         return (CSA_SUCCESS);
492 }
493
494 /*
495  * Debugging function - count the number of entries in the list and print it out
496  */
497 extern void
498 _DtCm_count_entry_in_list(caddr_t elist)
499 {
500         int i;
501         _DtCm_libentry *list;
502
503         for (i = 0, list = (_DtCm_libentry *)elist;
504             list != NULL;
505             i++, list = list->next)
506                 ;
507
508         fprintf(stderr, "number of entries = %d\n", i);
509 }
510
511 /******************************************************************************
512  * static functions used within in the file
513  ******************************************************************************/
514
515 /*
516  * owner should point to a buffer big enough to hold the owner name
517  * We test whether the calendar name is a user name, if so, the
518  * owner will be the same as the calendar name.
519  * Otherwise, we don't know the owner.
520  */
521 static CSA_return_code
522 _get_owner_from_old_cal(Calendar *cal, char *owner)
523 {
524         char            *calname;
525
526         if ((calname = _DtCmGetPrefix(cal->name, '@')) == NULL)
527                 return (CSA_E_INSUFFICIENT_MEMORY);
528
529         if (_DtCmIsUserName(calname) == B_TRUE)
530                 strcpy(owner, calname);
531         else
532                 *owner = '\0';
533
534         free(calname);
535         return (CSA_SUCCESS);
536 }
537
538 static CSA_return_code
539 _get_calendar_owner(
540         Calendar        *cal,
541         uint            num_names,
542         char            **names,
543         CSA_attribute   *attr)
544 {
545         CSA_return_code         stat;
546         CSA_attribute_value     *val;
547         char                    *owner, buf[BUFSIZ];
548
549         if (cal->rpc_version >= _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION) {
550                 if (cal->got_attrs == B_FALSE) {
551                         if ((stat = _DtCm_rpc_get_cal_attrs(cal, 0, num_names,
552                             names)) != CSA_SUCCESS)
553                                 return (stat);
554                 }
555                 owner = cal->attrs[CSA_CAL_ATTR_CALENDAR_OWNER_I].value->\
556                         item.string_value;
557         } else {
558                 if ((stat = _get_owner_from_old_cal(cal, buf)) != CSA_SUCCESS)
559                         return (stat);
560                 else if (*buf == '\0')
561                         return (CSA_SUCCESS);
562                 else
563                         owner = buf;
564         }
565
566         if (attr->name = strdup(CSA_CAL_ATTR_CALENDAR_OWNER)) {
567                 if ((val = (CSA_attribute_value *)calloc(1,
568                     sizeof(CSA_attribute_value))) == NULL) {
569                         free(attr->name);
570                         return (CSA_E_INSUFFICIENT_MEMORY);
571                 }
572
573                 val->type = CSA_VALUE_CALENDAR_USER;
574
575                 if ((val->item.calendar_user_value = (CSA_calendar_user *)
576                     calloc(1, sizeof(CSA_calendar_user))) == NULL) {
577                         free(val);
578                         free(attr->name);
579                         return (CSA_E_INSUFFICIENT_MEMORY);
580                 }
581
582                 if (val->item.calendar_user_value->user_name = strdup(owner)) {
583                         attr->value = val;
584                         return (CSA_SUCCESS);
585                 } else {
586                         free(val->item.calendar_user_value);
587                         free(val);
588                         free(attr->name);
589                         return (CSA_E_INSUFFICIENT_MEMORY);
590                 }
591         } else
592                 return (CSA_E_INSUFFICIENT_MEMORY);
593 }
594
595 static CSA_return_code
596 _get_calendar_name(Calendar *cal, CSA_attribute *attr)
597 {
598         if (attr->name = strdup(CSA_CAL_ATTR_CALENDAR_NAME))
599                 return (_DtCm_set_csa_string_attrval(cal->name, &attr->value,
600                         CSA_VALUE_STRING));
601         else
602                 return (CSA_E_INSUFFICIENT_MEMORY);
603 }
604
605 static CSA_return_code
606 _get_product_identifier(Calendar *cal, CSA_attribute *attr)
607 {
608         if (attr->name = strdup(CSA_CAL_ATTR_PRODUCT_IDENTIFIER))
609                 return (_DtCm_set_csa_string_attrval(_DtCM_PRODUCT_IDENTIFIER,
610                         &attr->value, CSA_VALUE_STRING));
611         else
612                 return (CSA_E_INSUFFICIENT_MEMORY);
613 }
614
615 static CSA_return_code
616 _get_version_supported(Calendar *cal, CSA_attribute *attr)
617 {
618         if (attr->name = strdup(CSA_CAL_ATTR_VERSION))
619                 return (_DtCm_set_csa_string_attrval(
620                         _DtCM_SPEC_VERSION_SUPPORTED, &attr->value,
621                         CSA_VALUE_STRING));
622         else
623                 return (CSA_E_INSUFFICIENT_MEMORY);
624 }
625
626 static CSA_return_code
627 _get_server_version(Calendar *cal, CSA_attribute *attr)
628 {
629         if (attr->name = strdup(CSA_X_DT_CAL_ATTR_SERVER_VERSION))
630                 return (_DtCm_set_csa_uint32_attrval(cal->rpc_version,
631                         &attr->value));
632         else
633                 return (CSA_E_INSUFFICIENT_MEMORY);
634 }
635
636 static CSA_return_code
637 _get_data_version(Calendar *cal, CSA_attribute *attr)
638 {
639         if (attr->name = strdup(CSA_X_DT_CAL_ATTR_DATA_VERSION))
640                 return (_DtCm_set_csa_uint32_attrval(cal->file_version,
641                         &attr->value));
642         else
643                 return (CSA_E_INSUFFICIENT_MEMORY);
644 }
645
646 static CSA_return_code
647 _get_access_list(
648         Calendar        *cal,
649         uint            num_names,
650         char            **names,
651         CSA_attribute   *attr)
652 {
653         CSA_return_code stat = CSA_SUCCESS;
654
655         if (cal->rpc_version < _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION)
656                 stat = _DtCm_rpc_get_cal_attrs(cal, CSA_CAL_ATTR_ACCESS_LIST_I,
657                         0, NULL);
658         else if (cal->got_attrs == B_FALSE)
659                 stat = _DtCm_rpc_get_cal_attrs(cal, 0, num_names, names);
660
661         if (stat == CSA_SUCCESS)
662                 stat = _DtCm_cms2csa_attribute(
663                         cal->attrs[CSA_CAL_ATTR_ACCESS_LIST_I], attr);
664
665         return (stat);
666 }
667
668 static CSA_return_code
669 _get_number_entries(
670         Calendar        *cal,
671         uint            num_names,
672         char            **names,
673         CSA_attribute   *attr)
674 {
675         CSA_return_code stat = CSA_SUCCESS;
676
677         if (cal->rpc_version < _DtCM_FIRST_EXTENSIBLE_SERVER_VERSION)
678                 stat = _DtCm_rpc_get_cal_attrs(cal,
679                         CSA_CAL_ATTR_NUMBER_ENTRIES_I, 0, NULL);
680         else if (cal->got_attrs == B_FALSE)
681                 stat = _DtCm_rpc_get_cal_attrs(cal, 0, num_names, names);
682
683         if (stat == CSA_SUCCESS)
684                 stat = _DtCm_cms2csa_attribute(
685                         cal->attrs[CSA_CAL_ATTR_NUMBER_ENTRIES_I], attr);
686
687         return (stat);
688 }
689