6f7ebb58c628b945e7d20a36a668fba2b79b132c
[citadel.git] / libcitadel / lib / urlhandling.c
1 #include "sysdep.h"
2 #include <ctype.h>
3 #include <errno.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <string.h>
7 #include <stdio.h>
8 #include <sys/select.h>
9 #include <fcntl.h>
10 #include <sys/types.h>
11 #include "libcitadel.h"
12
13 /**
14  * @defgroup URLHandling ParsedURL object to handle connection data
15  */
16
17 /**
18  * @ingroup URLHandling
19  * @brief frees a linked list of ParsedURL 
20  * @param Url (list) of ParsedURL to be freet; Pointer is NULL'ed for the caller.
21  */
22 void FreeURL(ParsedURL** Url)
23 {
24         if (*Url != NULL) {
25                 FreeStrBuf(&(*Url)->URL);
26                 if ((*Url)->Next != NULL)
27                         FreeURL(&(*Url)->Next);
28                 free(*Url);
29                 *Url = NULL;
30         }
31 }
32
33 /**
34  * @ingroup URLHandling
35  * @brief parses the string provided with UrlStr into *Url
36  * @param Url on success this contains the parsed object; needs to be free'd by caller.
37  * @param UrlStr String we should parse into parts
38  * @param DefaultPort Which is the default port here?
39  */
40 int ParseURL(ParsedURL **Url, StrBuf *UrlStr, unsigned short DefaultPort)
41 {
42         const char *pch, *pEndHost, *pPort, *pCredEnd, *pUserEnd;
43         ParsedURL *url = (ParsedURL *)malloc(sizeof(ParsedURL));
44         memset(url, 0, sizeof(ParsedURL));
45
46         url->af = AF_INET;
47         url->Port =  DefaultPort;
48         /*
49          * http://username:passvoid@[ipv6]:port/url 
50          */
51         url->URL = NewStrBufDup(UrlStr);
52         url->Host = pch = ChrPtr(url->URL);
53         url->LocalPart = strchr(pch, '/');
54         if (url->LocalPart != NULL) {
55                 if ((*(url->LocalPart + 1) == '/') && 
56                     (*(url->LocalPart + 2) == ':')) { /* TODO: find default port for this protocol... */
57                         url->Host = url->LocalPart + 3;
58                         url->LocalPart = strchr(url->Host, '/');
59                 }
60         }
61         if (url->LocalPart == NULL) {
62                 url->LocalPart = pch + StrLength(url->URL);
63         }
64
65         pCredEnd = strchr(pch, '@');
66         if (pCredEnd >= url->LocalPart)
67                 pCredEnd = NULL;
68         if (pCredEnd != NULL)
69         {
70                 url->User = url->Host;
71                 url->Host = pCredEnd + 1;
72                 pUserEnd = strchr(url->User, ':');
73                 
74                 if (pUserEnd > pCredEnd)
75                         pUserEnd = pCredEnd;
76                 else {
77                         url->Pass = pUserEnd + 1;
78                 }
79                 StrBufPeek(url->URL, pUserEnd, 0, '\0');
80                 StrBufPeek(url->URL, pCredEnd, 0, '\0');                
81         }
82         
83         pPort = NULL;
84         if (*url->Host == '[') {
85                 url->Host ++;
86                 pEndHost = strchr(url->Host, ']');
87                 if (pEndHost == NULL) {
88                         FreeStrBuf(&url->URL);
89                         free(url);
90                         return 0; /* invalid syntax, no ipv6 */
91                 }
92                 StrBufPeek(url->URL, pEndHost, 0, '\0');
93                 if (*(pEndHost + 1) == ':'){
94                         StrBufPeek(url->URL, pEndHost + 1, 0, '\0');
95                         pPort = pEndHost + 2;
96                 }
97                 url->af = AF_INET6;
98         }
99         else {
100                 pPort = strchr(url->Host, ':');
101                 if (pPort != NULL) {
102                         StrBufPeek(url->URL, pPort, 0, '\0');
103                         pPort ++;
104                 }
105         }
106         if (pPort != NULL)
107                 url->Port = atol(pPort);
108         url->IsIP = inet_pton(url->af, url->Host, &url->Addr.sin6_addr);
109         *Url = url;
110         return 1;
111 }