1 /*
2 ** Copyright 2001-2010 Double Precision, Inc. See COPYING for
3 ** distribution information.
4 */
5
6
7 /*
8 */
9 #include "sqwebmail.h"
10 #include "pcp.h"
11 #include "pref.h"
12 #include "htmllibdir.h"
13 #include "sqconfig.h"
14 #include "auth.h"
15 #include "addressbook.h"
16 #include "pcp/pcp.h"
17 #include "cgi/cgi.h"
18 #include "rfc822/rfc822.h"
19 #include "rfc822/rfc822hdr.h"
20 #include "rfc822/rfc2047.h"
21 #include "maildir/maildircreate.h"
22 #include "maildir/maildirmisc.h"
23 #include "maildir/maildirquota.h"
24 #include "maildir/maildirgetquota.h"
25 #include "numlib/numlib.h"
26 #include "maildir.h"
27 #include "newmsg.h"
28 #include "pref.h"
29 #include "courierauth.h"
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <signal.h>
34 #include <ctype.h>
35 #include <unistd.h>
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #if HAVE_SYS_WAIT_H
40 #include <sys/wait.h>
41 #endif
42 #if HAVE_FCNTL_H
43 #include <fcntl.h>
44 #endif
45
46 #ifndef WEXITSTATUS
47 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
48 #endif
49 #ifndef WIFEXITED
50 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
51 #endif
52
53 #define CACHE "calendar.cache"
54 #define TOKEN "calendar.authtoken"
55
56 #define CHANGEDFILE "calendar/changed" /* Hack */
57
58 #include "strftime.h"
59
60 extern FILE *open_langform(const char *lang, const char *formname,
61 int print_header);
62
63 extern const char *myhostname();
64 extern void output_attrencoded_oknl_fp(const char *, FILE *);
65 extern void output_scriptptrget();
66 extern void output_attrencoded(const char *);
67 extern void print_safe(const char *);
68 extern const char *sqwebmail_content_charset;
69 extern const char *sqwebmail_content_language;
70 extern void output_form(const char *);
71 extern void newmsg_preview(const char *);
72 extern void output_urlencoded(const char *);
73 extern void attachments_head(const char *, const char *, const char *);
74 extern char *newmsg_createsentmsg(const char *, int *);
75 extern const char *sqwebmail_mailboxid;
76 extern char *scriptptrget();
77 extern void attach_delete(const char *);
78 extern int attach_upload(const char *,
79 const char *,
80 const char *);
81
82 extern void newmsg_showfp(FILE *, int *);
83
84 static struct PCP *calendar=NULL;
85 static void refreshcache(struct PCP *);
86 extern size_t get_timeoutsoft();
87
88
89 /*
90 ** CGI process startup
91 */
92
sqpcp_init()93 void sqpcp_init()
94 {
95 calendar=NULL;
96 }
97
98 /*
99 ** CGI process shutdown
100 */
101
sqpcp_close()102 void sqpcp_close()
103 {
104 if (calendar)
105 {
106 pcp_close(calendar);
107 calendar=NULL;
108 }
109 }
110
111 static int checked_calendar_mode=0;
112 static char calendar_mode[24];
113
sqpcp_mode()114 static const char *sqpcp_mode()
115 {
116 if (!checked_calendar_mode)
117 {
118 FILE *f;
119 char *p;
120
121 calendar_mode[0]=0;
122
123 f=fopen(CALENDARMODE, "r");
124
125 if (f)
126 {
127 if (fgets(calendar_mode, sizeof(calendar_mode),
128 f) == NULL)
129 {
130 calendar_mode[0]=0;
131 }
132 fclose(f);
133 }
134
135 if ((p=strchr(calendar_mode, '\n')) != 0)
136 *p=0;
137 checked_calendar_mode=1;
138 }
139
140 return (calendar_mode[0] ? calendar_mode:NULL);
141 }
142
143 /*
144 ** Log in to calendar.
145 */
146
147 static void do_pcplogin(const char *userid, const char *password, int showerr);
148
sqpcp_login(const char * userid,const char * password)149 void sqpcp_login(const char *userid, const char *password)
150 {
151 do_pcplogin(userid, password, 0);
152 }
153
do_pcplogin(const char * userid,const char * password,int showerr)154 static void do_pcplogin(const char *userid, const char *password, int showerr)
155 {
156 struct PCP *pcp;
157
158 unlink(TOKEN);
159 unlink(CACHE); /* Rebuild it later*/
160
161 if (!sqpcp_mode())
162 return;
163
164 mkdir("calendar", 0700);
165
166 if (sqpcp_has_groupware()) /* Groupware mode, login to server */
167 {
168 char *errflag=0;
169
170 pcp=pcp_open_server(userid, password, &errflag);
171
172 if (!pcp && errflag && showerr)
173 {
174 printf("%s<div class=\"indent\"><pre class=\"small-error\">",
175 getarg("CALENDARLOGINERR"));
176 output_attrencoded_oknl_fp(errflag, stdout);
177 printf("</pre></div>\n");
178 }
179 if (errflag)
180 free(errflag);
181 }
182 else
183 {
184 pcp=sqpcp_calendar();
185 }
186
187 if (pcp)
188 {
189 const char *p=pcp_authtoken(pcp);
190
191 if (p)
192 {
193 FILE *f;
194 int u=umask(077);
195
196 f=fopen(TOKEN, "w");
197 umask(u);
198 if (f)
199 {
200 fprintf(f, "%s\n", p);
201 fclose(f);
202 }
203 }
204 pcp_cleanup(pcp);
205 refreshcache(pcp);
206 }
207 }
208
209 /*
210 ** Format of the CACHE file:
211 **
212 ** start<TAB>end<TAB>eventid<TAB>flags<TAB>subject
213 */
214
215 struct cacherecord {
216 time_t start, end;
217 char *eventid;
218 char *flags;
219 char *subject;
220 } ;
221
sqpcp_has_calendar()222 int sqpcp_has_calendar()
223 {
224 return (sqpcp_mode() ? 1:0);
225 }
226
sqpcp_has_groupware()227 int sqpcp_has_groupware()
228 {
229 const char *p=sqpcp_mode();
230
231 return (p && strcmp(p, "net") == 0);
232 }
233
234 static int createcache(struct PCP *,
235 struct cacherecord **, unsigned *, time_t, time_t);
236 static void destroycache(struct cacherecord *, unsigned);
237
238 /*
239 ** Are we logged in? If so, refresh the calendar event cache that we
240 ** display on the main folders screen, if it is stale.
241 */
242
243 static int need_refresh();
244
sqpcp_loggedin()245 int sqpcp_loggedin()
246 {
247 struct PCP *pcp;
248
249 if (!sqpcp_mode())
250 return (0);
251
252 if (sqpcp_has_groupware())
253 {
254 struct stat stat_buf;
255
256 if (stat(TOKEN, &stat_buf))
257 return (0); /* Login session dropped */
258 }
259
260 if (!need_refresh())
261 return (1);
262 pcp=sqpcp_calendar();
263 if (pcp)
264 refreshcache(pcp);
265 return (1);
266 }
267
268 /* Check if it's time to rebuild CACHE file */
269
parsetimet(const char * buf,time_t * tp)270 static const char *parsetimet(const char *buf, time_t *tp)
271 {
272 *tp=libmail_strtotime_t(&buf);
273
274 if (*buf == '\t')
275 ++buf;
276 return buf;
277 }
278
need_refresh()279 static int need_refresh()
280 {
281 FILE *fp;
282 struct stat stat_buf;
283
284 /* Check whether it's time to rebuild the cache */
285
286 fp=fopen(CACHE, "r");
287
288 if (stat(CHANGEDFILE, &stat_buf) == 0)
289 {
290 if (fp)
291 fclose(fp);
292 return (1);
293 }
294
295 if (fp)
296 {
297 struct stat stat_buf;
298
299 char buffer[BUFSIZ];
300 const char *p;
301
302 time_t a, b;
303
304 int ch=getc(fp);
305
306 if (ch == EOF)
307 {
308 fclose(fp);
309 return (0); /* No events scheduled */
310 }
311
312 ungetc(ch, fp);
313 if (fgets(buffer, sizeof(buffer), fp) &&
314 (p=parsetimet(buffer, &a)) &&
315 parsetimet(p, &b))
316 {
317 time_t now;
318
319 time(&now);
320
321 if (now < b) /* Event expired */
322 {
323 if (fstat(fileno(fp), &stat_buf) == 0)
324 {
325 /*
326 ** Check in every TIMEOUTSOFT/2 in
327 ** any case.
328 */
329
330 if (stat_buf.st_mtime >
331 now - get_timeoutsoft()/2)
332 {
333 fclose(fp); /* Not yet */
334 return (0);
335 }
336 }
337 }
338 }
339 fclose(fp);
340 unlink(CACHE);
341 return (1);
342 }
343 return (0);
344 }
345
refreshcache(struct PCP * pcp)346 static void refreshcache(struct PCP *pcp)
347 {
348 struct cacherecord *recs;
349 unsigned n_recs;
350 unsigned i;
351 char *new_name;
352 int new_fd;
353 char *p;
354 time_t now;
355 FILE *new_fp;
356
357 unlink(CHANGEDFILE);
358 time(&now);
359 if (createcache(pcp, &recs, &n_recs, now, now + 5 * 24 * 60 * 60))
360 return;
361
362 new_fd=maildir_createmsg(INBOX, "cache", &new_name);
363 if (new_fd < 0 || (new_fp=fdopen(new_fd, "w")) == 0)
364 {
365 if (new_fd >= 0) close(new_fd);
366 destroycache(recs, n_recs);
367 return;
368 }
369
370 p=malloc(sizeof("tmp/")+strlen(new_name));
371 if (!p)
372 {
373 fclose(new_fp);
374 free(new_name);
375 destroycache(recs, n_recs);
376 return;
377 }
378 strcat(strcpy(p, "tmp/"), new_name);
379 free(new_name);
380 new_name=p;
381
382 /* Save a max of 5 events, for the main page listing */
383
384 for (i=0; i<n_recs && i < 5; i++)
385 {
386 char buf1[NUMBUFSIZE], buf2[NUMBUFSIZE];
387
388 fprintf(new_fp, "%s\t%s\t%s\t%s\t%s\n",
389 libmail_str_time_t(recs[i].start, buf1),
390 libmail_str_time_t(recs[i].end, buf2),
391 recs[i].eventid,
392 recs[i].flags,
393 recs[i].subject);
394 }
395
396 if (fflush(new_fp) || ferror(new_fp))
397 {
398 fclose(new_fp);
399 unlink(new_name);
400 free(new_name);
401 destroycache(recs, n_recs);
402 return;
403 }
404 fclose(new_fp);
405 rename(new_name, CACHE);
406 free(new_name);
407 destroycache(recs, n_recs);
408 return;
409 }
410
411 struct cacherecord_list {
412 struct cacherecord_list *next;
413 struct cacherecord rec;
414 } ;
415
cmp_reclist(const void * a,const void * b)416 static int cmp_reclist(const void *a, const void *b)
417 {
418 struct cacherecord_list *aa=*(struct cacherecord_list **)a;
419 struct cacherecord_list *bb=*(struct cacherecord_list **)b;
420
421 return ( aa->rec.end < bb->rec.end ? -1:
422 aa->rec.end > bb->rec.end ? 1:
423 aa->rec.start < bb->rec.start ? -1:
424 aa->rec.start > bb->rec.start ? 1:
425 strcmp(aa->rec.eventid, bb->rec.eventid));
426 }
427
428 static int callback_createcache(struct PCP_list_all *, void *);
429 static int callback_retr_status(struct PCP_retr *, int, void *);
430 static int callback_retr_headers(struct PCP_retr *, const char *,
431 const char *, void *);
432
433 static void destroycache_rec(struct cacherecord *);
434
435 struct retr_xinfo {
436 struct cacherecord *recs;
437 unsigned n_recs;
438 } ;
439
createcache(struct PCP * pcp,struct cacherecord ** recs,unsigned * n_recs,time_t start,time_t end)440 static int createcache(struct PCP *pcp,
441 struct cacherecord **recs, unsigned *n_recs,
442 time_t start, time_t end)
443 {
444 struct cacherecord_list *list=NULL, *p, **a;
445 struct PCP_list_all la;
446 struct PCP_retr r;
447 struct retr_xinfo xr;
448
449 unsigned i,n;
450 const char **event_ids;
451
452 *recs=0;
453 *n_recs=0;
454
455 memset(&la, 0, sizeof(la));
456 la.list_from=start;
457 la.list_to=end;
458 la.callback_func=callback_createcache;
459 la.callback_arg= &list;
460
461 if (pcp_list_all(pcp, &la))
462 {
463 while ((p=list) != NULL)
464 {
465 list=p->next;
466 destroycache_rec(&p->rec);
467 free(p);
468 }
469 return (0);
470 }
471
472 /* Sort the returned event list, in chronological order. */
473
474
475 /* First, create an array out of the list */
476
477 for (n=0, p=list; p; p=p->next)
478 ++n;
479
480 if (!n)
481 return (0); /* Nothing */
482
483 a=malloc(sizeof(struct cacherecord_list *)*n);
484 if (!a)
485 {
486 fprintf(stderr, "NOTICE: malloc failed\n");
487
488 while ((p=list) != NULL)
489 {
490 list=p->next;
491 destroycache_rec(&p->rec);
492 free(p);
493 }
494 return (-1);
495 }
496 for (n=0, p=list; p; p=p->next)
497 a[n++]=p;
498
499 /* Sort it, copy the sorted array to the return ptr */
500
501 qsort(a, n, sizeof(*a), cmp_reclist);
502
503 if ((*recs=malloc(sizeof(struct cacherecord)*n)) == NULL)
504 {
505 fprintf(stderr, "NOTICE: malloc failed\n");
506
507 while ((p=list) != NULL)
508 {
509 list=p->next;
510 destroycache_rec(&p->rec);
511 free(p);
512 }
513 free(a);
514 return (-1);
515 }
516
517 for (i=0; i<n; i++)
518 (*recs)[i]= a[i]->rec;
519 *n_recs=n;
520 free(a);
521 while ((p=list) != NULL)
522 {
523 list=p->next;
524 free(p);
525 }
526
527 /* Get the subject of all the events */
528
529 event_ids=malloc(sizeof(const char *)*(n+1));
530
531 if (!event_ids)
532 {
533 fprintf(stderr, "NOTICE: malloc failed\n");
534
535 destroycache(*recs, *n_recs);
536 return (-1);
537 }
538
539 for (i=0; i< *n_recs; i++)
540 event_ids[i]= (*recs)[i].eventid;
541 event_ids[i]=NULL;
542
543 memset(&r, 0, sizeof(r));
544 r.event_id_list=event_ids;
545 r.callback_arg=&xr;
546 xr.recs= *recs;
547 xr.n_recs= *n_recs;
548
549 r.callback_retr_status=callback_retr_status;
550 r.callback_headers_func=callback_retr_headers;
551
552 if (pcp_retr(pcp, &r))
553 {
554 fprintf(stderr, "NOTICE: pcp_retr: error: %s\n", pcp_errmsg(pcp));
555 free(event_ids);
556 destroycache(*recs, *n_recs);
557 return (-1);
558 }
559 free(event_ids);
560 return (0);
561 }
562
563 /* Callback from PCP LIST - save the event ID in the cacherecord_list */
564
callback_createcache(struct PCP_list_all * a,void * vp)565 static int callback_createcache(struct PCP_list_all *a, void *vp)
566 {
567 struct cacherecord_list **listp=(struct cacherecord_list **)vp, *p;
568
569 if ((p=malloc(sizeof(struct cacherecord_list))) == NULL)
570 return (-1);
571
572 p->rec.start=a->event_from;
573 p->rec.end=a->event_to;
574
575 if ((p->rec.eventid=strdup(a->event_id)) == NULL)
576 {
577 free(p);
578 return (-1);
579 }
580
581 /* Initialize the other fields, so all ptrs are live */
582
583 if ((p->rec.flags=strdup("")) == NULL)
584 {
585 free(p->rec.eventid);
586 free(p);
587 return (-1);
588 }
589
590 if ((p->rec.subject=strdup("")) == NULL)
591 {
592 free(p->rec.flags);
593 free(p->rec.eventid);
594 free(p);
595 return (-1);
596 }
597
598 p->next= *listp;
599 *listp=p;
600 return (0);
601 }
602
callback_retr_status(struct PCP_retr * r,int s,void * vp)603 static int callback_retr_status(struct PCP_retr *r, int s, void *vp)
604 {
605 struct cacherecord *recs=( (struct retr_xinfo *)vp)->recs;
606 unsigned n_recs=( (struct retr_xinfo *)vp)->n_recs;
607 unsigned i;
608
609 char stat_buf[256];
610 char *p;
611
612 stat_buf[0]=0;
613
614 if (s & LIST_CANCELLED)
615 {
616 strcat(stat_buf, " CANCELLED");
617 }
618
619 if (s & LIST_BOOKED)
620 {
621 strcat(stat_buf, " BOOKED");
622 }
623
624 p=stat_buf;
625 if (*p)
626 ++p;
627
628 for (i=0; i<n_recs; i++)
629 {
630 if (strcmp(recs[i].eventid, r->event_id) == 0)
631 {
632 char *s=strdup(p);
633
634 if (!s)
635 return (-1);
636 free(recs[i].flags);
637 recs[i].flags=s;
638 break;
639 }
640 }
641 return (0);
642 }
643
644 /* RETR callback for headers - save the Subject: header */
645
collapse_subject(char * s)646 static void collapse_subject(char *s)
647 {
648 /* Collapse multiline subjects */
649
650 char *t, *u;
651
652 for (t=u=s; *t; )
653 {
654 if (*t != '\n')
655 {
656 *u++=*t++;
657 continue;
658 }
659
660 while (*t && isspace((int)(unsigned char)*t))
661 ++t;
662 *u++=' ';
663 }
664 *u=0;
665 }
666
callback_retr_headers(struct PCP_retr * r,const char * h,const char * v,void * vp)667 static int callback_retr_headers(struct PCP_retr *r, const char *h,
668 const char *v, void *vp)
669 {
670 struct cacherecord *recs=( (struct retr_xinfo *)vp)->recs;
671 unsigned n_recs=( (struct retr_xinfo *)vp)->n_recs;
672 unsigned i;
673
674 if (strcasecmp(h, "Subject") || !v)
675 return (0);
676
677 for (i=0; i<n_recs; i++)
678 {
679 if (strcmp(recs[i].eventid, r->event_id) == 0)
680 {
681 char *s;
682
683 s=strdup(v);
684
685 if (!s)
686 return (-1);
687
688 collapse_subject(s);
689 free(recs[i].subject);
690 recs[i].subject=s;
691 }
692 }
693
694 return (0);
695 }
696
destroycache(struct cacherecord * c,unsigned n)697 static void destroycache(struct cacherecord *c, unsigned n)
698 {
699 unsigned i;
700
701 for (i=0; i<n; i++)
702 {
703 destroycache_rec(c+i);
704 }
705 if (c)
706 free(c);
707 }
708
destroycache_rec(struct cacherecord * c)709 static void destroycache_rec(struct cacherecord *c)
710 {
711 free(c->eventid);
712 free(c->flags);
713 free(c->subject);
714 }
715
parsecache_rec(char * p,struct cacherecord * cr)716 static void parsecache_rec(char *p, struct cacherecord *cr)
717 {
718 unsigned long a;
719
720 memset(cr, 0, sizeof(*cr));
721 cr->eventid="";
722 cr->flags="";
723 cr->subject="";
724
725 if (!p || sscanf(p, "%lu", &a) <= 0)
726 return;
727 p=strchr(p, '\t');
728 cr->start= (time_t)a;
729 if (!p || sscanf(p, "%lu", &a) <= 0)
730 return;
731 cr->end= (time_t)a;
732 p=strchr(p+1, '\t');
733 if (!p) return;
734 ++p;
735
736 cr->eventid=p;
737 p=strchr(p, '\t');
738 if (!p) return;
739 *p++=0;
740
741 cr->flags=p;
742 p=strchr(p, '\t');
743 if (!p) return;
744 *p++=0;
745
746 cr->subject=p;
747 }
748
sqpcp_calendar()749 struct PCP *sqpcp_calendar()
750 {
751 const char *p;
752
753 if (!sqpcp_mode())
754 {
755 errno=ENOENT;
756 return (NULL);
757 }
758
759 if (calendar)
760 return (calendar);
761
762 p=getenv("AUTHADDR");
763
764 if (!p)
765 {
766 errno=ENOENT;
767 return (NULL);
768 }
769
770 if (sqpcp_has_groupware())
771 {
772 char token[256];
773 char *pp;
774
775 FILE *f=fopen(TOKEN, "r");
776
777 if (!f)
778 return (NULL);
779
780 if (fgets(token, sizeof(token), f) == NULL)
781 {
782 fclose(f);
783 return (NULL);
784 }
785
786 if ((pp=strchr(token, '\n')) != 0) *pp=0;
787
788 fclose(f);
789 if (token[0] == 0)
790 {
791 unlink(TOKEN);
792 return (NULL);
793 }
794
795 calendar=pcp_reopen_server(p, token, NULL);
796
797 if (calendar)
798 {
799 p=pcp_authtoken(calendar);
800
801 if (p && strcmp(p, token))
802 {
803 int u=umask(077);
804
805 /* Save new authentication token */
806
807 f=fopen(TOKEN, "w");
808 umask(u);
809 if (f)
810 {
811 fprintf(f, "%s\n", token);
812 fclose(f);
813 }
814 }
815 }
816 else
817 {
818 unlink(TOKEN);
819 }
820 return (calendar);
821 }
822
823 return ((calendar=pcp_open_dir("calendar", p)));
824 }
825
826
827 /* ---------------------------------------------------------------- */
828 /* Display event information */
829 /* ---------------------------------------------------------------- */
830
831 static struct PCP_event_time *event_time_list=0;
832 static unsigned n_event_time_list=0;
833 static FILE *openoldfp(const char *p, unsigned long *prev_size);
834
835 struct my_participant {
836 struct my_participant *next;
837 char *name;
838 char *address;
839 } ;
840
841 static struct my_participant *my_participant_list=0;
842
add_my_participant(const char * h)843 static void add_my_participant(const char *h)
844 {
845 struct my_participant *m=
846 malloc(sizeof(struct my_participant));
847
848 if (!m)
849 enomem();
850
851 memset(m, 0, sizeof(*m));
852 m->next=my_participant_list;
853 my_participant_list=m;
854
855 if ((m->address=strdup(h)) == NULL)
856 enomem();
857 }
858
859 static char *from_buf=0, *subj_buf=0;
860
sqpcp_eventstart()861 void sqpcp_eventstart()
862 {
863 const char *p=cgi("draftmessage");
864 FILE *oldfp;
865 struct rfc822hdr h;
866 struct PCP_event_time_list {
867 struct PCP_event_time_list *next;
868 struct PCP_event_time t;
869 } *event_time_listp=NULL, **lastp= &event_time_listp;
870 unsigned event_time_list_cnt=0;
871
872 sqpcp_eventend();
873
874 if (!p || !*p)
875 return;
876
877 oldfp=openoldfp(p, NULL);
878 if (!oldfp)
879 return;
880
881 rfc822hdr_init(&h, 8192);
882 while (rfc822hdr_read(&h, oldfp, NULL, 0) == 0)
883 {
884 if (strcasecmp(h.header, "X-Event-Time") == 0 && h.value)
885 {
886 unsigned long n1, n2;
887
888 if (sscanf(h.value, "%lu %lu", &n1, &n2) == 2)
889 {
890 struct PCP_event_time_list *t=
891 malloc(sizeof(**lastp));
892
893 if (!t)
894 {
895 rfc822hdr_free(&h);
896 sqpcp_eventend();
897 enomem();
898 return;
899 }
900 *lastp=t;
901 t->next=NULL;
902 t->t.start=(time_t)n1;
903 t->t.end=(time_t)n2;
904 ++event_time_list_cnt;
905 lastp=&t->next;
906 }
907 }
908 else if (strcasecmp(h.header, "X-Event-Participant") == 0 && h.value)
909 {
910 add_my_participant(h.value);
911 }
912 else if (strcasecmp(h.header, "from") == 0 && h.value)
913 {
914 rfc822hdr_collapse(&h);
915 if (from_buf)
916 free(from_buf);
917
918 from_buf=NULL;
919
920 if ((from_buf=
921 rfc822_display_hdrvalue_tobuf(h.header,
922 h.value,
923 sqwebmail_content_charset,
924 NULL, NULL)) == NULL)
925 from_buf=strdup(h.value);
926
927 if (from_buf)
928 cgi_put("from", from_buf);
929 }
930 else if (strcasecmp(h.header, "subject") == 0 && h.value)
931 {
932 rfc822hdr_collapse(&h);
933 if (subj_buf)
934 free(subj_buf);
935
936 subj_buf=rfc822_display_hdrvalue_tobuf(h.header,
937 h.value,
938 sqwebmail_content_charset,
939 NULL, NULL);
940 if (subj_buf)
941 subj_buf=strdup(subj_buf);
942
943 if (subj_buf)
944 cgi_put("headersubject", subj_buf);
945 }
946 }
947 rfc822hdr_free(&h);
948 if (event_time_list_cnt)
949 {
950 struct PCP_event_time *list1;
951 struct PCP_event_time_list *p;
952
953 list1=malloc(sizeof(struct PCP_event_time_list)
954 *event_time_list_cnt);
955 if (!list1)
956 {
957 sqpcp_eventend();
958 enomem();
959 return;
960 }
961 event_time_list_cnt=0;
962 while ((p=event_time_listp) != NULL)
963 {
964 list1[event_time_list_cnt]=p->t;
965 ++event_time_list_cnt;
966 event_time_listp=p->next;
967 free(p);
968 }
969
970 event_time_list=list1;
971 n_event_time_list=event_time_list_cnt;
972 }
973 }
974
sqpcp_eventend()975 void sqpcp_eventend()
976 {
977 struct my_participant *m;
978
979 while ((m=my_participant_list) != NULL)
980 {
981 my_participant_list=m->next;
982 if (m->name)
983 free(m->name);
984 if (m->address)
985 free(m->address);
986 free(m);
987 }
988
989 if (event_time_list)
990 free(event_time_list);
991 event_time_list=NULL;
992 n_event_time_list=0;
993
994 }
995
sqpcp_eventtimes()996 void sqpcp_eventtimes()
997 {
998 char buffer[512];
999 unsigned i;
1000
1001 for (i=0; i<n_event_time_list; i++)
1002 {
1003 if (i)
1004 printf("<br />\n");
1005 if (pcp_fmttimerange(buffer, sizeof(buffer),
1006 event_time_list[i].start,
1007 event_time_list[i].end))
1008 continue;
1009 printf("<span class=\"tt\">");
1010 print_safe(buffer);
1011 printf(" </span><a href=\"");
1012 output_scriptptrget();
1013 printf("&form=newevent&draftmessage=");
1014 output_urlencoded(cgi("draftmessage"));
1015 printf("&do.deleventtime=%s-%s\"><font size=\"-2\">"
1016 "(%s)</font></a>",
1017 libmail_str_time_t(event_time_list[i].start, buffer),
1018 libmail_str_time_t(event_time_list[i].end, buffer+NUMBUFSIZE),
1019 getarg("REMOVE")
1020 );
1021 }
1022 }
1023
save_participant_names(const char * addr,const char * name,void * vp)1024 static int save_participant_names(const char *addr, const char *name,
1025 void *vp)
1026 {
1027 struct my_participant *p=(struct my_participant *)vp;
1028
1029 for ( ; name && p; p=p->next)
1030 if (strcasecmp(p->address, addr) == 0 && p->name == 0)
1031 p->name=strdup(name);
1032 return (0);
1033 }
1034
sqpcp_eventparticipants()1035 void sqpcp_eventparticipants()
1036 {
1037 struct my_participant *m;
1038
1039 if (!my_participant_list)
1040 return;
1041
1042 (void)ab_get_nameaddr(save_participant_names, my_participant_list);
1043
1044 printf("<table border=\"0\">");
1045
1046 for (m=my_participant_list; m; m=m->next)
1047 {
1048 printf("<tr><td><span class=\"tt\">");
1049 if (m->address)
1050 ab_nameaddr_show(m->name, m->address);
1051
1052 printf("</span></td><td> <a href=\"");
1053
1054 output_scriptptrget();
1055 printf("&form=newevent&draftmessage=");
1056 output_urlencoded(cgi("draftmessage"));
1057 printf("&do.delparticipant=");
1058 output_urlencoded(m->address);
1059 printf("\"><font size=\"-2\">(%s)</font></a></td></tr>\n",
1060 getarg("REMOVE"));
1061 }
1062 printf("</table>");
1063 }
1064
sqpcp_eventfrom()1065 void sqpcp_eventfrom()
1066 {
1067 if (auth_getoptionenvint("wbnochangingfrom"))
1068 {
1069 printf("<span class=\"tt\">");
1070 print_safe(login_fromhdr());
1071 printf("</span>");
1072 }
1073 else
1074 {
1075 const char *p=cgi("headerfrom");
1076
1077 if (!p || !*p)
1078 p=pref_from;
1079 if (!p || !*p)
1080 p=login_fromhdr();
1081 if (!p)
1082 p="";
1083
1084 printf("<input type=\"text\" name=\"headerfrom\" size=\"60\" value=\"");
1085 output_attrencoded(p);
1086 printf("\" />");
1087 }
1088 }
1089
sqpcp_eventtext()1090 void sqpcp_eventtext()
1091 {
1092 const char *p;
1093
1094 printf("<textarea name=\"message\" cols=\"%d\" rows=\"15\" wrap=\"soft\">",
1095 MYLINESIZE);
1096 p=cgi("draftmessage");
1097
1098 if (p && *p)
1099 {
1100 FILE *fp=openoldfp(p, NULL);
1101 int dummy;
1102
1103 if (fp)
1104 {
1105 newmsg_showfp(fp, &dummy);
1106 }
1107 fclose(fp);
1108 }
1109 printf("</textarea>\n");
1110 }
1111
sqpcp_eventattach()1112 void sqpcp_eventattach()
1113 {
1114 const char *p;
1115
1116 p=cgi("draftmessage");
1117
1118 if (p && *p)
1119 {
1120 attachments_head(NULL, cgi("pos"), p);
1121 }
1122 }
1123
1124 /* ------- Display the cached event summary -------- */
1125
1126 static void print_event_subject(char *, const char *, unsigned);
1127 static void print_event_link_url(const char *, const char *);
1128
sqpcp_summary()1129 void sqpcp_summary()
1130 {
1131 FILE *fp;
1132 int cnt=0;
1133 time_t now;
1134 struct tm *tmptr;
1135
1136 if (!sqpcp_mode())
1137 return;
1138
1139 if (*cgi("do.calendarlogin"))
1140 {
1141 const char *userid=getenv("AUTHADDR");
1142 const char *password=cgi("password");
1143
1144 if (userid && password)
1145 {
1146 do_pcplogin(userid, password, 1);
1147 }
1148 }
1149
1150 if (sqpcp_has_groupware())
1151 {
1152 if (!sqpcp_loggedin())
1153 {
1154 insert_include("calendarlogin");
1155 return;
1156 }
1157 }
1158
1159 time(&now);
1160 tmptr=localtime(&now);
1161
1162 if (tmptr)
1163 {
1164 char *p=scriptptrget();
1165 char *q=malloc(strlen(p)+200);
1166
1167 if (!q)
1168 {
1169 free(p);
1170 enomem();
1171 }
1172
1173 strcpy(q, p);
1174 free(p);
1175 strcat(q, "&form=eventdaily&clearcache=1&date=");
1176 sprintf(q+strlen(q), "%04d%02d%02d",
1177 tmptr->tm_year + 1900,
1178 tmptr->tm_mon+1,
1179 tmptr->tm_mday);
1180
1181 printf(getarg("CALENDAR"), q);
1182 free(q);
1183 }
1184
1185 printf("<table class=\"eventsummary\" width=\"100%%\">");
1186
1187 if ((fp=fopen(CACHE, "r")) != NULL)
1188 {
1189 char buffer[BUFSIZ];
1190 int i;
1191 char last_date[256];
1192 char date[256];
1193 char date2[256];
1194 struct tm *tm;
1195 char yyyymmdd[100];
1196
1197 char time1[128];
1198 char time2[128];
1199
1200 last_date[0]=0;
1201
1202 for (;;)
1203 {
1204 int c;
1205 struct cacherecord cr;
1206
1207 i=0;
1208
1209 while ((c=getc(fp)) != EOF && c != '\n')
1210 {
1211 if (i < sizeof(buffer)-1)
1212 buffer[i++]=(char)c;
1213 }
1214 buffer[i]=0;
1215 if (i == 0 && c == EOF)
1216 break;
1217
1218 parsecache_rec(buffer, &cr);
1219
1220 if (pcp_fmttime(date, sizeof(date),
1221 cr.start, FMTTIME_DATE))
1222 continue;
1223 if (pcp_fmttime(date2, sizeof(date2),
1224 cr.end, FMTTIME_DATE))
1225 continue;
1226
1227 if (pcp_fmttime(time1, sizeof(time1),
1228 cr.start,
1229 FMTTIME_TIME))
1230 continue;
1231
1232 if (pcp_fmttime(time2,
1233 sizeof(time2),
1234 cr.end,
1235 FMTTIME_TIME))
1236 continue;
1237
1238 tm=localtime(&cr.start);
1239 if (!tm)
1240 continue;
1241 sprintf(yyyymmdd, "%04d%02d%02d",
1242 tm->tm_year + 1900,
1243 tm->tm_mon + 1,
1244 tm->tm_mday);
1245
1246 i=0;
1247 if (last_date[0] && strcmp(last_date, date) == 0)
1248 {
1249 if (strcmp(last_date, date2) == 0)
1250 {
1251 /* Same day as last event */
1252
1253 printf("<tr><td align=\"left\" width=\"1%%\"> </td>"
1254 "<td align=\"left\"> "
1255 "<a href=\"");
1256 print_event_link_url(cr.eventid, "");
1257 printf("&date=%s\">", yyyymmdd);
1258 print_safe(time1);
1259 printf(" - ");
1260 print_safe(time2);
1261 printf("</a></td>");
1262 i=1;
1263 }
1264 else
1265 {
1266 last_date[0]=0;
1267 }
1268 }
1269 else
1270 {
1271 last_date[0]=0;
1272 if (strcmp(date, date2) == 0)
1273 strcpy(last_date, date);
1274 }
1275
1276 if (!i)
1277 {
1278 if (cnt)
1279 printf("<tr><td style=\"line-height: 0px; font-size: 8px\" colspan=\"3\">"
1280 " "
1281 "</td></tr>\n");
1282 if (strcmp(date, date2))
1283 {
1284 printf("<tr><td colspan=\"2\">"
1285 "<a href=\"");
1286 print_event_link_url(cr.eventid, "");
1287 printf("&date=%s\">", yyyymmdd);
1288 print_safe(date);
1289 printf(" ");
1290 print_safe(time1);
1291 printf(" - ");
1292 print_safe(date2);
1293 printf(" ");
1294 print_safe(time2);
1295 printf("</a></td>");
1296 }
1297 else
1298 {
1299 printf("<tr><td width=\"1%%\">"
1300 "<a href=\"");
1301 print_event_link_url(cr.eventid, "");
1302 printf("&date=%s\">", yyyymmdd);
1303 print_safe(date);
1304 printf("</a></td><td> "
1305 "<a href=\"");
1306 print_event_link_url(cr.eventid, "");
1307 printf("&date=%s\">", yyyymmdd);
1308 print_safe(time1);
1309 printf(" - ");
1310 print_safe(time2);
1311 printf("</a></td>");
1312 }
1313 }
1314
1315 printf("<td width=\"100%%\">"
1316 "<a href=\"");
1317 print_event_link_url(cr.eventid, "");
1318 printf("&date=%s\"> ", yyyymmdd);
1319 print_event_subject(cr.flags, cr.subject, 60);
1320 printf("</a></td></tr>\n");
1321 ++cnt;
1322 }
1323 fclose(fp);
1324 }
1325
1326 if (cnt == 0)
1327 {
1328 printf("<tr><td align=\"center\">%s</td></tr>\n",
1329 getarg("NOEVENTS"));
1330 }
1331
1332 printf("</table>\n");
1333 printf("<a href=\"");
1334 output_scriptptrget();
1335 printf("&form=newevent\">%s</a>", getarg("NEWEVENT"));
1336 }
1337
1338
print_event_subject(char * flags,const char * subject,unsigned w)1339 static void print_event_subject(char *flags, const char *subject, unsigned w)
1340 {
1341 unsigned i;
1342 char *p;
1343
1344 /* Print event flags first: CANCELLED... */
1345
1346 for (p=flags; p && (p=strtok(p, " \t\r")) != 0; p=0)
1347 {
1348 printf("%s", getarg(p));
1349 }
1350
1351 p=rfc822_display_hdrvalue_tobuf("subject",
1352 subject ? subject:"",
1353 sqwebmail_content_charset,
1354 NULL,
1355 NULL);
1356
1357 if (!p)
1358 p=strdup(subject ? subject:"");
1359
1360 if (!p)
1361 return;
1362
1363 if (strlen(p) > w)
1364 {
1365 /* Truncate long subject lines */
1366 i=w-5;
1367 while (i)
1368 {
1369 if (isspace((int)(unsigned char) p[i]))
1370 {
1371 strcpy(p+i, "...");
1372 break;
1373 }
1374 --i;
1375 }
1376 }
1377 print_safe(p);
1378 free(p);
1379 }
1380
1381 /* ------- New event support code -------- */
1382
1383 static int addtime(int);
1384 static void addparticipant(int, const char *);
1385
openoldfp(const char * p,unsigned long * prev_size)1386 static FILE *openoldfp(const char *p, unsigned long *prev_size)
1387 {
1388 struct stat stat_buf;
1389 char *filename;
1390 int x;
1391 FILE *oldfp;
1392
1393 CHECKFILENAME(p);
1394
1395 filename=maildir_find(INBOX "." DRAFTS, p);
1396 if (!filename)
1397 return (NULL);
1398
1399 x=maildir_safeopen(filename, O_RDONLY, 0);
1400 free(filename);
1401 if (x < 0)
1402 return (NULL);
1403
1404
1405 if (fstat(x, &stat_buf) < 0 || (oldfp=fdopen(x, "r")) == NULL)
1406 {
1407 close(x);
1408 return (NULL);
1409 }
1410
1411 if (prev_size)
1412 *prev_size=stat_buf.st_size;
1413 return (oldfp);
1414 }
1415
1416
1417 /* ------------- Conflict indicators ---------------- */
1418
1419 struct conflict_list {
1420 struct conflict_list *next;
1421 char *event_id;
1422 time_t start, end;
1423 char *address;
1424 char *subject;
1425 } ;
1426
1427 static struct conflict_list *conflict_list=NULL;
1428
init_save_conflict()1429 static void init_save_conflict()
1430 {
1431 while (conflict_list)
1432 {
1433 struct conflict_list *p=conflict_list;
1434
1435 conflict_list=p->next;
1436 if (p->event_id)
1437 free(p->event_id);
1438 if (p->address)
1439 free(p->address);
1440 if (p->subject)
1441 free(p->subject);
1442 free(p);
1443 }
1444 }
1445
save_conflict(const char * event_id,time_t start,time_t end,const char * address,void * dummy)1446 static int save_conflict(const char *event_id, time_t start, time_t end,
1447 const char *address,
1448 void *dummy)
1449 {
1450 struct conflict_list *p, **ptr;
1451
1452 for (ptr= &conflict_list; *ptr; ptr=&(*ptr)->next)
1453 {
1454 if ( (*ptr)->end > end)
1455 break;
1456 }
1457
1458 if ((p=malloc(sizeof(struct conflict_list))) == NULL)
1459 return (-1);
1460 memset(p, 0, sizeof(*p));
1461 p->next= *ptr;
1462 *ptr=p;
1463
1464 p->start=start;
1465 p->end=end;
1466 if ((p->event_id=strdup(event_id)) == NULL ||
1467 (address && (p->address=strdup(address)) == NULL))
1468 return (-1);
1469
1470 return (0);
1471 }
1472
1473 static int save_conflict_subj(struct PCP_retr *, const char *,
1474 const char *, void *);
1475
show_conflict_error(struct PCP * pcp)1476 static void show_conflict_error(struct PCP *pcp)
1477 {
1478 unsigned n;
1479 struct conflict_list *p;
1480 const char **l;
1481 struct PCP_retr r;
1482
1483 for (n=0, p=conflict_list; p; p=p->next)
1484 if (p->event_id && (!p->address ||
1485 strcmp(p->address, "@") == 0))
1486 ++n;
1487
1488 if ((l=malloc(sizeof(const char *)*(n+1))) == NULL)
1489 return;
1490
1491 for (n=0, p=conflict_list; p; p=p->next)
1492 if (p->event_id && (!p->address ||
1493 strcmp(p->address, "@") == 0))
1494 {
1495 l[n]=p->event_id;
1496 ++n;
1497 }
1498
1499 l[n]=0;
1500 memset(&r, 0, sizeof(r));
1501 r.event_id_list=l;
1502 r.callback_headers_func=save_conflict_subj;
1503
1504 if (n == 0 || pcp_retr(pcp, &r) == 0)
1505 {
1506 printf("<table border=\"0\" width=\"100%%\" class=\"small-error\">");
1507 for (p=conflict_list; p; p=p->next)
1508 {
1509 char buffer[512];
1510
1511 printf("<tr><td width=\"30\"> </td><td><span class=\"tt\">");
1512 if (pcp_fmttimerange(buffer, sizeof(buffer),
1513 p->start,
1514 p->end) == 0)
1515 {
1516 print_safe(buffer);
1517 }
1518 printf("</span></td><td width=\"30\"> </td><td width=\"100%%\"><span class=\"tt\">");
1519 if (p->address && strcmp(p->address, "@"))
1520 {
1521 printf("%s", getarg("CONFLICTERR2"));
1522 print_safe(p->address);
1523 }
1524 else
1525 print_event_subject("", p->subject
1526 ? p->subject:"", 60);
1527 printf("</span></td></tr>\n");
1528 }
1529 printf("<tr><td colspan=\"4\"><hr width=\"90%%\" /></td></tr></table>\n");
1530 }
1531 free(l);
1532 init_save_conflict();
1533 }
1534
save_conflict_subj(struct PCP_retr * r,const char * h,const char * v,void * dummy)1535 static int save_conflict_subj(struct PCP_retr *r, const char *h,
1536 const char *v, void *dummy)
1537 {
1538 struct conflict_list *p;
1539
1540 if (strcasecmp(h, "subject") || !v)
1541 return (0);
1542
1543 for (p=conflict_list; p; p=p->next)
1544 if (p->event_id && strcmp(p->event_id, r->event_id) == 0)
1545 {
1546 if (p->subject)
1547 free(p->subject);
1548 if ((p->subject=strdup(v)) != NULL)
1549 collapse_subject(p->subject);
1550 break;
1551 }
1552 return (0);
1553 }
1554
1555 /* -------------------------------------------------- */
1556
showerror()1557 static void showerror()
1558 {
1559 const char *p;
1560
1561 p=cgi("error");
1562 if (strcmp(p, "quota") == 0)
1563 printf("%s", getarg("QUOTAERR"));
1564 if (strcmp(p, "time") == 0)
1565 printf("%s", getarg("NOTIMEERR"));
1566 if (strcmp(p, "conflict") == 0)
1567 {
1568 struct PCP *pcp=sqpcp_calendar();
1569
1570 printf("%s", getarg("CONFLICTERR"));
1571 if (pcp)
1572 show_conflict_error(pcp);
1573 }
1574 if (strcmp(p, "calendar") == 0)
1575 {
1576 printf(getarg("CALENDARERR"), cgi("pcperror"));
1577 }
1578 if (strcmp(p, "locked") == 0)
1579 printf("%s", getarg("LOCKERR"));
1580 if (strcmp(p, "notfound") == 0)
1581 printf("%s", getarg("NOTFOUNDERR"));
1582 if (strcmp(p, "eventlocked") == 0)
1583 printf("%s", getarg("EVENTLOCKEDERR"));
1584 }
1585
1586 #if 0
1587 /*
1588 ** Create/Estimate the To: header which lists event participants.
1589 */
1590
1591 static void mktohdr(char *h, size_t *sizep)
1592 {
1593 int need_toh=1;
1594 size_t l=0;
1595 struct my_participant *p;
1596
1597 *sizep=4;
1598
1599 for (p=my_participant_list; p; p=p->next)
1600 {
1601 const char *c;
1602
1603 if (*sizep - l > 500)
1604 {
1605 if (h)
1606 *h++='\n';
1607 ++*sizep;
1608 need_toh=1;
1609 l= *sizep;
1610 }
1611
1612 if (need_toh)
1613 {
1614 if (h)
1615 {
1616 strcpy(h, "To: ");
1617 h += 4;
1618 }
1619 *sizep += 4;
1620 need_toh=0;
1621 }
1622 else
1623 {
1624 if (h)
1625 {
1626 strcpy(h, ",\n ");
1627 h += 4;
1628 }
1629 *sizep += 4;
1630 }
1631
1632 if (p->name && *p->name)
1633 {
1634 if (h)
1635 *h++='"';
1636 ++*sizep;
1637
1638 for (c=p->name; *c; c++)
1639 {
1640 if (*c == '"' || *c == '\\')
1641 {
1642 if (h)
1643 *h++ = '\\';
1644 ++*sizep;
1645 }
1646 if (h)
1647 *h++ = *c;
1648 ++*sizep;
1649 }
1650
1651 if (h)
1652 {
1653 *h++='"';
1654 *h++=' ';
1655 }
1656 *sizep += 2;
1657 }
1658
1659 if (h)
1660 *h++='<';
1661 ++*sizep;
1662
1663 for (c=p->address; *c; c++)
1664 {
1665 if (h)
1666 *h++= *c;
1667 ++*sizep;
1668 }
1669 if (h)
1670 *h++='>';
1671 ++*sizep;
1672 }
1673
1674 if (my_participant_list)
1675 {
1676 if (h)
1677 *h++='\n';
1678 ++*sizep;
1679 }
1680
1681 if (h)
1682 *h++=0;
1683 ++*sizep;
1684 }
1685 #endif
1686
sqpcp_newevent()1687 void sqpcp_newevent()
1688 {
1689 char *draftfilename;
1690 int newdraftfd;
1691 const char *p;
1692 unsigned long prev_size=0;
1693 FILE *oldfp=NULL;
1694 int errflag=0;
1695 int do_newevent= *cgi("do.neweventtime") ? 1:0;
1696 int do_newparticipant= *cgi("do.addparticipant") ? 1:0;
1697 int do_delevent=0;
1698 int do_delparticipant= *cgi("do.delparticipant") ? 1:0;
1699 time_t delstart=0, delend=0;
1700
1701 static char *draftmessage_buf=0;
1702
1703 showerror();
1704
1705 if (!do_newevent)
1706 {
1707 if ((p=cgi("do.deleventtime")) && *p)
1708 {
1709 unsigned long a, b;
1710
1711 if (sscanf(p, "%lu-%lu", &a, &b) == 2)
1712 {
1713 delstart=(time_t)a;
1714 delend=(time_t)b;
1715 do_delevent=1;
1716 }
1717 }
1718 }
1719
1720 p=cgi("draftmessage");
1721
1722 if (!do_newevent && !do_delevent && !do_newparticipant
1723 && !do_delparticipant)
1724 {
1725 if (*cgi("do.neweventpreview") && p && *p)
1726 {
1727 printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\" class=\"box-small-outer\"><tr><td>\n");
1728 printf("<table width=\"100%%\" border=\"0\" cellspacing=\"0\" cellpadding=\"4\" class=\"preview\"><tr><td>\n");
1729 newmsg_preview(p);
1730 printf("</td></tr></table>\n");
1731 printf("</td></tr></table>\n");
1732 }
1733 return;
1734 }
1735
1736 if (p && *p)
1737 {
1738 oldfp=openoldfp(p, &prev_size);
1739 if (!oldfp)
1740 p="";
1741 }
1742
1743 if (p && *p)
1744 {
1745 newdraftfd=maildir_recreatemsg(INBOX "." DRAFTS, p, &draftfilename);
1746 }
1747 else
1748 {
1749 newdraftfd=maildir_createmsg(INBOX "." DRAFTS, 0, &draftfilename);
1750 maildir_writemsgstr(newdraftfd, "X-Event: 1\n");
1751
1752 if (draftmessage_buf)
1753 free(draftmessage_buf);
1754 if ((draftmessage_buf=strdup(draftfilename)) != 0)
1755 cgi_put("draftmessage", draftmessage_buf);
1756 }
1757
1758 if (do_newevent || do_delevent || do_newparticipant
1759 || do_delparticipant)
1760 {
1761 if (oldfp)
1762 {
1763 struct rfc822hdr h;
1764
1765 rfc822hdr_init(&h, 8192);
1766 while (rfc822hdr_read(&h, oldfp, NULL, 0) == 0)
1767 {
1768 unsigned long a, b;
1769 if (do_delevent && strcasecmp(h.header,
1770 "X-Event-Time")
1771 == 0 && h.value && sscanf(h.value,
1772 "%lu %lu",
1773 &a, &b) == 2)
1774
1775 {
1776 if ( (time_t)a == delstart &&
1777 (time_t)b == delend)
1778 continue;
1779 }
1780
1781 if (do_delparticipant
1782 && strcasecmp(h.header, "X-Event-Participant")
1783 == 0 && h.value)
1784 {
1785 if (strcmp(h.value,
1786 cgi("do.delparticipant"))
1787 == 0)
1788 continue;
1789 }
1790 if (strcasecmp(h.header,
1791 "X-Event-Participant") == 0 &&
1792 h.value)
1793 add_my_participant(h.value);
1794
1795 if (strcasecmp(h.header, "To") == 0)
1796 continue;
1797 /* To: header rebuilt later */
1798
1799 maildir_writemsgstr(newdraftfd, h.header);
1800 maildir_writemsgstr(newdraftfd, ": ");
1801 maildir_writemsgstr(newdraftfd, h.value);
1802 maildir_writemsgstr(newdraftfd, "\n");
1803 }
1804 rfc822hdr_free(&h);
1805
1806 }
1807
1808 if (do_newevent && addtime(newdraftfd))
1809 {
1810 errflag=1;
1811 printf("%s", getarg("TIMEERR"));
1812 }
1813
1814 if (do_newparticipant)
1815 {
1816 const char *p=cgi("addressbookname");
1817
1818 if (!*p)
1819 p=cgi("participant1");
1820
1821 addparticipant(newdraftfd, p);
1822 }
1823
1824 (void)ab_get_nameaddr(save_participant_names,
1825 my_participant_list);
1826
1827 #if 0
1828 {
1829 struct rfc822t *t;
1830 struct rfc822a *a;
1831 char *p;
1832 char *tohdr;
1833 size_t tohdr_size;
1834
1835 mktohdr(NULL, &tohdr_size);
1836
1837 tohdr=malloc(tohdr_size);
1838 if (!tohdr)
1839 enomem();
1840
1841 mktohdr(tohdr, &tohdr_size);
1842
1843 if ((t=rfc822t_alloc_new(tohdr, NULL, NULL)) == NULL)
1844 {
1845 free(tohdr);
1846 enomem();
1847 }
1848
1849 if ((a=rfc822a_alloc(t)) == NULL)
1850 {
1851 rfc822t_free(t);
1852 free(tohdr);
1853 enomem();
1854 }
1855
1856 p=rfc2047_encode_header(a,sqwebmail_content_charset);
1857
1858 if (!p)
1859 {
1860 rfc822a_free(a);
1861 rfc822t_free(t);
1862 free(tohdr);
1863 enomem();
1864 }
1865 free(tohdr);
1866 tohdr=p;
1867 rfc822a_free(a);
1868 rfc822t_free(t);
1869
1870 maildir_writemsgstr(newdraftfd, tohdr);
1871 maildir_writemsgstr(newdraftfd, "\n");
1872 free(tohdr);
1873 }
1874 #endif
1875
1876 sqpcp_eventend(); /* Deallocate participant list */
1877
1878 maildir_writemsgstr(newdraftfd, "\n");
1879 }
1880
1881 if (oldfp)
1882 {
1883 char buf[BUFSIZ];
1884 int n;
1885
1886 while ((n=fread(buf, 1, sizeof(buf), oldfp)) > 0)
1887 maildir_writemsg(newdraftfd, buf, n);
1888 }
1889
1890 if (oldfp)
1891 fclose(oldfp);
1892
1893 if (errflag)
1894 {
1895 maildir_deletenewmsg(newdraftfd, INBOX "." DRAFTS, draftfilename);
1896 }
1897 else if (maildir_closemsg(newdraftfd, INBOX "." DRAFTS, draftfilename, 1,
1898 prev_size))
1899 {
1900 printf("%s", getarg("QUOTAERR"));
1901 }
1902
1903 free(draftfilename);
1904 }
1905
1906 /* Split apart date/time string into space-separated words */
1907
mkargv(char * p,int * argc)1908 static char **mkargv(char *p, int *argc)
1909 {
1910 int pass;
1911 char **argv=0;
1912 char *q;
1913
1914 /* Two passes - count words, then make them */
1915
1916 for (pass=0; pass<2; pass++)
1917 {
1918 if (pass)
1919 {
1920 if ((argv=malloc(sizeof(char *)* (*argc+1))) == NULL)
1921 return (NULL);
1922 }
1923 *argc=0;
1924
1925 for (q=p; *q; )
1926 {
1927 if (isspace((int)(unsigned char)*q))
1928 {
1929 ++q;
1930 continue; /* Skip leading space */
1931 }
1932
1933 if (pass)
1934 argv[ *argc ] = q;
1935 ++*argc;
1936
1937 while (*q) /* Look for next space */
1938 {
1939 if (isspace((int)(unsigned char)*q))
1940 {
1941 if (pass)
1942 *q=0;
1943 ++q;
1944 break;
1945 }
1946 ++q;
1947 }
1948 }
1949 }
1950 argv[ *argc ] = 0;
1951 return (argv);
1952 }
1953
1954 static int savetime(time_t, time_t, void *);
1955
addtime(int newdraftfd)1956 static int addtime(int newdraftfd)
1957 {
1958 struct pcp_parse_datetime_info pdi;
1959 char *t_buf;
1960 char **t_argv;
1961 time_t starttime, endtime;
1962 int argn, argc;
1963 int h, m;
1964
1965 pdi.today_name=cgi("today"); /* Locale string */
1966 pdi.tomorrow_name=cgi("tomorrow"); /* Locale string */
1967
1968 t_buf=strdup(cgi("starttime"));
1969 if (!t_buf)
1970 return (-1);
1971 t_argv=mkargv(t_buf, &argc);
1972 if (!t_argv)
1973 {
1974 free(t_buf);
1975 return (-1);
1976 }
1977
1978 argn=0;
1979 starttime=pcp_parse_datetime(&argn, argc, t_argv, &pdi);
1980 free(t_argv);
1981 free(t_buf);
1982 if (!starttime)
1983 return (-1);
1984 h=atoi(cgi("hours"));
1985 m=atoi(cgi("mins"));
1986 if (h < 0 || m < 0 || h > 999 || m > 59)
1987 return (-1);
1988
1989 endtime=starttime + h * 60 * 60 + m * 60;
1990
1991 argn=0;
1992 t_buf=strdup(cgi("endtime"));
1993 if (!t_buf)
1994 return (-1);
1995 t_argv=mkargv(t_buf, &argc);
1996 if (!t_argv)
1997 {
1998 free(t_buf);
1999 return (-1);
2000 }
2001
2002 if (argc == 0) /* Not a weekly event */
2003 {
2004 savetime(starttime, endtime, &newdraftfd);
2005 }
2006 else
2007 {
2008 if (pcp_parse_datetime_until(starttime, endtime, &argn, argc,
2009 t_argv,
2010 atoi(cgi("recurring")),
2011 savetime, &newdraftfd))
2012 {
2013 free(t_argv);
2014 free(t_buf);
2015 return (-1);
2016 }
2017 }
2018 free(t_argv);
2019 free(t_buf);
2020 return (0);
2021 }
2022
savetime(time_t from,time_t to,void * dummy)2023 static int savetime(time_t from, time_t to, void *dummy)
2024 {
2025 char buf[NUMBUFSIZE];
2026 int fd= *(int *)dummy;
2027
2028 maildir_writemsgstr(fd, "X-Event-Time: ");
2029 maildir_writemsgstr(fd, libmail_str_time_t(from, buf));
2030 maildir_writemsgstr(fd, " ");
2031 maildir_writemsgstr(fd, libmail_str_time_t(to, buf));
2032 maildir_writemsgstr(fd, "\n");
2033 return (0);
2034 }
2035
addparticipant(int fd,const char * n)2036 static void addparticipant(int fd, const char *n)
2037 {
2038 char *nn, *p, *q;
2039
2040 const char *domain;
2041
2042 domain=getenv("AUTHADDR");
2043
2044 if (domain)
2045 domain=strrchr(domain, '@');
2046
2047 if (domain)
2048 ++domain;
2049 else
2050 domain=myhostname();
2051
2052 while (n && isspace((int)(unsigned char)*n))
2053 ++n;
2054
2055 if (!n || !*n)
2056 return;
2057
2058 if (strchr(n, '\n') || strchr(n, '\r'))
2059 return;
2060
2061 if ((nn=malloc(strlen(n)+strlen(domain)+2)) == NULL)
2062 enomem();
2063
2064 strcpy(nn, n);
2065
2066 for (p=q=nn; *p; p++)
2067 if (!isspace((int)(unsigned char)*p))
2068 q=p+1;
2069 *q=0;
2070
2071 if (strchr(nn, '@') == 0)
2072 strcat(strcat(nn, "@"), domain);
2073
2074
2075 maildir_writemsgstr(fd, "X-Event-Participant: ");
2076 maildir_writemsgstr(fd, nn);
2077 maildir_writemsgstr(fd, "\n");
2078 add_my_participant(nn);
2079 free(nn);
2080 }
2081
2082 /* ------------- Save text ------------- */
2083
savedraft()2084 static char *savedraft()
2085 {
2086 const char *p=cgi("draftmessage");
2087 char *msg, *filename;
2088
2089 if (p && *p)
2090 {
2091 CHECKFILENAME(p);
2092 }
2093
2094 filename=p && *p ? maildir_find(INBOX "." DRAFTS, p):NULL;
2095
2096 msg=newmsg_createdraft_do(filename, cgi("message"), NEWMSG_PCP);
2097 if (filename)
2098 free(filename);
2099
2100 if (!msg)
2101 enomem();
2102 return (msg);
2103 }
2104
previewdraft(char * msg,void (* func)(const char *))2105 static void previewdraft(char *msg, void (*func)(const char *))
2106 {
2107 char *msg2, *msg2p;
2108
2109 msg2=maildir_find(INBOX "." DRAFTS, msg);
2110 free(msg);
2111 if (!msg2)
2112 enomem();
2113 if ((msg2p=strrchr(msg2, '/')) != 0)
2114 ++msg2p;
2115 else
2116 msg2p=msg2;
2117
2118 cgi_put("draftmessage", msg2p);
2119 if (func)
2120 (*func)(msg2p);
2121 output_form("newevent.html");
2122 free(msg2);
2123 }
2124
sqpcp_preview()2125 void sqpcp_preview()
2126 {
2127 char *msg;
2128
2129 msg=savedraft();
2130 previewdraft(msg, NULL);
2131 }
2132
sqpcp_postpone()2133 void sqpcp_postpone()
2134 {
2135 char *msg;
2136
2137 msg=savedraft();
2138 free(msg);
2139 output_form("folders.html");
2140 }
2141
2142 static void deleteattach(const char *);
2143
sqpcp_deleteattach()2144 void sqpcp_deleteattach()
2145 {
2146 char *msg;
2147
2148 msg=savedraft();
2149 previewdraft(msg, deleteattach);
2150 }
2151
deleteattach(const char * msg)2152 static void deleteattach(const char *msg)
2153 {
2154 attach_delete(msg);
2155 }
2156
2157 static void doupload(const char *);
2158
sqpcp_uploadattach()2159 void sqpcp_uploadattach()
2160 {
2161 char *msg;
2162
2163 msg=savedraft();
2164 previewdraft(msg, doupload);
2165 }
2166
doupload(const char * msg)2167 static void doupload(const char *msg)
2168 {
2169 int flag;
2170
2171 flag=attach_upload(msg, NULL, NULL);
2172
2173 if (flag)
2174 cgi_put("error", "quota");
2175 }
2176
2177
sqpcp_attachpubkey()2178 void sqpcp_attachpubkey()
2179 {
2180 char *msg;
2181
2182 msg=savedraft();
2183 previewdraft(msg, NULL);
2184 }
2185
sqpcp_attachprivkey()2186 void sqpcp_attachprivkey()
2187 {
2188 char *msg;
2189
2190 msg=savedraft();
2191 previewdraft(msg, NULL);
2192 }
2193
2194 /* ---------------- Save event ------------------ */
2195
2196 struct participant_list {
2197 struct participant_list *next;
2198 char *address;
2199 } ;
2200
2201 struct saveinfo {
2202 struct PCP_event_time *times;
2203 unsigned n_times;
2204 struct PCP_event_participant *participants;
2205 unsigned n_participants;
2206 struct participant_list *participant_list;
2207
2208 char *old_eventid;
2209 } ;
2210
init_saveinfo(struct saveinfo * si,FILE * fp)2211 static int init_saveinfo(struct saveinfo *si, FILE *fp)
2212 {
2213 struct rfc822hdr h;
2214
2215 struct savetimelist {
2216 struct savetimelist *next;
2217 struct PCP_event_time event_time;
2218 } *tlist=NULL, *p;
2219 unsigned tcnt=0;
2220 struct participant_list *l;
2221
2222
2223 si->times=NULL;
2224 si->n_times=0;
2225 si->old_eventid=0;
2226 si->participants=NULL;
2227 si->n_participants=0;
2228 si->participant_list=NULL;
2229
2230 rfc822hdr_init(&h, BUFSIZ);
2231 while (rfc822hdr_read(&h, fp, NULL, 0) == 0)
2232 {
2233 unsigned long a, b;
2234
2235 if (strcasecmp(h.header, "X-Event-Participant") == 0 && h.value)
2236 {
2237 l=malloc(sizeof(struct participant_list));
2238 if (!l || (l->address=strdup(h.value)) == NULL)
2239 {
2240 if (l)
2241 free(l);
2242
2243 while ((l=si->participant_list) != NULL)
2244 {
2245 si->participant_list=l->next;
2246 free(l->address);
2247 free(l);
2248 }
2249 while (tlist)
2250 {
2251 p=tlist;
2252 tlist=p->next;
2253 free(p);
2254 }
2255 rfc822hdr_free(&h);
2256 return (-1);
2257 }
2258 l->next=si->participant_list;
2259 si->participant_list=l;
2260 ++si->n_participants;
2261 }
2262 else if (strcasecmp(h.header, "X-Event-Time") == 0 &&
2263 h.value && sscanf(h.value, "%lu %lu", &a, &b) == 2)
2264 {
2265 if ((p=malloc(sizeof(struct savetimelist))) == NULL)
2266 {
2267 while ((l=si->participant_list) != NULL)
2268 {
2269 si->participant_list=l->next;
2270 free(l->address);
2271 free(l);
2272 }
2273 while (tlist)
2274 {
2275 p=tlist;
2276 tlist=p->next;
2277 free(p);
2278 }
2279 rfc822hdr_free(&h);
2280 return (-1);
2281 }
2282 p->next=tlist;
2283 tlist=p;
2284 p->event_time.start=a;
2285 p->event_time.end=b;
2286 ++tcnt;
2287 }
2288
2289 if (strcasecmp(h.header, "X-Old-EventId") == 0 && h.value)
2290 {
2291 if (si->old_eventid)
2292 free(si->old_eventid);
2293 si->old_eventid=strdup(h.value);
2294 if (!si->old_eventid)
2295 {
2296 rfc822hdr_free(&h);
2297 return (-1);
2298 }
2299 }
2300 }
2301 rfc822hdr_free(&h);
2302
2303 if (si->n_participants)
2304 {
2305 unsigned n=0;
2306
2307 if ((si->participants
2308 =calloc(sizeof(struct PCP_event_participant),
2309 si->n_participants)) == NULL)
2310 {
2311 while ((l=si->participant_list) != NULL)
2312 {
2313 si->participant_list=l->next;
2314 free(l->address);
2315 free(l);
2316 }
2317 while (tlist)
2318 {
2319 p=tlist;
2320 tlist=p->next;
2321 free(p);
2322 }
2323 return (-1);
2324 }
2325
2326 for (l=si->participant_list; l; l=l->next)
2327 {
2328 si->participants[n].address=l->address;
2329 ++n;
2330 }
2331 }
2332
2333 if (tcnt)
2334 {
2335 si->n_times=tcnt;
2336 if ((si->times=malloc(sizeof(struct PCP_event_time)
2337 *tcnt)) == NULL)
2338 {
2339 while ((l=si->participant_list) != NULL)
2340 {
2341 si->participant_list=l->next;
2342 free(l->address);
2343 free(l);
2344 }
2345 while (tlist)
2346 {
2347 p=tlist;
2348 tlist=p->next;
2349 free(p);
2350 }
2351 if (si->old_eventid)
2352 free(si->old_eventid);
2353 return (-1);
2354 }
2355 tcnt=0;
2356 while (tlist)
2357 {
2358 p=tlist;
2359 tlist=p->next;
2360 si->times[tcnt]=p->event_time;
2361 free(p);
2362 ++tcnt;
2363 }
2364 }
2365 return (0);
2366 }
2367
free_saveinfo(struct saveinfo * si)2368 static void free_saveinfo(struct saveinfo *si)
2369 {
2370 struct participant_list *l;
2371
2372 if (si->participants)
2373 free(si->participants);
2374
2375 while ((l=si->participant_list) != NULL)
2376 {
2377 si->participant_list=l->next;
2378 free(l->address);
2379 free(l);
2380 }
2381
2382 if (si->times)
2383 free(si->times);
2384 if (si->old_eventid)
2385 free(si->old_eventid);
2386 }
2387
dropquota(const char * filename,int fd)2388 static void dropquota(const char *filename, int fd)
2389 {
2390 unsigned long filesize=0;
2391
2392 if (maildir_parsequota(filename, &filesize))
2393 {
2394 struct stat stat_buf;
2395
2396 if (fstat(fd, &stat_buf))
2397 stat_buf.st_size=0;
2398 filesize=stat_buf.st_size;
2399 }
2400
2401 maildir_quota_deleted(".", (int64_t)-filesize, -1);
2402 }
2403
2404 /* ------------------------------------------------------------------------
2405 **
2406 ** Save a calendar event
2407 ** ----------------------------------------------------------------------*/
2408
2409 static int dosave(FILE *, struct saveinfo *);
2410
sqpcp_save()2411 void sqpcp_save()
2412 {
2413 char *msg, *sentmsg, *p;
2414 FILE *fp;
2415 struct saveinfo si;
2416 int isgpgerr;
2417
2418 msg=savedraft();
2419 if (*cgi("error")) /* Error, go back to the screen */
2420 {
2421 previewdraft(msg, NULL);
2422 return;
2423 }
2424
2425 fp=openoldfp(msg, NULL);
2426 if (!fp)
2427 {
2428 free(msg);
2429 enomem();
2430 }
2431
2432 if (init_saveinfo(&si, fp))
2433 {
2434 fclose(fp);
2435 free(msg);
2436 enomem();
2437 }
2438
2439 if (si.times == 0)
2440 {
2441 fclose(fp);
2442 cgi_put("error", "time");
2443 previewdraft(msg, NULL);
2444 return;
2445 }
2446 fclose(fp);
2447
2448 sentmsg=newmsg_createsentmsg(msg, &isgpgerr);
2449
2450 /* Immediately remove the formatted event text from the sent folder */
2451
2452 if (sentmsg)
2453 {
2454 p=maildir_find(INBOX "." SENT, sentmsg);
2455 free(sentmsg);
2456 sentmsg=p;
2457 }
2458
2459 if (!sentmsg)
2460 {
2461 cgi_put("error", "quota"); /* TODO: gpgerr */
2462 free_saveinfo(&si);
2463 previewdraft(msg, NULL);
2464 return;
2465 }
2466
2467
2468 fp=fopen(sentmsg, "r");
2469 if (!fp)
2470 {
2471 free(sentmsg);
2472 free(msg);
2473 free_saveinfo(&si);
2474 enomem();
2475 return;
2476 }
2477
2478 fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
2479
2480 unlink(sentmsg);
2481 dropquota(sentmsg, fileno(fp));
2482 free(sentmsg);
2483
2484 if (dosave(fp, &si))
2485 {
2486 fclose(fp);
2487 free_saveinfo(&si);
2488 previewdraft(msg, NULL);
2489 return;
2490 }
2491 fclose(fp);
2492
2493 p=maildir_find(INBOX "." DRAFTS, msg);
2494 free(msg);
2495
2496 fp=p ? fopen(p, "r"):NULL;
2497 unlink(p);
2498 if (fp)
2499 {
2500 dropquota(p, fileno(fp));
2501 fclose(fp);
2502 }
2503 free(p);
2504 free_saveinfo(&si);
2505 output_form("folders.html");
2506 }
2507
2508 /* With all the preliminaries out of the way, put it on the calendar */
2509
saveerror(struct PCP * pcp,const int * xerror)2510 static void saveerror(struct PCP *pcp, const int *xerror)
2511 {
2512 static char *errmsgbuf=0;
2513 const char *p;
2514
2515 if (xerror)
2516 switch (*xerror) {
2517 case PCP_ERR_SYSERR: /* Can be deliberate, see addacl() */
2518 cgi_put("error", "calendar");
2519 cgi_put("pcperror", strerror(errno));
2520 return;
2521 case PCP_ERR_LOCK:
2522 cgi_put("error", "locked");
2523 return;
2524 case PCP_ERR_CONFLICT:
2525 cgi_put("error", "conflict");
2526 return;
2527 case PCP_ERR_EVENTNOTFOUND:
2528 cgi_put("error", "notfound");
2529 return;
2530 case PCP_ERR_EVENTLOCKED:
2531 cgi_put("error", "eventlocked");
2532 return;
2533 }
2534
2535 cgi_put("error", "calendar");
2536
2537 if (errmsgbuf)
2538 free(errmsgbuf);
2539
2540 /*
2541 ** Save err msg into a static buffer, because err msg text memory
2542 ** may go away after the handle is closed.
2543 */
2544
2545 p=pcp_errmsg(pcp);
2546 errmsgbuf=strdup(p ? p:"");
2547 cgi_put("pcperror", errmsgbuf);
2548 }
2549
2550 struct proxy_list_entry {
2551 struct proxy_list_entry *next;
2552 char *userid;
2553 } ;
2554
2555 struct proxy_update_list {
2556 struct proxy_list_entry *new_list;
2557 struct proxy_list_entry *delete_list;
2558 } ;
2559
proxy_update_list_save(const char * action,const char * userid,void * voidarg)2560 static void proxy_update_list_save(const char *action,
2561 const char *userid,
2562 void *voidarg)
2563 {
2564 struct proxy_update_list *pul=(struct proxy_update_list *)voidarg;
2565
2566 struct proxy_list_entry **eptr, *e;
2567
2568 if (strcmp(action, "NEW") == 0)
2569 eptr= &pul->new_list;
2570 else if (strcmp(action, "DELETE") == 0)
2571 eptr= &pul->delete_list;
2572 else
2573 return;
2574
2575 while (*eptr && strcmp( (*eptr)->userid, userid) == 0)
2576 eptr= &(*eptr)->next;
2577
2578 if ((e=malloc(sizeof(struct proxy_list_entry))) == NULL ||
2579 (e->userid=strdup(userid)) == NULL)
2580 {
2581 if (e)
2582 free(e);
2583 fprintf(stderr, "CRIT: out of memory.\n");
2584 return;
2585 }
2586
2587 e->next= *eptr;
2588 *eptr=e;
2589 }
2590
proxy_update_list_free(struct proxy_update_list * p)2591 static void proxy_update_list_free(struct proxy_update_list *p)
2592 {
2593 struct proxy_list_entry *e;
2594
2595 while ((e=p->new_list) != NULL)
2596 {
2597 p->new_list=e->next;
2598 free(e->userid);
2599 free(e);
2600 }
2601
2602 while ((e=p->delete_list) != NULL)
2603 {
2604 p->delete_list=e->next;
2605 free(e->userid);
2606 free(e);
2607 }
2608 }
2609
2610 static void proxy_notify_email_msg(FILE *, struct proxy_list_entry *,
2611 const char *,
2612 const struct PCP_event_time *,
2613 unsigned);
2614
proxy_notify_email(FILE * f,struct proxy_update_list * pul,const struct PCP_event_time * t,unsigned tn)2615 static void proxy_notify_email(FILE *f, struct proxy_update_list *pul,
2616 const struct PCP_event_time *t,
2617 unsigned tn)
2618 {
2619 proxy_notify_email_msg(f, pul->new_list, "eventnotifynew.txt",
2620 t, tn);
2621 proxy_notify_email_msg(f, pul->delete_list, "eventnotifydelete.txt",
2622 NULL, 0);
2623 }
2624
2625 static void dosendnotice(FILE *, FILE *, FILE *, struct proxy_list_entry *,
2626 const char *, const struct PCP_event_time *,
2627 unsigned);
2628
proxy_notify_email_msg(FILE * f,struct proxy_list_entry * l,const char * template,const struct PCP_event_time * t,unsigned tn)2629 static void proxy_notify_email_msg(FILE *f, struct proxy_list_entry *l,
2630 const char *template,
2631 const struct PCP_event_time *t,
2632 unsigned tn)
2633 {
2634 FILE *tmpfp;
2635 pid_t p, p2;
2636 int waitstat;
2637 int pipefd[2];
2638 FILE *tofp;
2639 const char *returnaddr=login_returnaddr();
2640 char subjectlabel[100];
2641
2642 if (!l)
2643 return;
2644
2645 if (fseek(f, 0L, SEEK_SET) < 0
2646 || lseek(fileno(f), 0L, SEEK_SET) < 0)
2647 {
2648 fprintf(stderr, "CRIT: seek failed: %s\n", strerror(errno));
2649 return;
2650 }
2651
2652 subjectlabel[0]=0;
2653
2654 if ((tmpfp=open_langform(sqwebmail_content_language,
2655 "eventnotifysubject.txt", 0)) != NULL)
2656 {
2657 if (fgets(subjectlabel, sizeof(subjectlabel), tmpfp) == NULL)
2658 subjectlabel[0]=0;
2659 else
2660 {
2661 char *p=strchr(subjectlabel, '\n');
2662
2663 if (p) *p=0;
2664 }
2665 fclose(tmpfp);
2666 }
2667 if (subjectlabel[0] == 0)
2668 strcpy(subjectlabel, "[calendar]");
2669
2670 if ((tmpfp=open_langform(sqwebmail_content_language, template, 0))
2671 == NULL)
2672 {
2673 fprintf(stderr, "CRIT: %s: %s\n", template, strerror(errno));
2674 return;
2675 }
2676
2677 signal(SIGPIPE, SIG_IGN);
2678
2679 if (pipe(pipefd) < 0)
2680 {
2681 fclose(tmpfp);
2682 fprintf(stderr, "CRIT: pipe: %s\n", strerror(errno));
2683 return;
2684 }
2685
2686 p=fork();
2687
2688 if (p < 0)
2689 {
2690 close(pipefd[0]);
2691 close(pipefd[1]);
2692 fclose(tmpfp);
2693 fprintf(stderr, "CRIT: fork: %s\n", strerror(errno));
2694 return;
2695 }
2696
2697 if (p == 0)
2698 {
2699 dup2(pipefd[0], 0);
2700 close(pipefd[0]);
2701 close(pipefd[1]);
2702 execl(SENDITSH, "sendit.sh", returnaddr,
2703 sqwebmail_mailboxid, NULL);
2704 fprintf(stderr, "CRIT: exec " SENDITSH ": %s\n", strerror(errno));
2705 exit(1);
2706 }
2707 close(pipefd[0]);
2708 if ((tofp=fdopen(pipefd[1], "w")) == NULL)
2709 {
2710 fprintf(stderr, "CRIT: exec " SENDITSH ": %s\n", strerror(errno));
2711 }
2712 else
2713 {
2714 dosendnotice(tofp, tmpfp, f, l, subjectlabel, t, tn);
2715 }
2716 fclose(tofp);
2717 close(pipefd[1]);
2718 fclose(tmpfp);
2719
2720 waitstat=256;
2721 while ((p2=wait(&waitstat)) != p && p2 >= 0)
2722 ;
2723
2724 if (!WIFEXITED(waitstat) || WEXITSTATUS(waitstat))
2725 fprintf(stderr, "CRIT: event notify mail failed\n");
2726 }
2727
2728 /*
2729 ** Ok, the preliminaries are out of the way, now spit it out.
2730 */
2731
dosendnotice(FILE * tofp,FILE * tmpfp,FILE * eventfp,struct proxy_list_entry * idlist,const char * subjectlabel,const struct PCP_event_time * time_list,unsigned n_time_list)2732 static void dosendnotice(FILE *tofp, /* Pipe to sendit.sh */
2733 FILE *tmpfp, /*
2734 ** Template file with MIME headers and
2735 ** canned verbiage
2736 */
2737 FILE *eventfp, /* Original event */
2738 struct proxy_list_entry *idlist,
2739 const char *subjectlabel,
2740 const struct PCP_event_time *time_list,
2741 unsigned n_time_list)
2742 {
2743 struct rfc822hdr h;
2744 const char *p;
2745 int c;
2746 unsigned u;
2747
2748 rfc822hdr_init(&h, 8192);
2749
2750 while (rfc822hdr_read(&h, eventfp, NULL, 0) == 0)
2751 {
2752 if (strcasecmp(h.header, "From") == 0 ||
2753 strcasecmp(h.header, "Date") == 0)
2754 {
2755 fprintf(tofp, "%s: %s\n", h.header,
2756 h.value ? h.value:"");
2757 }
2758 else if (strcasecmp(h.header, "Subject") == 0)
2759 {
2760 fprintf(tofp, "%s: %s %s\n", h.header,
2761 subjectlabel,
2762 h.value ? h.value:"");
2763 }
2764 }
2765 rfc822hdr_free(&h);
2766
2767 p="To: ";
2768
2769 while (idlist)
2770 {
2771 fprintf(tofp, "%s%s", p, idlist->userid);
2772 p=",\n ";
2773 idlist=idlist->next;
2774 }
2775 fprintf(tofp, "\n");
2776
2777 while ((c=getc(tmpfp)) != EOF)
2778 putc(c, tofp);
2779
2780 for (u=0; u<n_time_list; u++)
2781 {
2782 char buffer[200];
2783
2784 if (pcp_fmttimerange(buffer, sizeof(buffer),
2785 time_list[u].start,
2786 time_list[u].end) == 0)
2787 {
2788 fprintf(tofp, " %s\n", buffer);
2789 }
2790 }
2791 }
2792
dosave(FILE * fp,struct saveinfo * si)2793 static int dosave(FILE *fp, struct saveinfo *si)
2794 {
2795 struct PCP *pcp=sqpcp_calendar();
2796 struct PCP_save_event se;
2797 struct PCP_new_eventid *nei;
2798 struct PCP_commit c;
2799
2800 struct proxy_update_list pul;
2801
2802 if (!pcp)
2803 {
2804 cgi_put("error", "calendar"); /* TODO: actual error */
2805 cgi_put("pcperror", "");
2806 return (-1);
2807 }
2808
2809 memset(&se, 0, sizeof(se));
2810 se.write_event_fd=fileno(fp);
2811 se.event_participants=si->participants;
2812 se.n_event_participants=si->n_participants;
2813
2814 if (*cgi("okconflict"))
2815 se.flags |= PCP_OK_CONFLICT;
2816 if (*cgi("okerrors"))
2817 se.flags |= PCP_OK_PROXY_ERRORS;
2818
2819 nei=pcp_new_eventid(pcp, si->old_eventid, &se);
2820 if (!nei)
2821 {
2822 saveerror(pcp, NULL);
2823 return (-1);
2824 }
2825
2826 memset(&c, 0, sizeof(c));
2827 c.event_times=si->times;
2828 c.n_event_times=si->n_times;
2829 c.flags=se.flags;
2830
2831 init_save_conflict();
2832 c.add_conflict_callback=save_conflict;
2833
2834 memset(&pul, 0, sizeof(pul));
2835
2836 c.proxy_callback= &proxy_update_list_save;
2837 c.proxy_callback_ptr= &pul;
2838
2839 if (pcp_commit(pcp, nei, &c))
2840 {
2841 proxy_update_list_free(&pul);
2842 saveerror(pcp, &c.errcode);
2843 pcp_destroy_eventid(pcp, nei);
2844 return (-1);
2845 }
2846 pcp_destroy_eventid(pcp, nei);
2847 unlink(CACHE); /* Have it rebuilt */
2848 proxy_notify_email(fp, &pul, c.event_times, c.n_event_times);
2849 proxy_update_list_free(&pul);
2850 refreshcache(pcp);
2851 return (0);
2852 }
2853
2854 /* -------------- Daily stuff --------------- */
2855
sqpcp_todays_date()2856 void sqpcp_todays_date()
2857 {
2858 unsigned y, m, d;
2859 time_t start;
2860 time_t end;
2861 char buf[100];
2862
2863 if (sscanf(cgi("date"), "%4u%2u%2u", &y, &m, &d) != 3
2864 || pcp_parse_ymd(y, m, d, &start, &end)
2865 || pcp_fmttime(buf, sizeof(buf), start, FMTTIME_DATE))
2866 return;
2867
2868 print_safe(buf);
2869 }
2870
sqpcp_todays_date_verbose()2871 void sqpcp_todays_date_verbose()
2872 {
2873 unsigned y, m, d;
2874 time_t start;
2875 time_t end;
2876 char buf[500];
2877 struct tm *tmptr;
2878
2879 if (sscanf(cgi("date"), "%4u%2u%2u", &y, &m, &d) != 3
2880 || pcp_parse_ymd(y, m, d, &start, &end)
2881 || (tmptr=localtime(&start)) == NULL
2882 || strftime(buf, sizeof(buf), getarg("DATEFORMAT"), tmptr) == 0)
2883 return;
2884
2885 print_safe(buf);
2886 }
2887
sqpcp_weeklylink()2888 void sqpcp_weeklylink()
2889 {
2890 output_scriptptrget();
2891 printf("&form=eventweekly&weekof=%s", cgi("date"));
2892 }
2893
sqpcp_monthlylink()2894 void sqpcp_monthlylink()
2895 {
2896 const char *p=cgi("date");
2897
2898 if (!*p)
2899 p=cgi("weekof");
2900 output_scriptptrget();
2901 printf("&form=eventmonthly&monthof=%s", p);
2902 }
2903
2904 #define VIEW_DAILY 0
2905 #define VIEW_WEEKLY 1
2906 #define VIEW_MONTHLY 2
2907
2908 static void do_daily_view(struct cacherecord *, unsigned, int,
2909 time_t *, time_t *);
2910
show_pcp_errmsg(const char * p)2911 static void show_pcp_errmsg(const char *p)
2912 {
2913 printf("<pre class=\"error\">");
2914 output_attrencoded_oknl_fp(p, stdout);
2915 printf("</pre>");
2916 }
2917
sqpcp_daily_view()2918 void sqpcp_daily_view()
2919 {
2920 unsigned y, m, d;
2921 time_t start;
2922 time_t end;
2923
2924 struct PCP *pcp;
2925 struct cacherecord *recs;
2926 unsigned n_recs;
2927
2928 if (*cgi("clearcache"))
2929 unlink(CACHE);
2930
2931 if (sscanf(cgi("date"), "%4u%2u%2u", &y, &m, &d) != 3
2932 || pcp_parse_ymd(y, m, d, &start, &end))
2933 return;
2934
2935 if ((pcp=sqpcp_calendar()) == NULL)
2936 {
2937 printf("<span class=\"error\">%s</span>", strerror(errno));
2938 return;
2939 }
2940
2941 if (createcache(pcp, &recs, &n_recs, start, end))
2942 {
2943 show_pcp_errmsg(pcp_errmsg(pcp));
2944 return;
2945 }
2946
2947 (void)do_daily_view(recs, n_recs, VIEW_DAILY, NULL, NULL);
2948 destroycache(recs, n_recs);
2949 }
2950
print_event_link_url(const char * id,const char * extra)2951 static void print_event_link_url(const char *id, const char *extra)
2952 {
2953 output_scriptptrget();
2954 printf("%s&form=eventshow&eventid=", extra);
2955 output_urlencoded(id);
2956 if (*cgi("date"))
2957 printf("&date=%s", cgi("date"));
2958 if (*cgi("weekof"))
2959 printf("&weekof=%s", cgi("weekof"));
2960 if (*cgi("monthof"))
2961 printf("&monthof=%s", cgi("monthof"));
2962 }
2963
print_event_link(const char * id,const char * extra,const char * extra2)2964 static void print_event_link(const char *id, const char *extra,
2965 const char *extra2)
2966 {
2967 printf("<a href=\"");
2968 print_event_link_url(id, extra);
2969 printf("\" %s >", extra2);
2970 }
2971
do_daily_view(struct cacherecord * recs,unsigned n_recs,int viewtype,time_t * start_ptr,time_t * end_ptr)2972 static void do_daily_view(struct cacherecord *recs, unsigned n_recs,
2973 int viewtype, time_t *start_ptr, time_t *end_ptr)
2974 {
2975 unsigned i;
2976 int printed=0;
2977
2978 printf("<table width=\"100%%\">");
2979
2980 for (i=0; i<n_recs; i++)
2981 {
2982 char date1[256];
2983 char date2[256];
2984
2985 char time1[128];
2986 char time2[128];
2987
2988 time_t start=recs[i].start;
2989 time_t end=recs[i].end;
2990
2991 if (start_ptr && *start_ptr >= end)
2992 continue;
2993
2994 if (end_ptr && *end_ptr <= start)
2995 continue;
2996
2997 if ( start_ptr && *start_ptr > start)
2998 start= *start_ptr;
2999
3000 if ( end_ptr && *end_ptr < end)
3001 end= *end_ptr;
3002
3003 if (pcp_fmttime(date1, sizeof(date1),
3004 start, FMTTIME_DATE))
3005 continue;
3006 if (pcp_fmttime(date2, sizeof(date2),
3007 end, FMTTIME_DATE))
3008 continue;
3009
3010 printed=1;
3011
3012 if (strcmp(date1, date2) && viewtype == VIEW_DAILY)
3013 {
3014 char timerange[512];
3015
3016 if (pcp_fmttimerange(timerange, sizeof(timerange),
3017 start, end))
3018 continue;
3019
3020 printf("<tr><td align=\"left\">");
3021 print_event_link(recs[i].eventid, "", "class=\"dailyeventtimes\"");
3022 print_safe(timerange);
3023 }
3024 else
3025 {
3026 if (pcp_fmttime(time1, sizeof(time1),
3027 start,
3028 FMTTIME_TIME))
3029 continue;
3030
3031 if (pcp_fmttime(time2,
3032 sizeof(time2),
3033 end,
3034 FMTTIME_TIME))
3035 continue;
3036
3037 printf("<tr><td align=\"left\">");
3038 print_event_link(recs[i].eventid, "", "class=\"dailyeventtimes\"");
3039 print_safe(time1);
3040 printf(" - ");
3041 print_safe(time2);
3042 }
3043 printf("</a>");
3044
3045 if (viewtype == VIEW_DAILY)
3046 {
3047 printf("</td><td width=\"100%%\">");
3048 }
3049 else
3050 printf("<br />");
3051
3052 printf(" ");
3053 print_event_link(recs[i].eventid, "", "class=\"dailyeventsubject\"");
3054 print_event_subject(recs[i].flags, recs[i].subject,
3055 viewtype == VIEW_DAILY ? 80:15);
3056 printf("</a>");
3057 if (viewtype != VIEW_DAILY)
3058 printf("<br /> ");
3059
3060 printf("</td></tr>\n");
3061 }
3062
3063 if (!printed)
3064 {
3065 printf("<tr><td align=\"center\">%s</td></tr>",
3066 getarg("NOEVENTS"));
3067 }
3068
3069 printf("</table>\n");
3070 }
3071
sqpcp_prevday()3072 void sqpcp_prevday()
3073 {
3074 unsigned y, m, d;
3075 time_t start;
3076 time_t end;
3077 struct tm *tm;
3078 char buf[256];
3079
3080 if (sscanf(cgi("date"), "%4u%2u%2u", &y, &m, &d) != 3
3081 || pcp_parse_ymd(y, m, d, &start, &end))
3082 return;
3083
3084 start -= 12 * 60 * 60;
3085
3086 if ((tm=localtime(&start)) == NULL)
3087 return;
3088
3089 y=tm->tm_year + 1900;
3090 m=tm->tm_mon + 1;
3091 d=tm->tm_mday;
3092
3093 if (pcp_parse_ymd(y, m, d, &start, &end)
3094 || (tm=localtime(&start)) == NULL
3095 || strftime(buf, sizeof(buf), getarg("PREVDAY"), tm) == 0)
3096 return;
3097
3098 printf("<a class=\"dailynextprev\" href=\"");
3099 output_scriptptrget();
3100 printf("&form=eventdaily&date=%04d%02d%02d\">%s</a>", y, m, d, buf);
3101 }
3102
sqpcp_nextday()3103 void sqpcp_nextday()
3104 {
3105 unsigned y, m, d;
3106 time_t start;
3107 time_t end;
3108 struct tm *tm;
3109 char buf[256];
3110
3111 if (sscanf(cgi("date"), "%4u%2u%2u", &y, &m, &d) != 3
3112 || pcp_parse_ymd(y, m, d, &start, &end))
3113 return;
3114
3115 start=end;
3116
3117 if ((tm=localtime(&start)) == NULL)
3118 return;
3119
3120 y=tm->tm_year + 1900;
3121 m=tm->tm_mon + 1;
3122 d=tm->tm_mday;
3123
3124 if (pcp_parse_ymd(y, m, d, &start, &end)
3125 || (tm=localtime(&start)) == NULL
3126 || strftime(buf, sizeof(buf), getarg("NEXTDAY"), tm) == 0)
3127 return;
3128
3129 printf("<a class=\"dailynextprev\" href=\"");
3130 output_scriptptrget();
3131 printf("&form=eventdaily&date=%04d%02d%02d\">%s</a>", y, m, d, buf);
3132 }
3133
3134 /* -------------- Display event stuff --------------- */
3135
3136 struct display_retr_time_list {
3137 struct display_retr_time_list *next;
3138 time_t start;
3139 time_t end;
3140 } ;
3141
3142 struct display_retr_participant_list {
3143 struct display_retr_participant_list *next;
3144 char *participant;
3145 } ;
3146
3147 struct display_retr {
3148 FILE *f;
3149
3150 struct display_retr_time_list *time_list;
3151 struct display_retr_participant_list *participant_list;
3152
3153 } ;
3154
free_display_retr(struct display_retr * r)3155 static void free_display_retr(struct display_retr *r)
3156 {
3157 }
3158
3159
3160 static int save_displayed_event(struct PCP_retr *, const char *, int, void *);
3161
3162 static int set_status(struct PCP_retr *, int, void *);
3163
sqpcp_displayeventinit()3164 void sqpcp_displayeventinit()
3165 {
3166 struct PCP *pcp;
3167 const char *event_id_list[2];
3168 struct PCP_retr r;
3169
3170 showerror();
3171
3172 pcp=sqpcp_calendar();
3173
3174 if (!pcp)
3175 return;
3176
3177 event_id_list[0]=cgi("eventid");
3178 event_id_list[1]=0;
3179
3180 init_save_conflict();
3181 if (*cgi("docancel"))
3182 {
3183 if (pcp_cancel(pcp, event_id_list[0], NULL))
3184 show_pcp_errmsg(pcp_errmsg(pcp));
3185 unlink(CACHE);
3186 }
3187
3188 if (*cgi("douncancel"))
3189 {
3190 struct PCP_uncancel u;
3191 int flags=0;
3192
3193 memset(&u, 0, sizeof(u));
3194
3195 if (*cgi("okconflict"))
3196 flags |= PCP_OK_CONFLICT;
3197
3198 u.uncancel_conflict_callback=save_conflict;
3199 if (pcp_uncancel(pcp, event_id_list[0], flags, &u))
3200 {
3201 saveerror(pcp, &u.errcode);
3202 showerror();
3203 if (u.errcode == PCP_ERR_CONFLICT)
3204 cgi_put("okconflict", "1");
3205 }
3206 unlink(CACHE);
3207 }
3208
3209 memset(&r, 0, sizeof(r));
3210 r.event_id_list=event_id_list;
3211 r.callback_retr_status=set_status;
3212
3213 if (pcp_retr(pcp, &r))
3214 {
3215 show_pcp_errmsg(pcp_errmsg(pcp));
3216 return;
3217 }
3218
3219 }
3220
set_status(struct PCP_retr * pcp,int status,void * dummy)3221 static int set_status(struct PCP_retr *pcp, int status, void *dummy)
3222 {
3223 cgi_put("event_cancelled", status & LIST_CANCELLED ? "1":"");
3224 cgi_put("event_booked", status & LIST_BOOKED ? "1":"");
3225 cgi_put("event_proxy", status & LIST_PROXY ? "1":"");
3226 return (0);
3227 }
3228
save_displayed_date(struct PCP_retr * r,time_t start,time_t end,void * vp)3229 static int save_displayed_date(struct PCP_retr *r, time_t start, time_t end,
3230 void *vp)
3231 {
3232 struct display_retr *dr=(struct display_retr *)vp;
3233
3234 struct display_retr_time_list **ptr, *p;
3235
3236 for (ptr= &dr->time_list; *ptr; ptr=&(*ptr)->next)
3237 if ((*ptr)->start > start)
3238 break;
3239
3240 if ((p=malloc(sizeof(struct display_retr_time_list))) == NULL)
3241 return (-1);
3242
3243 p->next= *ptr;
3244 *ptr=p;
3245 p->start=start;
3246 p->end=end;
3247
3248 return (0);
3249 }
3250
save_displayed_participants(struct PCP_retr * r,const char * address,const char * dummy,void * vp)3251 static int save_displayed_participants(struct PCP_retr *r, const char *address,
3252 const char *dummy, void *vp)
3253 {
3254 struct display_retr *dr=(struct display_retr *)vp;
3255
3256 struct display_retr_participant_list **ptr, *p;
3257
3258 for (ptr= &dr->participant_list; *ptr; ptr=&(*ptr)->next)
3259 if (strcasecmp((*ptr)->participant, address) > 0)
3260 break;
3261
3262 if ((p=malloc(sizeof(struct display_retr_participant_list))) == NULL)
3263 return (-1);
3264
3265 if ((p->participant=strdup(address)) == NULL)
3266 {
3267 free(p);
3268 return (-1);
3269 }
3270 p->next= *ptr;
3271 *ptr=p;
3272 return (0);
3273 }
3274
sqpcp_displayevent()3275 void sqpcp_displayevent()
3276 {
3277 struct PCP *pcp=sqpcp_calendar();
3278 const char *event_id_list[2];
3279 struct PCP_retr r;
3280 struct display_retr dr;
3281 struct maildir_tmpcreate_info createInfo;
3282 struct display_retr_time_list *tl;
3283 struct display_retr_participant_list *pl;
3284
3285 if (!pcp)
3286 return;
3287
3288 event_id_list[0]=cgi("eventid");
3289 event_id_list[1]=0;
3290
3291 memset(&r, 0, sizeof(r));
3292 memset(&dr, 0, sizeof(dr));
3293 r.event_id_list=event_id_list;
3294 r.callback_arg=&dr;
3295 r.callback_rfc822_func=save_displayed_event;
3296 r.callback_retr_date=save_displayed_date;
3297 r.callback_retr_participants=save_displayed_participants;
3298
3299 maildir_purgemimegpg(); /* Delete previous :calendar: file */
3300
3301 maildir_tmpcreate_init(&createInfo);
3302 createInfo.uniq=":calendar:";
3303 createInfo.doordie=1;
3304
3305 if ((dr.f=maildir_tmpcreate_fp(&createInfo)) == NULL)
3306 {
3307 error(strerror(errno));
3308 }
3309
3310 cgi_put(MIMEGPGFILENAME, strrchr(createInfo.tmpname, '/')+1);
3311
3312 if (pcp_retr(pcp, &r))
3313 {
3314 free_display_retr(&dr);
3315 fclose(dr.f);
3316 cgi_put(MIMEGPGFILENAME, "");
3317 unlink(createInfo.tmpname);
3318 maildir_tmpcreate_free(&createInfo);
3319 show_pcp_errmsg(pcp_errmsg(pcp));
3320 return;
3321 }
3322 fclose(dr.f);
3323
3324 printf("<table class=\"calendarevent\" align=\"center\" border=\"0\"><tr valign=\"top\"><th align=\"left\">%s</th><td>",
3325 getarg("EVENT"));
3326
3327 for (tl=dr.time_list; tl; tl=tl->next)
3328 {
3329 char buffer[512];
3330
3331 if (pcp_fmttimerange(buffer, sizeof(buffer),
3332 tl->start, tl->end))
3333 continue;
3334
3335 printf("<span class=\"tt\">");
3336 print_safe(buffer);
3337 printf("</span><br />\n");
3338 }
3339 printf("</td></tr>\n");
3340
3341 if (dr.participant_list)
3342 {
3343 printf("<tr valign=\"top\"><th align=\"left\">%s</th><td>",
3344 getarg("PARTICIPANTS"));
3345 for (pl=dr.participant_list; pl; pl=pl->next)
3346 {
3347 printf("<span class=\"tt\"><");
3348 print_safe(pl->participant);
3349 printf("></span><br />\n");
3350 }
3351 printf("</td></tr>");
3352 }
3353 printf("</table>\n");
3354 folder_showmsg(INBOX "." DRAFTS, 0);
3355 free_display_retr(&dr);
3356 cgi_put(MIMEGPGFILENAME, "");
3357 maildir_tmpcreate_free(&createInfo);
3358 }
3359
save_displayed_event(struct PCP_retr * r,const char * buf,int cnt,void * vp)3360 static int save_displayed_event(struct PCP_retr *r,
3361 const char *buf, int cnt,
3362 void *vp)
3363 {
3364 if (fwrite( buf, cnt, 1, ((struct display_retr *)vp)->f) != 1)
3365 return (-1);
3366
3367 return (0);
3368 }
3369
3370
back_to_summary()3371 static void back_to_summary()
3372 {
3373 const char *p;
3374
3375 if (*(p=cgi("monthof")) != 0)
3376 {
3377 printf("&form=eventmonthly&monthof=%s", p);
3378 }
3379 else if (*(p=cgi("weekof")) != 0)
3380 {
3381 printf("&form=eventweekly&weekof=%s", p);
3382 }
3383 else
3384 {
3385 p=cgi("date");
3386 printf("&form=eventdaily&date=%s", p);
3387 }
3388 }
3389
sqpcp_eventbacklink()3390 void sqpcp_eventbacklink()
3391 {
3392 output_scriptptrget();
3393 back_to_summary();
3394 }
3395
sqpcp_eventeditlink()3396 void sqpcp_eventeditlink()
3397 {
3398 const char *p=cgi("date");
3399
3400 output_scriptptrget();
3401 printf("&form=event-edit&date=%s&eventid=", p);
3402 output_urlencoded(cgi("eventid"));
3403 }
3404
sqpcp_eventdeletelink()3405 void sqpcp_eventdeletelink()
3406 {
3407 const char *p=cgi("date");
3408
3409 output_scriptptrget();
3410 printf("&eventid=");
3411
3412 output_urlencoded(cgi("eventid"));
3413 printf("&form=eventdelete&date=%s", p);
3414 }
3415
sqpcp_eventcanceluncancellink()3416 void sqpcp_eventcanceluncancellink()
3417 {
3418 print_event_link_url(cgi("eventid"), *cgi("event_cancelled")
3419 ? (*cgi("okconflict") ?
3420 "&okconflict=1&douncancel=1"
3421 :"&douncancel=1")
3422 :"&docancel=1");
3423 }
3424
sqpcp_eventcanceluncancelimage()3425 void sqpcp_eventcanceluncancelimage()
3426 {
3427 printf("%s", getarg(*cgi("event_cancelled")
3428 ? "UNCANCELIMAGE":"CANCELIMAGE"));
3429 }
3430
sqpcp_eventcanceluncanceltext()3431 void sqpcp_eventcanceluncanceltext()
3432 {
3433 printf("%s", getarg(*cgi("event_cancelled")
3434 ? "UNCANCELTEXT":"CANCELTEXT"));
3435 }
3436
sqpcp_deleteeventinit()3437 void sqpcp_deleteeventinit()
3438 {
3439 sqpcp_displayeventinit();
3440 if (*cgi("event_proxy"))
3441 printf("%s", getarg("PROXYWARN"));
3442 }
3443
save_orig_headers(struct PCP_retr * pcp,const char * h,const char * v,void * vp)3444 static int save_orig_headers(struct PCP_retr *pcp,
3445 const char *h, const char *v, void *vp)
3446 {
3447 FILE *fp=(FILE *)vp;
3448
3449 if (strcasecmp(h, "Date"))
3450 fprintf(fp, "%s: %s\n", h, v);
3451 return (0);
3452 }
3453
3454
sqpcp_dodelete()3455 void sqpcp_dodelete()
3456 {
3457 struct PCP *pcp=sqpcp_calendar();
3458 struct PCP_retr r;
3459 const char *event_list_ary[2];
3460 struct PCP_delete del;
3461 struct proxy_update_list pul;
3462 FILE *tmpfp;
3463
3464 if (!pcp)
3465 return;
3466
3467 memset(&del, 0, sizeof(del));
3468 del.id=cgi("eventid");
3469
3470 memset(&r, 0, sizeof(r));
3471 event_list_ary[0]=del.id;
3472 event_list_ary[1]=NULL;
3473 r.event_id_list=event_list_ary;
3474 r.callback_headers_func=save_orig_headers;
3475
3476 tmpfp=tmpfile();
3477 if (!tmpfp)
3478 enomem();
3479 r.callback_arg=tmpfp;
3480 pcp_retr(pcp, &r);
3481
3482 {
3483 time_t t;
3484
3485 time(&t);
3486
3487 fprintf(tmpfp, "Date: %s\n\n", rfc822_mkdate(t));
3488 }
3489
3490 memset(&pul, 0, sizeof(pul));
3491 del.proxy_callback=&proxy_update_list_save;
3492 del.proxy_callback_ptr=&pul;
3493
3494 if (pcp_delete(pcp, &del))
3495 {
3496 saveerror(pcp, &del.errcode);
3497 output_form("eventdelete.html");
3498 }
3499 else
3500 {
3501 proxy_notify_email(tmpfp, &pul, NULL, 0);
3502 }
3503 fclose(tmpfp);
3504 proxy_update_list_free(&pul);
3505 unlink(CACHE);
3506 output_form("eventdaily.html");
3507 }
3508
3509 /* ------------- Bring in an event to edit -------------------------- */
3510
3511 static int doeventedit(struct PCP *, int);
3512
sqpcp_eventedit()3513 int sqpcp_eventedit()
3514 {
3515 struct PCP *pcp=sqpcp_calendar();
3516 int newdraftfd;
3517 char *draftfilename;
3518
3519 if (!pcp)
3520 return (-1);
3521
3522 newdraftfd=maildir_createmsg(INBOX "." DRAFTS, 0, &draftfilename);
3523 if (doeventedit(pcp, newdraftfd))
3524 {
3525 maildir_deletenewmsg(newdraftfd, INBOX "." DRAFTS, draftfilename);
3526 }
3527 else if (maildir_closemsg(newdraftfd, INBOX "." DRAFTS, draftfilename, 1, 0))
3528 {
3529 cgi_put("error", "quota");
3530 }
3531 else
3532 {
3533 static char *filenamebuf=0;
3534
3535 if (filenamebuf)
3536 free(filenamebuf);
3537
3538 filenamebuf=draftfilename;
3539 cgi_put("draftmessage", filenamebuf);
3540 return (0);
3541 }
3542 free(draftfilename);
3543 return (-1);
3544 }
3545
3546 struct getedit_info {
3547 int fd;
3548 int flag;
3549
3550 int in_headers;
3551 int sol;
3552 int skiph;
3553
3554 } ;
3555
get_date(struct PCP_retr * r,time_t start,time_t end,void * vp)3556 static int get_date(struct PCP_retr *r, time_t start, time_t end, void *vp)
3557 {
3558 char buf[NUMBUFSIZE];
3559 struct getedit_info *ge=(struct getedit_info *)vp;
3560
3561 maildir_writemsgstr(ge->fd, "X-Event-Time: ");
3562 maildir_writemsgstr(ge->fd, libmail_str_time_t(start, buf));
3563 maildir_writemsgstr(ge->fd, " ");
3564 maildir_writemsgstr(ge->fd, libmail_str_time_t(end, buf));
3565 maildir_writemsgstr(ge->fd, "\n");
3566
3567 return (0);
3568 }
3569
get_participants(struct PCP_retr * r,const char * address,const char * dummy,void * vp)3570 static int get_participants(struct PCP_retr *r, const char *address,
3571 const char *dummy, void *vp)
3572 {
3573 struct getedit_info *ge=(struct getedit_info *)vp;
3574
3575 maildir_writemsgstr(ge->fd, "X-Event-Participant: ");
3576 maildir_writemsgstr(ge->fd, address);
3577 maildir_writemsgstr(ge->fd, "\n");
3578
3579 return (0);
3580 }
3581
get_msgtext(struct PCP_retr * r,const char * ptr,int n,void * vp)3582 static int get_msgtext(struct PCP_retr *r, const char *ptr, int n, void *vp)
3583 {
3584 struct getedit_info *ge=(struct getedit_info *)vp;
3585
3586 /* We want to drop all X headers when we read in this event */
3587 /* Also, drop CRs */
3588
3589 ge->flag=1;
3590
3591 while (n)
3592 {
3593 int i;
3594
3595 if (!ge->in_headers) /* Write out msg body */
3596 {
3597 while (n)
3598 {
3599 if (*ptr == '\r')
3600 {
3601 ++ptr;
3602 --n;
3603 continue;
3604 }
3605
3606 for (i=0; i<n; i++)
3607 if (ptr[i] == '\r')
3608 break;
3609
3610 maildir_writemsg(ge->fd, ptr, i);
3611 ptr += i;
3612 n -= i;
3613 }
3614 break;
3615 }
3616
3617 if (*ptr == '\r')
3618 {
3619 ++ptr;
3620 --n;
3621 continue;
3622 }
3623
3624 if (*ptr == '\n')
3625 {
3626 if (!ge->skiph)
3627 maildir_writemsgstr(ge->fd, "\n");
3628
3629 ge->skiph=0;
3630 if (ge->sol)
3631 ge->in_headers=0; /* End of headers */
3632 ge->sol=1;
3633 ++ptr;
3634 --n;
3635 continue;
3636 }
3637
3638 if (ge->sol && (*ptr == 'x' || *ptr == 'X'))
3639 ge->skiph=1;
3640
3641 for (i=0; i<n; i++)
3642 if (ptr[i] == '\r' || ptr[i] == '\n')
3643 break;
3644
3645 if (!ge->skiph) /* Skip X- header */
3646 maildir_writemsg(ge->fd, ptr, i);
3647 ptr += i;
3648 n -= i;
3649 }
3650 return (0);
3651 }
3652
doeventedit(struct PCP * pcp,int fd)3653 static int doeventedit(struct PCP *pcp, int fd)
3654 {
3655 const char *p=cgi("eventid");
3656 struct PCP_retr r;
3657 struct getedit_info ge;
3658
3659 const char *eventid[2];
3660
3661 if (!p || !*p)
3662 return (-1);
3663
3664 maildir_writemsgstr(fd, "X-Event: 1\nX-Old-EventId: ");
3665 maildir_writemsgstr(fd, p);
3666 maildir_writemsgstr(fd, "\n");
3667
3668 memset(&r, 0, sizeof(r));
3669 eventid[0]=p;
3670 eventid[1]=NULL;
3671
3672 r.event_id_list=eventid;
3673
3674 ge.fd=fd;
3675 ge.flag=0;
3676 r.callback_arg=≥
3677
3678 r.callback_retr_date=get_date;
3679 r.callback_retr_participants=get_participants;
3680
3681 if (pcp_retr(pcp, &r))
3682 {
3683 saveerror(pcp, &r.errcode);
3684 return (-1);
3685 }
3686
3687 memset(&r, 0, sizeof(r));
3688 eventid[0]=p;
3689 eventid[1]=NULL;
3690
3691 r.event_id_list=eventid;
3692
3693 ge.fd=fd;
3694 ge.flag=0;
3695 r.callback_arg=≥
3696
3697 ge.in_headers=1;
3698 ge.sol=1;
3699 ge.skiph=0;
3700
3701 r.callback_rfc822_func=get_msgtext;
3702 if (pcp_retr(pcp, &r))
3703 {
3704 saveerror(pcp, &r.errcode);
3705 return (-1);
3706 }
3707
3708 if (!ge.flag)
3709 {
3710 cgi_put("error", "notfound");
3711 return (-1);
3712 }
3713
3714 return (0);
3715 }
3716
3717 /* ------ Weekly stuff ------- */
3718
prevday(time_t * tm)3719 static void prevday(time_t *tm)
3720 {
3721 struct tm *tmptr;
3722 time_t t= *tm - 12 * 60 * 60;
3723
3724 if ((tmptr=localtime(&t)) == NULL)
3725 {
3726 enomem();
3727 return;
3728 }
3729
3730 if (pcp_parse_ymd(tmptr->tm_year + 1900, tmptr->tm_mon + 1,
3731 tmptr->tm_mday, tm, &t))
3732 {
3733 enomem();
3734 }
3735 }
3736
nextday(time_t * tm)3737 static void nextday(time_t *tm)
3738 {
3739 struct tm *tmptr;
3740 time_t t= *tm + 36 * 60 * 60;
3741
3742 if ((tmptr=localtime(&t)) == NULL)
3743 {
3744 enomem();
3745 return;
3746 }
3747
3748 if (pcp_parse_ymd(tmptr->tm_year + 1900, tmptr->tm_mon + 1,
3749 tmptr->tm_mday, tm, &t))
3750 {
3751 enomem();
3752 }
3753 }
3754
get_start_of_week()3755 static time_t get_start_of_week()
3756 {
3757 unsigned y, m, d;
3758 time_t start;
3759 time_t end;
3760 struct tm *tmptr;
3761 int i;
3762
3763 if (sscanf(cgi("weekof"), "%4u%2u%2u", &y, &m, &d) != 3
3764 || pcp_parse_ymd(y, m, d, &start, &end))
3765 {
3766 time(&start);
3767 if ((tmptr=localtime(&start)) == NULL)
3768 {
3769 enomem();
3770 return (0);
3771 }
3772 y=tmptr->tm_year + 1900;
3773 m=tmptr->tm_mon + 1;
3774 d=tmptr->tm_mday;
3775
3776 if (pcp_parse_ymd(y, m, d, &start, &end))
3777 {
3778 enomem();
3779 return (0);
3780 }
3781 }
3782
3783 for (i=0; i<7; i++)
3784 {
3785 tmptr=localtime(&start);
3786 if (!tmptr)
3787 enomem();
3788
3789 if (tmptr->tm_wday == pref_startofweek)
3790 break;
3791
3792 prevday(&start);
3793 }
3794
3795 return (start);
3796 }
3797
sqpcp_show_cal_week()3798 void sqpcp_show_cal_week()
3799 {
3800 time_t start=get_start_of_week();
3801 struct tm *tmptr;
3802 char buf[512];
3803
3804 if ((tmptr=localtime(&start)) == NULL)
3805 return;
3806
3807 if (strftime(buf, sizeof(buf), getarg("DATEFORMAT"), tmptr) == 0)
3808 return;
3809
3810 print_safe(buf);
3811 }
3812
sqpcp_show_cal_nextweek()3813 void sqpcp_show_cal_nextweek()
3814 {
3815 time_t start=get_start_of_week();
3816 int i;
3817 struct tm *tmptr;
3818
3819 for (i=0; i<7; i++)
3820 nextday(&start);
3821
3822 if ((tmptr=localtime(&start)) == NULL)
3823 return;
3824
3825 output_scriptptrget();
3826 printf("&form=eventweekly&weekof=%04d%02d%02d",
3827 tmptr->tm_year + 1900, tmptr->tm_mon+1, tmptr->tm_mday);
3828
3829 }
3830
sqpcp_show_cal_prevweek()3831 void sqpcp_show_cal_prevweek()
3832 {
3833 time_t start=get_start_of_week();
3834 int i;
3835 struct tm *tmptr;
3836
3837 for (i=0; i<7; i++)
3838 prevday(&start);
3839
3840 if ((tmptr=localtime(&start)) == NULL)
3841 return;
3842
3843 output_scriptptrget();
3844 printf("&form=eventweekly&weekof=%04d%02d%02d",
3845 tmptr->tm_year + 1900, tmptr->tm_mon+1, tmptr->tm_mday);
3846
3847 }
3848
sqpcp_displayweek()3849 void sqpcp_displayweek()
3850 {
3851 int i;
3852 time_t start=get_start_of_week(), save_start;
3853 time_t end;
3854 struct PCP *pcp=sqpcp_calendar();
3855 struct cacherecord *recs;
3856 unsigned n_recs;
3857
3858 if (!pcp)
3859 return;
3860
3861 save_start=start;
3862
3863 for (i=0; i<7; i++)
3864 {
3865 nextday(&start);
3866 }
3867
3868 if (createcache(pcp, &recs, &n_recs, save_start, start))
3869 {
3870 show_pcp_errmsg(pcp_errmsg(pcp));
3871 return;
3872 }
3873
3874 printf("<table align=\"center\" border=\"0\" class=\"weekly-border\""
3875 " cellpadding=\"0\" cellspacing=\"0\" width=\"100%%\">"
3876 "<tr><td>\n");
3877 printf("<table border=\"1\" class=\"weekly-bg\" cellspacing=\"0\" cellpadding=\"10\" width=\"100%%\">"
3878 "<tr valign=\"top\">");
3879
3880 start=save_start;
3881 for (i=0; i<7; i++)
3882 {
3883 const char *p;
3884 struct tm *tmptr;
3885
3886 printf("<td width=\"14%%\">");
3887 p=pcp_wdayname((i + pref_startofweek) % 7);
3888 printf("<div align=\"center\" class=\"weekly-day\">");
3889 printf("<a href=\"");
3890 output_scriptptrget();
3891 printf("&form=eventdaily&date=");
3892
3893 tmptr=localtime(&start);
3894
3895 if (tmptr)
3896 {
3897 printf("%04d%02d%02d", tmptr->tm_year + 1900,
3898 tmptr->tm_mon+1,
3899 tmptr->tm_mday);
3900 }
3901 printf("\">");
3902 print_safe(p);
3903 printf("</a><hr width=\"70%%\" />");
3904 printf("</div>\n");
3905
3906 end=start;
3907 nextday(&end);
3908
3909
3910 do_daily_view(recs, n_recs, VIEW_WEEKLY, &start, &end);
3911
3912 start=end;
3913 printf("</td>");
3914 }
3915 destroycache(recs, n_recs);
3916 printf("</tr></table>\n");
3917 printf("</td></tr></table>\n");
3918 }
3919
3920 /* ---------------- Monthly view ---------------- */
3921
get_start_of_month()3922 static time_t get_start_of_month()
3923 {
3924 unsigned y, m;
3925 time_t start;
3926 time_t end;
3927 struct tm *tmptr;
3928
3929 if (sscanf(cgi("monthof"), "%4u%2u", &y, &m) != 2
3930 || pcp_parse_ymd(y, m, 1, &start, &end))
3931 {
3932 time(&start);
3933 if ((tmptr=localtime(&start)) == NULL)
3934 {
3935 enomem();
3936 return (0);
3937 }
3938 y=tmptr->tm_year + 1900;
3939 m=tmptr->tm_mon + 1;
3940
3941 if (pcp_parse_ymd(y, m, 1, &start, &end))
3942 {
3943 enomem();
3944 return (0);
3945 }
3946 }
3947
3948 return (start);
3949 }
3950
sqpcp_show_cal_month()3951 void sqpcp_show_cal_month()
3952 {
3953 time_t start=get_start_of_month();
3954 struct tm *tmptr;
3955 char buf[512];
3956
3957 if ((tmptr=localtime(&start)) == NULL)
3958 return;
3959
3960 if (strftime(buf, sizeof(buf), getarg("DATEFORMAT"), tmptr) == 0)
3961 return;
3962
3963 print_safe(buf);
3964
3965 }
3966
sqpcp_show_cal_nextmonth()3967 void sqpcp_show_cal_nextmonth()
3968 {
3969 time_t start=get_start_of_month();
3970 struct tm *tmptr;
3971 int m, y;
3972
3973 if ((tmptr=localtime(&start)) == NULL)
3974 return;
3975
3976 y=tmptr->tm_year + 1900;
3977 m=tmptr->tm_mon + 1;
3978
3979 ++m;
3980 if (m > 12)
3981 {
3982 m=1;
3983 ++y;
3984 }
3985
3986 output_scriptptrget();
3987 printf("&form=eventmonthly&monthof=%04d%02d01", y, m);
3988 }
3989
sqpcp_show_cal_prevmonth()3990 void sqpcp_show_cal_prevmonth()
3991 {
3992 time_t start=get_start_of_month();
3993 struct tm *tmptr;
3994 int m, y;
3995
3996 if ((tmptr=localtime(&start)) == NULL)
3997 return;
3998
3999 y=tmptr->tm_year + 1900;
4000 m=tmptr->tm_mon + 1;
4001
4002 --m;
4003 if (m <= 0)
4004 {
4005 m=12;
4006 --y;
4007 }
4008
4009 output_scriptptrget();
4010 printf("&form=eventmonthly&monthof=%04d%02d01", y, m);
4011 }
4012
sqpcp_displaymonth()4013 void sqpcp_displaymonth()
4014 {
4015 int i, y, m;
4016 time_t start=get_start_of_month(), save_start;
4017 time_t end;
4018 struct PCP *pcp=sqpcp_calendar();
4019 struct cacherecord *recs;
4020 unsigned n_recs;
4021 struct tm *tmptr;
4022
4023 if (!pcp)
4024 return;
4025
4026 if ((tmptr=localtime(&start)) == NULL)
4027 return;
4028
4029 y=tmptr->tm_year + 1900;
4030 m=tmptr->tm_mon + 1;
4031
4032 if (++m > 12)
4033 {
4034 m=1;
4035 ++y;
4036 }
4037
4038 if (pcp_parse_ymd(y, m, 1, &end, &save_start))
4039 return;
4040
4041 if (createcache(pcp, &recs, &n_recs, start, end))
4042 {
4043 show_pcp_errmsg(pcp_errmsg(pcp));
4044 return;
4045 }
4046
4047 printf("<table align=\"center\" border=\"0\" class=\"monthly-border\""
4048 " cellpadding=\"0\" cellspacing=\"0\" width=\"100%%\">"
4049 "<tr><td>\n");
4050 printf("<table border=\"1\" class=\"monthly-bg\" cellspacing=\"0\" cellpadding=\"10\" width=\"100%%\">"
4051 "<tr valign=\"top\">");
4052
4053 for (i=0; i<7; i++)
4054 {
4055 printf("<td width=\"14%%\" align=\"center\" class=\"monthly-day\">");
4056 print_safe(pcp_wdayname((i + pref_startofweek) % 7));
4057 printf("</td>");
4058 }
4059 printf("</tr>\n");
4060
4061 while (start < end)
4062 {
4063 printf("<tr valign=\"top\">\n");
4064
4065 for (i=0; i<7; i++)
4066 {
4067 struct tm *tmptr;
4068 time_t next_day;
4069
4070 tmptr=localtime(&start);
4071
4072 if (tmptr->tm_wday != (i + pref_startofweek) % 7
4073 || start >= end)
4074 {
4075 printf("<td width=\"14%%\" class=\"monthly-bg-othermonth\"> </td>");
4076 continue;
4077 }
4078
4079 printf("<td width=\"14%%\">");
4080
4081
4082 printf("<a href=\"");
4083 output_scriptptrget();
4084 printf("&form=eventdaily&date=");
4085
4086 if (tmptr)
4087 {
4088 printf("%04d%02d%02d", tmptr->tm_year + 1900,
4089 tmptr->tm_mon+1,
4090 tmptr->tm_mday);
4091 }
4092 printf("\" class=\"monthly-day\">");
4093
4094 printf("%2d", tmptr->tm_mday);
4095 printf("</a><div align=\"center\"><hr width=\"70%%\" /></div>\n");
4096
4097 next_day=start;
4098 nextday(&next_day);
4099
4100 do_daily_view(recs, n_recs, VIEW_MONTHLY, &start,
4101 &next_day);
4102
4103 start=next_day;
4104 printf("</td>\n");
4105 }
4106 printf("</tr>\n");
4107 }
4108 destroycache(recs, n_recs);
4109 printf("</table>\n");
4110 printf("</td></tr></table>\n");
4111 }
4112
4113 /* -------------------------------------------------------------------- */
4114 /* Access control lists */
4115
4116 static void addacl(const char *);
4117
4118 struct acl_list {
4119 struct acl_list *next;
4120 char *addr;
4121 char *name;
4122 int flags;
4123 } ;
4124
listacl(const char * a,int f,void * vp)4125 static int listacl(const char *a, int f, void *vp)
4126 {
4127 struct acl_list **p=(struct acl_list **)vp, *q;
4128
4129 if ((q=malloc(sizeof(struct acl_list))) == NULL)
4130 return (-1);
4131 memset(q, 0, sizeof(*q));
4132 if ((q->addr=strdup(a)) == NULL)
4133 {
4134 free(q);
4135 return (-1);
4136 }
4137
4138 q->flags=f;
4139
4140 while (*p)
4141 {
4142 if (strcasecmp( (*p)->addr, a) > 0)
4143 break;
4144 p= &(*p)->next;
4145 }
4146
4147 q->next= *p;
4148 *p=q;
4149 return (0);
4150 }
4151
save_listacl_names(const char * addr,const char * name,void * vp)4152 static int save_listacl_names(const char *addr, const char *name,
4153 void *vp)
4154 {
4155 struct acl_list *p=(struct acl_list *)vp;
4156
4157 for ( ; name && p; p=p->next)
4158 if (strcasecmp(p->addr, addr) == 0 && p->name == 0)
4159 p->name=strdup(name);
4160 return (0);
4161 }
4162
sqpcp_eventacl()4163 void sqpcp_eventacl()
4164 {
4165 const char *p;
4166 struct acl_list *acl_list=NULL;
4167 struct PCP *pcp;
4168 struct acl_list *pp;
4169
4170 if (!sqpcp_has_groupware())
4171 return;
4172
4173 p=cgi("addemail");
4174
4175 while (*p && isspace((int)(unsigned char)*p))
4176 ++p;
4177
4178 if (!*p)
4179 p=cgi("addressbookname");
4180
4181 if (*p)
4182 addacl(p);
4183
4184 pcp=sqpcp_calendar();
4185
4186 if (!pcp)
4187 return;
4188
4189 if (*(p=cgi("remove")))
4190 {
4191 if (pcp_acl(pcp, p, 0))
4192 {
4193 saveerror(pcp, NULL);
4194 showerror();
4195 }
4196 }
4197
4198 if (pcp_list_acl(pcp, listacl, &acl_list))
4199 {
4200 saveerror(pcp, NULL);
4201 showerror();
4202 }
4203 else if (ab_get_nameaddr(save_listacl_names, acl_list))
4204 {
4205 int dummy=PCP_ERR_SYSERR;
4206
4207 saveerror(NULL, &dummy);
4208 showerror();
4209 }
4210 else if (acl_list)
4211 {
4212 printf("<table align=\"center\">\n");
4213
4214 for (pp=acl_list; pp; pp=pp->next)
4215 {
4216 printf("<tr><td align=\"right\"><span class=\"tt\">");
4217 if (pp->addr)
4218 ab_nameaddr_show(pp->name, pp->addr);
4219
4220 printf("</span></td><td>-");
4221 if (pp->flags & PCP_ACL_MODIFY)
4222 printf(" %s", getarg("MODIFY"));
4223 if (pp->flags & PCP_ACL_CONFLICT)
4224 printf(" %s", getarg("CONFLICT"));
4225 printf("</td><td><a href=\"");
4226 output_scriptptrget();
4227 printf("&form=eventacl&remove=");
4228 output_urlencoded(pp->addr);
4229 printf("\">%s</a></td></tr>\n", getarg("REMOVE"));
4230 }
4231 printf("</table>\n");
4232 }
4233
4234 while ((pp=acl_list) != NULL)
4235 {
4236 acl_list=pp->next;
4237 if (pp->addr)
4238 free(pp->addr);
4239 if (pp->name)
4240 free(pp->name);
4241 free(pp);
4242 }
4243 }
4244
addacl(const char * p)4245 static void addacl(const char *p)
4246 {
4247 int flags=0;
4248 struct PCP *pcp;
4249
4250 if (strchr(p, '@') == NULL)
4251 {
4252 const char *mhn=myhostname();
4253 char *q=malloc(strlen(p)+strlen(mhn)+2);
4254
4255 if (!q)
4256 enomem();
4257
4258 strcat(strcat(strcpy(q, p), "@"), mhn);
4259 addacl(q);
4260 free(q);
4261 return;
4262 }
4263
4264 if (*cgi("aclMODIFY"))
4265 flags |= PCP_ACL_MODIFY;
4266
4267 if (*cgi("aclCONFLICT"))
4268 flags |= PCP_ACL_CONFLICT;
4269
4270 if (!flags)
4271 return; /* Noop */
4272
4273 pcp=sqpcp_calendar();
4274
4275 if (!pcp)
4276 {
4277 int xerror=PCP_ERR_SYSERR;
4278
4279 saveerror(NULL, &xerror);
4280 showerror();
4281 return;
4282 }
4283
4284 if (!pcp_has_acl(pcp))
4285 {
4286 printf("%s\n", getarg("NOACL"));
4287 return;
4288 }
4289
4290 if (pcp_acl(pcp, p, flags))
4291 {
4292 saveerror(pcp, NULL);
4293 showerror();
4294 return;
4295 }
4296 }
4297