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>
16 // frees a linked list of ParsedURL
17 // Url (list) of ParsedURL to be freet; Pointer is NULL'ed for the caller.
18 void FreeURL(ParsedURL** Url) {
20 FreeStrBuf(&(*Url)->URL);
21 FreeStrBuf(&(*Url)->UrlWithoutCred);
22 FreeStrBuf(&(*Url)->CurlCreds);
23 FreeStrBuf(&(*Url)->UsrName);
24 FreeStrBuf(&(*Url)->Password);
25 if ((*Url)->Next != NULL)
26 FreeURL(&(*Url)->Next);
32 // parses the string provided with UrlStr into *Url
33 // Url on success this contains the parsed object; needs to be free'd by caller.
34 // UrlStr String we should parse into parts
35 // DefaultPort Which is the default port here?
36 int ParseURL(ParsedURL **Url, StrBuf *UrlStr, unsigned short DefaultPort) {
37 const char *pch, *pPort, *pCredEnd, *pUserEnd;
38 ParsedURL *url = (ParsedURL *)malloc(sizeof(ParsedURL));
39 memset(url, 0, sizeof(ParsedURL));
42 url->Port = DefaultPort;
43 url->URL = NewStrBufDup(UrlStr); // http://username:password@[ipv6]:port/url
44 url->Host = pch = ChrPtr(url->URL);
45 url->LocalPart = strchr(pch, '/');
46 if (url->LocalPart != NULL) {
47 if ((*(url->LocalPart + 1) == '/') &&
48 (*(url->LocalPart - 1) == ':')) {
49 url->Host = url->LocalPart + 2;
50 url->LocalPart = strchr(url->Host, '/');
51 if (url->LocalPart != NULL)
53 StrBufPeek(url->URL, url->LocalPart, 0, '\0');
58 if (url->LocalPart == NULL) {
59 url->LocalPart = ChrPtr(url->URL) + StrLength(url->URL);
62 pCredEnd = strrchr(ChrPtr(url->URL), '@');
63 if (pCredEnd >= url->LocalPart)
65 if (pCredEnd != NULL) {
66 url->User = url->Host;
67 url->Host = pCredEnd + 1;
68 pUserEnd = strchr(url->User, ':');
70 if (pUserEnd > pCredEnd)
73 url->Pass = pUserEnd + 1;
75 StrBufPeek(url->URL, pUserEnd, 0, '\0');
76 StrBufPeek(url->URL, pCredEnd, 0, '\0');
82 if (*url->Host == '[') {
85 pEndHost = strchr(url->Host, ']');
86 if (pEndHost == NULL) {
87 FreeStrBuf(&url->URL);
89 return 0; /* invalid syntax, no ipv6 */
91 StrBufPeek(url->URL, pEndHost, 0, '\0');
92 if (*(pEndHost + 1) == ':'){
93 StrBufPeek(url->URL, pEndHost + 1, 0, '\0');
99 pPort = strchr(url->Host, ':');
101 StrBufPeek(url->URL, pPort, 0, '\0');
106 url->Port = atol(pPort);
108 url->IsIP = inet_pton(AF_INET6, url->Host, &url->Addr.sin6_addr);
110 url->Addr.sin6_port = htons(url->Port);
111 url->Addr.sin6_port = AF_INET6;
115 url->IsIP = inet_pton(AF_INET, url->Host, &((struct sockaddr_in *)&(url->Addr))->sin_addr);
117 ((struct sockaddr_in *)&(url->Addr))->sin_port = htons(url->Port);
118 ((struct sockaddr_in *)&(url->Addr))->sin_family = AF_INET;
122 if (url->User != NULL) {
123 url->UsrName = NewStrBufPlain(url->User, pUserEnd - url->User);
124 StrBufUnescape(url->UsrName, 0);
125 url->User = ChrPtr(url->UsrName);
128 if (url->Pass != NULL) {
129 url->Password = NewStrBufPlain(url->Pass, pCredEnd - url->Pass);
130 StrBufUnescape(url->Password, 0);
131 url->Pass = ChrPtr(url->Password);
140 void CurlPrepareURL(ParsedURL *Url) {
141 if (!strcmp(ChrPtr(Url->URL), "http"))
142 Url->UrlWithoutCred = NewStrBufPlain(ChrPtr(Url->URL), -1);
144 Url->UrlWithoutCred = NewStrBufPlain(HKEY("http://"));
145 StrBufAppendBufPlain(Url->UrlWithoutCred, Url->Host, -1, 0);
147 StrBufAppendBufPlain(Url->UrlWithoutCred, HKEY(":"), 0);
149 StrBufAppendPrintf(Url->UrlWithoutCred, "%u", Url->Port);
151 StrBufAppendBufPlain(Url->UrlWithoutCred, HKEY("/"), 0);
152 if (Url->LocalPart) {
153 StrBufAppendBufPlain(Url->UrlWithoutCred, Url->LocalPart, -1, 0);
155 if (Url->User != NULL) {
156 Url->CurlCreds = NewStrBufPlain(Url->User, -1);
157 StrBufAppendBufPlain(Url->CurlCreds, HKEY(":"), 0);
158 if (Url->Pass != NULL)
159 StrBufAppendBufPlain(Url->CurlCreds, Url->Pass, -1, 0);
161 Url->PlainUrl = ChrPtr(Url->UrlWithoutCred);