Back to index

courier  0.68.2
Defines | Functions | Variables
cgi.c File Reference
#include "cgi.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>

Go to the source code of this file.

Defines

#define CGIMAXARG   500000
#define CGIMAXFORMDATAARG   2000000

Functions

void error (const char *)
static void enomem ()
static size_t cgi_maxarg ()
static size_t cgi_maxformarg ()
static void cgi_setup_1 ()
void cgi_setup ()
static char * cgiurlencode_common (const char *buf, const char *punct)
char * cgiurlencode (const char *buf)
char * cgiurlencode_noamp (const char *buf)
char * cgiurlencode_noeq (const char *buf)
void cgi_cleanup ()
const char * cgi (const char *arg)
char * cgi_multiple (const char *arg, const char *sep)
static char * nybble (char *p, int *n)
void cgiurldecode (char *q)
void cgi_put (const char *cginame, const char *cgivalue)
int cgi_set_cookie_url (struct cgi_set_cookie_info *cookie_info, const char *url)
void cgi_set_cookies (struct cgi_set_cookie_info *cookies, size_t n_cookies)
static size_t get_cookie_value (const char *ptr, const char **out_ptr, char *out_value)
char * cgi_get_cookie (const char *cookie_name)

Variables

static char * cgi_args = 0
struct cgi_arglistcgi_arglist = 0

Define Documentation

#define CGIMAXARG   500000

Definition at line 31 of file cgi.c.

#define CGIMAXFORMDATAARG   2000000

Definition at line 35 of file cgi.c.


Function Documentation

const char* cgi ( const char *  arg)

Definition at line 289 of file cgi.c.

{
struct cgi_arglist *argp;

       for (argp=cgi_arglist; argp; argp=argp->next)
              if (strcmp(argp->argname, arg) == 0)
                     return (argp->argvalue);
       return ("");
}
void cgi_cleanup ( )

Definition at line 276 of file cgi.c.

{
#if    CGIFORMDATA

       if (hascgiformfd)
       {
              close(cgiformfd);
              hascgiformfd=0;
       }
#endif

}
char* cgi_get_cookie ( const char *  cookie_name)

Definition at line 794 of file cgi.c.

{
       size_t cookie_name_len=strlen(cookie_name);
       const char *cookie=getenv("HTTP_COOKIE");

       if (!cookie)
              cookie="";

       while (*cookie)
       {
              if (isspace((int)(unsigned char)*cookie) ||
                  *cookie == ';' || *cookie == ',')
              {
                     ++cookie;
                     continue;
              }

              if (strncmp(cookie, cookie_name, cookie_name_len) == 0 &&
                  cookie[cookie_name_len] == '=')
              {
                     char *buf;

                     cookie += cookie_name_len;
                     ++cookie;

                     if ((buf=malloc(get_cookie_value(cookie, NULL, NULL)))
                         == NULL)
                     {
                            return NULL;
                     }

                     get_cookie_value(cookie, NULL, buf);

                     if (*buf == 0) /* Pretend not found */
                     {
                            free(buf);
                            errno=ENOENT;
                            return NULL;
                     }

                     return buf;
              }

              get_cookie_value(cookie, &cookie, NULL);
       }

       errno=ENOENT;
       return NULL;
}

Here is the call graph for this function:

static size_t cgi_maxarg ( ) [static]

Definition at line 76 of file cgi.c.

{
       const char *p=getenv("SQWEBMAIL_MAXARGSIZE");
       size_t n=0;

       if (p)
              n=atoi(p);

       if (n < CGIMAXARG)
              n=CGIMAXARG;
       return n;
}

Here is the caller graph for this function:

static size_t cgi_maxformarg ( ) [static]

Definition at line 89 of file cgi.c.

{
       const char *p=getenv("SQWEBMAIL_MAXATTSIZE");
       size_t n=0;

       if (p)
              n=atoi(p);

       if (n < CGIMAXFORMDATAARG)
              n=CGIMAXFORMDATAARG;
       return n;
}

Here is the caller graph for this function:

char* cgi_multiple ( const char *  arg,
const char *  sep 
)

Definition at line 299 of file cgi.c.

{
struct cgi_arglist *argp;
size_t l=1;
char   *buf;

       for (argp=cgi_arglist; argp; argp=argp->next)
              if (strcmp(argp->argname, arg) == 0)
                     l += strlen(argp->argvalue)+strlen(sep);

       buf=malloc(l);
       if (!buf)     return(0);
       *buf=0;

       /*
       ** Because the cgi list is build from the tail end up, we go backwards
       ** now, so that we return options in the same order they were selected.
       */

       argp=cgi_arglist;
       while (argp && argp->next)
              argp=argp->next;

       for (; argp; argp=argp->prev)
              if (strcmp(argp->argname, arg) == 0)
              {
                     if (*buf)     strcat(buf, sep);
                     strcat(buf, argp->argvalue);
              }
       return (buf);
}

Here is the caller graph for this function:

void cgi_put ( const char *  cginame,
const char *  cgivalue 
)

Definition at line 372 of file cgi.c.

{
struct cgi_arglist *argp;

       for (argp=cgi_arglist; argp; argp=argp->next)
              if (strcmp(argp->argname, cginame) == 0)
              {
                     argp->argvalue=cgivalue;
                     return;
              }

       argp=malloc(sizeof(*cgi_arglist));
       if (!argp)    enomem();
       argp->next=cgi_arglist;
       argp->prev=0;
       if (argp->next)
              argp->next->prev=argp;
       cgi_arglist=argp;
       argp->argname=cginame;
       argp->argvalue=cgivalue;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int cgi_set_cookie_url ( struct cgi_set_cookie_info cookie_info,
const char *  url 
)

Definition at line 660 of file cgi.c.

{
       const char *p;

       if (cookie_info->domain)
              free(cookie_info->domain);
       if (cookie_info->path)
              free(cookie_info->domain);

       cookie_info->secure=0;

       if (strncmp(url, "https://", 8) == 0)
              cookie_info->secure=1;

       for (p=url; *p; p++)
       {
              if (*p == ':')
              {
                     url= ++p;
                     break;
              }

              if (*p == '/')
                     break;
       }

       if (strncmp(url, "//", 2) == 0)
       {
              p= url += 2;

              while (*url)
              {
                     if (*url == '/')
                            break;
                     ++url;
              }

              if ((cookie_info->domain=malloc(url-p+1)) == NULL)
                     return -1;

              memcpy(cookie_info->domain, p, url-p);
              cookie_info->domain[url-p]=0;
       }

       if ((cookie_info->path=strdup(url)) == NULL)
              return -1;
       return 0;
}

Here is the call graph for this function:

void cgi_set_cookies ( struct cgi_set_cookie_info cookies,
size_t  n_cookies 
)

Definition at line 710 of file cgi.c.

{
       size_t i;
       const char *sep="";

       printf("Set-Cookie: ");

       for (i=0; i<n_cookies; i++, cookies++)
       {
              printf("%s%s=\"%s\"; ", sep, cookies->name, cookies->value);
              sep="; ";

              if (cookies->path)
                     printf("Path=\"%s\"; ", cookies->path);

              if (cookies->secure)
                     printf("Secure; ");

              if (cookies->age >= 0)
                     printf("Max-Age=%d; ", cookies->age);
              printf("Version=1");
       }

       printf("\n");
       fflush(stdout);
}
void cgi_setup ( )

Definition at line 110 of file cgi.c.

{
struct cgi_arglist *p;

       cgi_setup_1();

       if (cgi_arglist)
              cgi_arglist->prev=0;

       /* Initialize the prev pointer */

       for (p=cgi_arglist; p; p=p->next)
              if (p->next)
                     p->next->prev=p;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void cgi_setup_1 ( ) [static]

Definition at line 127 of file cgi.c.

{
char   *p=getenv("REQUEST_METHOD"), *q, *r;
char   *args;
unsigned long cl;
int    c;
struct cgi_arglist *argp;

       if (p && strcmp(p, "GET") == 0)    /* This is a GET post */
       {
              args=getenv("QUERY_STRING");
              if (!args)    return;
              if (strlen(args) > cgi_maxarg())   enomem();
              cgi_args=malloc(strlen(args)+1);   /* Extra insurance */
              if (!cgi_args)       return;
              strcpy(cgi_args,args);
              args=cgi_args;
       }
       else if (p && strcmp(p, "POST") == 0)
       {
              args=getenv("CONTENT_TYPE");
              if (!args)    return;

#if    CGIFORMDATA

              if (strncasecmp(args,"multipart/form-data;", 20) == 0)
              {
                     args=getenv("CONTENT_LENGTH");
                     if (!args)    return;
                     cl=atol(args);
                     if (cl > cgi_maxformarg())
                     {
                            printf("Content-Type: text/html\n\n");
                            printf("<html><body><h1>Attachment size (%ld MB) exceeds limit set by system administrator (%ld MB)</h1></body></html>\n",
                                   (long)(cl / (1024 * 1024)),
                                   (long)(cgi_maxformarg() / (1024 * 1024)));
                            fake_exit(1);
                     }
                     cgi_formdata(cl);
                     return;
              }
#endif

              if (strncmp(args, "application/x-www-form-urlencoded", 33))
                     return;
              args=getenv("CONTENT_LENGTH");
              if (!args)    return;
              cl=atol(args);
              if (cl > cgi_maxarg())
              {
                     printf("Content-Type: text/html\n\n");
                     printf("<html><body><h1>Message size (%ld MB) exceeds limit set by system administrator (%ld MB)</h1></body></html>\n",
                            (long)(cl / (1024 * 1024)),
                            (long)(cgi_maxarg() / (1024 * 1024)));
                     fake_exit(1);
              }
       cgi_args=malloc(cl+1);      /* Extra insurance */
              if (!cgi_args)       return;
              q=cgi_args;
              while (cl)
              {
                     c=getchar();
                     if (c < 0)
                     {
                            free(cgi_args);
                            cgi_args=0;
                            return;
                     }
                     *q++=c;
                     --cl;
              }
              *q=0;
              args=cgi_args;
       }
       else   return;

       q=args;
       while (*q)
       {
              argp=malloc(sizeof(*cgi_arglist));
              if (!argp)    enomem();
              argp->next=cgi_arglist;
              cgi_arglist=argp;
              argp->argname=q;
              argp->argvalue="";
              p=q;
              while (*q && *q != '&')
                     q++;
              if (*q)       *q++=0;
              if ((r=strchr(p, '=')) != 0)
              {
                     *r++='\0';
                     argp->argvalue=r;
                     cgiurldecode(r);
              }
              cgiurldecode(p);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cgiurldecode ( char *  q)

Definition at line 342 of file cgi.c.

{
char   *p=q;
int    c;

       while (*q)
       {
              if (*q == '+')
              {
                     *p++=' ';
                     q++;
                     continue;
              }
              if (*q != '%')
              {
                     *p++=*q++;
                     continue;
              }
              ++q;
              c=0;
              q=nybble(q, &c);
              q=nybble(q, &c);

              if (c && c != '\r')
                     /* Ignore CRs we get in TEXTAREAS */
                     *p++=c;
       }
       *p++=0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* cgiurlencode ( const char *  buf)

Definition at line 261 of file cgi.c.

{
       return (cgiurlencode_common(buf, "\"?;<>&=/:%@+#"));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* cgiurlencode_common ( const char *  buf,
const char *  punct 
) [static]

Definition at line 226 of file cgi.c.

{
char   *newbuf=0;
size_t cnt=0;
int    pass;
const char *p;
static const char hex[]="0123456789ABCDEF";

       for (pass=0; pass<2; pass++)
       {
              if (pass && (newbuf=malloc(cnt+1)) == 0)  enomem();
              cnt=0;
              for (p=buf; *p; p++)
              {
                     if (strchr(punct, *p) || *p < 32 || *p >= 127)
                     {
                            if (pass)
                            {
                                   newbuf[cnt]='%';
                                   newbuf[cnt+1]=hex[
                                          ((int)(unsigned char)*p) / 16];
                                   newbuf[cnt+2]=hex[ *p & 15 ];
                            }
                            cnt += 3;
                            continue;
                     }
                     if (pass)
                            newbuf[cnt]= *p == ' ' ? '+':*p;
                     ++cnt;
              }
       }
       newbuf[cnt]=0;
       return (newbuf);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* cgiurlencode_noamp ( const char *  buf)

Definition at line 266 of file cgi.c.

{
       return (cgiurlencode_common(buf, "\"?<>=/:%@+#"));
}

Here is the call graph for this function:

char* cgiurlencode_noeq ( const char *  buf)

Definition at line 271 of file cgi.c.

{
       return (cgiurlencode_common(buf, "\"?;<>&/:%@+#"));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void enomem ( ) [static]

Definition at line 67 of file cgi.c.

{
       error("Out of memory.");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void error ( const char *  )

Definition at line 23 of file showmsg2html.c.

{
       fprintf(stderr, "%s\n", p);
       exit(1);
}
static size_t get_cookie_value ( const char *  ptr,
const char **  out_ptr,
char *  out_value 
) [static]

Definition at line 749 of file cgi.c.

{
       int in_quote=0;
       size_t cnt=1;

       while (*ptr)
       {
              if (!in_quote)
              {
                     if (*ptr == ';' || *ptr == ',' ||
                         isspace((int)(unsigned char)*ptr))
                            break;
              }

              if (*ptr == '"')
              {
                     in_quote= ~in_quote;
                     ++ptr;
                     continue;
              }

              if (out_value)
                     *out_value++ = *ptr;
              ++cnt;
              ++ptr;
       }

       if (out_value)
              *out_value=0;

       if (out_ptr)
              *out_ptr=ptr;
       return cnt;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* nybble ( char *  p,
int *  n 
) [static]

Definition at line 331 of file cgi.c.

{
       if ( *p >= '0' && *p <= '9')
              (*n) = (*n) * 16 + (*p++ - '0');
       else if ( *p >= 'A' && *p <= 'F')
              (*n) = (*n) * 16 + (*p++ - 'A' + 10);
       else if ( *p >= 'a' && *p <= 'f')
              (*n) = (*n) * 16 + (*p++ - 'a' + 10);
       return (p);
}

Here is the caller graph for this function:


Variable Documentation

struct cgi_arglist* cgi_arglist = 0

Definition at line 74 of file cgi.c.

char* cgi_args = 0 [static]

Definition at line 72 of file cgi.c.