gert wrote:
> This based on a example i found at http://www.cs.tut.fi/~jkorpela/
> forms/cgic.html
>
> #include <fcgi_stdio.h>
> #include <stdlib.h>
>
> int urldecode(char *src, char *last, char *dest){
> int code;
> for (; src != last; src++, dest++){
> if (*src == '+') *dest = ' ';
> else if(*src == '%') {
> if(sscanf(src+1, "%2x", &code) != 1) code = '?';
> *dest = code;
> src +=2;
> }
> else *dest = *src;
> }
> *dest = '\n';
> *++dest = '\0';
> return 0;
> }
I had written something similar for a toy cgi form util I did a while back...
It's not super well checked for errors, but I do remember it atleast working.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct cgi_var__ {
char *key;
char *val;
size_t key_l;
size_t val_l;
};
static int form_decode(cgi_var *cv, size_t off)
{
char c, tmp[4];
int r;
if (cv->val[off] != '%') {
fprintf(stdout, "form_decode: bad value\n");
return -1;
}
if ((r = (cv->val + cv->val_l) - (cv->val + off)) < 3) {
fprintf(stdout, "form_decode: length too short\n");
return -1;
}
memcpy(tmp, cv->val + off, MIN(3, r)); tmp[3] = '\0';
c = (unsigned char)strtol(tmp + 1, NULL, 16);
/*
* data == text%7Cj%25%5C%25
* 01234567890123456
*
* c == |, off == 4, r == 13
* c == %, off == 6, r == 9
* c == \, off == 7, r == 6
* c == %, off == 8, r == 3
*/
memcpy(cv->val + off, &c, sizeof c);
memmove(cv->val + off + 1, cv->val + off + 3, r - 3);
cv->val_l -= 2;
r = (cv->val + cv->val_l) - (cv->val + off);
return 0;
}
static int cv_filter(cgi_var *cv)
{
size_t i;
/* filter out rug-rats or decode %xx */
for (i = 0; i < cv->val_l; i++) {
if (cv->val[i] == '%')
form_decode(cv, i);
switch (cv->val[i]) {
case '+': case '\'': case '`': case '"':
cv->val[i] = ' '; break;
default: break;
}
}
return 0;
}