paulo@0: /* paulo@0: * $Id: url.c,v 1.1 2004/03/24 06:34:36 hipnod Exp $ paulo@0: * paulo@0: * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net) paulo@0: * paulo@0: * This program is free software; you can redistribute it and/or modify it paulo@0: * under the terms of the GNU General Public License as published by the paulo@0: * Free Software Foundation; either version 2, or (at your option) any paulo@0: * later version. paulo@0: * paulo@0: * This program is distributed in the hope that it will be useful, but paulo@0: * WITHOUT ANY WARRANTY; without even the implied warranty of paulo@0: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU paulo@0: * General Public License for more details. paulo@0: */ paulo@0: paulo@0: #include "gt_gnutella.h" paulo@0: #include "encoding/url.h" paulo@0: paulo@0: #include paulo@0: paulo@0: /*****************************************************************************/ paulo@0: /* url decode/encode helpers */ paulo@0: paulo@0: static int oct_value_from_hex (char hex_char) paulo@0: { paulo@0: if (!isxdigit (hex_char)) paulo@0: return 0; paulo@0: paulo@0: if (hex_char >= '0' && hex_char <= '9') paulo@0: return (hex_char - '0'); paulo@0: paulo@0: hex_char = toupper (hex_char); paulo@0: paulo@0: return ((hex_char - 'A') + 10); paulo@0: } paulo@0: paulo@0: char *gt_url_decode (const char *encoded) paulo@0: { paulo@0: char *decoded, *ptr; paulo@0: paulo@0: if (!encoded) paulo@0: return NULL; paulo@0: paulo@0: /* make sure we are using our own memory here ... */ paulo@0: ptr = strdup (encoded); paulo@0: paulo@0: /* save the head */ paulo@0: decoded = ptr; paulo@0: paulo@0: /* convert '+' -> ' ' and %2x -> char value */ paulo@0: while (*ptr) paulo@0: { paulo@0: switch (*ptr) paulo@0: { paulo@0: case '+': paulo@0: *ptr = ' '; paulo@0: break; paulo@0: case '%': paulo@0: if (isxdigit (ptr[1]) && isxdigit (ptr[2])) paulo@0: { paulo@0: int oct_val; paulo@0: paulo@0: oct_val = oct_value_from_hex (ptr[1]) * 16; paulo@0: oct_val += oct_value_from_hex (ptr[2]); paulo@0: paulo@0: *ptr = (char) oct_val; paulo@0: paulo@0: string_move (ptr + 1, ptr + 3); paulo@0: } paulo@0: break; paulo@0: default: paulo@0: break; paulo@0: } paulo@0: paulo@0: ptr++; paulo@0: } paulo@0: paulo@0: return decoded; paulo@0: } paulo@0: paulo@0: static char *gt_url_encode_char (char *stream, unsigned char c) paulo@0: { paulo@0: const char hex_alpha[] = "0123456789abcdef"; paulo@0: paulo@0: *stream++ = '%'; paulo@0: paulo@0: *stream++ = hex_alpha[(c & 0xf0) >> 4]; paulo@0: *stream++ = hex_alpha[(c & 0x0f)]; paulo@0: paulo@0: return stream; paulo@0: } paulo@0: paulo@0: /* paulo@0: * This is a bit overzealous about what to encode..hopefully that's ok. This paulo@0: * escapes path components ('/'). paulo@0: */ paulo@0: static BOOL is_safe_char (unsigned char c) paulo@0: { paulo@0: if (c >= 'A' && c <= 'Z') paulo@0: return TRUE; paulo@0: paulo@0: if (c >= 'a' && c <= 'z') paulo@0: return TRUE; paulo@0: paulo@0: if (c >= '0' && c <= '9') paulo@0: return TRUE; paulo@0: paulo@0: switch (c) paulo@0: { paulo@0: case '-': paulo@0: case '.': paulo@0: case '_': paulo@0: return TRUE; paulo@0: default: paulo@0: return FALSE; paulo@0: } paulo@0: paulo@0: return FALSE; paulo@0: } paulo@0: paulo@0: char *gt_url_encode (const char *decoded) paulo@0: { paulo@0: char *encoded, *ptr; paulo@0: unsigned char chr; paulo@0: paulo@0: if (!decoded) paulo@0: return NULL; paulo@0: paulo@0: /* allocate a large enough buffer for all cases */ paulo@0: encoded = ptr = malloc ((strlen (decoded) * 3) + 1); paulo@0: paulo@0: while ((chr = *decoded) != 0) paulo@0: { paulo@0: if (is_safe_char (chr)) paulo@0: *ptr++ = chr; paulo@0: else paulo@0: ptr = gt_url_encode_char (ptr, chr); paulo@0: paulo@0: decoded++; paulo@0: } paulo@0: paulo@0: *ptr = 0; paulo@0: paulo@0: return encoded; paulo@0: } paulo@0: paulo@0: /*****************************************************************************/ paulo@0: paulo@0: #if 0 paulo@0: int main (int argc, char **argv) paulo@0: { paulo@0: int i; paulo@0: paulo@0: for (i = 1; i < argc; i++) paulo@0: { paulo@0: char *enc, *dec; paulo@0: paulo@0: enc = gt_url_encode (argv[i]); paulo@0: dec = gt_url_decode (enc); paulo@0: paulo@0: printf ("%s\n%s\n%s\n", argv[i], enc, dec); paulo@0: paulo@0: assert (strcmp (argv[i], dec) == 0); paulo@0: } paulo@0: paulo@0: return 0; paulo@0: } paulo@0: #endif