/* --- @encode@ --- *
*
- * Arguments: @dstr *d@ = pointer to output string
+ * Arguments: @url_ectx *ctx@ = encoding context
+ * @dstr *d@ = pointer to output string
* @const char *p@ = pointer to thing to encode
*
* Returns: ---
* Use: Encodes the input string into the output string.
*/
-static void encode(dstr *d, const char *p)
+static void encode(url_ectx *ctx, dstr *d, const char *p)
{
while (*p) {
switch (*p) {
DPUTC(d, '+');
break;
default:
- if (isalnum((unsigned char)*p))
- DPUTC(d, *p);
- else
- dstr_putf(d, "%%%02x", *p);
- break;
+ if ((ctx->f & URLF_LAX) || isalnum((unsigned char)*p))
+ goto safe;
+ else
+ goto unsafe;
+ case '/':
+ case '~':
+ if (ctx->f & URLF_STRICT)
+ goto unsafe;
+ case '-':
+ case '.':
+ case '_':
+ safe:
+ DPUTC(d, *p);
+ break;
+ unsafe:
+ case '+':
+ case '%':
+ case '=':
+ case '&':
+ case ';':
+ dstr_putf(d, "%%%02x", *p);
+ break;
}
p++;
}
void url_enc(url_ectx *ctx, dstr *d, const char *name, const char *value)
{
if (ctx->f & URLF_SEP)
- DPUTC(d, '&');
- encode(d, name);
+ DPUTC(d, (ctx->f & URLF_SEMI) ? ';' : '&');
+ encode(ctx, d, name);
DPUTC(d, '=');
- encode(d, value);
+ encode(ctx, d, value);
DPUTZ(d);
ctx->f |= URLF_SEP;
}
* Use: Initializes a URL decoding context.
*/
-void url_initdec(url_dctx *ctx, const char *p) { ctx->p = p; }
+void url_initdec(url_dctx *ctx, const char *p) { ctx->p = p; ctx->f = 0; }
/* --- @decode@ --- *
*
- * Arguments: @dstr *d@ = pointer to output string
+ * Arguments: @url_dctx *ctx@ = pointer to the context
+ * @dstr *d@ = pointer to output string
* @const char *p@ = pointer to input data
* @int eq@ = whether to stop at `=' characters
*
* Use: Does a URL decode.
*/
-static const char *decode(dstr *d, const char *p, int eq)
+static const char *decode(url_dctx *ctx, dstr *d, const char *p, int eq)
{
if (!*p)
return (0);
case '=':
if (eq)
return (p);
- DPUTC(d, *p);
- break;
+ goto boring;
+ case ';':
+ if (ctx->f & URLF_SEMI)
+ return (p);
+ goto boring;
case 0:
case '&':
return (p);
}
}
default:
+ boring:
DPUTC(d, *p);
break;
}
size_t l = n->len;
again:
- if ((p = decode(n, p, 1)) == 0 || *p == 0)
+ if ((p = decode(ctx, n, p, 1)) == 0 || *p == 0)
return (0);
if (*p != '=') {
p++;
goto again;
}
p++;
- if ((p = decode(v, p, 0)) == 0)
+ if ((p = decode(ctx, v, p, 0)) == 0)
return (0);
DPUTZ(n);
DPUTZ(v);