Back to index

courier  0.68.2
Classes | Defines | Functions
pcpnet.c File Reference
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/un.h>
#include <rfc822/rfc822hdr.h>
#include "pcp.h"
#include "calendardir.h"

Go to the source code of this file.

Classes

struct  PCPnet
struct  PCPnet_new_eventid
struct  sock_list

Defines

#define dirent   direct
#define HOSTNAMELEN   256
#define EVENTID_MAXLEN   512
#define ADDR_MAXLEN   512
#define EVENTID_SSCANF   "%511s"
#define ADDR_SSCANF   "%511s"

Functions

static void pcp_close_quit_net (struct PCPnet *)
static void pcp_close_net (struct PCPnet *)
static int cleanup (struct PCPnet *)
static struct PCP_new_eventidneweventid (struct PCPnet *, const char *, struct PCP_save_event *)
static void destroyeventid (struct PCPnet *, struct PCPnet_new_eventid *)
static int commitevent (struct PCPnet *, struct PCPnet_new_eventid *, struct PCP_commit *)
static int bookevent (struct PCPnet *, struct PCPnet_new_eventid *, struct PCP_commit *)
static int listallevents (struct PCPnet *, struct PCP_list_all *)
static int cancelevent (struct PCPnet *, const char *, int *)
static int uncancelevent (struct PCPnet *, const char *, int, struct PCP_uncancel *)
static int deleteevent (struct PCPnet *, struct PCP_delete *)
static int retrevent (struct PCPnet *, struct PCP_retr *)
static int setacl (struct PCPnet *, const char *, int)
static int listacl (struct PCPnet *, int(*)(const char *, int, void *), void *)
static void noop (struct PCPnet *)
static const char * getauthtoken (struct PCPnet *pcp)
static const char * errmsg (struct PCPnet *pcp)
static struct PCPnetmkpcp (const char *username)
static int cmp_str (const void *a, const void *b)
static int dowrite (struct PCPnet *pcp, const char *s, int l)
static int readch (struct PCPnet *pcp, size_t n)
static int getfullreply (struct PCPnet *pcp)
static int getonelinereply (struct PCPnet *pcp)
static int docmd (struct PCPnet *pcp, const char *cmd, int cmdl)
static int checkstatus (struct PCPnet *pcp, int *errcode)
static char * getword (struct PCPnet *pcp, char **p)
static int parseauthtoken (struct PCPnet *pcp)
static int has100 (struct PCPnet *pcp, const char *kw)
static int doconnect (struct PCPnet *pcp, const char *dir, const char *username, const char *sockname, const char *clustername, char **errmsg)
static struct PCPsetcapabilities (struct PCPnet *, int)
struct PCPpcp_open_server (const char *username, const char *password, char **errmsg)
struct PCPpcp_find_proxy (const char *username, const char *clustername, char **errmsg)
int pcp_set_proxy (struct PCP *pcp_ptr, const char *proxy)
struct PCPpcp_reopen_server (const char *username, const char *authtoken, char **errmsg)
static int docommitevent2 (struct PCPnet *pn, int *, void(*)(const char *, const char *, void *), void *)
static int docommitresponse (struct PCPnet *, int(*)(const char *, time_t, time_t, const char *, void *), void *, int *)
static int parse105 (struct PCPnet *pn, time_t *from_t, time_t *to_t, char eventid[EVENTID_MAXLEN])
static int retr_105 (struct PCPnet *, struct PCP_retr *)
static int retr_106 (struct PCPnet *, struct PCP_retr *)
static int retr_110 (struct PCPnet *, struct PCP_retr *)
static int retr_107 (struct PCPnet *, struct PCP_retr *, int)

Class Documentation

struct PCPnet

Definition at line 49 of file pcpnet.c.

Class Members
char * authtoken
int fd
int haserrmsg
char * readbuf
size_t readbuflen
size_t readleft
char * readptr
char * sockname
char * username
struct PCPnet_new_eventid

Definition at line 65 of file pcpnet.c.

Class Members
int isbooked
struct sock_list

Definition at line 201 of file pcpnet.c.

Collaboration diagram for sock_list:
Class Members
char * filename
struct sock_list * next

Define Documentation

#define ADDR_MAXLEN   512

Definition at line 44 of file pcpnet.c.

#define ADDR_SSCANF   "%511s"

Definition at line 47 of file pcpnet.c.

#define dirent   direct

Definition at line 29 of file pcpnet.c.

#define EVENTID_MAXLEN   512

Definition at line 43 of file pcpnet.c.

#define EVENTID_SSCANF   "%511s"

Definition at line 46 of file pcpnet.c.

#define HOSTNAMELEN   256

Definition at line 41 of file pcpnet.c.


Function Documentation

static int bookevent ( struct PCPnet pn,
struct PCPnet_new_eventid id,
struct PCP_commit ci 
) [static]

Definition at line 1389 of file pcpnet.c.

{
       char *q;
       unsigned i;
       int ss;

       ci->errcode=0;
       pn->haserrmsg=0;

       if (ci->n_event_times <= 0)
       {
              errno=EINVAL;
              return (-1);
       }

       pn->haserrmsg=1;

       switch (checkstatus(pn, NULL) / 100) {
       case 1:
       case 2:
       case 3:
              break;
       default:
              return (-1);
       }

       /* yyyymmddhhmmss - 14 chars.  Each time is <space>start-end */

       pn->haserrmsg=0;

       q=malloc(ci->n_event_times * 32 + 20);    /* Eh, that's enough */

       if (!q)
              return (-1);

       strcpy(q, "BOOK");

       for (i=0; i<ci->n_event_times; i++)
       {
              char buf[15];

              pcp_gmtimestr(ci->event_times[i].start, buf);
              strcat(strcat(q, " "), buf);
              pcp_gmtimestr(ci->event_times[i].end, buf);
              strcat(strcat(q, "-"), buf);
       }
       strcat(q, "\n");

       if (dowrite(pn, q, 0))
       {
              free(q);
              return (-1);
       }
       free(q);

       ss=docommitresponse(pn, ci->add_conflict_callback,
                         ci->add_conflict_callback_ptr,
                         &ci->errcode);

       if (ss == 0)
              id->isbooked=1;
       return (ss);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int cancelevent ( struct PCPnet pn,
const char *  id,
int *  errcode 
) [static]

Definition at line 1604 of file pcpnet.c.

{
       char *buf;

       if (errcode)
              *errcode=0;

       pn->haserrmsg=0;

       if (strchr(id, '\r') || strchr(id, '\n'))
       {
              errno=EINVAL;
              return (-1);
       }

       buf=malloc(strlen(id)+20);
       if (!buf)
              return (-1);

       strcat(strcat(strcpy(buf, "CANCEL "), id), "\n");
       if (docmd(pn, buf, 0))
       {
              free(buf);
              return (-1);
       }
       pn->haserrmsg=1;

       switch (checkstatus(pn, errcode) / 100) {
       case 1:
       case 2:
       case 3:
              break;
       default:
              return (-1);
       }
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int checkstatus ( struct PCPnet pcp,
int *  errcode 
) [static]

Definition at line 372 of file pcpnet.c.

{
       const char *p=strrchr(pcp->readbuf, '\n');
       int n;

       if (p)
              ++p;
       else
              p=pcp->readbuf;
       n=atoi(p);
       if (errcode)
              switch (n) {
              case 504:
                     *errcode=PCP_ERR_EVENTNOTFOUND;
                     break;
              case 506:
                     *errcode=PCP_ERR_EVENTLOCKED;
                     break;
              }
       return (n);
}

Here is the caller graph for this function:

static int cleanup ( struct PCPnet pn) [static]

Definition at line 1063 of file pcpnet.c.

{
       return (0);
}
static int cmp_str ( const void *  a,
const void *  b 
) [static]

Definition at line 206 of file pcpnet.c.

{
       return (strcmp(*(const char **)a, *(const char **)b));
}

Here is the caller graph for this function:

static int commitevent ( struct PCPnet pn,
struct PCPnet_new_eventid id,
struct PCP_commit ci 
) [static]

Definition at line 1323 of file pcpnet.c.

{
       if (!id->isbooked)
       {
              int rc=bookevent(pn, id, ci);

              if (rc)
                     return (rc);
       }

       return (docommitevent2(pn, &ci->errcode, ci->proxy_callback,
                            ci->proxy_callback_ptr));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int deleteevent ( struct PCPnet pn,
struct PCP_delete del 
) [static]

Definition at line 1708 of file pcpnet.c.

{
       char *buf;

       pn->haserrmsg=0;
       del->errcode=0;

       if (strchr(del->id, '\r') || strchr(del->id, '\n'))
       {
              errno=EINVAL;
              return (-1);
       }
       if (docmd(pn, "RSET\n", 0))
              return (-1);
       pn->haserrmsg=1;

       switch (checkstatus(pn, NULL) / 100) {
       case 1:
       case 2:
       case 3:
              break;
       default:
              return (-1);
       }
       pn->haserrmsg=0;

       buf=malloc(strlen(del->id)+20);
       if (!buf)
              return (-1);

       strcat(strcat(strcpy(buf, "DELETE "), del->id), "\n");
       if (docmd(pn, buf, 0))
       {
              free(buf);
              return (-1);
       }

       pn->haserrmsg=1;

       switch (checkstatus(pn, &del->errcode) / 100) {
       case 1:
       case 2:
       case 3:
              break;
       default:
              return (-1);
       }

       return (docommitevent2(pn, &del->errcode,
                            del->proxy_callback,
                            del->proxy_callback_ptr));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void destroyeventid ( struct PCPnet pn,
struct PCPnet_new_eventid id 
) [static]

Definition at line 1313 of file pcpnet.c.

{
       free(id->eventid.eventid);
       free(id);
}

Here is the caller graph for this function:

static int docmd ( struct PCPnet pcp,
const char *  cmd,
int  cmdl 
) [static]

Definition at line 365 of file pcpnet.c.

{
       if (dowrite(pcp, cmd, cmdl) < 0)
              return (-1);
       return (getfullreply(pcp));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int docommitevent2 ( struct PCPnet pn,
int *  errcode,
void(*)(const char *, const char *, void *)  proxy_callback,
void *  proxy_callback_ptr 
) [static]

Definition at line 1338 of file pcpnet.c.

{
       int s;

       pn->haserrmsg=0;

       if (dowrite(pn, "COMMIT\n", 0))
              return (-1);

       pn->haserrmsg=1;

       while ((s=getonelinereply(pn)) >= 0)
       {
              int n=checkstatus(pn, errcode);

              if (n == 111)
              {
                     char *p=pn->readbuf+3;
                     char *action;

                     if (*p)
                            ++p;


                     action=getword(pn, &p);

                     while (*p && isspace((int)(unsigned char)*p))
                            ++p;

                     if (proxy_callback)
                            (*proxy_callback)(action, p,
                                            proxy_callback_ptr);
              }

              if (s > 0)
                     return ( (n / 100) < 4 ? 0:-1);
       }
       pn->haserrmsg=0;
       return (-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int docommitresponse ( struct PCPnet pn,
int(*)(const char *, time_t, time_t,const char *, void *)  conflict_func,
void *  callback_arg,
int *  errcode 
) [static]

Definition at line 1454 of file pcpnet.c.

{
       int s;
       int rc=0;

       pn->haserrmsg=0;

       while ((s=getonelinereply(pn)) >= 0)
       {
              int ss=checkstatus(pn, errcode);

              switch (ss / 100) {
              case 1:
              case 2:
              case 3:
                     break;
              default:
                     if (ss == 403)
                     {
                            char eventid[EVENTID_MAXLEN];
                            char from[15];
                            char to[15];
                            char addr[ADDR_MAXLEN];
                            char dummy;
                            time_t from_t, to_t;

                            if (sscanf(pn->readbuf,
                                      "403%c" ADDR_SSCANF " %14s %14s "
                                      EVENTID_SSCANF,
                                      &dummy,
                                      addr, from, to,
                                      eventid)
                                != 5)
                            {
                                   rc= -1;
                                   return (-1);
                            }

                            from_t=pcp_gmtime_s(from);
                            to_t=pcp_gmtime_s(to);
                            if (!from_t || !to_t)
                            {
                                   errno=EIO;
                                   return (-1);
                            }

                            if (rc == 0 && conflict_func)
                                   rc= (*conflict_func)
                                          (eventid, from_t, to_t, addr,
                                           callback_arg);
                            if (errcode)
                                   *errcode=PCP_ERR_CONFLICT;
                     }
                     rc= -1;
              }
              pn->haserrmsg=1;
              if (s > 0)
                     break;
              pn->haserrmsg=0;
       }

       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int doconnect ( struct PCPnet pcp,
const char *  dir,
const char *  username,
const char *  sockname,
const char *  clustername,
char **  errmsg 
) [static]

Definition at line 472 of file pcpnet.c.

{
       DIR *dirp=opendir(dir);
       struct sock_list *l=NULL;
       struct dirent *de;
       struct sock_list *nl;
       unsigned i,cnt=0;
       char **a;
       int fd;
       char *buf;
       int clustername_l=clustername ? strlen(clustername):0;

       if (errmsg)
              *errmsg=0;

       while (dirp && (de=readdir(dirp)) != NULL)
       {
              if (strchr(de->d_name, '.'))
                     continue;

              if (sockname && strcmp(de->d_name, sockname))
                     continue;

              /*
              ** When the proxy connection comes in via the proxy cluster,
              ** ignore the proxy cluster client's socket, so we don't end
              ** up in an infinite loop!
              */

              if (clustername)
              {
                     const char *p=de->d_name;

                     while (p && isdigit((int)(unsigned char)*p))
                            ++p;

                     if (strncasecmp(p, clustername, clustername_l) == 0
                         && p[clustername_l] == '.')
                            continue;
              }

              nl=malloc(sizeof(struct sock_list));

              if (!nl || (nl->filename=malloc(strlen(dir)+2+
                                          strlen(de->d_name))) == NULL)
              {
                     if (nl) free(nl);

                     while ((nl=l) != NULL)
                     {
                            l=nl->next;
                            free(nl->filename);
                            free(nl);
                     }
                     return (-1);
              }
              strcat(strcat(strcpy(nl->filename, dir), "/"), de->d_name);
              ++cnt;
              nl->next=l;
              l=nl;
       }

       if (dirp)
              closedir(dirp);

       if (!l)
       {
              errno=ENOENT;
              return (-1);
       }

       if ((a=malloc(sizeof(char *)*cnt)) == NULL)
       {
              while ((nl=l) != NULL)
              {
                     l=nl->next;
                     free(nl->filename);
                     free(nl);
              }
              return (-1);
       }

       cnt=0;
       for (nl=l; nl; nl=nl->next)
              a[cnt++]=nl->filename;

       qsort(a, cnt, sizeof(*a), cmp_str);

       fd= -1;

       for (i=0; i<cnt; i++)
       {
              struct  sockaddr_un skun;
              int rc;

              fd=socket(PF_UNIX, SOCK_STREAM, 0);
              if (fd < 0)
                     break;

              skun.sun_family=AF_UNIX;
              strcpy(skun.sun_path, a[i]);

              if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
              {
                     close(fd);
                     fd= -1;
                     break;
              }

              if ( pcp->sockname )
                     free(pcp->sockname);
              if ( (pcp->sockname=strdup(a[i])) == NULL)
              {
                     close(fd);
                     fd= -1;
                     break;
              }

              if ( connect(fd,
                          (const struct sockaddr *)&skun,
                          sizeof(skun)) == 0)
              {
                     /* That was easy, we're done. */

                     if (fcntl(fd, F_SETFL, 0) < 0)
                     {
                            close(fd);
                            fd= -1;
                            break;
                     }
              }
              else if ( errno != EINPROGRESS && errno != EWOULDBLOCK)
              {
                     close(fd);
                     fd= -1;
                     break;
              }
              else
              {
                     struct timeval tv;
                     fd_set fdr;
                     int rc;

                     FD_ZERO(&fdr);
                     FD_SET(fd, &fdr);
                     tv.tv_sec=30;
                     tv.tv_usec=0;

                     rc=select(fd+1, 0, &fdr, 0, &tv);
                     if (rc <= 0 || !FD_ISSET(fd, &fdr))
                     {
                            close(fd);
                            fd= -1;
                            break;
                     }

                     if ( connect(fd, (const struct sockaddr *)&skun,
                                 sizeof(skun)))
                     {
                            if (errno != EISCONN)
                            {
                                   close(fd);
                                   break;
                            }
                     }

                     if (fcntl(fd, F_SETFL, 0) < 0)
                     {
                            close(fd);
                            break;
                     }
              }

              pcp->fd=fd;
              if (docmd(pcp, "CAPABILITY\n", 0))
              {
                     fd= -1;
                     break;
              }

              if ((rc=checkstatus(pcp, NULL)) != 100)
              {
                     close(fd);
                     fd= -1;
                     continue;
              }

              if (!has100(pcp, "PCP1"))
              {
                     close(fd);
                     fd= -1;
                     continue;
              }

              buf=malloc(strlen(username)+sizeof("USERID \n"));
              if (buf == 0)
              {
                     close(fd);
                     fd= -1;
                     break;

              }

              strcat(strcat(strcpy(buf, "USERID "), username), "\n");

              if (docmd(pcp, buf, 0))
              {
                     fd= -1;
                     free(buf);
                     break;
              }
              pcp->fd= -1;
              free(buf);

              switch ((rc=checkstatus(pcp, NULL)) / 100) {
              case 1:
              case 2:
              case 3:
                     break;
              default:
                     errno=EIO;
                     if (errmsg)
                     {
                            if (*errmsg)
                                   free(*errmsg);
                            *errmsg=strdup(pcp->readbuf);
                     }
                     close(fd);
                     fd= -1;
                     break;
              case 5:
                     errno=ENOENT;
                     if (errmsg)
                     {
                            if (*errmsg)
                                   free(*errmsg);
                            *errmsg=strdup("Calendar not found.");
                     }
                     close(fd);
                     fd= -1;
                     continue;
              }

              if (rc == 102)
              {
                     if (parseauthtoken(pcp))
                     {
                            close(fd);
                            fd= -1;
                     }
                     break;
              }
              break;
       }

       free(a);
       while ((nl=l) != NULL)
       {
              l=nl->next;
              free(nl->filename);
              free(nl);
       }
       return (fd);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int dowrite ( struct PCPnet pcp,
const char *  s,
int  l 
) [static]

Definition at line 211 of file pcpnet.c.

{
       if (l <= 0)
              l=strlen(s);

       if (pcp->fd < 0)
       {
              errno=ENETDOWN;
              return (-1);
       }

       while (l)
       {
              int n=write(pcp->fd, s, l);

              if (n <= 0)
              {
                     errno=ENETDOWN;
                     close(pcp->fd);
                     pcp->fd= -1;
                     return (-1);
              }

              s += n;
              l -= n;
       }
       return (0);
}

Here is the caller graph for this function:

static const char* errmsg ( struct PCPnet pcp) [static]

Definition at line 102 of file pcpnet.c.

{
       if (pcp->haserrmsg)
              return (pcp->readbuf);
       return (strerror(errno));
}

Here is the caller graph for this function:

static const char* getauthtoken ( struct PCPnet pcp) [static]

Definition at line 97 of file pcpnet.c.

{
       return (pcp->authtoken);
}

Here is the caller graph for this function:

static int getfullreply ( struct PCPnet pcp) [static]

Definition at line 295 of file pcpnet.c.

{
       size_t n=0;
       int ch;

       for (;;)
       {
              size_t nn=n;

              while ((ch=readch(pcp, nn)) != EOF)
              {
                     if (ch == '\n')
                            break;
                     pcp->readbuf[nn++]=ch;
              }

              if (ch == EOF)
                     return (-1);

              if (nn-n >= 4 &&
                  isdigit((int)(unsigned char)pcp->readbuf[n]) &&
                  isdigit((int)(unsigned char)pcp->readbuf[n+1]) &&
                  isdigit((int)(unsigned char)pcp->readbuf[n+2]) &&
                  isspace((int)(unsigned char)pcp->readbuf[n+3]))
              {
                     pcp->readbuf[nn]=0;
                     break;
              }
              n= ++nn;
       }

       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int getonelinereply ( struct PCPnet pcp) [static]

Definition at line 329 of file pcpnet.c.

{
       size_t nn;
       int islast;

       nn=0;
       for (;;)
       {
              int ch;

              while ((ch=readch(pcp, nn)) != EOF)
              {
                     if (ch == '\n')
                            break;
                     pcp->readbuf[nn++]=ch;
                     if (nn >= 8192)
                            nn=8192;
              }
              pcp->readbuf[nn]=0;
              if (ch == EOF)
                     return (-1);

              if (!isdigit((int)(unsigned char)pcp->readbuf[0])
                  || !isdigit((int)(unsigned char)pcp->readbuf[1])
                  || !isdigit((int)(unsigned char)pcp->readbuf[2]))
              {
                     nn=0;
                     continue;
              }
              islast= pcp->readbuf[3] != '-';
              break;
       }
       return (islast);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* getword ( struct PCPnet pcp,
char **  p 
) [static]

Definition at line 394 of file pcpnet.c.

{
       char *q;

       while (**p && isspace((int)(unsigned char)**p))
              ++*p;

       if (!**p)
              return (NULL);
       q= *p;

       while (**p && !isspace((int)(unsigned char)**p))
              ++*p;

       if (**p)
       {
              **p=0;
              ++*p;
       }
       return (q);
}

Here is the caller graph for this function:

static int has100 ( struct PCPnet pcp,
const char *  kw 
) [static]

Definition at line 449 of file pcpnet.c.

{
       char *p=pcp->readbuf;
       int l = strlen(kw);

       while (*p)
       {
              while (isdigit((int)(unsigned char)*p))
                     ++p;
              if (*p != '\n')
                     ++p;

              if (strncasecmp(p, kw, l) == 0 &&
                  (p[l] == 0 || isspace((int)(unsigned char)p[l])))
                     return (1);

              while (*p)
                     if (*p++ == '\n')
                            break;
       }
       return (0);
}

Here is the caller graph for this function:

static int listacl ( struct PCPnet pn,
int(*)(const char *, int, void *)  func,
void *  arg 
) [static]

Definition at line 2141 of file pcpnet.c.

{
       int rc;
       int s;

       pn->haserrmsg=0;
       if (dowrite(pn, "ACL LIST\n", 0) < 0)
              return (-1);

       rc=0;
       pn->haserrmsg=1;

       while ((s=getonelinereply(pn)) >= 0)
       {
              int n=checkstatus(pn, NULL);
              if (n >= 400)
                     rc= -1;
              if (n == 103)
              {
                     char addr[ADDR_MAXLEN];
                     char dummy;

                     if (sscanf(pn->readbuf, "103%c" ADDR_SSCANF,
                               &dummy, addr) == 2)
                     {
                            const char *p=pn->readbuf+4;
                            int flags=0;

                            for ( ; *p; p++)
                                   if (isspace((int)(unsigned char)*p))
                                          break;

                            while (*p)
                            {
                                   const char *q;
                                   char buf[256];

                                   if (isspace((int)(unsigned char)*p))
                                   {
                                          ++p;
                                          continue;
                                   }
                                   q=p;

                                   for ( ; *p; p++)
                                          if (isspace((int)
                                                     (unsigned char)*p))
                                                 break;
                                   buf[0]=0;
                                   strncat(buf, q, p-q < 255 ? p-q:255);

                                   flags |= pcp_acl_num(buf);
                            }

                            if (rc == 0)
                                   rc= (*func)(addr, flags, arg);
                     }
                     else
                     {
                            if (rc == 0)
                            {
                                   rc= -1;
                                   errno=EIO;
                            }
                     }
              }
              if (s > 0)
                     break;
       }

       if (s < 0)
       {
              pn->haserrmsg=0;
              rc= -1;
       }
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int listallevents ( struct PCPnet pn,
struct PCP_list_all la 
) [static]

Definition at line 1540 of file pcpnet.c.

{
       char cmdbuf[100];
       int rc, s;

       strcpy(cmdbuf, "LIST");

       if (la->list_from || la->list_to)
       {
              char buf[15];

              strcat(cmdbuf, " FROM ");
              if (la->list_from)
              {
                     pcp_gmtimestr(la->list_from, buf);
                     strcat(cmdbuf, buf);
              }
              strcat(cmdbuf, "-");
              if (la->list_to)
              {
                     pcp_gmtimestr(la->list_to, buf);
                     strcat(cmdbuf, buf);
              }
       }

       strcat(cmdbuf, "\n");

       pn->haserrmsg=0;
       if (dowrite(pn, cmdbuf, 0) < 0)
              return (-1);

       rc=0;
       pn->haserrmsg=1;

       while ((s=getonelinereply(pn)) >= 0)
       {
              int n=checkstatus(pn, NULL);
              if (n >= 400)
                     rc= -1;
              if (n == 105)
              {
                     char eventid[EVENTID_MAXLEN];

                     if (parse105(pn, &la->event_from, &la->event_to,
                                 eventid) == 0)
                     {
                            la->event_id=eventid;
                            if (rc == 0)
                                   rc= (*la->callback_func)
                                          (la, la->callback_arg);
                     }
              }
              if (s > 0)
                     break;
       }

       if (s < 0)
       {
              pn->haserrmsg=0;
              rc= -1;
       }
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct PCPnet* mkpcp ( const char *  username) [static, read]

Definition at line 109 of file pcpnet.c.

{
       struct PCPnet *pd=(struct PCPnet *)malloc(sizeof(struct PCPnet));
       const char *p;

       if (!pd)
              return (NULL);

       if (!*username)
       {
              free(pd);
              errno=EIO;
              return (NULL);
       }

       for (p=username; *p; p++)
              if (isspace((int)(unsigned char)*p))
              {
                     free(pd);
                     errno=EIO;
                     return (NULL);
              }

       memset(pd, 0, sizeof(*pd));

       pd->fd= -1;
       pd->username=strdup(username);
       if (!pd->username)
       {
              free(pd);
              return (NULL);
       }

       pd->pcp.authtoken_func=(const char *(*)(struct PCP *))getauthtoken;
       pd->pcp.close_func= (void (*)(struct PCP *)) pcp_close_quit_net;
       pd->pcp.cleanup_func= (int (*)(struct PCP *)) cleanup;

       pd->pcp.create_new_eventid_func=
              (struct PCP_new_eventid *(*)(struct PCP *, const char *,
                                        struct PCP_save_event *))
              neweventid;

       pd->pcp.destroy_new_eventid_func=
              (void (*)(struct PCP *, struct PCP_new_eventid *))
              destroyeventid;

       pd->pcp.commit_func=
              (int (*)(struct PCP *, struct PCP_new_eventid *,
                      struct PCP_commit *))
              commitevent;

       pd->pcp.book_func=
              (int (*)(struct PCP *, struct PCP_new_eventid *,
                      struct PCP_commit *))
              bookevent;

       pd->pcp.list_all_func=
              (int (*)(struct PCP *, struct PCP_list_all *))
              listallevents;

       pd->pcp.cancel_func=
              (int (*)(struct PCP *, const char *, int *))
              cancelevent;

       pd->pcp.uncancel_func=
              (int (*)(struct PCP *, const char *, int,
                      struct PCP_uncancel *))
              uncancelevent;

       pd->pcp.delete_func=
              (int (*)(struct PCP *, struct PCP_delete *))
              deleteevent;

       pd->pcp.retr_func=
              (int (*)(struct PCP *, struct PCP_retr *))
              retrevent;

       pd->pcp.errmsg_func=
              (const char *(*)(struct PCP *))
              errmsg;

       pd->pcp.noop_func=(void (*)(struct PCP *))noop;

       pd->pcp.acl_func=
              (int (*)(struct PCP *, const char *, int))setacl;
       pd->pcp.listacl_func=
              (int (*)(struct PCP *, int (*)(const char *, int, void *),
                      void *))listacl;

       return (pd);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct PCP_new_eventid * neweventid ( struct PCPnet pn,
const char *  ev,
struct PCP_save_event se 
) [static, read]

Definition at line 1068 of file pcpnet.c.

{
       struct PCPnet_new_eventid *p;
       char *q;
       char rbuf[BUFSIZ], wbuf[BUFSIZ];
       char *rbufptr;
       int bufl;
       char *wbufptr;
       int wbufleft;
       char *s;
       unsigned new_len, n;

       int seeneol;

       pn->haserrmsg=0;
       if (ev && (strchr(ev, '\n') || strchr(ev, '\r')))
       {
              errno=EINVAL;
              return (NULL);
       }

       p=malloc(sizeof(struct PCPnet_new_eventid));
       if (!p)
              return (NULL);
       memset(p, 0, sizeof(*p));

       pn->haserrmsg=1;

       if (docmd(pn, "RSET\n", 0))
       {
              free(p);
              return (NULL);
       }
       switch (checkstatus(pn, NULL) / 100) {
       case 1:
       case 2:
       case 3:
              break;
       default:
              free(p);
              return (NULL);
       }

       if (docmd(pn, se->flags & PCP_OK_CONFLICT
                ? "CONFLICT ON\n":"CONFLICT OFF\n", 0))
       {
              free(p);
              errno=EINVAL;
              return (NULL);
       }

       if (docmd(pn, se->flags & PCP_OK_PROXY_ERRORS
                ? "FORCE ON\n":"FORCE OFF\n", 0))
       {
              free(p);
              errno=EINVAL;
              return (NULL);
       }

       if (ev)
       {
              pn->haserrmsg=0;
              q=malloc(sizeof("DELETE \n")+strlen(ev));
              if (!q)
              {
                     free(p);
                     return (NULL);
              }
              pn->haserrmsg=1;
              strcat(strcat(strcpy(q, "DELETE "), ev), "\n");
              if (docmd(pn, q, 0))
              {
                     free(q);
                     free(p);
                     return (NULL);
              }
              free(q);

              switch (checkstatus(pn, NULL) / 100) {
              case 1:
              case 2:
              case 3:
                     break;
              default:
                     free(p);
                     return (NULL);
              }
       }

       new_len=30;
       for (n=0; n<se->n_event_participants; n++)
       {
              const char *pp=se->event_participants[n].address;

              if (pp)
              {
                     if (strchr(pp, '\n') || strchr(pp, '\r'))
                     {
                            errno=EINVAL;
                            free(p);
                            return (NULL);
                     }

                     new_len += strlen(pp)+1;
              }
       }

       if ((s=malloc(new_len)) == NULL)
       {
              free(p);
              return (NULL);
       }

       strcpy(s, "NEW");

       for (n=0; n<se->n_event_participants; n++)
       {
              const char *p=se->event_participants[n].address;

              if (p)
                     strcat(strcat(s, " "), p);
       }

       strcat(s, "\n");

       if (docmd(pn, s, 0))
       {
              free(s);
              free(p);
              return (NULL);
       }
       free(s);

       if ((checkstatus(pn, NULL) / 100) != 3)
       {
              free(p);
              return (NULL);
       }

       wbufptr=wbuf;
       wbufleft=sizeof(wbuf);
       seeneol=1;

       while ((bufl=pcp_read_saveevent(se, rbuf, sizeof(rbuf))) > 0)
       {
              rbufptr=rbuf;

              while (bufl)
              {
                     if (seeneol && *rbufptr == '.')
                     {
                            if (!wbufleft)
                            {
                                   if (dowrite(pn, wbuf, sizeof(wbuf)))
                                          break;
                                   wbufptr=wbuf;
                                   wbufleft=sizeof(wbuf);
                            }
                            *wbufptr++='.';
                            --wbufleft;
                     }

                     if (!wbufleft)
                     {
                            if (dowrite(pn, wbuf, sizeof(wbuf)))
                                   break;
                            wbufptr=wbuf;
                            wbufleft=sizeof(wbuf);
                     }

                     seeneol= *rbufptr == '\n';
                     *wbufptr++ = *rbufptr++;
                     --wbufleft;
                     --bufl;
              }
       }

       if (bufl)     /* Write error, flush things through */
       {
              if (bufl > 0)
                     while ((bufl=pcp_read_saveevent(se, rbuf,
                                                 sizeof(rbuf))) > 0)
                            ;
              free(p);
              return (NULL);
       }

       s=seeneol ? ".\n":"\n.\n";

       while (*s)
       {
              if (!wbufleft)
              {
                     if (dowrite(pn, wbuf, sizeof(wbuf)))
                     {
                            free(p);
                            return (NULL);
                     }
                     wbufptr=wbuf;
                     wbufleft=sizeof(wbuf);
              }
              *wbufptr++= *s++;
              --wbufleft;
       }

       if (wbufptr > wbuf && dowrite(pn, wbuf, wbufptr-wbuf))
       {
              free(p);
              return (NULL);
       }

       if (getfullreply(pn))
       {
              free(p);
              return (NULL);
       }

       if (checkstatus(pn, NULL) != 109)
       {
              errno=EIO;
              free(p);
              return (NULL);
       }

       s=pn->readbuf;

       getword(pn, &s);     /* Skip 109 */

       q=getword(pn, &s);
       if (!q)
       {
              errno=EIO;
              free(p);
              return (NULL);
       }
       if ((p->eventid.eventid=strdup(q)) == NULL)
       {
              free(p);
              return (NULL);
       }
       return (&p->eventid);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void noop ( struct PCPnet pd) [static]

Definition at line 2220 of file pcpnet.c.

{
       docmd(pd, "NOOP\n", 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int parse105 ( struct PCPnet pn,
time_t *  from_t,
time_t *  to_t,
char  eventid[EVENTID_MAXLEN] 
) [static]

Definition at line 1522 of file pcpnet.c.

{
       char dummy;
       char from[15];
       char to[15];

       if (sscanf(pn->readbuf, "105%c" EVENTID_SSCANF " %14s %14s",
                 &dummy, eventid, from, to) == 4)
       {
              if ((*from_t=pcp_gmtime_s(from)) &&
                  (*to_t=pcp_gmtime_s(to)))
                     return (0);
       }
       errno=EIO;
       return (-1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int parseauthtoken ( struct PCPnet pcp) [static]

Definition at line 418 of file pcpnet.c.

{
       char *p=pcp->readbuf;
       char *q;

       getword(pcp, &p);    /* skip 102 */

       q=getword(pcp, &p);

       if (!q)
       {
              errno=EIO;
              return (-1);
       }

       if (pcp->authtoken)
              free(pcp->authtoken);

       if ((p=strrchr(pcp->sockname, '/')) != 0)
              ++p;
       else
              p=pcp->sockname;

       if ((pcp->authtoken=malloc(strlen(p)+strlen(q)+2)) == NULL)
              return (-1);
       strcat(strcat(strcpy(pcp->authtoken, p), "/"), q);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void pcp_close_net ( struct PCPnet pd) [static]

Definition at line 1049 of file pcpnet.c.

{
       if (pd->fd >= 0)
              close(pd->fd);
       if (pd->sockname)
              free(pd->sockname);
       if (pd->authtoken)
              free(pd->authtoken);
       if (pd->readbuf)
              free(pd->readbuf);
       free(pd->username);
       free(pd);
}

Here is the caller graph for this function:

static void pcp_close_quit_net ( struct PCPnet pcp) [static]

Definition at line 1042 of file pcpnet.c.

{
       if (pcp->fd >= 0)
              docmd(pcp, "QUIT\n", 0);
       pcp_close_net(pcp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct PCP* pcp_find_proxy ( const char *  username,
const char *  clustername,
char **  errmsg 
) [read]

Definition at line 866 of file pcpnet.c.

{
       struct PCPnet *pcp=mkpcp(username);

       if (errmsg)
              *errmsg=0;
       if (!pcp)
              return (NULL);

       if (strchr(username, '\r') || strchr(username, '\n'))
       {
              errno=EINVAL;
              pcp_close_net(pcp);
              return (NULL);
       }

       if ((pcp->fd=doconnect(pcp, CALENDARDIR "/private", username, NULL,
                            clustername,
                            errmsg)) < 0)
       {
              pcp_close_net(pcp);
              return (NULL);
       }
       return ((struct PCP *)pcp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct PCP* pcp_open_server ( const char *  username,
const char *  password,
char **  errmsg 
) [read]

Definition at line 742 of file pcpnet.c.

{
       struct PCPnet *pcp=mkpcp(username);

       if (errmsg)
              *errmsg=0;
       if (!pcp)
              return (NULL);

       if (strchr(username, '\r') || strchr(username, '\n'))
       {
              errno=EINVAL;
              pcp_close_net(pcp);
              return (NULL);
       }

       if (strchr(password, '\r') || strchr(password, '\n'))
       {
              errno=EINVAL;
              pcp_close_net(pcp);
              return (NULL);
       }


       if ((pcp->fd=doconnect(pcp, CALENDARDIR "/public", username, NULL,
                            NULL, errmsg)) < 0)
       {
              pcp_close_net(pcp);
              return (NULL);
       }

       if (pcp->authtoken == NULL)
       {
              char *buf;
              int rc;

              if (strchr(password, '\n') || strchr(password, '\r'))
              {
                     errno=EINVAL;
                     pcp_close_net(pcp);
                     return (NULL);
              }

              buf=malloc(strlen(password)+sizeof("PASSWORD \n"));
              if (buf == 0)
              {
                     pcp_close_net(pcp);
                     return (NULL);
              }

              strcat(strcat(strcpy(buf, "PASSWORD "), password), "\n");

              if (docmd(pcp, buf, 0))
              {
                     free(buf);
                     pcp_close_net(pcp);
                     return (NULL);
              }
              free(buf);

              switch ((rc=checkstatus(pcp, NULL)) / 100) {
              case 1:
              case 2:
              case 3:
                     break;
              default:
                     if (errmsg)
                     {
                            if (*errmsg)
                                   free(*errmsg);
                            *errmsg=strdup(pcp->readbuf);
                     }
                     pcp_close_net(pcp);
                     errno=EPERM;
                     return (NULL);
              }

              if (rc == 102)
              {
                     if (parseauthtoken(pcp))
                     {
                            pcp_close_net(pcp);
                            return (NULL);
                     }
              }
       }

       return (setcapabilities(pcp, 1));
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct PCP* pcp_reopen_server ( const char *  username,
const char *  authtoken,
char **  errmsg 
) [read]

Definition at line 936 of file pcpnet.c.

{
       struct PCPnet *pcp=mkpcp(username);
       char *authtoken_cpy;
       char *p, *q;

       if (!pcp)
              return (NULL);

       /* auth token is: sockname/token */

       if ((authtoken_cpy=strdup(authtoken)) == NULL)
       {
              pcp_close_net(pcp);
              return (NULL);
       }

       if ((p=strchr(authtoken_cpy, '/')) == NULL)
       {
              errno=EINVAL;
              free(authtoken_cpy);
              pcp_close_net(pcp);
              return (NULL);
       }

       *p++=0;

       for (q=p; *q; ++q)
              if (isspace((int)(unsigned char)*q))
              {
                     errno=EINVAL;
                     free(authtoken_cpy);
                     pcp_close_net(pcp);
                     return (NULL);
              }

       if ((pcp->fd=doconnect(pcp, CALENDARDIR "/public", username,
                            authtoken_cpy, NULL, errmsg)) < 0)
       {
              free(authtoken_cpy);
              pcp_close_net(pcp);
              return (NULL);
       }

       if (pcp->authtoken == NULL)
       {
              char *buf;
              int rc;

              buf=malloc(strlen(p)+sizeof("RELOGIN \n"));
              if (buf == 0)
              {
                     free(authtoken_cpy);
                     pcp_close_net(pcp);
                     return (NULL);
              }

              strcat(strcat(strcpy(buf, "RELOGIN "), p), "\n");
              free(authtoken_cpy);

              if (docmd(pcp, buf, 0))
              {
                     free(buf);
                     pcp_close_net(pcp);
                     return (NULL);
              }
              free(buf);

              switch ((rc=checkstatus(pcp, NULL)) / 100) {
              case 1:
              case 2:
              case 3:
                     break;
              default:
                     errno=EIO;
                     if (errmsg)
                     {
                            if (*errmsg)
                                   free(*errmsg);
                            *errmsg=strdup(pcp->readbuf);
                     }
                     pcp_close_net(pcp);
                     return (NULL);
              }
              if (rc == 102)
              {
                     if (parseauthtoken(pcp))
                     {
                            pcp_close_net(pcp);
                            return (NULL);
                     }
              }
              else   /* Keeping the same token */
                     if ((pcp->authtoken=strdup(authtoken)) == NULL)
              {
                     pcp_close_net(pcp);
                     return (NULL);
              }
       }
       else
              free(authtoken_cpy);

       return (setcapabilities(pcp, 1));
}

Here is the call graph for this function:

Here is the caller graph for this function:

int pcp_set_proxy ( struct PCP pcp_ptr,
const char *  proxy 
)

Definition at line 894 of file pcpnet.c.

{
       struct PCPnet *pcp=(struct PCPnet *)pcp_ptr;
       int rc;
       char *p;

       pcp->haserrmsg=0;

       if (strchr(proxy, '\r') || strchr(proxy, '\n'))
       {
              errno=EINVAL;
              return (-1);
       }

       p=malloc(strlen(proxy)+sizeof("PROXY \n"));

       if (!p)
              return (-1);

       strcat(strcat(strcpy(p, "PROXY "), proxy), "\n");

       if (docmd(pcp, p, 0))
       {
              free(p);
              return (-1);
       }

       free(p);
       switch ((rc=checkstatus(pcp, NULL)) / 100) {
       case 1:
       case 2:
       case 3:
              break;
       default:
              return (-1);
       }

       if (setcapabilities(pcp, 0) == NULL)
              return (-1);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int readch ( struct PCPnet pcp,
size_t  n 
) [static]

Definition at line 240 of file pcpnet.c.

{
       if (pcp->readleft == 0)
       {
              int l;
              struct timeval tv;
              fd_set fds;

              /* Read the next chunk after the current line :-) */

              if (n + BUFSIZ > pcp->readbuflen)
              {
                     size_t nn=n+BUFSIZ;
                     char *p= pcp->readbuf ?
                            realloc(pcp->readbuf, nn):malloc(nn);
                     if (!p)
                     {
                            close(pcp->fd);
                            pcp->fd= -1;
                            return (-1);
                     }
                     pcp->readbuf=p;
                     pcp->readbuflen=nn;
              }

              pcp->readptr=pcp->readbuf + n;

              FD_ZERO(&fds);
              FD_SET(pcp->fd, &fds);
              tv.tv_sec=300;
              tv.tv_usec=0;
              if (select(pcp->fd+1, &fds, NULL, NULL, &tv) <= 0)
              {
                     errno=ETIMEDOUT;
                     close(pcp->fd);
                     pcp->fd= -1;
                     return (EOF);
              }
              l=read(pcp->fd, pcp->readptr, BUFSIZ);
              if (l <= 0)
              {
                     if (l == 0)
                            errno=0;
                     close(pcp->fd);
                     pcp->fd= -1;
                     errno=ECONNRESET;
                     return (EOF);
              }
              pcp->readleft=l;
       }

       --pcp->readleft;
       return ((int)(unsigned char)*pcp->readptr++);
}

Here is the caller graph for this function:

static int retr_105 ( struct PCPnet pn,
struct PCP_retr ri 
) [static]

Definition at line 1888 of file pcpnet.c.

{
       char eventid[EVENTID_MAXLEN];
       time_t from_t, to_t;

       if (parse105(pn, &from_t, &to_t, eventid) == 0)
       {
              ri->event_id=eventid;

              if (ri->callback_retr_date)
                     return ( (*ri->callback_retr_date)
                             (ri, from_t, to_t, ri->callback_arg));
       }

       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int retr_106 ( struct PCPnet pn,
struct PCP_retr ri 
) [static]

Definition at line 1905 of file pcpnet.c.

{
       char dummy;
       char eventid[EVENTID_MAXLEN];
       char addr[ADDR_MAXLEN];

       if (sscanf(pn->readbuf, "106%c" EVENTID_SSCANF " " ADDR_SSCANF,
                 &dummy, eventid, addr) == 3)
       {
              ri->event_id=eventid;

              if (ri->callback_retr_participants)
                     return ( (*ri->callback_retr_participants)
                             (ri, addr, NULL, ri->callback_arg));
       }

       return (0);
}

Here is the caller graph for this function:

static int retr_107 ( struct PCPnet pn,
struct PCP_retr ri,
int  ignore 
) [static]

Definition at line 1986 of file pcpnet.c.

{
       char dummy;
       char eventid[EVENTID_MAXLEN];
       int rc=0;
       int ch;
       int seeneol;
       int seendot;
       size_t nn;

       if (sscanf(pn->readbuf, "107%c" EVENTID_SSCANF,
                 &dummy, eventid) != 2)
       {
              errno=EIO;
              rc= -1;
       }

       ri->event_id=eventid;

       if (rc == 0 && ri->callback_begin_func)
              rc= (*ri->callback_begin_func)(ri, ri->callback_arg);

       seeneol=1;
       seendot=1;
       nn=0;

       ch=EOF;
       for (;;)
       {
              if (ch == EOF)
                     ch=readch(pn, nn);
              if (ch == EOF)
              {
                     rc= -1;
                     break;
              }
              if (ch == '\r')
                     continue;

              if (seeneol)
                     seendot= ch == '.';
              else
              {
                     if ( ch == '\n' && seendot)
                            break;
                     seendot=0;
              }
              seeneol= ch == '\n';

              if (!seendot)
                     pn->readbuf[nn++]=ch;
              ch=EOF;

              if (ri->callback_rfc822_func)
              {
                     if (nn >= 8192)
                     {
                            if (rc == 0)
                                   rc= (*ri->callback_rfc822_func)
                                          (ri, pn->readbuf, nn,
                                           ri->callback_arg);
                            nn=0;
                     }
              }
              else if (ri->callback_headers_func)
              {
                     if (nn > 8192)
                            nn=8192;      /* Trim excessive hdrs */

                     if (seeneol)
                     {
                            char *h;
                            char *v;

                            ch=readch(pn, nn);
                            if (ch == EOF)
                            {
                                   rc= -1;
                                   break;
                            }

                            if (ch != '\n' && isspace(ch))
                            {
                                   /* Header wrapped */

                                   while (ch != EOF && ch != '\n'
                                          && isspace(ch))
                                          ch=readch(pn, nn);
                                   pn->readbuf[nn-1]=' ';
                                   continue;
                            }
                            pn->readbuf[nn-1]=0;
                            h=pn->readbuf;
                            if ((v=strchr(h, ':')) == NULL)
                                   v="";
                            else
                            {
                                   *v++=0;
                                   while (*v &&
                                          isspace((int)(unsigned char)*v))
                                          ++v;
                            }
                            if (rc == 0)
                                   rc=(*ri->callback_headers_func)
                                          (ri, h, v, ri->callback_arg);
                            nn=0;
                     }
              }
              else nn=0;
       }

       if (ri->callback_rfc822_func)
       {
              if (rc == 0)
                     rc= (*ri->callback_rfc822_func)
                            (ri, pn->readbuf, nn, ri->callback_arg);
       }

       if (rc == 0 && ri->callback_end_func)
              rc= (*ri->callback_end_func)(ri, ri->callback_arg);
       return (rc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int retr_110 ( struct PCPnet pn,
struct PCP_retr ri 
) [static]

Definition at line 1924 of file pcpnet.c.

{
       char dummy;
       char eventid[EVENTID_MAXLEN];

       if (sscanf(pn->readbuf, "110%c" EVENTID_SSCANF, 
                 &dummy, eventid) == 2)
       {
              const char *p, *q;
              char *r, *s;
              int flags=0;

              ri->event_id=eventid;

              p=pn->readbuf+4;
              while (p)
              {
                     if (isspace((int)(unsigned char)*p))
                            break;
                     ++p;
              }

              while (p)
              {
                     if (!isspace((int)(unsigned char)*p))
                            break;
                     ++p;
              }

              for (q=p; *q; q++)
              {
                     if (isspace((int)(unsigned char)*q))
                            break;
              }
              r=malloc(q-p+1);
              if (!r)
              {
                     pn->haserrmsg=0;
                     return (-1);
              }
              memcpy(r, p, q-p);
              r[q-p]=0;

              for (s=r; (s=strtok(s, ",")) != 0; s=0)
              {
                     if (strcasecmp(s, "CANCELLED") == 0)
                            flags |= LIST_CANCELLED;
                     else if (strcasecmp(s, "BOOKED") == 0)
                            flags |= LIST_BOOKED;
                     else if (strcasecmp(s, "PROXY") == 0)
                            flags |= LIST_PROXY;
              }


              if (ri->callback_retr_status)
                     return ( (*ri->callback_retr_status)
                             (ri, flags, ri->callback_arg));
       }

       return (0);
}

Here is the caller graph for this function:

static int retrevent ( struct PCPnet pn,
struct PCP_retr ri 
) [static]

Definition at line 1767 of file pcpnet.c.

{
       char items_buf[256];
       unsigned i;
       size_t cnt;
       char *q;
       int errflag;

       items_buf[0]=0;
       pn->haserrmsg=0;

       if (ri->callback_retr_status)
              strcat(items_buf, " STATUS");
       if (ri->callback_retr_date)
              strcat(items_buf, " DATE");
       if (ri->callback_retr_participants)
              strcat(items_buf, " ADDR");
       if (ri->callback_rfc822_func)
              strcat(items_buf, " TEXT");
       else if (ri->callback_headers_func)
              strcat(items_buf, " HEADERS");

       if (items_buf[0] == 0)
       {
              errno=EIO;
              return (-1);
       }

       cnt=strlen(items_buf)+256;

       for (i=0; ri->event_id_list[i]; i++)
       {
              const char *p=ri->event_id_list[i];

              if (strchr(p, '\n'))
              {
                     errno=EIO;
                     return (-1);
              }
              cnt += 1 + strlen(p);
       }

       q=malloc(cnt);

       if (!q)
              return (-1);

       strcat(strcat(strcpy(q, "RETR"), items_buf), " EVENTS");

       for (i=0; ri->event_id_list[i]; i++)
       {
              strcat(strcat(q, " "), ri->event_id_list[i]);
       }
       strcat(q, "\n");

       if (dowrite(pn, q, 0) < 0)
       {
              free(q);
              return (-1);
       }
       free(q);

       errflag=0;

       for (;;)
       {
              int rc;

              if (!errflag)
                     pn->haserrmsg=0;
              if (getfullreply(pn) < 0)
                     return (-1);

              if (!errflag)
                     pn->haserrmsg=1;
              rc=checkstatus(pn, NULL);

              if ( rc < 100 || rc >= 400)
                     return (-1);
              if (rc == 108)
                     break;
              pn->haserrmsg=0;

              switch (rc) {
              case 105:
                     if (errflag)
                            break;
                     rc=retr_105(pn, ri);
                     if (rc)
                            errflag=rc;
                     break;
              case 106:
                     if (errflag)
                            break;
                     rc=retr_106(pn, ri);
                     if (rc)
                            errflag=rc;
                     break;
              case 110:
                     if (errflag)
                            break;
                     rc=retr_110(pn, ri);
                     if (rc)
                            errflag=rc;
                     break;
              case 107:
                     rc=retr_107(pn, ri, errflag);
                     if (!errflag && rc)
                            errflag=rc;
                     break;
              default:
                     close(pn->fd);
                     pn->fd= -1;
                     errno=EIO;
                     return (-1);
              }
       }

       return (errflag);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int setacl ( struct PCPnet pn,
const char *  who,
int  flags 
) [static]

Definition at line 2110 of file pcpnet.c.

{
       char buf[1024];

       pn->haserrmsg=0;
       if (strchr(who, '\r') || strchr(who, '\n') || strlen(who) > 512)
       {
              errno=EINVAL;
              return (-1);
       }

       sprintf(buf, "ACL SET %s", who);
       pcp_acl_name(flags, buf);
       strcat(buf, "\n");

       if (docmd(pn, buf, 0))
              return (-1);
       pn->haserrmsg=1;
       switch (checkstatus(pn, NULL) / 100) {
       case 1:
       case 2:
       case 3:
              break;
       default:
              errno=EIO;
              return (-1);
       }
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct PCP * setcapabilities ( struct PCPnet pcp,
int  dofree 
) [static, read]

Definition at line 833 of file pcpnet.c.

{
       int rc;

       if (docmd(pcp, "CAPABILITY\n", 0))
       {
              if (dofree)
                     pcp_close_net(pcp);
              return (NULL);
       }

       if ((rc=checkstatus(pcp, NULL)) != 100)
       {
              if (dofree)
                     pcp_close_net(pcp);
              return (NULL);
       }

       if (!has100(pcp, "PCP1"))
       {
              if (dofree)
                     pcp_close_net(pcp);
              return (NULL);
       }

       if (!has100(pcp, "ACL"))
       {
              pcp->pcp.acl_func=NULL;
              pcp->pcp.listacl_func=NULL;
       }
       return ((struct PCP *)pcp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int uncancelevent ( struct PCPnet pn,
const char *  id,
int  flags,
struct PCP_uncancel ui 
) [static]

Definition at line 1642 of file pcpnet.c.

{
       char *buf;

       pn->haserrmsg=0;
       if (ui)
              ui->errcode=0;

       if (strchr(id, '\r') || strchr(id, '\n'))
       {
              errno=EINVAL;
              return (-1);
       }
       if (docmd(pn, "RSET\n", 0))
              return (-1);
       pn->haserrmsg=1;

       switch (checkstatus(pn, NULL) / 100) {
       case 1:
       case 2:
       case 3:
              break;
       default:
              return (-1);
       }

       pn->haserrmsg=0;
       if (docmd(pn, flags & PCP_OK_CONFLICT
                ? "CONFLICT ON\n":"CONFLICT OFF\n", 0))
       {
              return (-1);
       }
       if (docmd(pn, flags & PCP_OK_PROXY_ERRORS
                ? "FORCE ON\n":"FORCE OFF\n", 0))
       {
              return (-1);
       }

       pn->haserrmsg=1;

       switch (checkstatus(pn, NULL) / 100) {
       case 1:
       case 2:
       case 3:
              break;
       default:
              return (-1);
       }

       buf=malloc(strlen(id)+20);
       if (!buf)
              return (-1);

       strcat(strcat(strcpy(buf, "UNCANCEL "), id), "\n");
       if (dowrite(pn, buf, 0))
       {
              free(buf);
              return (-1);
       }

       return (docommitresponse(pn, ui ? ui->uncancel_conflict_callback:NULL,
                             ui ? ui->uncancel_conflict_callback_ptr:NULL,
                             ui ? &ui->errcode:NULL));
}

Here is the call graph for this function:

Here is the caller graph for this function: