diff options
author | Steve Holme <steve_holme@hotmail.com> | 2013-04-13 10:49:42 +0100 |
---|---|---|
committer | Steve Holme <steve_holme@hotmail.com> | 2013-04-13 10:49:42 +0100 |
commit | 73aa95592f47d461f0246eef1187f5d569aa6afa (patch) | |
tree | dcf5efb83c021e87a2b4fb2b45259ef0100f0947 | |
parent | ad3fdbc0a46e8cdb0ce19df17a278309c2cfb2cf (diff) |
url: Added support for parsing login options from the URL
As well as parsing the username and password from the URL, added support
for parsing the optional options part from the login details, to allow
the following supported URL format:
schema://username:password;options@example.com/path?q=foobar
This will only be used by IMAP, POP3 and SMTP at present but any
protocol that may be given login options in the URL will be able to
add support for them.
-rw-r--r-- | lib/url.c | 79 | ||||
-rw-r--r-- | lib/urldata.h | 3 |
2 files changed, 62 insertions, 20 deletions
@@ -2452,6 +2452,7 @@ static void conn_free(struct connectdata *conn) Curl_safefree(conn->user); Curl_safefree(conn->passwd); + Curl_safefree(conn->options); Curl_safefree(conn->proxyuser); Curl_safefree(conn->proxypasswd); Curl_safefree(conn->allocptr.proxyuserpwd); @@ -4342,24 +4343,27 @@ static CURLcode parse_url_userpass(struct SessionHandle *data, struct connectdata *conn, char *user, char *passwd) { + char options[MAX_CURL_OPTIONS_LENGTH]; + /* At this point, we're hoping all the other special cases have * been taken care of, so conn->host.name is at most - * [user[:password]]@]hostname + * [user[:password][;options]]@]hostname * * We need somewhere to put the embedded details, so do that first. */ - char *ptr=strchr(conn->host.name, '@'); + char *ptr = strchr(conn->host.name, '@'); char *userpass = conn->host.name; - user[0] =0; /* to make everything well-defined */ - passwd[0]=0; + user[0] = 0; /* to make everything well-defined */ + passwd[0] = 0; + options[0] = 0; /* We will now try to extract the - * possible user+password pair in a string like: + * possible login information in a string like: * ftp://user:password@ftp.my.site:8021/README */ if(ptr != NULL) { - /* there's a user+password given here, to the left of the @ */ + /* There's login information to the left of the @ */ conn->host.name = ++ptr; @@ -4369,26 +4373,46 @@ static CURLcode parse_url_userpass(struct SessionHandle *data, * set user/passwd, but doing that first adds more cases here :-( */ - conn->bits.userpwd_in_url = TRUE; if(data->set.use_netrc != CURL_NETRC_REQUIRED) { - /* We could use the one in the URL */ - - conn->bits.user_passwd = TRUE; /* enable user+password */ - + /* We could use the information in the URL so extract it */ if(*userpass != ':') { - /* the name is given, get user+password */ - sscanf(userpass, "%" MAX_CURL_USER_LENGTH_TXT "[^:@]:" - "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", - user, passwd); + if(*userpass != ';') { + /* The user is given so extract the user, password and options */ + int result = sscanf(userpass, + "%" MAX_CURL_USER_LENGTH_TXT "[^:;@]:" + "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^;@];" + "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", + user, passwd, options); + + /* The extract failed so extract the user and options instead */ + if(result == 1) + sscanf(userpass, "%" MAX_CURL_USER_LENGTH_TXT "[^:;@];" + "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", + user, options); + } + else { + /* No name or password are given so extract the options only */ + sscanf(userpass, ";%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", options); + } } else - /* no name given, get the password only */ - sscanf(userpass, ":%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", passwd); + /* No name is given so extract the password and options */ + sscanf(userpass, ":%" MAX_CURL_PASSWORD_LENGTH_TXT "[^;@];" + "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", + passwd, options); if(user[0]) { - char *newname=curl_easy_unescape(data, user, 0, NULL); + char *newname; + + /* We have a user in the URL */ + conn->bits.userpwd_in_url = TRUE; + conn->bits.user_passwd = TRUE; /* enable user+password */ + + /* Decode the user */ + newname = curl_easy_unescape(data, user, 0, NULL); if(!newname) return CURLE_OUT_OF_MEMORY; + if(strlen(newname) < MAX_CURL_USER_LENGTH) strcpy(user, newname); @@ -4396,18 +4420,33 @@ static CURLcode parse_url_userpass(struct SessionHandle *data, the unconverted name, it'll be wrong but what the heck */ free(newname); } + if(passwd[0]) { - /* we have a password found in the URL, decode it! */ - char *newpasswd=curl_easy_unescape(data, passwd, 0, NULL); + /* We have a password in the URL so decode it */ + char *newpasswd = curl_easy_unescape(data, passwd, 0, NULL); if(!newpasswd) return CURLE_OUT_OF_MEMORY; + if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH) strcpy(passwd, newpasswd); free(newpasswd); } + + if(options[0]) { + /* We have an options list in the URL so decode it */ + char *newoptions = curl_easy_unescape(data, options, 0, NULL); + if(!newoptions) + return CURLE_OUT_OF_MEMORY; + + if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH) + conn->options = newoptions; + else + free(newoptions); + } } } + return CURLE_OK; } diff --git a/lib/urldata.h b/lib/urldata.h index 1113020ee..13a01d4b3 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -859,6 +859,7 @@ struct connectdata { char *user; /* user name string, allocated */ char *passwd; /* password string, allocated */ + char *options; /* options string, allocated */ char *proxyuser; /* proxy user name string, allocated */ char *proxypasswd; /* proxy password string, allocated */ @@ -1136,8 +1137,10 @@ typedef enum { * Session-data MUST be put in the connectdata struct and here. */ #define MAX_CURL_USER_LENGTH 256 #define MAX_CURL_PASSWORD_LENGTH 256 +#define MAX_CURL_OPTIONS_LENGTH 256 #define MAX_CURL_USER_LENGTH_TXT "255" #define MAX_CURL_PASSWORD_LENGTH_TXT "255" +#define MAX_CURL_OPTIONS_LENGTH_TXT "255" struct auth { unsigned long want; /* Bitmask set to the authentication methods wanted by |