/* -*- mode: C; c-basic-offset: 8; indent-tabs-mode: nil; tab-width: 8 -*- */ #include "config.h" #include #include #ifdef HAVE_STRINGS_H #include #endif #include #include "url.h" #include "util.h" /* void safe_free(void *ptr) { if( ptr ) { debug("safe_free [%p]", ptr); free(ptr); ptr = NULL; } } */ int is_probably_an_url(char *string) { if( strstr(string, "://") ) return 1; return 0; } static char * get_service_type(char *string, Url *u) { /* fixme: what if the string isn't at the beginning of the *string? */ if( strstr(string, "http://") ) { string += 7; /* skip past that part */ u->service_type = SERVICE_HTTP; return string; } if( strstr(string, "ftp://") ) { string += 6; u->service_type = SERVICE_FTP; return string; } if( strstr(string, "gopher://") ) { string += 9; u->service_type = SERVICE_GOPHER; return string; } if( strncasecmp(string, "www", 3) == 0 ) { u->service_type = SERVICE_HTTP; u->full_url = strconcat("http://", u->full_url, NULL); return string; } if( strncasecmp(string, "ftp", 3) == 0 ) { u->service_type = SERVICE_FTP; u->full_url = strconcat("ftp://", u->full_url, NULL); return string; } /* default to browser-style serviceless http URL */ u->full_url = strconcat("http://", u->full_url, NULL); u->service_type = SERVICE_HTTP; return string; } static char * get_username(char *string, Url *u) { int i; char *username; char *at; char *slash; at = strchr(string, '@'); slash = strchr(string, '/'); if( (!at) || (slash && (at >= slash)) ) return string; for( i = 0; string[i] && string[i] != ':' && string[i] != '@' && string[i] != '/'; i++); if( string[i] != '@' && string[i] != ':' ) { return string; } username = malloc(i); memcpy(username, string, i + 1); username[i] = '\0'; string += i + 1; u->username = username; return string; } static char * get_password(char *string, Url *u) { int i; char *password; char *at; char *slash; at = strchr(string, '@'); slash = strchr(string, '/'); if( (!at) || (slash && (at >= slash)) ) return string; /* skipping to the end of the host portion. this is kinda messy for the (rare) cases where someone has a slash and/or at in their password. It's not perfect; but it catches easy cases. If you know of a better way to do this, be my guest. I do not feel a particular paternal instinct towards my ugly code. I guess that applies to this whole program. */ for(i = 0 ; string[i] != '@'; i++); password = malloc(i); /* and finally, get the password portion */ memcpy(password, string, i); password[i] = '\0'; string += i + 1; u->password = password; return string; } static char * get_hostname(char *url, Url *u) { char *hostname; int i; /* skip to end, slash, or port colon */ for( i = 0; url[i] && url[i] != '/' && url[i] != ':'; i++ ); hostname = malloc(i + 1); memcpy(hostname, url, i); hostname[i] = '\0'; /* if there's a port */ if(url[i] == ':') url += i + 1; else url += i; u->host = hostname; return url; } static char * get_port(char *url, Url *u) { char *port_string; int i; for(i = 0; isdigit(url[i]); i++); if(i == 0) return url; port_string = malloc(i + 1); memcpy(port_string, url, i + 1); port_string[i] = '\0'; url += i; u->port = atoi(port_string); return url; } static char * get_path(char *url, Url *u) { int i; char *path; /* find where the last slash is */ for(i = strlen(url); i > 0 && url[i] != '/'; i--); if(url[i] != '/') return url; path = malloc(i + 2); memcpy(path, url, i + 1); path[i] = '/'; path[i + 1] = '\0'; url += i + 1; u->path = path; return url; } static char * get_file(char *string, Url *u) { char *file; if( !string[0] ) return NULL; file = malloc(strlen(string) + 1); memcpy(file, string, strlen(string) + 1); u->file = file; return string; } Url * url_new(void) { Url *new_url; new_url = malloc(sizeof(Url)); new_url->full_url = NULL; new_url->service_type = 0; new_url->username = NULL; new_url->password = NULL; new_url->host = NULL; new_url->port = 0; new_url->path = NULL; new_url->file = NULL; return new_url; } void url_destroy(Url *u) { if( !u ) return; safe_free(u->full_url); safe_free(u->username); safe_free(u->password); safe_free(u->host); safe_free(u->path); safe_free(u->file); } UrlResource * url_resource_new(void) { UrlResource *new_resource; new_resource = malloc(sizeof(UrlResource)); new_resource->url = NULL; new_resource->outfile = NULL; new_resource->proxy = NULL; new_resource->proxy_username = NULL; new_resource->proxy_password = NULL; new_resource->options = 0; new_resource->outfile_size = 0; new_resource->outfile_offset = 0; return new_resource; } void url_resource_destroy(UrlResource *rsrc) { if( !rsrc ) return; if(rsrc->url) url_destroy(rsrc->url); safe_free(rsrc->outfile); free(rsrc); } Url * url_init(Url *u, char *string) { char *sp; /* since we're going to walk through string, use a copy instead. */ sp = string; u->full_url = (char *)strdup(string); if( ! (sp = get_service_type(sp, u)) ) return 0; /* only get username/password if they are not null, allows us to handle redirects properly */ if( !u->username ) sp = get_username(sp, u); if( !u->password ) sp = get_password(sp, u); sp = get_hostname(sp, u); if( ! (u->host && *(u->host)) ) return NULL; sp = get_port(sp, u); sp = get_path(sp, u); sp = get_file(sp, u); return u; }