aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Holme <steve_holme@hotmail.com>2013-04-13 10:49:42 +0100
committerSteve Holme <steve_holme@hotmail.com>2013-04-13 10:49:42 +0100
commit73aa95592f47d461f0246eef1187f5d569aa6afa (patch)
treedcf5efb83c021e87a2b4fb2b45259ef0100f0947
parentad3fdbc0a46e8cdb0ce19df17a278309c2cfb2cf (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.c79
-rw-r--r--lib/urldata.h3
2 files changed, 62 insertions, 20 deletions
diff --git a/lib/url.c b/lib/url.c
index 4399162a9..20823d078 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -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