#include "precompile.h" #include "url.h" #include #include #include #include #include "memutil.h" /* from libasynchttp */ TOOLKIT_API char* urlencode(unsigned char *string) { int escapecount = 0; unsigned char *src, *dest; unsigned char *newstr; char hextable[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; if (string == NULL) return NULL; for (src = string; *src != 0; src++) if (!isalnum(*src)) escapecount++; newstr = (unsigned char*)malloc(strlen((char*)string) - escapecount + (escapecount * 3) + 1); src = string; dest = newstr; while (*src != 0) { if (!isalnum(*src)) { *dest++ = '%'; *dest++ = hextable[*src >> 4]; *dest++ = hextable[*src & 0x0F]; src++; } else { *dest++ = *src++; } } *dest = 0; return (char*)newstr; } TOOLKIT_API unsigned char* urldecode(char *string) { int destlen = 0; unsigned char *src, *dest; unsigned char *newstr; if (string == NULL) return NULL; for (src = (unsigned char*)string; *src != 0; src++) { if (*src == '%') { src+=2; } /* FIXME: this isn't robust. should check the next two chars for 0 */ destlen++; } newstr = (unsigned char*)malloc(destlen + 1); src = (unsigned char*)string; dest = newstr; while (*src != 0) { if (*src == '%') { char h = toupper(src[1]); char l = toupper(src[2]); int vh, vl; vh = isalpha(h) ? (10+(h-'A')) : (h-'0'); vl = isalpha(l) ? (10+(l-'A')) : (l-'0'); *dest++ = ((vh<<4)+vl); src += 3; } else if (*src == '+') { *dest++ = ' '; src++; } else { *dest++ = *src++; } } *dest = 0; return newstr; } TOOLKIT_API char* util_skipline(char *text) { while (*text != 0) { if (*text == '\n') { text++; break; } text++; } return text; } TOOLKIT_API char* util_getline(char *text) { int len; char *str; for (len = 0; text[len] != 0; len++) if (text[len] == '\r' || text[len] == '\n') break; str = (char*)malloc(len+1); memcpy(str, text, len+1); str[len] = 0; return str; } static char*strgrab(char *src, int len) { char *ret = (char*)malloc(len+1); memcpy(ret, src, len); ret[len] = 0; return ret; } static char* strscan(char *src, char *origsearch) { char *search; while (*src) { search = origsearch; while (*search) { if (*src == *search) return src; search++; } src++; } return src; } TOOLKIT_API int url_parse(char *url, url_fields *uf) { char *s, *e; memset(uf, 0, sizeof(url_fields)); /* search for end of scheme */ s = url; e = strscan(s, ":"); uf->scheme = strgrab(s, e-s); s = e+1; if (*s == 0) goto err; if (*s == '/' && *(s+1) == '/') { /* it's a net_path */ } else goto err; s = s+2; /* search for / or : trailing hostname */ e = strscan(s, "/:"); if (e == s) goto err; uf->host = strgrab(s, e-s); s = e; if (*s == ':') { char *port; s++; /* grab the port */ e = strscan(s, "/"); if (e == s) goto err; port = strgrab(s, e-s); uf->port = atoi(port); free(port); s = e; } /* grab remainder into path */ e = strscan(s, ""); uf->path = strgrab(s, e-s); /* if they've not specified a path, default to / */ if (uf->path[0] == 0) { free(uf->path); uf->path = _strdup("/"); } return 0; err: if (uf->path) free(uf->path); if (uf->host) free(uf->host); if (uf->scheme) free(uf->scheme); return -(e-url); } TOOLKIT_API void url_free_fields(url_fields *uf) { if (uf->scheme) free(uf->scheme); if (uf->host) free(uf->host); if (uf->path) free(uf->path); }