char *urlencode(const char *instr) { int ipos = 0, bpos = 0; char *str = NULL; int len = strlen(instr); if (!(str = malloc(sizeof(char) * (3 * len + 1)))) return ""; while (instr[ipos]) { while (isurlchar(instr[ipos])) str[bpos++] = instr[ipos++]; if (!instr[ipos]) break; snprintf(&str[bpos], 4, "%%%.2x", instr[ipos]); bpos += 3; ipos++; } str[bpos] = '\0'; /* free extra alloc'ed mem. */ len = strlen(str); str = realloc(str, sizeof(char) * (len + 1)); return (str); }
size_t url_encode_cstr( char *dest, const char*src, size_t max_size ) { size_t ret = 0; if(!max_size--) return 0; while(true) { const char src_char = *src++; if(src_char==0) break; if(max_size==0) { ret++; break; } if(isurlchar(src_char)) { *dest++ = src_char; ret++; max_size--; #if URL_ENCODE_SPACES_AS_PLUSES } else if(src_char == ' ') { *dest++ = '+'; // Stupid legacy space encoding. ret++; max_size--; #endif } else { if(max_size < 3) { // Dest buffer too small for the next character. ret++; break; } *dest++ = '%'; *dest++ = int_to_hex_digit(src_char >> 4); *dest++ = int_to_hex_digit(src_char & 0xF); ret += 3; max_size -= 3; } } *dest = 0; return ret; }
int url_parse( char* uri, struct url_components_s* components ) { int bytes_parsed = 0; char tmp; if(!url_is_absolute(uri)) goto skip_absolute_url_stuff; check_string(uri, "NULL URI parameter"); components->protocol = uri; while(*uri != ':') { require_string(*uri, bail, "unexpected end of string"); uri++; bytes_parsed++; } // Zero terminate the protocol; *uri++ = 0; bytes_parsed++; require_string(*uri, bail, "unexpected end of string"); if(uri[0] == '/' && uri[1] == '/') { char* addr_end; char* addr_begin; bool got_port = false; // Contains a hostname. Parse it. uri += 2; bytes_parsed += 2; addr_begin = uri; while( (tmp=*uri) != '/' && ( isurlchar(tmp) || (tmp == '[') || (tmp == ']') || (tmp == ':') || (tmp == '%') // Necessary for scoped addresses || (tmp == '@') ) ) { uri++; bytes_parsed++; } addr_end = uri - 1; if(*uri) { *uri++ = 0; bytes_parsed++; } for(; (addr_end >= addr_begin) && (*addr_end != '@') && (*addr_end != '['); addr_end-- ) { if(*addr_end == ']') { *addr_end = 0; got_port = true; } else if(!got_port && (*addr_end == ':')) { components->port = addr_end + 1; *addr_end = 0; got_port = true; } } components->host = addr_end + 1; if(*addr_end=='@') { *addr_end = 0; for(; (addr_end >= addr_begin) && (*addr_end != '/'); addr_end-- ) { if(*addr_end==':') { *addr_end = 0; components->password = addr_end + 1; } } if(*addr_end=='/') { components->username = addr_end + 1; } } } skip_absolute_url_stuff: components->path = uri; // Move to the end of the path. while( ((tmp=*uri) != '#') && (tmp != '?') && ( isurlchar(tmp) || (tmp == '[') || (tmp == ']') || (tmp == ':') || (tmp == '/') || (tmp == '=') || (tmp == '&') || (tmp == '%') ) ) { uri++; bytes_parsed++; } // Handle query component if(*uri == '?') { *uri++ = 0; bytes_parsed++; components->query = uri; // Move to the end of the query. while( ((tmp=*uri) != '#') && ( isurlchar(tmp) || (tmp == '[') || (tmp == ']') || (tmp == ':') || (tmp == '/') || (tmp == '=') || (tmp == '&') || (tmp == '%') || (tmp == ';') ) ) { uri++; bytes_parsed++; } } // Zero terminate if(*uri) { *uri = 0; bytes_parsed++; } bail: return bytes_parsed; }