joes        2003/01/22 23:00:41

  Modified:    src      apreq_cookie.h apreq_cookie.c apreq_env.h
                        apreq_tables.c apreq_tables.h apreq.h apreq.c
                        Makefile.am
  Log:
  Sweeping changes to implementation, just a few header tweaks tho.
  
  Revision  Changes    Path
  1.3       +11 -5     httpd-apreq-2/src/apreq_cookie.h
  
  Index: apreq_cookie.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_cookie.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- apreq_cookie.h    21 Jan 2003 15:22:23 -0000      1.2
  +++ apreq_cookie.h    23 Jan 2003 07:00:41 -0000      1.3
  @@ -11,7 +11,8 @@
   
   typedef enum { NETSCAPE, RFC } apreq_cookie_version_t;
   
  -#define APREQ_COOKIE_DEFAULT_VERSION       NETSCAPE
  +#define APREQ_COOKIE_VERSION               NETSCAPE
  +#define APREQ_COOKIE_LENGTH                4096
   
   typedef struct apreq_cookie_t {
   
  @@ -96,15 +97,20 @@
    * The cookie is allocated from the ctx pool.
    *
    * @param ctx   The current context.
  - * @param v     The cookie version, currently one of  ::NETSCAPE or ::RFC.
  + * @param v     The cookie version, currently one of ::NETSCAPE or ::RFC.
  + *              Use ::APREQ_COOKIE_VERSION if you'd like to leave
  + *              that decision up to libapreq.  Currently libapreq uses
  + *              Netscape cookies by default, but this may change in a
  + *              future version.
    * @param name  The cookie's name.
    * @param nlen  Length of name.
    * @param value The cookie's value.
    * @param vlen  Length of value.
    */
  -apreq_cookie_t *apreq_cookie_make(void *ctx, const apreq_cookie_version_t v,
  -                                  const char *name, const apr_ssize_t nlen, 
  -                                  const char *value, const apr_ssize_t vlen);
  +APREQ_DECLARE(apreq_cookie_t *) apreq_cookie_make(void *ctx, 
  +                                  const apreq_cookie_version_t version,
  +                                  const char *name, const apr_size_t nlen, 
  +                                  const char *value, const apr_size_t vlen);
   
   
   APREQ_DECLARE(apr_status_t) apreq_cookie_attr(apreq_cookie_t *c, 
  
  
  
  1.4       +98 -55    httpd-apreq-2/src/apreq_cookie.c
  
  Index: apreq_cookie.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_cookie.c,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- apreq_cookie.c    21 Jan 2003 20:59:41 -0000      1.3
  +++ apreq_cookie.c    23 Jan 2003 07:00:41 -0000      1.4
  @@ -100,8 +100,17 @@
           return APR_SUCCESS;
   
       case 'v': /* version */
  -        c->version = *val - '0';
  -        return APR_SUCCESS;
  +        while (*val && !apr_isdigit(*val))
  +            ++val;
  +        if (val) {
  +            c->version = *val - '0';
  +            return APR_SUCCESS;
  +        }
  +        else {
  +            apreq_warn(c->ctx, APR_BADARG, 
  +                       "Bad Version number (no digits found).");
  +            return APR_BADARG;
  +        }
   
       case 'e': case 'm': /* expires, max-age */
           apreq_cookie_expires(c, val);
  @@ -136,18 +145,20 @@
       case 's':
           c->secure = ( strcasecmp(val,"off")!=0 && *val != '0' );
           return APR_SUCCESS;
  +
       };
   
  -    apreq_warn(c->ctx, "unknown cookie attribute: `%s' => `%s'", 
  +    apreq_warn(c->ctx, APR_ENOTIMPL, 
  +               "unknown cookie attribute: `%s' => `%s'", 
                  attr, val);
   
  -    return APR_EGENERAL;
  +    return APR_ENOTIMPL;
   }
   
   APREQ_DECLARE(apreq_cookie_t *) apreq_cookie_make(void *ctx, 
  -                                  apreq_cookie_version_t version,
  -                                  const char *name, const apr_ssize_t nlen,
  -                                  const char *value, const apr_ssize_t vlen)
  +                                  const apreq_cookie_version_t version,
  +                                  const char *name, const apr_size_t nlen,
  +                                  const char *value, const apr_size_t vlen)
   {
       apr_pool_t *p = apreq_env_pool(ctx);
       apreq_cookie_t *c = apr_palloc(p, vlen + sizeof *c);
  @@ -180,8 +191,8 @@
   }
   
   static APR_INLINE apr_status_t get_pair(const char **data,
  -                                        const char **n, apr_ssize_t *nlen,
  -                                        const char **v, apr_ssize_t *vlen)
  +                                        const char **n, apr_size_t *nlen,
  +                                        const char **v, apr_size_t *vlen)
   {
       const char *d = *data;
       unsigned char in_quotes = 0;
  @@ -189,9 +200,11 @@
       *n = d;
   
       while( *d != '=' && !apr_isspace(*d) )
  -        if (*d++ == 0)  /*error: no '=' sign detected */
  -            return APR_EGENERAL;
  -
  +        if (*d++ == 0)  {
  +            /*error: no '=' sign detected */
  +            *data = d-1;
  +            return APR_NOTFOUND;
  +        }
       *nlen = d - *n;
   
       do ++d; while ( *d == '=' || apr_isspace(*d) );
  @@ -209,10 +222,14 @@
               goto pair_result;
   
           case '\\':
  -            if (*++d)
  +            if (*++d) {
                   break;
  -            else
  -                return APR_EGENERAL; /* shouldn't end on a sour note */      
          
  +            }
  +            else {  /* shouldn't end on a sour note */
  +                *vlen = d - *v;
  +                *data = d;
  +                return APR_BADCH;
  +            }
   
           case '"':
               in_quotes = ! in_quotes;
  @@ -223,11 +240,11 @@
    pair_result:
   
       *vlen = d - *v;
  +    *data = d;
   
       if (in_quotes)
  -        return APR_EGENERAL;
  +        return APR_BADARG;
   
  -    *data = d;
       return APR_SUCCESS;
   }
   
  @@ -242,7 +259,7 @@
   
       const char *origin;
       const char *name, *value; 
  -    apr_ssize_t nlen, vlen;
  +    apr_size_t nlen, vlen;
   
       /* initialize jar */
       
  @@ -272,11 +289,11 @@
       origin = data;
   
   #ifdef DEBUG
  -    apreq_debug(ctx, "parsing cookie data: %s", data);
  +    apreq_debug(ctx, 0, "parsing cookie data: %s", data);
   #endif
   
   
  -    /* parse d */
  +    /* parse data */
   
    parse_cookie_header:
   
  @@ -295,6 +312,7 @@
       }
   
       for (;;) {
  +        apr_status_t status;
   
           while (*data == ';' || apr_isspace(*data))
               ++data;
  @@ -302,34 +320,53 @@
           switch (*data) {
   
           case 0:
  +            /* this is the normal exit point for apreq_cookie_parse */
               return j;
   
  +
           case ',':
               ++data;
               goto parse_cookie_header;
   
  +
           case '$':
  -            if ( c == NULL || version == NETSCAPE ||
  -                 get_pair(&data, &name, &nlen, &value, &vlen) != 
  -                 APR_SUCCESS ) 
  -            {
  -                apreq_warn(ctx, "b0rked Cookie segment: %s", data);
  +            if (c == NULL) {
  +                apreq_error(ctx, APR_BADCH, "Saw attribute, "
  +                            "execting NAME=VALUE cookie pair: %s", data);
  +                return j;
  +            }
  +            else if (version == NETSCAPE) {
  +                c->v.status = APR_EMISMATCH;
  +                apreq_error(ctx, c->v.status, "Saw attribute in a "
  +                                 "Netscape Cookie header: %s", data);
                   return j;
               }
  -            apreq_cookie_attr(c, apr_pstrmemdup(p, name, nlen),
  -                                 apr_pstrmemdup(p, value, vlen));
  +
  +            status = get_pair(&data, &name, &nlen, &value, &vlen);
  +
  +            if (status == APR_SUCCESS)
  +                apreq_cookie_attr(c, apr_pstrmemdup(p, name, nlen),
  +                                     apr_pstrmemdup(p,value, vlen));    
  +            else {
  +                c->v.status = status;
  +                apreq_warn(ctx, c->v.status, 
  +                           "Ignoring bad attribute pair: %s", data);
  +            }
               break;
   
  +
           default:
  -            if ( get_pair(&data, &name, &nlen, &value, &vlen) 
  -                 != APR_SUCCESS ) 
  -            {
  -                apreq_warn(ctx, "Bad Cookie segment: %s", data);
  -                return j; /* XXX: log error? */
  -            }
  -            c = apreq_cookie_make(ctx, version, name, nlen, value, vlen);
  -            apreq_jar_add(j, c);
  +            status = get_pair(&data, &name, &nlen, &value, &vlen);
   
  +            if (status == APR_SUCCESS) {
  +                c = apreq_cookie_make(ctx, version, name, nlen, 
  +                                      value, vlen);
  +                apreq_jar_add(j, c);
  +            }
  +            else {
  +                apreq_warn(ctx, status, "Skipping bad NAME=VALUE pair: %s",
  +                           data);
  +            }
           }
       }
   
  @@ -406,10 +443,10 @@
   APREQ_DECLARE(const char*) apreq_cookie_as_string(const apreq_cookie_t *c,
                                                     apr_pool_t *p)
   {
  -    char s[4096];
  -    int n = apreq_cookie_serialize(c, s, 4096);
  +    char s[APREQ_COOKIE_LENGTH];
  +    int n = apreq_cookie_serialize(c, s, APREQ_COOKIE_LENGTH);
   
  -    if ( n > 0 && n < 4096 )
  +    if ( n < APREQ_COOKIE_LENGTH )
           return apr_pstrmemdup(p, s, n);
       else
           return NULL;
  @@ -417,29 +454,35 @@
   
   APREQ_DECLARE(apr_status_t) apreq_cookie_bake(apreq_cookie_t *c)
   {
  -    char s[4096];
  -    int n = apreq_cookie_serialize(c, s, 4096);
  +    const char *s = apreq_cookie_as_string(c, apreq_env_pool(c->ctx));
   
  -    if (n > 0 && n < 4096)
  -        return apreq_env_set_cookie(c->ctx, s);
  -    else
  -        return APR_EGENERAL;     /* cookie is too large */
  -}       
  +    if (s == NULL) {
  +        apreq_error(c->ctx, APR_ENAMETOOLONG, "Serialized cookie "
  +                    "exceeds APREQ_COOKIE_LENGTH = %d", 
  +                    APREQ_COOKIE_LENGTH);
  +        return APR_ENAMETOOLONG;
  +    }
  +
  +    return apreq_env_set_cookie(c->ctx, s);
  +}
   
   APREQ_DECLARE(apr_status_t) apreq_cookie_bake2(apreq_cookie_t *c)
   {
  -    char s[4096];
  -    int n;
  -
  -    if (c->version != RFC)
  -        return APREQ_ERROR;     /* wrong type */
  +    const char *s = apreq_cookie_as_string(c, apreq_env_pool(c->ctx));
   
  -    n = apreq_cookie_serialize(c, s, 4096);
  +    if ( s == NULL ) {
  +        apreq_error(c->ctx, APR_ENAMETOOLONG, "Serialized cookie "
  +                    "exceeds APREQ_COOKIE_LENGTH = %d", 
  +                    APREQ_COOKIE_LENGTH);
  +        return APR_ENAMETOOLONG;
  +    }
  +    else if ( c->version == NETSCAPE ) {
  +        apreq_error(c->ctx, APR_EMISMATCH, "Cannot bake2 "
  +                    "a Netscape cookie: %s", s);
  +        return APR_EMISMATCH;
  +    }
   
  -    if (n > 0 && n < 4096)
  -        return apreq_env_set_cookie2(c->ctx, s);
  -    else
  -        return APR_EGENERAL;     /* cookie is too large */
  +    return apreq_env_set_cookie2(c->ctx, s);
   }
   
   
  
  
  
  1.3       +6 -1      httpd-apreq-2/src/apreq_env.h
  
  Index: apreq_env.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_env.h,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- apreq_env.h       21 Jan 2003 20:59:41 -0000      1.2
  +++ apreq_env.h       23 Jan 2003 07:00:41 -0000      1.3
  @@ -67,7 +67,12 @@
   #define APREQ_LOG_ERROR(r)  AP_LOG_MARK, AP_LOG_ERR,0,(r)
   #define APREQ_LOG_WARN(r)   AP_LOG_MARK, AP_LOG_WARNING,0,(r)
   
  -APREQ_DECLARE(void) apreq_warn(void *ctx, const char *fmt, ...);
  +APREQ_DECLARE(void) apreq_debug(void *ctx, apr_status_t status,
  +                               const char *fmt, ...);
  +APREQ_DECLARE(void) apreq_warn(void *ctx, apr_status_t status,
  +                               const char *fmt, ...);
  +APREQ_DECLARE(void) apreq_error(void *ctx, apr_status_t status,
  +                                const char *fmt, ...);
   
   #ifdef __cplusplus
    }
  
  
  
  1.5       +79 -79    httpd-apreq-2/src/apreq_tables.c
  
  Index: apreq_tables.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.c,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- apreq_tables.c    21 Jan 2003 20:59:41 -0000      1.4
  +++ apreq_tables.c    23 Jan 2003 07:00:41 -0000      1.5
  @@ -157,8 +157,10 @@
   
   
   #define DEAD(idx)     ( (idx)[o].key == NULL )
  -#define KILL_ENTRY(t,idx) do { (idx)[o].key = NULL; \
  -                               (t)->ghosts++; } while (0)
  +#define KILL(t,idx) do { (idx)[o].key = NULL; \
  +                         (t)->ghosts++; } while (0)
  +#define RESURRECT(t,idx) do { (idx)[o].key = (idx)[o].val->name; \
  +                              (t)->ghosts--; } while (0)
   
   /* NEVER KILL AN ENTRY THAT'S STILL WITHIN THE FOREST */
   #define IN_FOREST(t,idx) ( (idx)[o].tree[PARENT] >= 0 || \
  @@ -672,33 +674,47 @@
   APREQ_DECLARE(apr_status_t) apreq_table_normalize(apreq_table_t *t)
   {
       if (t->flags & TF_MERGE) {
  +        apr_status_t status = APR_SUCCESS;
           int idx;
           apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  -        apr_array_header_t *a = apr_array_make(t->a.pool, 
APREQ_DEFAULT_NELTS,
  -                                               sizeof (apreq_value_t *));
  +        apreq_value_t *a[APREQ_DEFAULT_NELTS];
  +        apr_array_header_t arr = { t->a.pool, sizeof(apreq_value_t *), 0,
  +                                         APREQ_DEFAULT_NELTS, (char *)a };
           
           for (idx = 0; idx < t->a.nelts; ++idx) {
               int j = idx[o].tree[NEXT];
   
               if ( j >= 0 && IN_FOREST(t,idx) ) {
  +                apreq_value_t *v;
   
                   LOCK_TABLE(t);
  +                arr.nelts = 0;
   
  -                idx[o].tree[NEXT] = -1;
  -                a->nelts = 0;
  -                *(const apreq_value_t **)apr_array_push(a) = idx[o].val;
  +                *(const apreq_value_t **)apr_array_push(&arr) = idx[o].val;
   
                   for ( ; j >= 0; j = j[o].tree[NEXT]) {
  -                    *(const apreq_value_t **)apr_array_push(a) = j[o].val;
  -                    KILL_ENTRY(t,j);
  +                    *(const apreq_value_t **)apr_array_push(&arr) = j[o].val;
  +                    KILL(t,j);
                   }
   
  -                idx[o].val = t->merge(t->a.pool, a);
  +                v = t->merge(t->a.pool, &arr);
  +
  +                if (v == NULL) {
  +                    status = APR_EINCOMPLETE;
  +                    for (j = idx[o].tree[NEXT] ; j >= 0; 
  +                         j = j[o].tree[NEXT])
  +                        RESURRECT(t,j);
  +                }
  +                else {
  +                    v->name = idx[o].val->name;
  +                    idx[o].val = v;
  +                    idx[o].tree[NEXT] = -1;
  +                }
   
                   UNLOCK_TABLE(t);
               }
           }
  -        return APR_SUCCESS;
  +        return status;
       }
       else
           return APR_EGENERAL;
  @@ -751,6 +767,7 @@
   {
       return t->ghosts;
   }
  +
   APREQ_DECLARE(int) apreq_table_exorcise(apreq_table_t *t)
   {
       int rv = 0;
  @@ -823,20 +840,6 @@
       return v2c(idx[o].val);
   }
   
  -APREQ_DECLARE(apr_array_header_t *) apreq_table_keys(const apreq_table_t *t,
  -                                                     apr_pool_t *p)
  -{
  -    int i;
  -    apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  -    apr_array_header_t *a = apr_array_make(p, t->a.nelts, 
  -                                           sizeof(char *));
  -
  -    for (i = 0; i < t->a.nelts; ++i)
  -        if (IN_FOREST(t,i))
  -            *(const char **)apr_array_push(a) = i[o].key;
  -
  -    return a;
  -}
   
   APREQ_DECLARE(apr_array_header_t *) apreq_table_values(const apreq_table_t 
*t,
                                                          apr_pool_t *p,
  @@ -876,14 +879,7 @@
   
   #ifdef POOL_DEBUG
       {
  -     if (!apr_pool_is_ancestor(apr_pool_find(key), t->a.pool)) {
  -         fprintf(stderr, "table_set: key not in ancestor pool of t\n");
  -         abort();
  -     }
  -     if (!apr_pool_is_ancestor(apr_pool_find(val), t->a.pool)) {
  -         fprintf(stderr, "table_set: key not in ancestor pool of t\n");
  -         abort();
  -     }
  +        /* XXX */
       }
   #endif
   
  @@ -892,7 +888,7 @@
           idx[o].val = val;
   
           for ( n=idx[o].tree[NEXT]; n>=0; n=n[o].tree[NEXT] )
  -            KILL_ENTRY(t,n);
  +            KILL(t,n);
   
           idx[o].tree[NEXT] = -1;        
       }
  @@ -918,7 +914,7 @@
           delete(o,&t->root[TABLE_HASH(key)],idx,TREE_DROP);
   
           for ( n=idx; n>=0; n=n[o].tree[NEXT] )
  -            KILL_ENTRY(t,n);
  +            KILL(t,n);
   
           UNLOCK_TABLE(t);
       }
  @@ -928,53 +924,57 @@
   
   /********************* table_merge* *********************/
   
  -APREQ_DECLARE(void) apreq_table_merge(apreq_table_t *t,
  +APREQ_DECLARE(apr_status_t) apreq_table_merge(apreq_table_t *t,
                                         const apreq_value_t *val)
   {
       const char *key = val->name;
       int idx = t->root[TABLE_HASH(key)];
       apreq_table_entry_t *o = (apreq_table_entry_t *)t->a.elts;
  +    apreq_table_entry_t *e;
   
  -#ifdef POOL_DEBUG
  -    {
  -     if (!apr_pool_is_ancestor(apr_pool_find(val), t->a.pool)) {
  -            /* XXX */
  -         fprintf(stderr, "apreq_table_merge: val not in ancestor pool of 
t\n");
  -         abort();
  -     }
  -    }
  -#endif
   
  -    if (t->merge && idx >= 0 && search(t->cmp,o,&idx,val->name) == 0) {
  +    if (idx >= 0 && search(t->cmp,o,&idx,val->name) == 0) {
           int n;
  -        apr_array_header_t *arr = apr_array_make(t->a.pool, 
  -                                                 APREQ_DEFAULT_NELTS, 
  -                                                 sizeof(apreq_value_t *));
  +        apreq_value_t *a[APREQ_DEFAULT_NELTS];
  +        apr_array_header_t arr = { t->a.pool, sizeof(apreq_value_t *), 0,
  +                                         APREQ_DEFAULT_NELTS, (char *)a };
   
  -        if (idx[o].val)
  -            *(const apreq_value_t **)apr_array_push(arr) = idx[o].val;
  +        *(const apreq_value_t **)apr_array_push(&arr) = idx[o].val;
   
           for (n = idx[o].tree[NEXT]; n >= 0; n = n[o].tree[NEXT]) {
  -            KILL_ENTRY(t,n);
  -
  -            if (n[o].val)
  -                *(const apreq_value_t **)apr_array_push(arr) = n[o].val;
  +            *(const apreq_value_t **)apr_array_push(&arr) = n[o].val;
  +            KILL(t,n);
           }
   
  -        if (val)
  -            *(const apreq_value_t **)apr_array_push(arr) = val;
  +        *(const apreq_value_t **)apr_array_push(&arr) = val;
   
  -        if (arr->nelts > 1)
  -            idx[o].val = t->merge(t->a.pool, arr);
  +        val = t->merge(t->a.pool, &arr);
  +
  +        if (val == NULL) {
  +            for (n = idx[o].tree[NEXT]; n >= 0; n = n[o].tree[NEXT])
  +                RESURRECT(t,n);
  +
  +            return APR_ENOTIMPL;
  +        }
  +
  +        idx[o].val = val;
  +        idx[o].tree[NEXT] = -1;
  +        return val->status;
       }
  +    else {
   
  -    else { /* not found */
  -        apreq_table_entry_t *e = table_push(t);
  +#ifdef POOL_DEBUG
  +    {
  +        /* Xxx */
  +    }
  +#endif
  +        e = table_push(t);
           e->key = val->name;
           e->val = val;
           e->tree[NEXT] = -1;
           insert(t->cmp,o,&t->root[TABLE_HASH(key)],idx,e,TREE_PUSH);
       }
  +    return val->status;
   }
   
   
  @@ -990,14 +990,7 @@
   
   #ifdef POOL_DEBUG
       {
  -     if (!apr_pool_is_ancestor(apr_pool_find(key), t->a.pool)) {
  -         fprintf(stderr, "table_set: key not in ancestor pool of t\n");
  -         abort();
  -     }
  -     if (!apr_pool_is_ancestor(apr_pool_find(val), t->a.pool)) {
  -         fprintf(stderr, "table_set: key not in ancestor pool of t\n");
  -         abort();
  -     }
  +        /* XXX */
       }
   #endif
   
  @@ -1012,8 +1005,8 @@
   /********************* binary operations ********************/
   
   
  -
  -APREQ_DECLARE(void) apreq_table_cat(apreq_table_t *t, const apreq_table_t *s)
  +APREQ_DECLARE(void) apreq_table_cat(apreq_table_t *t, 
  +                                    const apreq_table_t *s)
   {
       const int n = t->a.nelts;
       int idx;
  @@ -1028,7 +1021,7 @@
               const unsigned char hash = TABLE_HASH(idx[o].key);
   
               if (idx[o].tree[PARENT] == idx - n) { /* ghost from s */
  -                KILL_ENTRY(t,idx);
  +                KILL(t,idx);
                   continue;
               }
   
  @@ -1115,17 +1108,21 @@
       return t;
   }
   
  -APREQ_DECLARE(void) apreq_table_overlap(apreq_table_t *a, 
  -                                      const apreq_table_t *b,
  -                                      const unsigned flags)
  +APREQ_DECLARE(apr_status_t) apreq_table_overlap(apreq_table_t *a, 
  +                                                const apreq_table_t *b,
  +                                                const unsigned flags)
   {
   
       const int m = a->a.nelts;
       const int n = b->a.nelts;
       apr_pool_t *p = b->a.pool;
  +    apr_status_t s;
  +
  +    if (m + n == 0)
  +        return APR_SUCCESS;
   
  -    if (m + n == 0 || a->cmp != b->cmp)
  -        return; /* ERROR !?!? */
  +    if ( a->cmp != b->cmp)
  +        return APR_EMISMATCH;
   
       /* copy (extend) a using b's pool */
       if (a->a.pool != p) {
  @@ -1136,12 +1133,15 @@
   
       if (flags == APR_OVERLAP_TABLES_SET) {
           apreq_value_merge_t *f = a->merge;
  +
           a->merge = collapse;
  -        apreq_table_normalize(a);
  +        s = apreq_table_normalize(a);
           a->merge = f;
       }
       else
  -        apreq_table_normalize(a);
  +        s = apreq_table_normalize(a);
  +
  +    return s;
   }
   
   
  
  
  
  1.4       +10 -19    httpd-apreq-2/src/apreq_tables.h
  
  Index: apreq_tables.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.h,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- apreq_tables.h    21 Jan 2003 20:59:41 -0000      1.3
  +++ apreq_tables.h    23 Jan 2003 07:00:41 -0000      1.4
  @@ -116,8 +116,8 @@
    * @param p The pool to allocate the APR table from
    * @param t The APREQ table to copy
    */
  -APREQ_DECLARE(apr_table_t *)apreq_table_export(const apreq_table_t *t, 
  -                                               apr_pool_t *p);
  +APREQ_DECLARE(apr_table_t *) apreq_table_export(const apreq_table_t *t, 
  +                                                apr_pool_t *p);
   
   /**
    * Create an APREQ Table from an APR Table.
  @@ -233,28 +233,19 @@
    */
   APREQ_DECLARE(const char *) apreq_table_get_cached(apreq_table_t *t,
                                                      const char *key);
  -/**
  - * Return the (unique) keys in a (char *) array, preserving their 
  - * original order.
  - * @param t Table.
  - * @param p Pool used to allocate the resulting array struct.
  - */
  -APREQ_DECLARE(apr_array_header_t *) apreq_table_keys(const apreq_table_t *t,
  -                                                     apr_pool_t *p);
   
   /**
    * Return the (unique) values in an (apreq_value_t *) array,
    * preserving their original order.
    * @param t Table.
    * @param p Pool used to allocate the resulting array struct.
  - * @remark For multivalued keys, the first apreq_value_t is 
  - * returned.
  + * @remark With key == NULL, all values are returned.  However,
  + * only the first value of a multivalued entry is used.
    */
  +
   APREQ_DECLARE(apr_array_header_t *) apreq_table_values(const apreq_table_t 
*t,
                                                          apr_pool_t *p,
                                                          const char *key);
  -
  -
   /**
    * Add an apreq_value_t to the table. If another value already exists
    * with the same name, this will replace the old value.
  @@ -283,8 +274,8 @@
    * via t->merge.
    */
   
  -APREQ_DECLARE(void) apreq_table_merge(apreq_table_t *t, 
  -                                      const apreq_value_t *v);
  +APREQ_DECLARE(apr_status_t) apreq_table_merge(apreq_table_t *t, 
  +                                              const apreq_value_t *v);
   
   /**
    * Add data to a table, regardless of whether there is another element with 
the
  @@ -354,9 +345,9 @@
    * </PRE>
    */
   
  -APREQ_DECLARE(void) apreq_table_overlap(apreq_table_t *a, 
  -                                        const apreq_table_t *b,
  -                                        const unsigned flags);
  +APREQ_DECLARE(apr_status_t) apreq_table_overlap(apreq_table_t *a, 
  +                                                const apreq_table_t *b,
  +                                                const unsigned flags);
   
   /** Iterator API */
   
  
  
  
  1.4       +19 -19    httpd-apreq-2/src/apreq.h
  
  Index: apreq.h
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq.h,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- apreq.h   21 Jan 2003 02:34:32 -0000      1.3
  +++ apreq.h   23 Jan 2003 07:00:41 -0000      1.4
  @@ -10,7 +10,9 @@
   #include "apr_pools.h"
   #include "apr_strings.h"
   
  -#define APREQ_DECLARE(d)        d
  +#include <stddef.h>
  +
  +#define APREQ_DECLARE(d)                d
   
   /* default enctypes */
   #define APREQ_URL_ENCTYPE               "application/x-www-form-urlencoded"
  @@ -20,8 +22,8 @@
   #define APREQ_XML_ENCTYPE               "application/xml"
   #define APREQ_XML_ENCTYPE_LENGTH        15
   
  -#define APREQ_EXPIRES_HTTP              1
  -#define APREQ_EXPIRES_COOKIE            2
  +#define APREQ_EXPIRES_HTTP              0
  +#define APREQ_EXPIRES_COOKIE            1
   
   #define APREQ_DEFAULT_POST_MAX         -1 /* XXX: unsafe default ??? */
   #define APREQ_DEFAULT_NELTS             8
  @@ -34,9 +36,10 @@
   #define APREQ_MATCH_PART                1
   
   /* join modes */
  -#define APREQ_ESCAPE                    1
  -#define APREQ_URLENCODE                 2
  -#define APREQ_QUOTE                     3
  +#define APREQ_JOIN_ESCAPE               1
  +#define APREQ_JOIN_UNESCAPE             2
  +#define APREQ_JOIN_URLENCODE            3
  +#define APREQ_JOIN_QUOTE                4
   
   /* status codes */
   #define APREQ_OK                        0
  @@ -46,14 +49,11 @@
   
   typedef struct apreq_value_t {
       const char          *name;
  -    apr_ssize_t          size;
  -    unsigned             flags;
  +    apr_size_t           size;
  +    apr_status_t         status;
       char                 data[1];
   } apreq_value_t;
   
  -typedef apreq_value_t *(apreq_value_make_t)(apr_pool_t *p, const char *name,
  -                                            const char *data,
  -                                            const apr_ssize_t size);
   typedef apreq_value_t *(apreq_value_merge_t)(apr_pool_t *p,
                                                const apr_array_header_t *a);
   typedef apreq_value_t *(apreq_value_copy_t)(apr_pool_t *p,
  @@ -66,15 +66,14 @@
   #define apreq_strlen(ptr) (apreq_strtoval(ptr)->size)
   
   apreq_value_t *apreq_value_make(apr_pool_t *p, const char *name, 
  -                                const char *data, const apr_ssize_t size);
  +                                const char *data, const apr_size_t size);
   apreq_value_t *apreq_value_copy(apr_pool_t *p, const apreq_value_t *val);
   apreq_value_t *apreq_value_merge(apr_pool_t *p, const apr_array_header_t 
*arr);
   
  -/* apr_array_pstrcat, w/ string separator and APREQ_ESCAPE mode */
  -char *apreq_pvcat(apr_pool_t *p, 
  -                  const apr_array_header_t *arr, 
  -                  const char *sep, 
  -                  int mode);
  +APREQ_DECLARE(const char *) apreq_join(apr_pool_t *p, 
  +                                       const char *sep, 
  +                                       const apr_array_header_t *arr, 
  +                                       int mode);
   
   /* XXX: should we drop this and replace it with apreq_index ? */
   char *apreq_memmem(char* hay, apr_off_t haylen, 
  @@ -84,8 +83,9 @@
                         const char* ndl, apr_off_t ndllen, int part);
   
   /* url-escapes non-alphanumeric characters */
  -char *apreq_escape(apr_pool_t *p, char *s);
  -apr_off_t apreq_unescape(char *s);
  +apr_size_t apreq_quote(char *dest, const char *src, const apr_size_t slen);
  +apr_size_t apreq_escape(char *dest, const char *src, const apr_size_t slen);
  +apr_ssize_t apreq_unescape(char *dest, const char *src, apr_size_t slen);
   
   /* returns date string, (time_str is offset from "now") formatted
    * either as an NSCOOKIE or HTTP date */
  
  
  
  1.4       +202 -145  httpd-apreq-2/src/apreq.c
  
  Index: apreq.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/apreq.c,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- apreq.c   21 Jan 2003 02:34:32 -0000      1.3
  +++ apreq.c   23 Jan 2003 07:00:41 -0000      1.4
  @@ -4,15 +4,19 @@
   #define MIN(a,b) ( (a) < (b) ? (a) : (b) )
   #define MAX(a,b) ( (a) > (b) ? (a) : (b) )
   
  -apreq_value_t *apreq_value_make(apr_pool_t *p, const char *n,
  -                                const char *d, const apr_ssize_t s)
  +apreq_value_t *apreq_value_make(apr_pool_t *p, const char *name,
  +                                const char *d, apr_size_t size)
   {
  -    apreq_value_t *v = apr_palloc(p, s + sizeof *v);
  -    memcpy(v->data, d, s);
  -    v->flags = 0;
  -    v->name = n;
  -    v->size = s;
  -    v->data[s] = 0;
  +    apreq_value_t *v = apr_palloc(p, size + sizeof *v);
  +    if (d == NULL || v == NULL)
  +        return NULL;
  +
  +    memcpy(v->data, d, size);
  +    v->size = size;
  +    v->status = APR_SUCCESS;
  +    v->name = name;
  +    v->data[size] = 0;
  +
       return v;
   }
   
  @@ -36,44 +40,11 @@
   apreq_value_t *apreq_value_merge(apr_pool_t *p,
                                    const apr_array_header_t *arr)
   {
  -    apr_ssize_t s;
  -    apreq_value_t *rv;
  -    apreq_value_t **a = (apreq_value_t **)arr->elts;
  -    int j, n = arr->nelts;
  -
  -    if (n == 0)
  -        return NULL;
  -
  -    while (*a == NULL && n > 0) {
  -        ++a;
  -        --n;
  -    }
  -    while (n > 0 && a[n-1] == NULL)
  -        --n;
  -
  -    if (n == 0)
  -        return NULL;
  -
  -    for (j=0, s=0; j < n; ++j)
  -        if (a[j] != NULL)
  -            s += a[j]->size + 2;
  -
  -    rv = apr_palloc(p, s + sizeof *rv);
  -    rv->size = 0;
  -
  -    memcpy(rv->data, a[0]->data, a[0]->size);
  -    rv->size = a[0]->size;
  -
  -    for (j = 1; j < n; ++j) {
  -        rv->data[rv->size++] = ',';
  -        rv->data[rv->size++] = ' ';
  -        memcpy(rv->data, a[j]->data, a[j]->size);
  -        rv->size += a[j]->size;
  -    }
  -    rv->flags = 0;              /* XXX */
  -    rv->name = a[0]->name;
  -    rv->data[rv->size] = 0;     /* nul-terminate rv->data */
  -    return rv;
  +    apreq_value_t *a = *(apreq_value_t **)(arr->elts);
  +    apreq_value_t *v = apreq_char_to_value( apreq_join(p, ", ", arr, 0) );
  +    if (arr->nelts > 0)
  +        v->name = a->name;
  +    return v;
   }
   
   char *apreq_expires(apr_pool_t *p, const char *time_str, const int type)
  @@ -232,60 +203,86 @@
       return (digit);
   }
   
  -apr_off_t apreq_unescape(char *s)
  +apr_ssize_t apreq_unescape(char *d, const char *s, const apr_size_t slen)
   {
  -    register int badesc, badpath;
  -    char *x, *y;
  -
  -    badesc = 0;
  -    badpath = 0;
  -    /* Initial scan for first '%'. Don't bother writing values before
  -     * seeing a '%' */
  -    y = strchr(s, '%');
  -    if (y == NULL) {
  +    register int badesc = 0;
  +    char *start = d;
  +    const char *end = s + slen;
  +    if (s == NULL || d == NULL)
           return -1;
  +
  +    if (s == (const char *)d) {     /* optimize for src = dest case */
  +        for ( ; s < end; ++s) {
  +            if (*s == '%' || *s == '+')
  +                break;
  +            else if (*s == 0)
  +                return s - (const char *)d;
  +        }
       }
   
  -    for (x = y; *y; ++x, ++y) {
  -        switch (*y) {
  +    for (; s < end; ++d, ++s) {
  +        switch (*s) {
  +
           case '+':
  -            *x = ' ';
  +            *d = ' ';
               break;
  +
           case '%':
  -         if (!apr_isxdigit(*(y + 1)) || !apr_isxdigit(*(y + 2))) {
  -             badesc = 1;
  -             *x = '%';
  +         if (apr_isxdigit(s[1]) && apr_isxdigit(s[2]))
  +            {
  +             *d = x2c(s + 1);
  +             s += 2;
            }
  +            else if (s[1] == 'u' && apr_isxdigit(s[2]) &&
  +                     apr_isxdigit(s[3]) && apr_isxdigit(s[4]) &&
  +                     apr_isxdigit(s[5]))
  +            {
  +                /* XXX: Need to decode oddball
  +                 * javascript unicode escapes: %uXXXX
  +                 * For now we'll just give up.
  +                 */
  +                badesc = 1;
  +                *d = '%';
  +            }
            else {
  -             *x = x2c(y + 1);
  -             y += 2;
  +             badesc = 1;
  +             *d = '%';
            }
               break;
  +
  +        case 0:
  +            *d = 0;
  +            return -1;
  +
           default:
  -            *x = *y;
  +            *d = *s;
           }
       }
  -    *x = '\0';
  +
  +    *d = 0;
  +
       if (badesc)
  -     return -1;
  +     return -2;
       else
  -     return x - s;
  +     return d - start;
   }
   
   
  -char *apreq_escape(apr_pool_t *p, char *str) 
  +apr_size_t apreq_escape(char *dest, const char *src, 
  +                        const apr_size_t slen) 
   {
  -    char *esc = apr_palloc(p, 3 * strlen(str) + 1);
  -    char *d = esc;
  -    const unsigned char *s = (const unsigned char *)str;
  +    char *d = dest;
  +    const unsigned char *s = (const unsigned char *)src;
       unsigned c;
  -    while((c = *s)) {
  -        if( apr_isalnum(c) ) {
  +
  +    for ( ;s < (const unsigned char *)src + slen; ++s) {
  +        c = *s;
  +        if ( apr_isalnum(c) )
               *d++ = c;
  -        } 
  -        else if ( c == ' ' ) {
  +
  +        else if ( c == ' ' )
               *d++ = '+';
  -        }
  +
           else {
   #if APR_CHARSET_EBCDIC
               c = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)c);
  @@ -294,102 +291,162 @@
               *d++ = c2x_table[c >> 4];
               *d++ = c2x_table[c & 0xf];
           }
  -        ++s;
       }
       *d = 0;
  -    return esc;
  +
  +    return d - dest;
   }
   
  -static char *apreq_array_pstrcat(apr_pool_t *p,
  -                                 const apr_array_header_t *arr,
  -                                 const char *sep, int mode)
  +apr_size_t apreq_quote(char *dest, const char *src, const apr_size_t slen) 
   {
  -    char *cp, *res, **strpp;
  -    apr_size_t len, size;
  -    int i;
  +    char *d = dest;
  +    const char *s = src;
   
  -    size = sep ? strlen(sep) : 0;
  +    if (slen == 0) {
  +        *d = 0;
  +        return 0;
  +    }
   
  -    if (arr->nelts <= 0 || arr->elts == NULL) {    /* Empty table? */
  -        return (char *) apr_pcalloc(p, 1);
  +    if (src[0] == '"' && src[slen-1] == '"') { /* src is already quoted */
  +        memcpy(dest, src, slen);
  +        return slen;
       }
   
  -    /* Pass one --- find length of required string */
  +    *d++ = '"';
   
  -    len = 0;
  -    for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
  -        if (strpp && *strpp != NULL) {
  -            len += strlen(*strpp);
  -        }
  -        if (++i >= arr->nelts) {
  -            break;
  +    while (s < src + slen) {
  +
  +        switch (*s) {
  +
  +        case '\\': 
  +            if (s < src + slen - 1) {
  +                *d++ = *s++;
  +                break;
  +            }
  +            /* else fall through */
  +
  +        case '"':
  +            *d++ = '\\';
           }
   
  -        len += size;
  +        *d++ = *s++;
       }
   
  -    /* Allocate the required string */
  +    *d++ = '"';
  +    *d = 0;
  +
  +    return d - dest;
  +}
  +
  +
  +APREQ_DECLARE(const char *) apreq_join(apr_pool_t *p, 
  +                                       const char *sep, 
  +                                       const apr_array_header_t *arr,
  +                                       int mode)
  +{
  +    apr_ssize_t len, slen;
  +    apreq_value_t *rv;
  +    const apreq_value_t **a = (const apreq_value_t **)arr->elts;
  +    char *d;
  +    const int n = arr->nelts;
  +    int j;
  +
  +    slen = sep ? strlen(sep) : 0;
  +
  +    if (n == 0)
  +        return NULL;
  +
  +    for (j=0, len=0; j < n; ++j)
  +        len += a[j]->size + slen;
  +
  +    /* Allocated the required space */
   
  -    if (mode == APREQ_ESCAPE)
  +    switch (mode) {
  +    case APREQ_JOIN_ESCAPE:
           len += 2 * len;
  -    else if(mode == APREQ_QUOTE)
  -        len += 2 * arr->nelts;
  +        break;
  +    case APREQ_JOIN_QUOTE:
  +        len = 2 * (len + n);
  +        break;
  +    }
   
  -    res = (char *) apr_palloc(p, len + 1);
  -    cp = res;
  +    rv = apr_palloc(p, len + sizeof *rv);
  +    rv->name = 0;
  +    rv->size = 0;
  +    rv->status = APR_SUCCESS;
  +    rv->data[0] = 0;
  +
  +    if (n == 0)
  +        return rv->data;
   
       /* Pass two --- copy the argument strings into the result space */
   
  -    for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
  -        if (strpp && *strpp != NULL) {
  -            len = strlen(*strpp);
  -
  -            if (mode == APREQ_ESCAPE) {
  -                const unsigned char *s = (const unsigned char *)*strpp;
  -                unsigned c;
  -                while((c = *s)) {
  -                    if( apr_isalnum(c) ) {
  -                        *cp++ = c;
  -                    } else if ( c == ' ' ) {
  -                        *cp++ = '+';
  -                    }
  -                    else {
  -#if APR_CHARSET_EBCDIC
  -                        c = apr_xlate_conv_byte(ap_hdrs_to_ascii, 
  -                                                (unsigned char)c);
  -#endif
  -                        *cp++ = '%';
  -                        *cp++ = c2x_table[c >> 4];
  -                        *cp++ = c2x_table[c & 0xf];
  -                    }
  -                    ++s;
  -                }
  -            } 
  -            else if (mode == APREQ_QUOTE) {
  -                *cp++ = '"';
  -                memcpy(cp, *strpp, len);
  -                cp += len;
  -                *cp++ = '"';
  +    d = rv->data;
   
  -            }
  +    switch (mode) {
   
  -            else {
  -                memcpy(cp, *strpp, len);
  -                cp += len;
  -            }
  +    case APREQ_JOIN_ESCAPE:
  +        d += apreq_escape(d, a[0]->data, a[0]->size);
   
  +        for (j = 1; j < n; ++j) {
  +                memcpy(d, sep, slen);
  +                d += slen;
  +                d += apreq_escape(d, a[j]->data, a[j]->size);
           }
  -        if (++i >= arr->nelts) {
  +        break;
  +
  +    case APREQ_JOIN_UNESCAPE:
  +        len = apreq_unescape(d, a[0]->data, a[0]->size);
  +
  +        if (len < 0) {
  +            rv->status = APR_BADCH;
               break;
           }
  -        if (sep) {
  -            memcpy(cp,sep,size);
  -            cp += size;
  +        else
  +            d += len;
  +
  +        for (j = 1; j < n; ++j) {
  +            memcpy(d, sep, slen);
  +            d += slen;
  +
  +            len = apreq_unescape(d, a[j]->data, a[j]->size);
  +
  +            if (len < 0) {
  +                rv->status = APR_BADCH;
  +                break;
  +            }
  +            else
  +                d += len;
           }
  +        break;
   
  -    }
   
  -    *cp = '\0';
  +    case APREQ_JOIN_QUOTE:
  +        d += apreq_quote(d, a[0]->data, a[0]->size);
  +
  +        for (j = 1; j < n; ++j) {
  +            memcpy(d, sep, slen);
  +            d += slen;
  +            d += apreq_quote(d, a[j]->data, a[j]->size);
  +        }
  +        break;
   
  -    return res;
  +
  +    default:
  +        memcpy(d,a[0]->data,a[0]->size);
  +        d += a[0]->size;
  +
  +        for (j = 0; j < n ; ++j) {
  +            memcpy(d, sep, slen);
  +            d += slen;
  +            memcpy(d, a[j]->data, a[j]->size);
  +            d += a[j]->size;
  +        }
  +        break;
  +
  +    }
  +
  +    *d = 0;
  +    rv->size = d - rv->data;
  +    return rv->data;
   }
  
  
  
  1.2       +4 -2      httpd-apreq-2/src/Makefile.am
  
  Index: Makefile.am
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/src/Makefile.am,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Makefile.am       17 Jan 2003 06:41:15 -0000      1.1
  +++ Makefile.am       23 Jan 2003 07:00:41 -0000      1.2
  @@ -1,5 +1,7 @@
   lib_LTLIBRARIES = libapreq.la
  -pkginclude_HEADERS = apreq.h apreq_cookie.h apreq_request.h apreq_tables.h 
apreq_env.h
  -libapreq_la_SOURCES = apreq.c apreq_tables.c apreq_cookie.c apreq_request.c
  +pkginclude_HEADERS = apreq.h apreq_cookie.h apreq_request.h \
  +                     apreq_tables.h apreq_env.h
  +libapreq_la_SOURCES = apreq.c apreq_tables.c apreq_cookie.c \
  +                      apreq_param.c apreq_parsers.c
   libapreq_la_LDFLAGS = -version-info 2:0
   INCLUDES = @APREQ_INCLUDES@
  
  
  

Reply via email to