dtcm: Resolve CID 87822
[oweals/cde.git] / cde / programs / dtcm / server / parser.y
1 /* $XConsortium: parser.y /main/6 1996/11/11 11:50:41 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 %{
11 #include <EUSCompat.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #if (defined(sun) && defined(_XOPEN_SOURCE)) || defined(linux)
16 #include <time.h>
17 #endif
18 #include "csa.h"
19 #include "rtable4.h"
20 #include "cm.h"
21 #include "lexer.h"
22 #include "cmscalendar.h"
23 #include "appt4.h"
24 #include "cmsdata.h"
25 #include "attr.h"
26 #include "v4ops.h"
27 #include "v5ops.h"
28 #include "delete.h"
29 #include "log.h"
30 #include "iso8601.h"
31
32 extern char *pgname;
33 extern _DtCmsCalendar *currentCalendar;
34 extern int yylineno;
35 extern void yyerror(char*);
36 extern void report_err(char*);
37 extern char *str_to_cr(char*);
38 extern time_t convert_2_tick(char *);
39
40 typedef struct {
41         int     total;
42         int     current;
43         cms_attribute *attrs;
44 } _attr_array;
45
46 static int              currentVersion;
47 static _attr_array      currentAttrs;
48
49
50 /*****************************************************************************
51  * forward declaration of static functions used within the file
52  *****************************************************************************/
53 static void add_hashed_attr_to_array(_attr_array *attrs, int num, char *value);
54 static void add_to_attr_array(_attr_array *attrs, char *name,
55                 char *tag, char *value);
56 static void grow_attr_array(_attr_array *attrs);
57 static CSA_enum get_tag_from_string(char *tagstr);
58 static CSA_return_code get_attr_value(int type, char *valstr,
59                 cms_attribute_value **attrval);
60 static CSA_return_code get_access_list_value(char *valstr,
61                 cms_attribute_value **attrval);
62 static CSA_return_code get_user_access_entry(char *string,
63                 cms_access_entry **a);
64 static CSA_return_code get_date_time_list_value(char *valstr,
65                 cms_attribute_value **attrval);
66 static int extend_entry_table(int hashednum, char *name, char *typestr);
67
68 %}
69
70 %start calendar
71
72 %union  {
73         int number;
74         char *s;
75         Interval_4 periodVal;
76         Appt_4 *appointment;
77         Attribute_4 *attributelist_4;
78         Except_4 *exceptionlist;
79         Access_Entry_4 *accesslist;
80         Event_Type_4 tagsVal;
81         Tag_4 *taglist;
82         Appt_Status_4 apptstatVal;
83         Privacy_Level_4 privacyVal;
84         void *entry;
85         }
86
87 %token VERSION COLON NUMBER QUOTEDSTRING DETAILS DURATION PERIODVAL NTIMES COMMA
88 %token OPENPAREN CLOSEPAREN WHAT REMOVE ADD ADDENTRY PERIOD EXCEPTION MAILTO NTH ENDDATE
89 %token AUTHOR ATTRIBUTES_4 ACCESS DENY PRIVACY PRIVACYENUM
90 %token KEY READ WRITE DELETE EXEC CONNECT BROWSE INSERT UPDATE
91 %token TAGS TAGSVAL
92 %token APPTSTATUS APPTSTATUSVAL
93 %token PRIVACYLEVEL PRIVACYVAL
94 %token ATTRIBUTES_5 CALATTRS
95 %token HASHEDATTRS TABLE
96
97 %type <s> quotedString what details mailto author
98 %type <number> number tick key ntimes duration accesstype nth enddate
99 %type <entry> appointmentBody 
100 %type <attributelist_4> attributes_4 attributelist_4 attributeitem_4
101 %type <periodVal> period 
102 %type <exceptionlist> exceptions exceptionlist exceptitem
103 %type <accesslist> accesses accesslist accessitem
104 %type <taglist> tags taglist tagitem 
105 %type <apptstatVal> apptstat
106 %type <privacyVal> privacy
107
108 %% /* Begining of rules section */
109
110 calendar        : versionStamp eventlist
111                 | versionStamp
112                 ;
113
114 versionStamp    : VERSION COLON number
115                         {
116                                 if ($3 > _DtCMS_VERSION4) { 
117                                         report_err("Unable to read callog file, unsupported version\n");
118                                         return -1;
119                                 } else {
120                                         currentVersion = $3;
121                                         if (_DtCmsSetFileVersion(
122                                             currentCalendar, $3))
123                                                 return -1;
124                                 }
125                         }
126                 | error OPENPAREN
127                         {
128                                 yyerror("Error reading callog file");
129                                 return -1;
130                         }
131                 ;
132
133 number          : NUMBER
134                         {
135                                 $$ = externNumberVal;
136                         }
137                 ;
138
139 eventlist       : event
140                 | eventlist event
141                 ;
142
143 event           : name_type_table
144                 | add 
145                 | remove 
146                 | access
147                 | calendar_attrs
148                 ;
149
150 add             : OPENPAREN ADD appointmentBody CLOSEPAREN
151                         {
152                                 if (currentVersion == _DtCMS_VERSION1) {
153                                         if (_DtCmsInsertAppt(currentCalendar,
154                                             (Appt_4 *)$3) != CSA_SUCCESS) {
155                                                 _DtCm_free_appt4((Appt_4 *)$3);
156
157                                                 fprintf(stderr,
158                                                         "Failed to insert appt at line %d\n",
159                                                         yylineno);
160                                                 return (-1);
161                                         }
162                                 } else {
163                                         if (_DtCmsInsertEntry4Parser(
164                                             currentCalendar, (cms_entry *)$3)
165                                             != CSA_SUCCESS) {
166
167                                                 fprintf(stderr, "Failed to insert entry at line %d\n",
168                                                         yylineno);
169                                                 return (-1);
170                                         }
171                                         _DtCm_free_cms_attributes(
172                                                 ((cms_entry *)$3)->num_attrs,
173                                                 ((cms_entry *)$3)->attrs);
174                                         free($3);
175                                 }
176                         }
177                 ;
178
179 remove          : OPENPAREN REMOVE tick key CLOSEPAREN
180                         {
181                                 Appt_4 *appt4;
182                                 Id_4 key;
183                                 cms_key ckey;
184
185                                 if (currentVersion == _DtCMS_VERSION1) {
186                                         key.tick = $3;
187                                         key.key = $4;
188                                         _DtCmsDeleteAppt(currentCalendar,
189                                                 NULL, 0, &key, &appt4);
190                                         if (appt4)
191                                                 _DtCm_free_appt4(appt4);
192                                 } else {
193                                         ckey.time = $3;
194                                         ckey.id = $4;
195                                         _DtCmsDeleteEntry(currentCalendar, NULL,
196                                                 0, &ckey, NULL);
197                                 }
198                         }
199                 ;
200
201 access          : OPENPAREN ACCESS accesstype accesses CLOSEPAREN
202                         {
203                                 _DtCmsSetAccess4Parser(currentCalendar, $4, $3);
204                         }
205                 ;
206
207 calendar_attrs: OPENPAREN CALATTRS attributelist_5 CLOSEPAREN
208                         {
209                                 _DtCmsSetCalendarAttrs4Parser(currentCalendar,
210                                         currentAttrs.current,
211                                         currentAttrs.attrs);
212
213                                 _DtCm_free_cms_attributes(currentAttrs.current,
214                                         currentAttrs.attrs);
215                                 currentAttrs.total = 0;
216                                 currentAttrs.current = 0;
217                                 currentAttrs.attrs = NULL;
218                         }
219                 ;
220
221 /*
222  * The attribute name and type hash table, each item contains
223  * the hash number for the corresponding attribute, the attribute name,
224  * and the value type of the attribute.
225  */
226 name_type_table : OPENPAREN TABLE name_type_list CLOSEPAREN
227                         {
228                                 currentCalendar->hashed = B_TRUE;
229                         }
230                 ;
231
232 name_type_list  : name_type_item
233                 | name_type_item name_type_list
234                 ;
235
236 name_type_item  : OPENPAREN number quotedString quotedString CLOSEPAREN
237                         {
238                                 if (extend_entry_table($2, $3, $4)) {
239                                         fprintf(stderr, "Failed to parse entry table at line # %d\n",
240                                                 yylineno);
241                                         return (-1);
242                                 }
243                         }
244                 ;
245
246 /*                1     2   3   4       5        6      7       8       9  10
247         11   12         13       14     15      16      17
248 */
249 appointmentBody : tick key what details duration period nth enddate ntimes exceptions mailto author attributes_4 tags apptstat privacy attributes_5 hashedattrs
250                         {
251                                 char *temp=NULL;
252                                 Attr_4 item;
253                                 Appt_4 *newp;
254                                 cms_entry *newe;
255                                 void    *aptr;
256
257                                 if (currentVersion == _DtCMS_VERSION1) {
258                                         newp = _DtCm_make_appt4(B_TRUE);
259                                         newp->appt_id.tick = $1;
260                                         newp->appt_id.key = $2;
261                                         newp->what = $3;
262                                         newp->client_data = $4;
263                                         newp->duration = $5;
264                                         newp->period.period = $6;
265                                         newp->period.nth = $7;
266                                         newp->period.enddate = $8;
267                                         newp->ntimes = $9;
268                                         newp->exception = $10;  
269
270                                         temp = $11;
271
272                                         newp->author = $12;
273                                         newp->attr = $13;
274
275                                         if (temp != NULL && (*temp)!='\0') {
276                                                 item = newp->attr;
277                                                 while(item!=NULL) {
278                                                         if(strcmp(item->attr, "ml")==0) {
279                                                                 item->clientdata= temp;
280                                                                 break;
281                                                         }
282                                                         item = item->next;
283                                                 }
284                                         }
285
286                                         newp->tag = $14;
287                                         newp->appt_status = $15;
288                                         newp->privacy = $16;
289                                         newp->next=NULL;
290                                         aptr = (void *)newp;
291                                 } else {
292                                         newe = (cms_entry *)calloc(1,
293                                                 sizeof(cms_entry));
294                                         newe->key.time = $1;
295                                         newe->key.id = $2;
296                                         newe->num_attrs = currentAttrs.current;
297                                         newe->attrs = currentAttrs.attrs;
298                                         currentAttrs.total = 0;
299                                         currentAttrs.current = 0;
300                                         currentAttrs.attrs = NULL;
301                                         aptr = (void *)newe;
302                                 }
303
304                                 $$ = aptr;
305                         }
306                 ;
307
308 tick            : /* empty */
309                         {
310                                 $$ = 0;
311                         }
312                 | quotedString 
313                         {
314                                 time_t  time;
315
316                                 if (strlen($1) == 24)
317                                         $$ = convert_2_tick($1);
318                                 else {
319                                         _csa_iso8601_to_tick($1, &time);
320                                         $$ = time;
321                                 }
322                                         
323                         }
324                 ;
325
326 quotedString    : QUOTEDSTRING
327                         {
328                                 $$ = externQuotedString;
329                         }
330                 ;
331
332 key             : /* empty */
333                         {
334                                 $$ = 0;
335                         }
336                 | KEY COLON number
337                         {
338                                 $$ = $3;
339                         }
340                 ;
341
342 what            : /* empty */
343                         {
344                                 $$ = strdup("");
345                         }
346                 | WHAT COLON quotedString
347                         {
348                                 $$ = str_to_cr($3);
349                                 free($3);
350                         }
351                 ;
352                                 
353 details         : /* empty */
354                         {
355                                 $$ = "";
356                         }
357                 | DETAILS COLON quotedString
358                         {
359                                 $$ = $3;
360                         }
361                 ;
362
363 mailto          : /* empty */
364                         {
365                                 $$ = "";
366                         }
367                 | MAILTO COLON quotedString
368                         {
369                                 $$ = $3;
370                         }
371                 ;
372
373 duration        : /* empty */
374                         {
375                                 $$ = '\0';
376                         }
377                 | DURATION COLON number
378                         {
379                                 $$ = $3;
380                         }
381                 ;
382
383 period          : /* empty */
384                         {
385                                 $$ = single_4;
386                         }
387                 | PERIOD COLON PERIODVAL
388                         {
389                                 $$ = externPeriod.period;
390                         }
391                 ;
392
393 nth             : /* empty */
394                         {
395                                 $$ = 0;
396                         }
397                 | NTH COLON number
398                         {
399                                 $$ = $3;
400                         }
401                 ;
402
403 enddate         : /* empty */
404                         {
405                                 $$ = 0;
406                         }
407                 | ENDDATE COLON quotedString
408                         {
409                                 $$ = convert_2_tick($3);
410                                 free($3);
411                         }
412                 ;
413                                 
414 privacy         : /* empty */
415                         {
416                                 $$ = public_4;
417                         }
418                 | PRIVACY COLON PRIVACYVAL
419                         {
420                                 $$ = externPrivacy;
421                         }
422                 ;
423
424 apptstat        : /* empty */
425                         {
426                                 $$ = active_4;
427                         }
428                 | APPTSTATUS COLON APPTSTATUSVAL
429                         {
430                                 $$ = externApptStatus;
431                         }
432                 ;
433
434 ntimes          : /* empty */
435                         {
436                                 $$ = 0;
437                         }
438                 | NTIMES COLON number
439                         {
440                                 $$ = $3;
441                         }
442                 ;
443
444 author          : /* empty */
445                         {
446                                 $$ = "";
447                         }
448                 | AUTHOR COLON quotedString
449                         {
450                                 $$ = $3;
451                         }
452                 ;
453
454 accesstype      : READ
455                         {
456                                 $$ = access_read_4;
457                         }
458                 | WRITE
459                         {
460                                 $$ = access_write_4;
461                         }
462                 | DELETE
463                         {
464                                 $$ = access_delete_4;
465                         }
466                 | EXEC
467                         {
468                                 $$ = access_exec_4;
469                         }
470                 ;
471
472 accesses        : /* empty */
473                         {
474                                 $$ = NULL;
475                         }
476                 | accesslist
477                         {
478                                 $$ = $1;
479                         }
480                 ;
481
482 accesslist      : accessitem
483                         {
484                                 $$ = $1;
485                         }
486
487                 | accessitem accesslist
488                         {
489                                 Access_Entry_4 *e = $1;
490                                 e->next = $2;
491                                 $$ = e;
492                         }
493                 ;
494
495 accessitem      : quotedString 
496                         {
497                                 Access_Entry_4 *e =
498                                         (Access_Entry_4 *)malloc(
499                                                 sizeof(Access_Entry_4));
500                                 e->who = $1;
501                                 e->next = (Access_Entry_4 *)NULL;
502                                 $$ = e;
503                         }
504                 ;
505
506 hashedattrs     : /* empty */
507                 | HASHEDATTRS COLON OPENPAREN hashedattrlist CLOSEPAREN
508                 ;
509
510 hashedattrlist : hashedattritem
511                 | hashedattritem hashedattrlist
512                 ;
513
514 hashedattritem :OPENPAREN number quotedString CLOSEPAREN
515                         {       
516                                 add_hashed_attr_to_array(&currentAttrs, $2, $3);
517                         }
518                 ;
519
520 attributes_5    : /* empty */
521                 | ATTRIBUTES_5 COLON OPENPAREN attributelist_5 CLOSEPAREN
522                 ;
523
524 attributelist_5 : attributeitem_5
525                 | attributeitem_5 attributelist_5
526                 ;
527
528 attributeitem_5 :OPENPAREN quotedString COMMA quotedString COMMA quotedString CLOSEPAREN
529                         {       
530                                 if (currentAttrs.total == currentAttrs.current)
531                                 {
532                                         grow_attr_array(&currentAttrs);
533                                 }
534                                 add_to_attr_array(&currentAttrs, $2, $4, $6);
535                         }
536                 ;
537
538 attributes_4    : /* empty */
539                         {
540                                 $$ = NULL;
541                         }
542                 | ATTRIBUTES_4 COLON OPENPAREN attributelist_4 CLOSEPAREN
543                         {
544                                 $$ = $4;
545                         }
546                 ;
547
548 attributelist_4  : attributeitem_4
549                         {
550                                 $$ = $1;
551                         }
552                 | attributeitem_4 attributelist_4
553                         {
554                                 Attr_4 p = $1;
555                                 p->next = $2;
556                                 $$ = p;
557                         }
558                 ;
559 attributeitem_4 :OPENPAREN quotedString COMMA quotedString COMMA quotedString CLOSEPAREN
560                         {       
561                                 Attr_4 newattr = _DtCm_make_attr4();
562                                 newattr->next = (Attr_4)NULL;
563                                 newattr->attr = $2;
564                                 newattr->value = $4;
565                                 newattr->clientdata = $6;
566                                 $$ = newattr;
567                         }
568                 | OPENPAREN quotedString COMMA quotedString CLOSEPAREN
569                         {
570                                 Attr_4 newattr = _DtCm_make_attr4();
571                                 newattr->next = (Attr_4)NULL;
572                                 newattr->attr = $2;
573                                 newattr->value = $4;
574                                 $$ = newattr;
575                         }
576                 ;
577
578 tags            : /* empty */
579                         {
580                                 Tag_4 *t = (Tag_4 *)malloc(sizeof(Tag_4));
581                                 t->next = (Tag_4 *)NULL;
582                                 t->tag = appointment_4;
583                                 t->showtime = 1;
584                                 $$ = t;
585                         }
586                 | TAGS COLON OPENPAREN taglist CLOSEPAREN
587                         {
588                                 $$ = $4;
589                         }
590                 ;
591
592 taglist         : tagitem
593                         {
594                                 $$ = $1;
595                         }
596                 | tagitem taglist
597                         {
598                                 Tag_4 *t = $1;
599                                 t->next = $2;
600                                 $$ = t;
601                         }
602                 ;
603
604 tagitem         : OPENPAREN TAGSVAL COMMA number CLOSEPAREN
605                         {
606                                 Tag_4 *t = (Tag_4 *)malloc(sizeof(Tag_4));
607                                 t->next = (Tag_4 *)NULL;
608                                 t->tag = externTag.tag;
609                                 t->showtime = $4;
610                                 $$ = t;
611                         }
612                 ;
613
614
615 exceptions      : /* empty */
616                         {
617                                 $$ = NULL;
618                         }
619                 | EXCEPTION COLON OPENPAREN exceptionlist CLOSEPAREN
620                         {
621                                 $$ = $4;
622                         }
623                 ;
624
625 exceptionlist : exceptitem
626                         {
627                                 $$ = $1;
628                         }
629                 | exceptitem exceptionlist
630                         {
631                                 Exception_4 p = $1;
632                                 p->next = $2;
633                                 $$ = p;
634                         }
635                 ;
636 exceptitem : number
637                 {
638                                 Exception_4 newexcept =
639                                         (Exception_4)malloc(sizeof(Except_4));
640                                 newexcept->next = (Exception_4)NULL;
641                                 newexcept->ordinal = $1;
642                                 $$ = newexcept;
643                 }
644                 ;
645
646
647 %% /* Begining of subroutine section */
648
649 void
650 yyerror(char *s)
651 {
652         (void)fprintf (stderr, "%s: %s\n", pgname, s);
653         (void)fprintf (stderr, "at line %d\n", yylineno);
654 }
655  
656 void
657 report_err(char *s)
658 {
659          (void)fprintf (stderr, "%s", s);
660 }
661
662 char *
663 str_to_cr(char *s)
664 {
665         int i, j, k;
666         char *newstr;
667
668         if (s==NULL) return(NULL);
669         i = strlen(s);
670
671         newstr= (char *)calloc(1, (unsigned)i + 1);
672         k = 0;
673         for (j=0; j<i; j++) {
674                 if (s[j]=='\\') {
675                         if (s[j+1]=='n') {
676                                 newstr[k] = '\n';
677                                 j++;
678                         }
679                         else if (s[j+1]=='\\') {
680                                 newstr[k] = '\\';
681                                 j++;
682                         }
683                         else if (s[j+1]=='\"') {
684                                 newstr[k] = '\"';
685                                 j++;
686                         }
687                         else {
688                                 newstr[k] = s[j];
689                         }
690                 }
691                 else {
692                         newstr[k] = s[j];
693                 }
694                 k++;
695         }
696         newstr[k] = '\0';
697         return(newstr);
698 }
699
700 int
701 get_wday(char *wday)
702 {
703         if (wday == NULL)
704                 return (-1);
705
706         if (strncmp(wday, "Sun", 3) == 0)
707                 return (0);
708         else if (strncmp(wday, "Mon", 3) == 0)
709                 return (1);
710         else if (strncmp(wday, "Tue", 3) == 0)
711                 return (2);
712         else if (strncmp(wday, "Wed", 3) == 0)
713                 return (3);
714         else if (strncmp(wday, "Thu", 3) == 0)
715                 return (4);
716         else if (strncmp(wday, "Fri", 3) == 0)
717                 return (5);
718         else if (strncmp(wday, "Sat", 3) == 0)
719                 return (6);
720         else
721                 return (-1);
722 }
723
724 int
725 get_month(char *month)
726 {
727         if (month == NULL)
728                 return (-1);
729
730         if (strncmp(month, "Jan", 3) == 0)
731                 return (0);
732         if (strncmp(month, "Feb", 3) == 0)
733                 return (1);
734         if (strncmp(month, "Mar", 3) == 0)
735                 return (2);
736         if (strncmp(month, "Apr", 3) == 0)
737                 return (3);
738         if (strncmp(month, "May", 3) == 0)
739                 return (4);
740         if (strncmp(month, "Jun", 3) == 0)
741                 return (5);
742         if (strncmp(month, "Jul", 3) == 0)
743                 return (6);
744         if (strncmp(month, "Aug", 3) == 0)
745                 return (7);
746         if (strncmp(month, "Sep", 3) == 0)
747                 return (8);
748         if (strncmp(month, "Oct", 3) == 0)
749                 return (9);
750         if (strncmp(month, "Nov", 3) == 0)
751                 return (10);
752         if (strncmp(month, "Dec", 3) == 0)
753                 return (11);
754                 
755         return (-1);
756 }
757
758 time_t
759 convert_2_tick(char *datestr)
760 {
761         struct tm tmstr;
762         char    datebuf[BUFSIZ];
763         char    *ptr, *tptr;
764
765         if (datestr == NULL)
766                 return (-1);
767
768         memset((void *)&tmstr, 0, sizeof(struct tm));
769
770         strcpy(datebuf, datestr);
771
772         /* get week day */
773         ptr = strtok(datebuf, " ");
774         if ((tmstr.tm_wday = get_wday(ptr)) == -1)
775                 return (-1);
776
777         /* get month */
778         ptr = strtok(NULL, " ");
779         if ((tmstr.tm_mon = get_month(ptr)) == -1)
780                 return (-1);
781
782         /* get day of month */
783         ptr = strtok(NULL, " ");
784         if (ptr != NULL)
785                 tmstr.tm_mday = atoi(ptr);
786         else
787                 return (-1);
788
789         /* get time */
790         ptr = strtok(NULL, " ");
791         if (ptr != NULL) {
792                 /* get hour */
793                 if ((tptr = strchr(ptr, ':')) == NULL)
794                         return (-1);
795                 else {
796                         *tptr = '\0';
797                         tmstr.tm_hour = atoi(ptr);
798                 }
799
800                 ptr = tptr + 1;
801                 if ((tptr = strchr(ptr, ':')) == NULL)
802                         return (-1);
803                 else {
804                         *tptr = '\0';
805                         tmstr.tm_min = atoi(ptr);
806                 }
807
808                 tmstr.tm_sec = atoi(tptr + 1);
809         } else
810                 return (-1);
811
812         ptr = strtok(NULL, " ");
813         if (ptr != NULL)
814                 tmstr.tm_year = atoi(ptr) - 1900;
815         else
816                 return (-1);
817
818         tmstr.tm_isdst = -1;
819
820         return(mktime(&tmstr));
821 }
822
823 static void
824 add_hashed_attr_to_array(_attr_array *attrs, int num, char *value)
825 {
826         int             type;
827
828         if (num > currentCalendar->entry_tbl->size)
829                 return;
830
831         if (attrs->current == attrs->total) {
832                 grow_attr_array(attrs);
833         }
834
835         attrs->attrs[attrs->current].name.num = num;
836         attrs->attrs[attrs->current].name.name =
837                 strdup(currentCalendar->entry_tbl->names[num]);
838
839         if (get_attr_value(currentCalendar->types[num], value,
840             &attrs->attrs[attrs->current].value) == CSA_SUCCESS)
841                 attrs->current++;
842
843         return;
844 }
845
846 static void
847 add_to_attr_array(_attr_array *attrs, char *name, char *tag, char *value)
848 {
849         int             type;
850
851         if (attrs->current == attrs->total) {
852                 grow_attr_array(attrs);
853         }
854
855         attrs->attrs[attrs->current].name.name = name;
856         if ((type = get_tag_from_string(tag)) == -1)
857                 return;
858
859         if (get_attr_value(type, value, &attrs->attrs[attrs->current].value)
860             == CSA_SUCCESS)
861                 attrs->current++;
862
863         return;
864 }
865
866 static CSA_enum
867 get_tag_from_string(char *tagstr)
868 {
869         int     i;
870
871         if (*tagstr < '0' || *tagstr > '9')
872                 return (-1);
873
874         i = atoi(tagstr);
875
876         if (i < CSA_VALUE_BOOLEAN || i > CSA_VALUE_OPAQUE_DATA ||
877             i == CSA_VALUE_ATTENDEE_LIST)
878                 return (-1);
879         else
880                 return (i);
881 }
882
883 static CSA_return_code
884 get_attr_value(int type, char *valstr, cms_attribute_value **attrval)
885 {
886         char            buf1[BUFSIZ], buf2[BUFSIZ];
887         char            *ptr1, *ptr2, *ptr3, *ptr4;
888         uint            unum;
889         CSA_reminder    remval;
890         CSA_opaque_data opqval;
891         CSA_return_code stat;
892
893         switch (type) {
894         case CSA_VALUE_ENUMERATED:
895         case CSA_VALUE_SINT32:
896                 stat = _DtCm_set_sint32_attrval(atoi(valstr), attrval);
897                 break;
898         case CSA_VALUE_BOOLEAN:
899         case CSA_VALUE_FLAGS:
900         case CSA_VALUE_UINT32:
901                 sscanf(valstr, "%u", &unum);
902                 stat = _DtCm_set_uint32_attrval(unum, attrval);
903                 break;
904         case CSA_VALUE_STRING:
905         case CSA_VALUE_DATE_TIME:
906         case CSA_VALUE_DATE_TIME_RANGE:
907         case CSA_VALUE_TIME_DURATION:
908         case CSA_VALUE_CALENDAR_USER:
909                 stat = _DtCm_set_string_attrval(valstr, attrval, type);
910                 break;
911         case CSA_VALUE_REMINDER:
912                 memset((void *)&remval, 0, sizeof (CSA_reminder));
913                 if (ptr1 = strchr(valstr, ':')) {
914                         *ptr1++ = '\0';
915                         if (ptr2 = strchr(ptr1, ':')) {
916                                 *ptr2++ = '\0';
917                                 ptr3 = strchr(ptr2, ':');
918                         }
919                 }
920
921                 if (ptr1 == NULL || ptr2 == NULL) {
922                         stat = CSA_E_INVALID_PARAMETER;
923                         break;
924                 }
925
926                 if (ptr3 == NULL) {
927                         /* format = "string:number:string" */
928                         remval.lead_time = valstr;
929                         remval.reminder_data.size = atoi(ptr1);
930                         remval.reminder_data.data = (unsigned char *)ptr2;
931                         stat = _DtCm_set_reminder_attrval(&remval, attrval);
932                 } else {
933                         /* format = "string:string:number:number:string" */
934                         *ptr3++ = '\0';
935                         if (ptr4 = strchr(ptr3, ':')) {
936                                 *ptr4++ = '\0';
937                                 remval.lead_time = valstr;
938                                 remval.snooze_time = ptr1;
939                                 remval.repeat_count = atoi(ptr2);
940                                 remval.reminder_data.size = atoi(ptr3);
941                                 remval.reminder_data.data =
942                                         (unsigned char *)ptr4;
943                                 stat = _DtCm_set_reminder_attrval(&remval,
944                                         attrval);
945                         } else
946                                 stat = CSA_E_INVALID_PARAMETER;
947                 }
948
949                 break;
950         case CSA_VALUE_ACCESS_LIST:
951                 stat = get_access_list_value(valstr, attrval);
952                 break;
953         case CSA_VALUE_DATE_TIME_LIST:
954                 stat = get_date_time_list_value(valstr, attrval);
955                 break;
956         case CSA_VALUE_OPAQUE_DATA:
957                 if (ptr1 = strchr(valstr, ':')) {
958                         *ptr1++ = '\0';
959                         opqval.size = atoi(valstr);
960                         opqval.data = (unsigned char *)ptr1;
961                         stat = _DtCm_set_opaque_attrval(&opqval, attrval);
962                 } else
963                         stat = CSA_E_INVALID_PARAMETER;
964                 break;
965         }
966
967         /* need to set type here since type may not be set correctly up there */
968         (*attrval)->type = type;
969
970         free(valstr);
971         return (stat);
972 }
973
974 static CSA_return_code
975 get_access_list_value(char *valstr, cms_attribute_value **attrval)
976 {
977         char *ptr;
978         cms_access_entry *a, *head, *prev;
979         CSA_return_code stat = CSA_SUCCESS;
980         cms_attribute_value *val;
981
982         if ((val = (cms_attribute_value *)calloc(1,
983             sizeof(cms_attribute_value))) == NULL)
984                 return (CSA_E_INSUFFICIENT_MEMORY);
985
986         val->type = CSA_VALUE_ACCESS_LIST;
987
988         if (*valstr == '\0') {
989                 *attrval = val;
990                 return (CSA_SUCCESS);
991         }
992
993         head = NULL;
994         while (ptr = strchr(valstr, ' ')) {
995
996                 *ptr = 0;
997                 stat = get_user_access_entry(valstr, &a);
998                 *ptr = ' ';
999
1000                 if (stat != CSA_SUCCESS)
1001                         break;
1002
1003                 if (head == NULL)
1004                         head = a;
1005                 else
1006                         prev->next = a;
1007                 prev = a;
1008
1009                 valstr = ptr + 1;
1010         }
1011
1012         if (stat == CSA_SUCCESS) {
1013                 if ((stat = get_user_access_entry(valstr, &a))
1014                     == CSA_SUCCESS) {
1015                         if (head == NULL)
1016                                 head = a;
1017                         else
1018                                 prev->next = a;
1019                 }
1020         }
1021
1022         if (stat == CSA_SUCCESS) {
1023                 val->item.access_list_value = head;
1024                 *attrval = val;
1025         } else {
1026                 _DtCm_free_cms_access_entry(head);
1027                 free(val);
1028         }
1029
1030         return (stat);
1031 }
1032
1033 static CSA_return_code
1034 get_user_access_entry(char *string, cms_access_entry **a)
1035 {
1036         char *ptr;
1037         cms_access_entry *item;
1038
1039         if ((ptr = strchr(string, ':')) == NULL)
1040                 return (CSA_E_INVALID_PARAMETER);
1041
1042         if ((item = (cms_access_entry *)malloc(sizeof(cms_access_entry)))
1043             == NULL) {
1044                 return (CSA_E_INSUFFICIENT_MEMORY);
1045         }
1046
1047         *ptr = '\0';
1048         if ((item->user = strdup(string)) == NULL) {
1049                 free(item);
1050                 return (CSA_E_INSUFFICIENT_MEMORY);
1051         }
1052         item->rights = atoi(ptr+1);
1053         item->next = NULL;
1054
1055         *a = item;
1056
1057         return (CSA_SUCCESS);
1058 }
1059
1060 #define _DEFAULT_ARRAY_SIZE     30
1061
1062 static void
1063 grow_attr_array(_attr_array *attrs)
1064 {
1065         cms_attribute *newptr;
1066
1067         if ((newptr = (cms_attribute *)realloc(attrs->attrs,
1068             sizeof(cms_attribute) * (attrs->total + _DEFAULT_ARRAY_SIZE)))
1069             == NULL)
1070                 return;
1071
1072         attrs->total += _DEFAULT_ARRAY_SIZE;
1073         attrs->attrs = newptr;
1074
1075         memset((void *)&attrs->attrs[attrs->current], 0,
1076                 sizeof(cms_attribute)*_DEFAULT_ARRAY_SIZE);
1077 }
1078
1079 static CSA_return_code
1080 get_date_time_list_value(char *valstr, cms_attribute_value **attrval)
1081 {
1082         char *ptr;
1083         CSA_date_time_entry *a, *head, *prev;
1084         CSA_return_code stat = CSA_SUCCESS;
1085         cms_attribute_value *val;
1086
1087         if (*valstr == '\0') {
1088                 *attrval = NULL;
1089                 return (CSA_SUCCESS);
1090         }
1091
1092         if ((val = (cms_attribute_value *)calloc(1,
1093             sizeof(cms_attribute_value))) == NULL)
1094                 return (CSA_E_INSUFFICIENT_MEMORY);
1095
1096         val->type = CSA_VALUE_DATE_TIME_LIST;
1097
1098         head = NULL;
1099         while (ptr = strchr(valstr, ' ')) {
1100
1101                 *ptr = 0;
1102                 if (!(a = calloc(1, sizeof(CSA_date_time_entry))) ||
1103                     !(a->date_time = strdup(valstr))) {
1104                         *ptr = ' ';
1105                         stat = CSA_E_INSUFFICIENT_MEMORY;
1106                         break;
1107                 }
1108                 *ptr = ' ';
1109
1110                 if (head == NULL)
1111                         head = a;
1112                 else
1113                         prev->next = a;
1114                 prev = a;
1115
1116                 valstr = ptr + 1;
1117         }
1118
1119         if (stat == CSA_SUCCESS) {
1120                 if ((a = calloc(1, sizeof(CSA_date_time_entry))) &&
1121                     (a->date_time = strdup(valstr))) {
1122                         if (head == NULL)
1123                                 head = a;
1124                         else
1125                                 prev->next = a;
1126                 } else
1127                         stat = CSA_E_INSUFFICIENT_MEMORY;
1128         }
1129
1130         if (stat == CSA_SUCCESS) {
1131                 val->item.date_time_list_value = head;
1132                 *attrval = val;
1133         } else {
1134                 _DtCm_free_date_time_list(head);
1135                 free(val);
1136         }
1137
1138         return (stat);
1139 }
1140
1141 static int
1142 extend_entry_table(int hashednum, char *name, char *typestr)
1143 {
1144         int     type;
1145
1146         if (hashednum > _DtCM_DEFINED_ENTRY_ATTR_SIZE) {
1147                 if ((type = get_tag_from_string(typestr)) == -1)
1148                         return (-1);
1149
1150                 (void)_DtCmExtendNameTable(name, hashednum, type,
1151                         _DtCm_entry_name_tbl, _DtCM_DEFINED_ENTRY_ATTR_SIZE,
1152                         _CSA_entry_attribute_names, &currentCalendar->entry_tbl,
1153                         &currentCalendar->types);
1154         }
1155         return (0);
1156 }
1157