annotate src/encoding/url.c @ 0:d39e1d0d75b6

initial add
author paulo@hit-nxdomain.opendns.com
date Sat, 20 Feb 2010 21:18:28 -0800
parents
children
rev   line source
paulo@0 1 /*
paulo@0 2 * $Id: url.c,v 1.1 2004/03/24 06:34:36 hipnod Exp $
paulo@0 3 *
paulo@0 4 * Copyright (C) 2001-2003 giFT project (gift.sourceforge.net)
paulo@0 5 *
paulo@0 6 * This program is free software; you can redistribute it and/or modify it
paulo@0 7 * under the terms of the GNU General Public License as published by the
paulo@0 8 * Free Software Foundation; either version 2, or (at your option) any
paulo@0 9 * later version.
paulo@0 10 *
paulo@0 11 * This program is distributed in the hope that it will be useful, but
paulo@0 12 * WITHOUT ANY WARRANTY; without even the implied warranty of
paulo@0 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
paulo@0 14 * General Public License for more details.
paulo@0 15 */
paulo@0 16
paulo@0 17 #include "gt_gnutella.h"
paulo@0 18 #include "encoding/url.h"
paulo@0 19
paulo@0 20 #include <ctype.h>
paulo@0 21
paulo@0 22 /*****************************************************************************/
paulo@0 23 /* url decode/encode helpers */
paulo@0 24
paulo@0 25 static int oct_value_from_hex (char hex_char)
paulo@0 26 {
paulo@0 27 if (!isxdigit (hex_char))
paulo@0 28 return 0;
paulo@0 29
paulo@0 30 if (hex_char >= '0' && hex_char <= '9')
paulo@0 31 return (hex_char - '0');
paulo@0 32
paulo@0 33 hex_char = toupper (hex_char);
paulo@0 34
paulo@0 35 return ((hex_char - 'A') + 10);
paulo@0 36 }
paulo@0 37
paulo@0 38 char *gt_url_decode (const char *encoded)
paulo@0 39 {
paulo@0 40 char *decoded, *ptr;
paulo@0 41
paulo@0 42 if (!encoded)
paulo@0 43 return NULL;
paulo@0 44
paulo@0 45 /* make sure we are using our own memory here ... */
paulo@0 46 ptr = strdup (encoded);
paulo@0 47
paulo@0 48 /* save the head */
paulo@0 49 decoded = ptr;
paulo@0 50
paulo@0 51 /* convert '+' -> ' ' and %2x -> char value */
paulo@0 52 while (*ptr)
paulo@0 53 {
paulo@0 54 switch (*ptr)
paulo@0 55 {
paulo@0 56 case '+':
paulo@0 57 *ptr = ' ';
paulo@0 58 break;
paulo@0 59 case '%':
paulo@0 60 if (isxdigit (ptr[1]) && isxdigit (ptr[2]))
paulo@0 61 {
paulo@0 62 int oct_val;
paulo@0 63
paulo@0 64 oct_val = oct_value_from_hex (ptr[1]) * 16;
paulo@0 65 oct_val += oct_value_from_hex (ptr[2]);
paulo@0 66
paulo@0 67 *ptr = (char) oct_val;
paulo@0 68
paulo@0 69 string_move (ptr + 1, ptr + 3);
paulo@0 70 }
paulo@0 71 break;
paulo@0 72 default:
paulo@0 73 break;
paulo@0 74 }
paulo@0 75
paulo@0 76 ptr++;
paulo@0 77 }
paulo@0 78
paulo@0 79 return decoded;
paulo@0 80 }
paulo@0 81
paulo@0 82 static char *gt_url_encode_char (char *stream, unsigned char c)
paulo@0 83 {
paulo@0 84 const char hex_alpha[] = "0123456789abcdef";
paulo@0 85
paulo@0 86 *stream++ = '%';
paulo@0 87
paulo@0 88 *stream++ = hex_alpha[(c & 0xf0) >> 4];
paulo@0 89 *stream++ = hex_alpha[(c & 0x0f)];
paulo@0 90
paulo@0 91 return stream;
paulo@0 92 }
paulo@0 93
paulo@0 94 /*
paulo@0 95 * This is a bit overzealous about what to encode..hopefully that's ok. This
paulo@0 96 * escapes path components ('/').
paulo@0 97 */
paulo@0 98 static BOOL is_safe_char (unsigned char c)
paulo@0 99 {
paulo@0 100 if (c >= 'A' && c <= 'Z')
paulo@0 101 return TRUE;
paulo@0 102
paulo@0 103 if (c >= 'a' && c <= 'z')
paulo@0 104 return TRUE;
paulo@0 105
paulo@0 106 if (c >= '0' && c <= '9')
paulo@0 107 return TRUE;
paulo@0 108
paulo@0 109 switch (c)
paulo@0 110 {
paulo@0 111 case '-':
paulo@0 112 case '.':
paulo@0 113 case '_':
paulo@0 114 return TRUE;
paulo@0 115 default:
paulo@0 116 return FALSE;
paulo@0 117 }
paulo@0 118
paulo@0 119 return FALSE;
paulo@0 120 }
paulo@0 121
paulo@0 122 char *gt_url_encode (const char *decoded)
paulo@0 123 {
paulo@0 124 char *encoded, *ptr;
paulo@0 125 unsigned char chr;
paulo@0 126
paulo@0 127 if (!decoded)
paulo@0 128 return NULL;
paulo@0 129
paulo@0 130 /* allocate a large enough buffer for all cases */
paulo@0 131 encoded = ptr = malloc ((strlen (decoded) * 3) + 1);
paulo@0 132
paulo@0 133 while ((chr = *decoded) != 0)
paulo@0 134 {
paulo@0 135 if (is_safe_char (chr))
paulo@0 136 *ptr++ = chr;
paulo@0 137 else
paulo@0 138 ptr = gt_url_encode_char (ptr, chr);
paulo@0 139
paulo@0 140 decoded++;
paulo@0 141 }
paulo@0 142
paulo@0 143 *ptr = 0;
paulo@0 144
paulo@0 145 return encoded;
paulo@0 146 }
paulo@0 147
paulo@0 148 /*****************************************************************************/
paulo@0 149
paulo@0 150 #if 0
paulo@0 151 int main (int argc, char **argv)
paulo@0 152 {
paulo@0 153 int i;
paulo@0 154
paulo@0 155 for (i = 1; i < argc; i++)
paulo@0 156 {
paulo@0 157 char *enc, *dec;
paulo@0 158
paulo@0 159 enc = gt_url_encode (argv[i]);
paulo@0 160 dec = gt_url_decode (enc);
paulo@0 161
paulo@0 162 printf ("%s\n%s\n%s\n", argv[i], enc, dec);
paulo@0 163
paulo@0 164 assert (strcmp (argv[i], dec) == 0);
paulo@0 165 }
paulo@0 166
paulo@0 167 return 0;
paulo@0 168 }
paulo@0 169 #endif