int handle_http_proppatch(http_req * req, http_rsp * rsp) { HashElement * e = NULL; char * propxml = NULL; int contentlen = 0; char * vpath = req->uri; WEBLOG_API(); #ifdef WEBCFG_SUPPORT_AUTH /* Authentication has a very high priority. */ if (OK != CheckAuthorization(req, rsp)) { return handle_http_error(401, req, rsp); } #endif if(OK != Webdav_CheckPath(req->uri)) { WEBLOG_ERROR("<%s> PROPFIND is not allowed for non-webdav path [%s].\n", __FUNCTION__, req->uri); return handle_http_error(403, req, rsp); } if(0 == strlen(vpath)) { strcat(vpath, "/"); WEBLOG_VERBOSE("<%s> redirect to root path. [%s].\n", __FUNCTION__, vpath); } #ifdef WEBCFG_MINIMIZE_SERVER #else if(OK != Webdav_CheckPath(req->uri)) { WEBLOG_ERROR("<%s> PROPFIND is not allowed for non-webdav path [%s].\n", __FUNCTION__, req->uri); return handle_http_error(403, req, rsp); } e = HashLookup(req->headOptions, "Content-Type"); if(e && strstr(e->value.data.string, "xml")) { char * xmlsockbuf = NULL; char * p = NULL; WEBLOG_INFO("<%s> Client provide props value in a xml body.\n", __FUNCTION__); e = HashLookup(req->headOptions, "Content-Length"); if(!e) { /* RFC2616, 14.23. */ WEBLOG_ERROR("<%s> Missing \"Content-Length\" for xml body.\n", __FUNCTION__); return handle_http_error(400, req, rsp); } contentlen = atoi(e->value.data.string); xmlsockbuf = (char *)webmalloc(contentlen+1); memset(xmlsockbuf, 0, contentlen+1); if(req->datalen > 0) // data left in head buffer. { memcpy(xmlsockbuf, req->sockbuf, req->datalen); WEBLOG_VERBOSE("<%s> previous buffered %d/%d bytes consumed.\n", __FUNCTION__, req->datalen, contentlen); } /* if there's more data in socket.... */ if (req->datalen < contentlen) { /* read rest of data from socket. */ p = xmlsockbuf + req->datalen; req->datalen = recv(req->sock, p, contentlen-req->datalen, 0); WEBLOG_VERBOSE("<%s> %d/%d bytes read from socket.\n", __FUNCTION__, req->datalen, contentlen); dumpText(xmlsockbuf, contentlen); } } #endif return handle_http_error(501, req, rsp); }
int handle_http_propfind(http_req * req, http_rsp * rsp) { int ret = OK; HashElement * e = NULL; int depth = -1; HashHandle props = NULL_HANDLE; CacheHandle cache = NULL_HANDLE; char * propxml = NULL; int contentlen = 0; char * vpath = req->uri; struct stat buf; WEBLOG_API(); #ifdef WEBCFG_SUPPORT_AUTH /* Authentication has a very high priority. */ if (OK != CheckAuthorization(req, rsp)) { return handle_http_error(401, req, rsp); } #endif if(OK != Webdav_CheckPath(req->uri)) { WEBLOG_ERROR("<%s> PROPFIND is not allowed for non-webdav path [%s].\n", __FUNCTION__, req->uri); handle_http_error(403, req, rsp); ret = NG; goto __error_out; } if(0 == strlen(vpath)) { strcat(vpath, "/"); WEBLOG_VERBOSE("<%s> redirect to root path. [%s].\n", __FUNCTION__, vpath); } WEBLOG_INFO("<%s> stat the file \"%s\".\n", __FUNCTION__, vpath); ret = stat(vpath, &buf); /* Check if statistics are valid: */ if(ret != 0) { WEBLOG_ERROR("<%s> fail to stat the file \"%s\".\n", __FUNCTION__, vpath); switch (errno) { case ENOENT: WEBLOG_ERROR("<%s> File %s not found.\n", __FUNCTION__, vpath); handle_http_error(404, req, rsp); ret = NG; goto __error_out; case EINVAL: /* no break */ default: /* Should never be reached. */ WEBLOG_ERROR("<%s> Unexpected error in _stat.\n", __FUNCTION__); handle_http_error(500, req, rsp); ret = NG; goto __error_out; } } props = HashTableCreate(64); ASSERT(props != NULL_HANDLE); /* get depth. */ e = HashLookup(req->headOptions, "Depth"); if(!e) depth = -1; else if(e->value.data.string[0] == '0') depth = 0; else if(e->value.data.string[0] == '1') depth = 1; else depth = -1; if(depth == -1 && TRUE == Webdav_isFolder(vpath)) { WEBLOG_ERROR("<%s> PROPFIND a collection with infinite depth is not allowed.\n", __FUNCTION__); handle_http_error(403, req, rsp); ret = NG; goto __error_out; } #ifdef WEBCFG_MINIMIZE_SERVER #else e = HashLookup(req->headOptions, "Content-Type"); if(e && strstr(e->value.data.string, "xml")) { char * xmlsockbuf = NULL; char strbuf[128] = {0}; char *end, *p, *q; HashValue eeee = HashString("", FALSE); // empty value! WEBLOG_INFO("<%s> Client request props in a xml body.\n", __FUNCTION__); e = HashLookup(req->headOptions, "Content-Length"); if(!e) { /* RFC2616, 14.23. */ WEBLOG_ERROR("<%s> Missing \"Content-Length\" for xml body.\n", __FUNCTION__); handle_http_error(400, req, rsp); ret = NG; goto __error_out; } contentlen = atoi(e->value.data.string); xmlsockbuf = (char *)webmalloc(contentlen+1); memset(xmlsockbuf, 0, contentlen+1); if(req->datalen > 0) // data left in head buffer. { memcpy(xmlsockbuf, req->sockbuf, req->datalen); WEBLOG_VERBOSE("<%s> previous buffered %d/%d bytes consumed.\n", __FUNCTION__, req->datalen, contentlen); } /* if there's more data in socket.... */ if (req->datalen < contentlen) { /* read rest of data from socket. */ p = xmlsockbuf + req->datalen; req->datalen = recv(req->sock, p, contentlen-req->datalen, 0); WEBLOG_VERBOSE("<%s> %d/%d bytes read from socket.\n", __FUNCTION__, req->datalen, contentlen); dumpText(xmlsockbuf, contentlen); } p = strstr(xmlsockbuf, "<prop>") + 6; end = strstr(xmlsockbuf, "</prop>"); if(strstr(xmlsockbuf, "<allprop/>")) { WEBLOG_INFO("<%s> client request all props.\n", __FUNCTION__); } else { ASSERT(p<end); *end = '\0'; /* good for str api. */ /* Possible Value: WinXP: <propname/> Cadaver: <propname xmlns="DAV:"/> */ do { p = strchr(p, '<'); if(!p) break; else p++; q = strstr(p, "/>"); ASSERT(q && (q-p < sizeof(strbuf))); strncpy(strbuf, p, q-p); p = strchr(strbuf, ' '); if(p) *p = '\0'; p = strtrim(strbuf); WEBLOG_INFO("<%s> client request prop: <%s>\n", __FUNCTION__, p); HashAdd(props, p, eeee); p = q + 2; } while(p<end); /* <xxx/>\r\n</prop> */ } } #endif cache = CacheCreate(); Webdav_Props(props, cache, vpath, depth); contentlen = CacheGetData(cache, &propxml); ASSERT(propxml); dumpText(propxml, contentlen); WEBLOG_INFO("<%s> response xml ready. len %d.\n", __FUNCTION__, contentlen); rsp->code = 207; rsp->body = propxml; http_add_rspoption(rsp, "Content-Type", "text/xml"); http_send_response(rsp); __error_out: if (props != NULL_HANDLE) HashTableDestroy(props); if (cache != NULL_HANDLE) CacheDestroy(cache); return ret; }
mce_match_element(reader, NULL, NULL) { dumpText(ctx, reader, level, textMode, parMode, cellMode, rowMode, prop_mode); }