rename wprintf to wc_printf; wchar.h also has a wprintf
[citadel.git] / webcit / groupdav_main.c
1 /*
2  * $Id$
3  *
4  * Entry point for GroupDAV functions
5  *
6  */
7
8 #include "webcit.h"
9 #include "webserver.h"
10 #include "groupdav.h"
11
12
13 /*
14  * Output HTTP headers which are common to all requests.
15  *
16  * Please observe that we don't use the usual output_headers()
17  * and wDumpContent() functions in the GroupDAV subsystem, so we
18  * do our own header stuff here.
19  *
20  */
21 void groupdav_common_headers(void) {
22         hprintf(
23                 "Server: %s / %s\r\n"
24                 "Connection: close\r\n",
25                 PACKAGE_STRING, ChrPtr(WC->serv_info->serv_software)
26         );
27 }
28
29
30
31 /*
32  * string conversion function
33  */
34 void euid_escapize(char *target, const char *source) {
35         int i, len;
36         int target_length = 0;
37
38         strcpy(target, "");
39         len = strlen(source);
40         for (i=0; i<len; ++i) {
41                 if ( (isalnum(source[i])) || (source[i]=='-') || (source[i]=='_') ) {
42                         target[target_length] = source[i];
43                         target[++target_length] = 0;
44                 }
45                 else {
46                         sprintf(&target[target_length], "=%02X", (0xFF & source[i]));
47                         target_length += 3;
48                 }
49         }
50 }
51
52 /*
53  * string conversion function
54  */
55 void euid_unescapize(char *target, const char *source) {
56         int a, b, len;
57         char hex[3];
58         int target_length = 0;
59
60         strcpy(target, "");
61
62         len = strlen(source);
63         for (a = 0; a < len; ++a) {
64                 if (source[a] == '=') {
65                         hex[0] = source[a + 1];
66                         hex[1] = source[a + 2];
67                         hex[2] = 0;
68                         b = 0;
69                         b = decode_hex(hex);
70                         target[target_length] = b;
71                         target[++target_length] = 0;
72                         a += 2;
73                 }
74                 else {
75                         target[target_length] = source[a];
76                         target[++target_length] = 0;
77                 }
78         }
79 }
80
81
82
83
84 /*
85  * Main entry point for GroupDAV requests
86  */
87 void groupdav_main(void)
88 {
89         wcsession *WCC = WC;
90         int i, len;
91
92         StrBufUnescape(WCC->Hdr->HR.ReqLine, 0);
93
94         StrBufStripSlashes(WCC->Hdr->HR.ReqLine, 0);
95
96         /*
97          * If there's an If-Match: header, strip out the quotes if present, and
98          * then if all that's left is an asterisk, make it go away entirely.
99          */
100         len = StrLength(WCC->Hdr->HR.dav_ifmatch);
101         if (len > 0) {
102                 StrBufTrim(WCC->Hdr->HR.dav_ifmatch);
103                 if (ChrPtr(WCC->Hdr->HR.dav_ifmatch)[0] == '\"') {
104                         StrBufCutLeft(WCC->Hdr->HR.dav_ifmatch, 1);
105                         len --;
106                         for (i=0; i<len; ++i) {
107                                 if (ChrPtr(WCC->Hdr->HR.dav_ifmatch)[i] == '\"') {
108                                         StrBufCutAt(WCC->Hdr->HR.dav_ifmatch, i, NULL);
109                                         len = StrLength(WCC->Hdr->HR.dav_ifmatch);
110                                 }
111                         }
112                 }
113                 if (!strcmp(ChrPtr(WCC->Hdr->HR.dav_ifmatch), "*")) {
114                         FlushStrBuf(WCC->Hdr->HR.dav_ifmatch);
115                 }
116         }
117
118         switch (WCC->Hdr->HR.eReqType)
119         {
120         /*
121          * The OPTIONS method is not required by GroupDAV.  This is an
122          * experiment to determine what might be involved in supporting
123          * other variants of DAV in the future.
124          */
125         case eOPTIONS:
126                 groupdav_options();
127                 break;
128
129
130         /*
131          * The PROPFIND method is basically used to list all objects in a
132          * room, or to list all relevant rooms on the server.
133          */
134         case ePROPFIND:
135                 groupdav_propfind();
136                 break;
137
138         /*
139          * The GET method is used for fetching individual items.
140          */
141         case eGET:
142                 groupdav_get();
143                 break;
144         
145         /*
146          * The PUT method is used to add or modify items.
147          */
148         case ePUT:
149                 groupdav_put();
150                 break;
151         
152         /*
153          * The DELETE method kills, maims, and destroys.
154          */
155         case eDELETE:
156                 groupdav_delete();
157                 break;
158         default:
159
160         /*
161          * Couldn't find what we were looking for.  Die in a car fire.
162          */
163                 hprintf("HTTP/1.1 501 Method not implemented\r\n");
164                 groupdav_common_headers();
165                 hprintf("Content-Type: text/plain\r\n");
166                 wc_printf("GroupDAV method \"%s\" is not implemented.\r\n",
167                         ReqStrs[WCC->Hdr->HR.eReqType]);
168                 end_burst();
169         }
170 }
171
172
173 /*
174  * Output our host prefix for globally absolute URL's.
175  */  
176 void groupdav_identify_host(void) {
177         wcsession *WCC = WC;
178
179         if (StrLength(WCC->Hdr->HR.http_host)!=0) {
180                 wc_printf("%s://%s",
181                         (is_https ? "https" : "http"),
182                         ChrPtr(WCC->Hdr->HR.http_host));
183         }
184 }
185
186 /*
187  * Output our host prefix for globally absolute URL's.
188  */  
189 void groupdav_identify_hosthdr(void) {
190         wcsession *WCC = WC;
191
192         if (StrLength(WCC->Hdr->HR.http_host)!=0) {
193                 hprintf("%s://%s",
194                         (is_https ? "https" : "http"),
195                         ChrPtr(WCC->Hdr->HR.http_host));
196         }
197 }
198
199
200 void Header_HandleIfMatch(StrBuf *Line, ParsedHttpHdrs *hdr)
201 {
202         hdr->HR.dav_ifmatch = Line;
203 }
204         
205 void Header_HandleDepth(StrBuf *Line, ParsedHttpHdrs *hdr)
206 {
207         if (!strcasecmp(ChrPtr(Line), "infinity")) {
208                 hdr->HR.dav_depth = 32767;
209         }
210         else if (strcmp(ChrPtr(Line), "0") == 0) {
211                 hdr->HR.dav_depth = 0;
212         }
213         else if (strcmp(ChrPtr(Line), "1") == 0) {
214                 hdr->HR.dav_depth = 1;
215         }
216 }
217
218 void 
219 InitModule_GROUPDAV
220 (void)
221 {
222         WebcitAddUrlHandler(HKEY("groupdav"), "", 0, groupdav_main, XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE);
223         RegisterHeaderHandler(HKEY("IF-MATCH"), Header_HandleIfMatch);
224         RegisterHeaderHandler(HKEY("DEPTH"), Header_HandleDepth);
225
226 }