onion_connection_status return_length(void *_, onion_request * req, onion_response * res) { ONION_DEBUG("Data size: %d", onion_block_size(onion_request_get_data(req))); onion_response_printf(res, "%ld\n", onion_block_size(onion_request_get_data(req))); return OCS_PROCESSED; }
/** * @short Allows to change some properties of the file */ onion_connection_status onion_webdav_proppatch(const char *filename, onion_webdav *wd, onion_request *req, onion_response *res){ xmlDocPtr doc; const onion_block *block=onion_request_get_data(req); // ONION_DEBUG("%s",onion_block_data(block)); if (!block) return OCS_INTERNAL_ERROR; doc = xmlParseMemory((char*)onion_block_data(block), onion_block_size(block)); xmlNode *root = NULL; root = xmlDocGetRootElement(doc); int ok=0; while (root){ ONION_DEBUG("%s", root->name); if (strcmp((const char*)root->name,"propertyupdate")==0){ xmlNode *propertyupdate = root->children; while (propertyupdate){ ONION_DEBUG("%s", propertyupdate->name); if (strcmp((const char*)propertyupdate->name,"set")==0){ xmlNode *set = propertyupdate->children; while (set){ ONION_DEBUG("%s", set->name); if (strcmp((const char*)set->name,"prop")==0){ ONION_DEBUG("in prop"); xmlNode *prop = set->children; while (prop){ ONION_DEBUG("prop %s", prop->name); if (strcmp((const char*)prop->name,"executable")==0){ ONION_DEBUG("Setting executable %s", prop->children->content); struct stat st; stat(filename, &st); if (toupper(prop->children->content[0])=='T'){ chmod(filename, st.st_mode | S_IXUSR | S_IXGRP | S_IXOTH); } else{ chmod(filename, st.st_mode & ~( S_IXUSR | S_IXGRP | S_IXOTH) ); } ok=1; } prop=prop->next; } } set=set->next; } } propertyupdate=propertyupdate->next; } } root=root->next; } xmlFreeDoc(doc); if (ok){ onion_response_write_headers(res); return OCS_PROCESSED; } else{ return OCS_INTERNAL_ERROR; } }
onion_connection_status process_request(void *_, onion_request * req, onion_response * res) { onion_response_write0(res, "Done"); const onion_block *data = onion_request_get_data(req); FAIL_IF_NOT(data); FAIL_IF_NOT_EQUAL_STR(onion_block_data(data), "{\n \"a\": \"10\",\n \"b\": \"20\"\n}"); ONION_DEBUG(onion_block_data(data)); return OCS_PROCESSED; }
/** * @short Handles a propfind * * @param path the shared path. */ onion_connection_status onion_webdav_propfind(const char *filename, onion_webdav *wd, onion_request* req, onion_response* res){ // Prepare the basepath, necesary for props. char *basepath=NULL; int pathlen=0; const char *current_path=onion_request_get_path(req); const char *fullpath=onion_request_get_fullpath(req); pathlen=(current_path-fullpath); basepath=alloca(pathlen+1); memcpy(basepath, fullpath, pathlen+1); ONION_DEBUG0("Pathbase initial <%s> %d", basepath, pathlen); while(basepath[pathlen]=='/' && pathlen>0) pathlen--; basepath[pathlen+1]=0; ONION_DEBUG0("PROPFIND; pathbase %s", basepath); int depth; { const char *depths=onion_request_get_header(req, "Depth"); if (!depths){ ONION_ERROR("Missing Depth header on webdav request"); return OCS_INTERNAL_ERROR; } if (strcmp(depths,"infinity")==0){ ONION_ERROR("Infinity depth not supported yet."); return OCS_INTERNAL_ERROR; } depth=atoi(depths); } int props=onion_webdav_parse_propfind(onion_request_get_data(req)); ONION_DEBUG("Asking for props %08X, depth %d", props, depth); onion_block *block=onion_webdav_write_propfind(basepath, filename, onion_request_get_path(req), depth, props); if (!block) // No block, resource does not exist return onion_shortcut_response("Not found", HTTP_NOT_FOUND, req, res); ONION_DEBUG0("Printing block %s", onion_block_data(block)); onion_response_set_header(res, "Content-Type", "text/xml; charset=\"utf-8\""); onion_response_set_length(res, onion_block_size(block)); onion_response_set_code(res, HTTP_MULTI_STATUS); onion_response_write_headers(res); onion_response_flush(res); onion_response_write(res, onion_block_data(block), onion_block_size(block)); onion_block_free(block); return OCS_PROCESSED; }
/** * @short Simple put on webdav is just move a file from tmp to the final destination (or copy if could not move). * */ onion_connection_status onion_webdav_put(const char *filename, onion_webdav *wd, onion_request *req, onion_response *res){ ONION_DEBUG("Webdav puts %s", filename); const char *tmpfile=onion_block_data(onion_request_get_data(req)); int ok=onion_shortcut_rename(tmpfile, filename); if (ok==0){ ONION_DEBUG("Created %s succesfully", filename); return onion_shortcut_response("201 Created", 201, req, res); } else{ ONION_ERROR("Could not rename %s to %s (%s)", tmpfile, filename, strerror(errno)); return onion_shortcut_response("Could not create resource", HTTP_FORBIDDEN, req, res); } }
onion_connection_status post_json_check(json_response *post, onion_request *req, onion_response *res){ post->processed=1; FAIL_IF_NOT_EQUAL_INT(onion_request_get_flags(req)&OR_METHODS, OR_POST); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req, "Content-Type"),"application/json"); const onion_block *data=onion_request_get_data(req); FAIL_IF_EQUAL(data, NULL); if (!data) return OCS_INTERNAL_ERROR; FAIL_IF_NOT_EQUAL_INT(onion_block_size(data), sizeof(JSON_EXAMPLE)); FAIL_IF_NOT_EQUAL_INT(memcmp(onion_block_data(data), JSON_EXAMPLE, sizeof(JSON_EXAMPLE)), 0); post->processed=2; return OCS_PROCESSED; }
/** * @short Main webdav handler, just redirects to the proper handler depending on headers and method */ onion_connection_status onion_webdav_handler(onion_webdav *wd, onion_request *req, onion_response *res){ onion_response_set_header(res, "Dav", "1,2"); onion_response_set_header(res, "MS-Author-Via", "DAV"); #ifdef __DEBUG__ const onion_block *data=onion_request_get_data(req); if (data){ ONION_DEBUG0("Have data!\n %s", onion_block_data(data)); } #endif char filename[512]; snprintf(filename, sizeof(filename), "%s/%s", wd->path, onion_request_get_path(req)); ONION_DEBUG("Check %s and %s", wd->path, filename); if (wd->check_permissions(wd->path, filename, req)!=0){ return onion_shortcut_response("Forbidden", HTTP_FORBIDDEN, req, res); } switch (onion_request_get_flags(req)&OR_METHODS){ case OR_GET: case OR_HEAD: return onion_webdav_get(filename, wd, req, res); case OR_OPTIONS: return onion_webdav_options(filename, wd, req, res); case OR_PROPFIND: return onion_webdav_propfind(filename, wd, req, res); case OR_PUT: return onion_webdav_put(filename, wd, req, res); case OR_DELETE: return onion_webdav_delete(filename, wd, req, res); case OR_MOVE: return onion_webdav_move(filename, wd, req, res); case OR_MKCOL: return onion_webdav_mkcol(filename, wd, req, res); case OR_PROPPATCH: return onion_webdav_proppatch(filename, wd, req, res); } onion_response_set_code(res, HTTP_NOT_IMPLEMENTED); onion_response_write0(res, "<h1>Work in progress...</h1>\n"); return OCS_PROCESSED; }
/** * @short Handles a propfind * * @param path the shared path. */ onion_connection_status onion_webdav_propfind(const char *filename, onion_webdav *wd, onion_request* req, onion_response* res){ ONION_DEBUG0("PROPFIND"); int depth; { const char *depths=onion_request_get_header(req, "Depth"); if (!depths){ ONION_ERROR("Missing Depth header on webdav request"); return OCS_INTERNAL_ERROR; } if (strcmp(depths,"infinity")==0){ ONION_ERROR("Infinity depth not supported yet."); return OCS_INTERNAL_ERROR; } depth=atoi(depths); } int props=onion_webdav_parse_propfind(onion_request_get_data(req)); ONION_DEBUG("Asking for props %08X, depth %d", props, depth); onion_block *block=onion_webdav_write_propfind(filename, onion_request_get_path(req), depth, props); if (!block) // No block, resource does not exist return onion_shortcut_response("Not found", HTTP_NOT_FOUND, req, res); ONION_DEBUG0("Printing block %s", onion_block_data(block)); onion_response_set_header(res, "Content-Type", "text/xml; charset=\"utf-8\""); onion_response_set_length(res, onion_block_size(block)); onion_response_set_code(res, HTTP_MULTI_STATUS); onion_response_write(res, onion_block_data(block), onion_block_size(block)); onion_block_free(block); return OCS_PROCESSED; }