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@