1 // This program is open source software. Use, duplication, or disclosure
2 // is subject to the terms of the GNU General Public License, version 3.
10 #include <sys/select.h>
12 #include <sys/types.h>
13 #include "libcitadel.h"
14 #include <sys/socket.h>
17 * @defgroup URLHandling ParsedURL object to handle connection data
21 * @ingroup URLHandling
22 * @brief frees a linked list of ParsedURL
23 * @param Url (list) of ParsedURL to be freet; Pointer is NULL'ed for the caller.
25 void FreeURL(ParsedURL** Url)
28 FreeStrBuf(&(*Url)->URL);
29 FreeStrBuf(&(*Url)->UrlWithoutCred);
30 FreeStrBuf(&(*Url)->CurlCreds);
31 FreeStrBuf(&(*Url)->UsrName);
32 FreeStrBuf(&(*Url)->Password);
33 if ((*Url)->Next != NULL)
34 FreeURL(&(*Url)->Next);
41 * @ingroup URLHandling
42 * @brief parses the string provided with UrlStr into *Url
43 * @param Url on success this contains the parsed object; needs to be free'd by caller.
44 * @param UrlStr String we should parse into parts
45 * @param DefaultPort Which is the default port here?
47 int ParseURL(ParsedURL **Url, StrBuf *UrlStr, unsigned short DefaultPort)
49 const char *pch, *pPort, *pCredEnd, *pUserEnd;
50 ParsedURL *url = (ParsedURL *)malloc(sizeof(ParsedURL));
51 memset(url, 0, sizeof(ParsedURL));
54 url->Port = DefaultPort;
56 * http://username:passvoid@[ipv6]:port/url
58 url->URL = NewStrBufDup(UrlStr);
59 url->Host = pch = ChrPtr(url->URL);
60 url->LocalPart = strchr(pch, '/');
61 if (url->LocalPart != NULL) {
62 if ((*(url->LocalPart + 1) == '/') &&
63 (*(url->LocalPart - 1) == ':')) { /* TODO: find default port for this protocol... */
64 url->Host = url->LocalPart + 2;
65 url->LocalPart = strchr(url->Host, '/');
66 if (url->LocalPart != NULL)
68 StrBufPeek(url->URL, url->LocalPart, 0, '\0');
73 if (url->LocalPart == NULL) {
74 url->LocalPart = ChrPtr(url->URL) + StrLength(url->URL);
77 pCredEnd = strrchr(ChrPtr(url->URL), '@');
78 if (pCredEnd >= url->LocalPart)
82 url->User = url->Host;
83 url->Host = pCredEnd + 1;
84 pUserEnd = strchr(url->User, ':');
86 if (pUserEnd > pCredEnd)
89 url->Pass = pUserEnd + 1;
91 StrBufPeek(url->URL, pUserEnd, 0, '\0');
92 StrBufPeek(url->URL, pCredEnd, 0, '\0');
98 if (*url->Host == '[') {
101 pEndHost = strchr(url->Host, ']');
102 if (pEndHost == NULL) {
103 FreeStrBuf(&url->URL);
105 return 0; /* invalid syntax, no ipv6 */
107 StrBufPeek(url->URL, pEndHost, 0, '\0');
108 if (*(pEndHost + 1) == ':'){
109 StrBufPeek(url->URL, pEndHost + 1, 0, '\0');
110 pPort = pEndHost + 2;
115 pPort = strchr(url->Host, ':');
117 StrBufPeek(url->URL, pPort, 0, '\0');
122 url->Port = atol(pPort);
125 url->IsIP = inet_pton(AF_INET6, url->Host, &url->Addr.sin6_addr);
128 url->Addr.sin6_port = htons(url->Port);
129 url->Addr.sin6_port = AF_INET6;
134 url->IsIP = inet_pton(AF_INET, url->Host, &((struct sockaddr_in *)&(url->Addr))->sin_addr);
137 ((struct sockaddr_in *)&(url->Addr))->sin_port = htons(url->Port);
138 ((struct sockaddr_in *)&(url->Addr))->sin_family = AF_INET;
142 if (url->User != NULL) {
143 url->UsrName = NewStrBufPlain(url->User, pUserEnd - url->User);
144 StrBufUnescape(url->UsrName, 0);
145 url->User = ChrPtr(url->UsrName);
148 if (url->Pass != NULL) {
149 url->Password = NewStrBufPlain(url->Pass, pCredEnd - url->Pass);
150 StrBufUnescape(url->Password, 0);
151 url->Pass = ChrPtr(url->Password);
160 void CurlPrepareURL(ParsedURL *Url)
162 if (!strcmp(ChrPtr(Url->URL), "http"))
163 Url->UrlWithoutCred = NewStrBufPlain(ChrPtr(Url->URL), -1);
165 Url->UrlWithoutCred = NewStrBufPlain(HKEY("http://"));
166 StrBufAppendBufPlain(Url->UrlWithoutCred, Url->Host, -1, 0);
168 StrBufAppendBufPlain(Url->UrlWithoutCred, HKEY(":"), 0);
170 StrBufAppendPrintf(Url->UrlWithoutCred, "%u", Url->Port);
172 StrBufAppendBufPlain(Url->UrlWithoutCred, HKEY("/"), 0);
175 StrBufAppendBufPlain(Url->UrlWithoutCred, Url->LocalPart, -1, 0);
177 if (Url->User != NULL)
179 Url->CurlCreds = NewStrBufPlain(Url->User, -1);
180 StrBufAppendBufPlain(Url->CurlCreds, HKEY(":"), 0);
181 if (Url->Pass != NULL)
182 StrBufAppendBufPlain(Url->CurlCreds, Url->Pass, -1, 0);
184 Url->PlainUrl = ChrPtr(Url->UrlWithoutCred);