00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include <misc.h>
00022 #include <ctype.h>
00023 #include "inet/url.h"
00024
00025
00026 typedef struct {
00027 char *scheme;
00028 unsigned port;
00029 } scheme_t;
00030
00031
00032 static scheme_t schemes[] = {
00033 {"ftp", DEFAULT_FTP_PORT},
00034 {"telnet", DEFAULT_TELNET_PORT},
00035 {"mailto", DEFAULT_SMTP_PORT},
00036 {"gopher", DEFAULT_GOPHER_PORT},
00037 {"http", DEFAULT_HTTP_PORT},
00038 {"nntp", DEFAULT_NNTP_PORT},
00039 {"news", DEFAULT_NNTP_PORT},
00040 {"wais", DEFAULT_WAIS_PORT},
00041 {"https", DEFAULT_HTTPS_PORT},
00042 {"snews", DEFAULT_SNEWS_PORT},
00043 { NULL, 0 }
00044 };
00045
00046
00055 static unsigned port_for_scheme(char *scheme)
00056 {
00057 scheme_t *s = schemes;
00058 while (s->scheme) {
00059 if (!stricmp(s->scheme, scheme))
00060 return s->port;
00061 s++;
00062 }
00063 return 0;
00064 }
00065
00066
00067 static unsigned char hexchars[] = "0123456789ABCDEF";
00068
00069
00076 static int htoi(char *s)
00077 {
00078 int value;
00079 int c;
00080
00081 c = s[0];
00082 if (isupper(c))
00083 c = tolower(c);
00084 value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
00085
00086 c = s[1];
00087 if (isupper(c))
00088 c = tolower(c);
00089 value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
00090
00091 return (value);
00092 }
00093
00094
00103 void free_url(URL *url)
00104 {
00105 if (url->scheme) free(url->scheme);
00106 if (url->user) free(url->user);
00107 if (url->pass) free(url->pass);
00108 if (url->host) free(url->host);
00109 if (url->path) free(url->path);
00110 if (url->query) free(url->query);
00111 if (url->fragment) free(url->fragment);
00112 free(url);
00113 }
00114
00115
00133 URL *parse_url(const char *urlString)
00134 {
00135
00136 char *urlStringCopy = strdup(urlString);
00137 if (!urlStringCopy)
00138 return NULL;
00139
00140
00141 URL *url = (URL*)malloc(sizeof(URL));
00142 if (!url) {
00143 free(urlStringCopy);
00144 return NULL;
00145 }
00146 memset(url, 0, sizeof(URL));
00147
00148 char *s = urlStringCopy;
00149 char *p1, *p2;
00150
00151
00152 p1 = strchr(s, ':');
00153 if (p1) {
00154 *p1 = '\0';
00155 url->scheme = strdup(s);
00156 s = p1+1;
00157
00158
00159 if (*s == '/') s++;
00160 if (*s == '/') s++;
00161 }
00162
00163
00164 p1 = strchr(s, '@');
00165 if (p1) {
00166 *p1 = '\0';
00167 p2 = strchr(s, ':');
00168 if (p2) {
00169 *p2 = '\0';
00170 url->pass = strdup(p2+1);
00171 }
00172 url->user = strdup(s);
00173 s = p1+1;
00174 }
00175
00176
00177 p1 = strchr(s, '/');
00178 if (p1)
00179 *p1 = '\0';
00180
00181
00182 p2 = strchr(s, ':');
00183 if (p2) {
00184 *p2 = '\0';
00185 sscanf(p2+1, "%u", &url->port);
00186 }
00187
00188
00189 url->host = strdup(s);
00190 if (p1)
00191 s = p1+1;
00192
00193
00194 if (p1) {
00195
00196 p1 = strchr(s, '#');
00197 if (p1) {
00198 *p1 = '\0';
00199 url->fragment = strdup(p1+1);
00200 }
00201
00202
00203 p1 = strchr(s, '?');
00204 if (p1) {
00205 *p1 = '\0';
00206 url->query = strdup(p1+1);
00207 }
00208
00209
00210 url->path = strdup(s);
00211 }
00212 free(urlStringCopy);
00213
00214 if (!url->port)
00215 url->port = port_for_scheme(url->scheme);
00216
00217 return url;
00218 }
00219
00220
00234 char *url_encode(char *s, unsigned len)
00235 {
00236 char *str = (char *)malloc(3*len + 1);
00237 if (!str)
00238 return NULL;
00239
00240 int x,y;
00241 for (x=0, y=0; len--; x++, y++) {
00242 str[y]=(char)s[x];
00243 if (
00244 (str[y] < '0' && str[y] != '-' && str[y] != '.') ||
00245 (str[y] < 'A' && str[y] > '9') ||
00246 (str[y] > 'Z' && str[y] < 'a' && str[y] != '_') ||
00247 (str[y] > 'z')
00248 ) {
00249 str[y++] = '%';
00250 str[y++] = hexchars[(unsigned char) s[x] >> 4];
00251 str[y] = hexchars[(unsigned char) s[x] & 15];
00252 }
00253 }
00254 str[y] = '\0';
00255 return str;
00256 }
00257
00258
00271 unsigned url_decode(char *str, unsigned len)
00272 {
00273 char *dst = str;
00274 char *src = str;
00275
00276 while (len--) {
00277 if ( *src == '%' && len >= 2 &&
00278 isxdigit(src[1]) && isxdigit(src[2]) )
00279 {
00280 *dst++ = (char)htoi(src + 1);
00281 src += 2;
00282 len -= 2;
00283 } else {
00284 *dst++ = *src++;
00285 }
00286 }
00287 *dst = '\0';
00288
00289 return (unsigned)(dst-str);
00290 }
00291