groupdav_main.c

00001 /*
00002  * $Id: groupdav_main.c 5147 2007-05-08 15:36:22Z ajc $
00003  *
00004  * Entry point for GroupDAV functions
00005  *
00006  */
00007 
00008 #include "webcit.h"
00009 #include "webserver.h"
00010 #include "groupdav.h"
00011 
00012 
00013 /*
00014  * Output HTTP headers which are common to all requests.
00015  *
00016  * Please observe that we don't use the usual output_headers()
00017  * and wDumpContent() functions in the GroupDAV subsystem, so we
00018  * do our own header stuff here.
00019  *
00020  */
00021 void groupdav_common_headers(void) {
00022         wprintf(
00023                 "Server: %s / %s\r\n"
00024                 "Connection: close\r\n",
00025                 SERVER, serv_info.serv_software
00026         );
00027 }
00028 
00029 
00030 
00031 /*
00032  * string conversion function
00033  */
00034 void euid_escapize(char *target, char *source) {
00035         int i;
00036         int target_length = 0;
00037 
00038         strcpy(target, "");
00039         for (i=0; i<strlen(source); ++i) {
00040                 if ( (isalnum(source[i])) || (source[i]=='-') || (source[i]=='_') ) {
00041                         target[target_length] = source[i];
00042                         target[++target_length] = 0;
00043                 }
00044                 else {
00045                         sprintf(&target[target_length], "=%02X", source[i]);
00046                         target_length += 3;
00047                 }
00048         }
00049 }
00050 
00051 /*
00052  * string conversion function
00053  */
00054 void euid_unescapize(char *target, char *source) {
00055         int a, b;
00056         char hex[3];
00057         int target_length = 0;
00058 
00059         strcpy(target, "");
00060 
00061         for (a = 0; a < strlen(source); ++a) {
00062                 if (source[a] == '=') {
00063                         hex[0] = source[a + 1];
00064                         hex[1] = source[a + 2];
00065                         hex[2] = 0;
00066                         b = 0;
00067                         sscanf(hex, "%02x", &b);
00068                         target[target_length] = b;
00069                         target[++target_length] = 0;
00070                         a += 2;
00071                 }
00072                 else {
00073                         target[target_length] = source[a];
00074                         target[++target_length] = 0;
00075                 }
00076         }
00077 }
00078 
00079 
00080 
00081 
00082 /*
00083  * Main entry point for GroupDAV requests
00084  */
00085 void groupdav_main(struct httprequest *req,
00086                         char *dav_content_type,
00087                         int dav_content_length,
00088                         char *dav_content
00089 ) {
00090         struct httprequest *rptr;
00091         char dav_method[256];
00092         char dav_pathname[256];
00093         char dav_ifmatch[256];
00094         int dav_depth;
00095         char *ds;
00096         int i;
00097 
00098         strcpy(dav_method, "");
00099         strcpy(dav_pathname, "");
00100         strcpy(dav_ifmatch, "");
00101         dav_depth = 0;
00102 
00103         for (rptr=req; rptr!=NULL; rptr=rptr->next) {
00104                 if (!strncasecmp(rptr->line, "Host: ", 6)) {
00105                         if (strlen(WC->http_host) == 0) {
00106                                 safestrncpy(WC->http_host, &rptr->line[6],
00107                                         sizeof WC->http_host);
00108                         }
00109                 }
00110                 if (!strncasecmp(rptr->line, "If-Match: ", 10)) {
00111                         safestrncpy(dav_ifmatch, &rptr->line[10],
00112                                 sizeof dav_ifmatch);
00113                 }
00114                 if (!strncasecmp(rptr->line, "Depth: ", 7)) {
00115                         if (!strcasecmp(&rptr->line[7], "infinity")) {
00116                                 dav_depth = 32767;
00117                         }
00118                         else if (!strcmp(&rptr->line[7], "0")) {
00119                                 dav_depth = 0;
00120                         }
00121                         else if (!strcmp(&rptr->line[7], "1")) {
00122                                 dav_depth = 1;
00123                         }
00124                 }
00125         }
00126 
00127         if (!WC->logged_in) {
00128                 wprintf("HTTP/1.1 401 Unauthorized\r\n");
00129                 groupdav_common_headers();
00130                 wprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n",
00131                         serv_info.serv_humannode);
00132                 wprintf("Content-Length: 0\r\n\r\n");
00133                 return;
00134         }
00135 
00136         extract_token(dav_method, req->line, 0, ' ', sizeof dav_method);
00137         extract_token(dav_pathname, req->line, 1, ' ', sizeof dav_pathname);
00138         unescape_input(dav_pathname);
00139 
00140         /* If the request does not begin with "/groupdav", prepend it.  If
00141          * we happen to introduce a double-slash, that's ok; we'll strip it
00142          * in the next step.
00143          * 
00144          * (THIS IS DISABLED BECAUSE WE ARE NOW TRYING TO DO REAL DAV.)
00145          *
00146         if (strncasecmp(dav_pathname, "/groupdav", 9)) {
00147                 char buf[512];
00148                 snprintf(buf, sizeof buf, "/groupdav/%s", dav_pathname);
00149                 safestrncpy(dav_pathname, buf, sizeof dav_pathname);
00150         }
00151          *
00152          */
00153         
00154         /* Remove any stray double-slashes in pathname */
00155         while (ds=strstr(dav_pathname, "//"), ds != NULL) {
00156                 strcpy(ds, ds+1);
00157         }
00158 
00159         /*
00160          * If there's an If-Match: header, strip out the quotes if present, and
00161          * then if all that's left is an asterisk, make it go away entirely.
00162          */
00163         if (strlen(dav_ifmatch) > 0) {
00164                 striplt(dav_ifmatch);
00165                 if (dav_ifmatch[0] == '\"') {
00166                         strcpy(dav_ifmatch, &dav_ifmatch[1]);
00167                         for (i=0; i<strlen(dav_ifmatch); ++i) {
00168                                 if (dav_ifmatch[i] == '\"') {
00169                                         dav_ifmatch[i] = 0;
00170                                 }
00171                         }
00172                 }
00173                 if (!strcmp(dav_ifmatch, "*")) {
00174                         strcpy(dav_ifmatch, "");
00175                 }
00176         }
00177 
00178         /*
00179          * The OPTIONS method is not required by GroupDAV.  This is an
00180          * experiment to determine what might be involved in supporting
00181          * other variants of DAV in the future.
00182          */
00183         if (!strcasecmp(dav_method, "OPTIONS")) {
00184                 groupdav_options(dav_pathname);
00185                 return;
00186         }
00187 
00188         /*
00189          * The PROPFIND method is basically used to list all objects in a
00190          * room, or to list all relevant rooms on the server.
00191          */
00192         if (!strcasecmp(dav_method, "PROPFIND")) {
00193                 groupdav_propfind(dav_pathname, dav_depth,
00194                                 dav_content_type, dav_content);
00195                 return;
00196         }
00197 
00198         /*
00199          * The GET method is used for fetching individual items.
00200          */
00201         if (!strcasecmp(dav_method, "GET")) {
00202                 groupdav_get(dav_pathname);
00203                 return;
00204         }
00205 
00206         /*
00207          * The PUT method is used to add or modify items.
00208          */
00209         if (!strcasecmp(dav_method, "PUT")) {
00210                 groupdav_put(dav_pathname, dav_ifmatch,
00211                                 dav_content_type, dav_content,
00212                                 dav_content_length);
00213                 return;
00214         }
00215 
00216         /*
00217          * The DELETE method kills, maims, and destroys.
00218          */
00219         if (!strcasecmp(dav_method, "DELETE")) {
00220                 groupdav_delete(dav_pathname, dav_ifmatch);
00221                 return;
00222         }
00223 
00224         /*
00225          * Couldn't find what we were looking for.  Die in a car fire.
00226          */
00227         wprintf("HTTP/1.1 501 Method not implemented\r\n");
00228         groupdav_common_headers();
00229         wprintf("Content-Type: text/plain\r\n"
00230                 "\r\n"
00231                 "GroupDAV method \"%s\" is not implemented.\r\n",
00232                 dav_method
00233         );
00234 }
00235 
00236 
00237 /*
00238  * Output our host prefix for globally absolute URL's.
00239  */  
00240 void groupdav_identify_host(void) {
00241         if (strlen(WC->http_host) > 0) {
00242                 wprintf("%s://%s",
00243                         (is_https ? "https" : "http"),
00244                         WC->http_host);
00245         }
00246 }

Generated on Wed Jun 20 23:13:08 2007 for webcit by  doxygen 1.5.2