diff options
Diffstat (limited to 'lib/imap.c')
-rw-r--r-- | lib/imap.c | 99 |
1 files changed, 93 insertions, 6 deletions
diff --git a/lib/imap.c b/lib/imap.c index 39230bbcd..3fb482862 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -1659,16 +1659,103 @@ static bool imap_is_bchar(char ch) */ static CURLcode imap_parse_url_path(struct connectdata *conn) { - /* The imap struct is already inited in imap_connect() */ + /* The imap struct is already initialised in imap_connect() */ + CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; struct IMAP *imap = data->state.proto.imap; - const char *path = data->state.path; + const char *begin = data->state.path; + const char *ptr = begin; + + /* See how much of the URL is a valid path and decode it */ + while(imap_is_bchar(*ptr)) + ptr++; + + if(ptr != begin) { + /* Remove the trailing slash if present */ + const char *end = ptr; + if(end > begin && end[-1] == '/') + end--; + + result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL, + TRUE); + if(result) + return result; + } + else + imap->mailbox = NULL; + + /* There can be any number of parameters in the form ";NAME=VALUE" */ + while(*ptr == ';') { + char *name; + char *value; + size_t valuelen; + + /* Decode the parameter name */ + begin = ++ptr; + while(*ptr && *ptr != '=') + ptr++; + + if(!*ptr) + return CURLE_URL_MALFORMAT; + + /* Decode the parameter name */ + result = Curl_urldecode(data, begin, ptr - begin, &name, NULL, TRUE); + if(result) + return result; + + begin = ++ptr; + while(imap_is_bchar(*ptr)) + ptr++; + + /* Decode the parameter value */ + result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE); + if(result) { + Curl_safefree(name); + return result; + } + + DEBUGF(infof(conn->data, "IMAP URL parameter '%s' = '%s'\n", name, value)); + + /* Process known parameters (UIDVALIDITY, UID and SECTION) and create + a virtual URL level as they should be followed by a slash, which needs + to be stripped. Note: Unknown parameters trigger URL_MALFORMAT error */ + if(Curl_raw_equal(name, "UIDVALIDITY") && !imap->uidvalidity) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + + imap->uidvalidity = value; + value = NULL; + } + else if(Curl_raw_equal(name, "UID") && !imap->uid) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; - if(!*path) - path = "INBOX"; + imap->uid = value; + value = NULL; + } + else if(Curl_raw_equal(name, "SECTION") && !imap->section) { + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; - /* URL decode the path and use this mailbox */ - return Curl_urldecode(data, path, 0, &imap->mailbox, NULL, TRUE); + imap->section = value; + value = NULL; + } + else { + Curl_safefree(name); + Curl_safefree(value); + + return CURLE_URL_MALFORMAT; + } + + Curl_safefree(name); + Curl_safefree(value); + } + + /* Any extra stuff at the end of the URL is an error */ + if(*ptr) + return CURLE_URL_MALFORMAT; + + return CURLE_OK; } /* Call this when the DO phase has completed */ |