Diff for /libaitwww/src/aitwww.c between versions 1.1.1.1.2.6 and 1.5.6.1

version 1.1.1.1.2.6, 2012/03/09 16:09:38 version 1.5.6.1, 2016/09/14 15:08:24
Line 12  terms: Line 12  terms:
 All of the documentation and software included in the ELWIX and AITNET  All of the documentation and software included in the ELWIX and AITNET
 Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>  Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012Copyright 2004 - 2016
         by Michael Pounov <misho@elwix.org>.  All rights reserved.          by Michael Pounov <misho@elwix.org>.  All rights reserved.
   
 Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
Line 44  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF TH Line 44  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF TH
 SUCH DAMAGE.  SUCH DAMAGE.
 */  */
 #include "global.h"  #include "global.h"
 #include "tools.h"  
 #include "mime.h"  #include "mime.h"
   
   
Line 56  char www_Error[STRSIZ]; Line 55  char www_Error[STRSIZ];
 #pragma GCC visibility pop  #pragma GCC visibility pop
   
 // www_GetErrno() Get error code of last operation  // www_GetErrno() Get error code of last operation
inline intint
 www_GetErrno()  www_GetErrno()
 {  {
         return www_Errno;          return www_Errno;
 }  }
   
 // www_GetError() Get error text of last operation  // www_GetError() Get error text of last operation
inline const char *const char *
 www_GetError()  www_GetError()
 {  {
         return www_Error;          return www_Error;
 }  }
   
 // www_SetErr() Set error to variables for internal use!!!  // www_SetErr() Set error to variables for internal use!!!
inline voidvoid
 www_SetErr(int eno, char *estr, ...)  www_SetErr(int eno, char *estr, ...)
 {  {
         va_list lst;          va_list lst;
   
         www_Errno = eno;          www_Errno = eno;
        memset(www_Error, 0, STRSIZ);        memset(www_Error, 0, sizeof www_Errno);
         va_start(lst, estr);          va_start(lst, estr);
        vsnprintf(www_Error, STRSIZ, estr, lst);        vsnprintf(www_Error, sizeof www_Errno, estr, lst);
         va_end(lst);          va_end(lst);
 }  }
   
Line 99  www_initCGI(void) Line 98  www_initCGI(void)
   
         str = getenv("REQUEST_METHOD");          str = getenv("REQUEST_METHOD");
         if (!str) {          if (!str) {
                www_SetErr(EBADMSG, "Request method not found");                www_SetErr(EFAULT, "Request method not found");
                 return NULL;                  return NULL;
         }          }
         if (!strcmp(str, "GET") || !strcmp(str, "HEAD")) {          if (!strcmp(str, "GET") || !strcmp(str, "HEAD")) {
                 /* GET | HEAD */                  /* GET | HEAD */
                 str = getenv("QUERY_STRING");                  str = getenv("QUERY_STRING");
                 if (!str) {                  if (!str) {
                        www_SetErr(EBADMSG, "Query string not found");                        www_SetErr(EFAULT, "Query string not found");
                         return NULL;                          return NULL;
                 }                  }
                 cgi = www_parseQuery(str);                  cgi = www_parseQuery(str);
Line 114  www_initCGI(void) Line 113  www_initCGI(void)
                 /* POST */                  /* POST */
                 str = getenv("CONTENT_LENGTH");                  str = getenv("CONTENT_LENGTH");
                 if (!str) {                  if (!str) {
                        www_SetErr(EBADMSG, "Content length not found");                        www_SetErr(EFAULT, "Content length not found");
                         return NULL;                          return NULL;
                 } else                  } else
                         ctlen = strtol(str, NULL, 0);                          ctlen = strtol(str, NULL, 0);
   
                 s = getenv("CONTENT_TYPE");                  s = getenv("CONTENT_TYPE");
                 if (!s) {                  if (!s) {
                        www_SetErr(EBADMSG, "Content type not found");                        www_SetErr(EFAULT, "Content type not found");
                         return NULL;                          return NULL;
                 }                  }
                 if (www_cmp(s, "multipart/form-data") &&                   if (www_cmp(s, "multipart/form-data") && 
                                 www_cmp(s, "application/x-www-form-urlencoded")) {                                  www_cmp(s, "application/x-www-form-urlencoded")) {
                        www_SetErr(EBADMSG, "MIME parts are broken");                        www_SetErr(EFAULT, "MIME parts are broken");
                         return NULL;                          return NULL;
                 }                  }
   
                 /* allocated space for post data */                  /* allocated space for post data */
                str = malloc(ctlen + 1);                str = e_malloc(ctlen + 1);
                 if (!str) {                  if (!str) {
                        LOGERR;                        www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                         return NULL;                          return NULL;
                 } else                  } else
                         memset(str, 0, ctlen + 1);                          memset(str, 0, ctlen + 1);
Line 146  www_initCGI(void) Line 145  www_initCGI(void)
                 else if (!www_cmp(s, "multipart/form-data"))                  else if (!www_cmp(s, "multipart/form-data"))
                         cgi = www_parseMultiPart(str, ctlen, s);                          cgi = www_parseMultiPart(str, ctlen, s);
   
                free(str);                e_free(str);
         } else {          } else {
                 /* Unknown method */                  /* Unknown method */
                www_SetErr(EBADMSG, "Unknown request method");                www_SetErr(EFAULT, "Unknown request method");
                 return NULL;                  return NULL;
         }          }
   
Line 171  www_closeCGI(cgi_t ** __restrict cgi) Line 170  www_closeCGI(cgi_t ** __restrict cgi)
                 return;                  return;
   
         while ((t = SLIST_FIRST(*cgi))) {          while ((t = SLIST_FIRST(*cgi))) {
                if (t->cgi_name)                ait_freeVar(&t->cgi_name);
                        free(t->cgi_name);                ait_freeVar(&t->cgi_value);
                if (t->cgi_value) 
                        free(t->cgi_value); 
   
                 SLIST_REMOVE_HEAD(*cgi, cgi_node);                  SLIST_REMOVE_HEAD(*cgi, cgi_node);
                free(t);                e_free(t);
         }          }
   
        free(*cgi);        e_free(*cgi);
         *cgi = NULL;          *cgi = NULL;
 }  }
   
Line 202  www_parseQuery(const char *str) Line 199  www_parseQuery(const char *str)
                 return NULL;                  return NULL;
         }          }
   
        cgi = malloc(sizeof(cgi_t));        cgi = e_malloc(sizeof(cgi_t));
         if (!cgi) {          if (!cgi) {
                LOGERR;                www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                 return NULL;                  return NULL;
         } else {          } else {
                 memset(cgi, 0, sizeof(cgi_t));                  memset(cgi, 0, sizeof(cgi_t));
                 SLIST_INIT(cgi);                  SLIST_INIT(cgi);
         }          }
   
        base = wrk = strdup(str);        base = wrk = e_strdup(str);
   
         while (*wrk) {          while (*wrk) {
                t = malloc(sizeof(struct tagCGI));                t = e_malloc(sizeof(struct tagCGI));
                 if (!t) {                  if (!t) {
                        LOGERR;                        www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                         www_closeCGI(&cgi);                          www_closeCGI(&cgi);
                         return NULL;                          return NULL;
                 } else                  } else
                         memset(t, 0, sizeof(struct tagCGI));                          memset(t, 0, sizeof(struct tagCGI));
   
                 t->cgi_name = www_getpair(&wrk, "=");                  t->cgi_name = www_getpair(&wrk, "=");
                www_unescape(t->cgi_name);                www_unescape(AIT_GET_STR(t->cgi_name));
   
                 t->cgi_value = www_getpair(&wrk, "&;");                  t->cgi_value = www_getpair(&wrk, "&;");
                www_unescape(t->cgi_value);                www_unescape(AIT_GET_STR(t->cgi_value));
   
                 if (!old)                  if (!old)
                         SLIST_INSERT_HEAD(cgi, t, cgi_node);                          SLIST_INSERT_HEAD(cgi, t, cgi_node);
Line 235  www_parseQuery(const char *str) Line 232  www_parseQuery(const char *str)
                 old = t;                  old = t;
         }          }
   
        free(base);        e_free(base);
         return cgi;          return cgi;
 }  }
   
Line 246  www_parseQuery(const char *str) Line 243  www_parseQuery(const char *str)
  * @name = Name of cgi variable   * @name = Name of cgi variable
  * return: NULL not found or !=NULL value   * return: NULL not found or !=NULL value
  */   */
inline const char *const char *
 www_getValue(cgi_t * __restrict cgi, const char *name)  www_getValue(cgi_t * __restrict cgi, const char *name)
 {  {
         struct tagCGI *t;          struct tagCGI *t;
Line 257  www_getValue(cgi_t * __restrict cgi, const char *name) Line 254  www_getValue(cgi_t * __restrict cgi, const char *name)
         }          }
   
         SLIST_FOREACH(t, cgi, cgi_node)          SLIST_FOREACH(t, cgi, cgi_node)
                if (t->cgi_name && !strcmp(name, t->cgi_name))                if (t->cgi_name && !strcmp(name, AIT_GET_STR(t->cgi_name)))
                        return t->cgi_value;                        return AIT_GET_STR(t->cgi_value);
   
         return NULL;          return NULL;
 }  }
Line 283  www_addValue(cgi_t * __restrict cgi, const char *name, Line 280  www_addValue(cgi_t * __restrict cgi, const char *name,
   
         /* search for update */          /* search for update */
         SLIST_FOREACH_SAFE(t, cgi, cgi_node, tmp) {          SLIST_FOREACH_SAFE(t, cgi, cgi_node, tmp) {
                if (t->cgi_name && !strcmp(name, t->cgi_name)) {                if (t->cgi_name && !strcmp(name, AIT_GET_STR(t->cgi_name))) {
                        if (t->cgi_value)                        AIT_FREE_VAL(t->cgi_value);
                                free(t->cgi_value);                        AIT_SET_STR(t->cgi_value, value);
                        if (value) 
                                t->cgi_value = strdup(value); 
                         /* update */                          /* update */
                         return 1;                          return 1;
                 }                  }
Line 297  www_addValue(cgi_t * __restrict cgi, const char *name, Line 292  www_addValue(cgi_t * __restrict cgi, const char *name,
         }          }
   
         /* add new one */          /* add new one */
        tmp = malloc(sizeof(struct tagCGI));        tmp = e_malloc(sizeof(struct tagCGI));
         if (!tmp) {          if (!tmp) {
                LOGERR;                www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                 return -1;                  return -1;
         } else          } else
                 memset(tmp, 0, sizeof(struct tagCGI));                  memset(tmp, 0, sizeof(struct tagCGI));
   
        tmp->cgi_name = strdup(name);        tmp->cgi_name = ait_allocVar();
        if (value)        if (!tmp->cgi_name) {
                tmp->cgi_value = strdup(value);                www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                 e_free(tmp);
                 return -1;
         } else
                 AIT_SET_STR(tmp->cgi_name, name);
         tmp->cgi_value = ait_allocVar();
         if (!tmp->cgi_name) {
                 www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                 ait_freeVar(&tmp->cgi_name);
                 e_free(tmp);
                 return -1;
         } else
                 AIT_SET_STR(tmp->cgi_value, value);
   
         if (!t)          if (!t)
                 SLIST_INSERT_HEAD(cgi, tmp, cgi_node);                  SLIST_INSERT_HEAD(cgi, tmp, cgi_node);
Line 334  www_delPair(cgi_t * __restrict cgi, const char *name) Line 341  www_delPair(cgi_t * __restrict cgi, const char *name)
   
         /* search for delete */          /* search for delete */
         SLIST_FOREACH_SAFE(t, cgi, cgi_node, tmp)          SLIST_FOREACH_SAFE(t, cgi, cgi_node, tmp)
                if (t->cgi_name && !strcmp(name, t->cgi_name)) {                if (t->cgi_name && !strcmp(name, AIT_GET_STR(t->cgi_name))) {
                         SLIST_REMOVE(cgi, t, tagCGI, cgi_node);                          SLIST_REMOVE(cgi, t, tagCGI, cgi_node);
   
                        if (t->cgi_name)                        ait_freeVar(&t->cgi_name);
                                free(t->cgi_name);                        ait_freeVar(&t->cgi_value);
                        if (t->cgi_value)                        e_free(t);
                                free(t->cgi_value); 
                        free(t); 
                         return 1;                          return 1;
                 }                  }
   
Line 356  www_delPair(cgi_t * __restrict cgi, const char *name) Line 361  www_delPair(cgi_t * __restrict cgi, const char *name)
  * @arg = Optional argument pass through callback   * @arg = Optional argument pass through callback
  * return: -1 error or >-1 number of elements   * return: -1 error or >-1 number of elements
  */   */
inline intint
 www_listPairs(cgi_t * __restrict cgi, list_cb_t func, void *arg)  www_listPairs(cgi_t * __restrict cgi, list_cb_t func, void *arg)
 {  {
         register int ret = 0;          register int ret = 0;
Line 383  www_listPairs(cgi_t * __restrict cgi, list_cb_t func,  Line 388  www_listPairs(cgi_t * __restrict cgi, list_cb_t func, 
  * @output = file handle   * @output = file handle
  * return: <1 error or >0 writed bytes   * return: <1 error or >0 writed bytes
  */   */
inline intint
 www_header(FILE *output)  www_header(FILE *output)
 {  {
         FILE *f = output ? output : stdout;          FILE *f = output ? output : stdout;
Line 391  www_header(FILE *output) Line 396  www_header(FILE *output)
         return fputs("Content-type: text/html\n\n", f);          return fputs("Content-type: text/html\n\n", f);
 }  }
   
static char *static ait_val_t *
 quotStr(const char *str, const char **end)  quotStr(const char *str, const char **end)
 {  {
        char *s, *e;        char *e;
         int n, len = 0;          int n, len = 0;
         register int i;          register int i;
           ait_val_t *s;
   
         /* get str w/o " */          /* get str w/o " */
         if (*str != '"') {          if (*str != '"') {
                 n = strspn(str, "!#$%&'*+-.0123456789?ABCDEFGHIJKLMNOPQRSTUVWXYZ"                  n = strspn(str, "!#$%&'*+-.0123456789?ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                 "^_`abcdefghijklmnopqrstuvwxyz{|}~");                                  "^_`abcdefghijklmnopqrstuvwxyz{|}~");
                s = malloc(n + 1);                s = ait_allocVar();
                 if (!s) {                  if (!s) {
                        LOGERR;                        www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                         return NULL;                          return NULL;
                 } else {                  } else {
                        strncpy(s, str, n);                        AIT_SET_STRSIZ(s, n + 1);
                        s[n] = 0;                        strlcpy(AIT_GET_STR(s), str, AIT_LEN(s));
                         *end = str + n;                          *end = str + n;
                         return s;                          return s;
                 }                  }
Line 419  quotStr(const char *str, const char **end) Line 425  quotStr(const char *str, const char **end)
                 return NULL;                  return NULL;
         else          else
                 len = e - str;                  len = e - str;
        s = malloc(len + 1);
         s = ait_allocVar();
         if (!s) {          if (!s) {
                LOGERR;                www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                 return NULL;                  return NULL;
           } else {
                   AIT_SET_STRSIZ(s, len + 1);
                   e = AIT_GET_STR(s);
         }          }
   
         for (i = 0; i < len; i++, str++) {          for (i = 0; i < len; i++, str++) {
                 if (*str == '\\' || *str == '\n')                  if (*str == '\\' || *str == '\n')
                        s[i] = *++str;                        e[i] = *++str;
                 else if (*str == '"')                  else if (*str == '"')
                         break;                          break;
                 else                  else
                        s[i] = *str;                        e[i] = *str;
         }          }
        s[i] = 0;        e[i] = 0;
   
         *end = ++str;          *end = ++str;
         return s;          return s;
Line 443  static struct tagCGI * Line 453  static struct tagCGI *
 addAttr(const char **ct)  addAttr(const char **ct)
 {  {
         struct tagCGI *a;          struct tagCGI *a;
        const char *c, *eq;        const char *c;
        char *name, *value;        char *eq;
   
         if (!*ct || !(c = strchr(*ct, ';')))          if (!*ct || !(c = strchr(*ct, ';')))
                 return NULL;                  return NULL;
         else          else
                 c++;                  c++;
        while (isspace(*c))        while (isspace((int) *c))
                 c++;                  c++;
   
         if (!(eq = strchr(c, '=')))          if (!(eq = strchr(c, '=')))
                 return NULL;                  return NULL;
   
        /* parse name */        a = e_malloc(sizeof(struct tagCGI));
        name = malloc(eq - c + 1);        if (!a) {
        if (!name) {                www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                LOGERR; 
                 return NULL;                  return NULL;
         } else {  
                 strncpy(name, c, eq - c);  
                 name[eq - c] = 0;  
         }          }
        /* parse value */        a->cgi_name = ait_allocVar();
        value = quotStr(++eq, &c);        if (!a->cgi_name) {
        if (!value) {                www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                free(name);                e_free(a);
                 return NULL;                  return NULL;
         }          }
   
        /* fill tagCGI */        *eq++ = 0;
        a = malloc(sizeof(struct tagCGI));        AIT_SET_STR(a->cgi_name, c);
        if (!a) {        a->cgi_value = quotStr(eq, &c);
                LOGERR;        if (!a->cgi_value) {
                 ait_freeVar(&a->cgi_name);
                 e_free(a);
                 return NULL;                  return NULL;
         } else {  
                 a->cgi_name = name;  
                 a->cgi_value = value;  
                 *ct = c;  
         }          }
   
           *ct = c;
         return a;          return a;
 }  }
   
Line 502  www_parseMultiPart(const char *str, int ctlen, const c Line 508  www_parseMultiPart(const char *str, int ctlen, const c
         struct tagCGI *t, *old = NULL;          struct tagCGI *t, *old = NULL;
         const char *s;          const char *s;
         int len;          int len;
           ait_val_t *v;
   
         if (!str) {          if (!str) {
                 www_SetErr(EINVAL, "String is NULL");                  www_SetErr(EINVAL, "String is NULL");
                 return NULL;                  return NULL;
         }          }
   
        cgi = malloc(sizeof(cgi_t));        cgi = e_malloc(sizeof(cgi_t));
         if (!cgi) {          if (!cgi) {
                LOGERR;                www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                 return NULL;                  return NULL;
         } else {          } else {
                 memset(cgi, 0, sizeof(cgi_t));                  memset(cgi, 0, sizeof(cgi_t));
Line 523  www_parseMultiPart(const char *str, int ctlen, const c Line 530  www_parseMultiPart(const char *str, int ctlen, const c
                 www_closeCGI(&cgi);                  www_closeCGI(&cgi);
                 return NULL;                  return NULL;
         }          }
        mime = mime_parseMultiPart(str, ctlen, www_getAttribute(attr, "boundary"), NULL);        v = www_getAttribute(attr, "boundary");
         mime = mime_parseMultiPart(str, ctlen, AIT_GET_STR(v), NULL);
         www_freeAttributes(&attr);          www_freeAttributes(&attr);
         if (!mime) {          if (!mime) {
                 www_closeCGI(&cgi);                  www_closeCGI(&cgi);
Line 538  www_parseMultiPart(const char *str, int ctlen, const c Line 546  www_parseMultiPart(const char *str, int ctlen, const c
                         continue;                          continue;
                 }                  }
   
                t = malloc(sizeof(struct tagCGI));                t = e_malloc(sizeof(struct tagCGI));
                 if (!t) {                  if (!t) {
                        LOGERR;                        www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                         mime_close(&mime);                          mime_close(&mime);
                         www_closeCGI(&cgi);                          www_closeCGI(&cgi);
                         return NULL;                          return NULL;
                 } else                  } else
                         memset(t, 0, sizeof(struct tagCGI));                          memset(t, 0, sizeof(struct tagCGI));
   
                t->cgi_name = strdup(www_getAttribute(attr, "name"));                AIT_COPY_VAL(t->cgi_name, www_getAttribute(attr, "name"));
                 len = mime_calcRawSize(m);                  len = mime_calcRawSize(m);
                t->cgi_value = malloc(len + 1);                t->cgi_value = ait_allocVar();
                if (t->cgi_value) {                if (!t->cgi_value) {
                        len = mime_getRawData(m, t->cgi_value, len + 1);                        www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                        t->cgi_value[len] = 0;                        ait_freeVar(&t->cgi_name);
                         e_free(t);
                         mime_close(&mime);
                         www_closeCGI(&cgi);
                         return NULL;
                 } else {
                         AIT_SET_STRSIZ(t->cgi_value, len + 1);
                         len = mime_getRawData(m, AIT_GET_STR(t->cgi_value), AIT_LEN(t->cgi_value));
                 }                  }
   
                 www_freeAttributes(&attr);                  www_freeAttributes(&attr);
Line 574  www_parseMultiPart(const char *str, int ctlen, const c Line 589  www_parseMultiPart(const char *str, int ctlen, const c
  * @ct = Content type   * @ct = Content type
  * return: NULL error or !=NULL attributes   * return: NULL error or !=NULL attributes
  */   */
inline cgi_t *cgi_t *
 www_parseAttributes(const char **ct)  www_parseAttributes(const char **ct)
 {  {
         struct tagCGI *t, *old = NULL;          struct tagCGI *t, *old = NULL;
Line 585  www_parseAttributes(const char **ct) Line 600  www_parseAttributes(const char **ct)
                 return NULL;                  return NULL;
         }          }
   
        attr = malloc(sizeof(cgi_t));        attr = e_malloc(sizeof(cgi_t));
         if (!attr) {          if (!attr) {
                LOGERR;                www_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                 return NULL;                  return NULL;
         } else {          } else {
                 memset(attr, 0, sizeof(cgi_t));                  memset(attr, 0, sizeof(cgi_t));
Line 607  www_parseAttributes(const char **ct) Line 622  www_parseAttributes(const char **ct)
 }  }
   
 /*  /*
 * www_freeAttributes() - Free attributes * www_getAttribute() - Get Attribute from attribute session
  *   *
 * @attr = Attributes * @cgi = Inited attribute session
 * return: none * @name = Name of attribute variable
  * return: NULL not found or !=NULL value
  */   */
inline voidait_val_t *
www_freeAttributes(cgi_t ** __restrict attr)www_getAttribute(cgi_t * __restrict cgi, const char *name)
 {  {
         struct tagCGI *t;          struct tagCGI *t;
   
        if (!attr || !*attr)        if (!cgi || !name) {
                return;                www_SetErr(EINVAL, "Invalid argument(s)");
                return NULL;
        /* free mime attributes */ 
        while ((t = SLIST_FIRST(*attr))) { 
                if (t->cgi_name) 
                        free(t->cgi_name); 
                if (t->cgi_value) 
                        free(t->cgi_value); 
                SLIST_REMOVE_HEAD(*attr, cgi_node); 
                free(t); 
         }          }
   
        free(*attr);        SLIST_FOREACH(t, cgi, cgi_node)
        *attr = NULL;                if (t->cgi_name && !strcmp(name, AIT_GET_STR(t->cgi_name)))
} 
 
/* 
 * www_getAttribute() - Get attribute by name 
 * 
 * @attr = Attributes 
 * @name = Name of attribute 
 * return: NULL not found or !=NULL attribute value 
 */ 
inline const char * 
www_getAttribute(cgi_t * __restrict attr, const char *name) 
{ 
        struct tagCGI *t; 
 
        SLIST_FOREACH(t, attr, cgi_node) 
                if (!strcasecmp(t->cgi_name, name)) 
                         return t->cgi_value;                          return t->cgi_value;
   
         return NULL;          return NULL;
 }  }
   

Removed from v.1.1.1.1.2.6  
changed lines
  Added in v.1.5.6.1


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>