/* * testDAV.c : a small tester program for WebDAV operations * * See Copyright for the status of this software. * * Daniel.Veillard@w3.org */ #ifdef WIN32 #define HAVE_FCNTL_H #include #else #include "config.h" #endif #include #include #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #include "xmlmemory.h" #include "nanohttp.h" #include "tree.h" #include "parser.h" static int debug = 0; typedef struct nodeinfo { struct nodeinfo *next; char *name; char *size; char *date; char *content; } nodeinfo, *nodeinfoPtr; char current_protocol[20] = "http"; char current_hostname[100] = "localhost"; char current_path[1024] = "/"; char current_file[1024] = ""; int current_port = 80; void scanURL(const char *URL) { const char *cur = URL; char buf[4096]; int index = 0; int port = 0; buf[index] = 0; while (*cur != 0) { if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) { buf[index] = 0; strcpy(current_protocol, buf); index = 0; cur += 3; break; } buf[index++] = *cur++; } if (*cur == 0) return; buf[index] = 0; while (1) { if (cur[0] == ':') { buf[index] = 0; strcpy(current_hostname, buf); index = 0; cur += 1; while ((*cur >= '0') && (*cur <= '9')) { port *= 10; port += *cur - '0'; cur++; } if (port != 0) current_port = port; while ((cur[0] != '/') && (*cur != 0)) cur++; break; } if ((*cur == '/') || (*cur == 0)) { buf[index] = 0; strcpy(current_hostname, buf); index = 0; break; } buf[index++] = *cur++; } if (*cur == 0) { strcpy(current_path, "/"); strcpy(current_file, ""); }else { buf[index] = 0; while (*cur != 0) { if ((cur[0] == '#') || (cur[0] == '?')) break; buf[index++] = *cur++; } buf[index] = 0; while ((index > 0) && (buf[index] != '/')) index--; strcpy(current_file, &buf[index + 1]); buf[index + 1] = 0; strcpy(current_path, buf); } } nodeinfoPtr nodeinfoNew() { nodeinfoPtr ret = xmlMalloc(sizeof(nodeinfo)); if (ret == NULL) return(NULL); memset(ret, 0, sizeof(nodeinfo)); return(ret); } void nodeinfoFree(nodeinfoPtr info) { if (info == NULL) return; if (info->name) xmlFree(info->name); if (info->date) xmlFree(info->date); if (info->size) xmlFree(info->date); if (info->content) xmlFree(info->content); } void nodeinfoListFree(nodeinfoPtr info) { nodeinfoPtr cur = info; while (cur != NULL) { info = info->next; nodeinfoFree(cur); cur = info; } } void nodeinfoPrint(nodeinfoPtr info) { if (info == NULL) return; if (info->date) printf("%s\t", info->date); if (info->name) printf("%s\t", info->name); else printf("???\t"); if (info->size) printf("%s\t", info->size); if (info->content) printf("%s\t", info->content); printf("\n"); } void nodeinfoListPrint(nodeinfoPtr info) { nodeinfoPtr cur = info; while (cur != NULL) { info = info->next; nodeinfoPrint(cur); cur = info; } } int propfindQuery(const char *URL, char **result) { void *ctxt; char *contentType = "text/xml; charset=\"utf-8\""; char *output; int len; int size = 40000; int returnCode; char *verboseQuery = "\ \ \ "; if ((URL == NULL) || (result == NULL)) return(-1); if (URL[strlen(URL) - 1] == '/') ctxt = xmlNanoHTTPMethod(URL, "PROPFIND", NULL, &contentType, "Depth: 1\r\n"); else ctxt = xmlNanoHTTPMethod(URL, "PROPFIND", verboseQuery, &contentType, "Depth: 0\r\n"); if (ctxt == NULL) { fprintf(stderr, "PROPFIND %s failed\n", URL); return(-1); } returnCode = xmlNanoHTTPReturnCode(ctxt); if ((returnCode >= 300) || ((contentType != NULL) && (strncmp(contentType, "text/xml", 8)))) { xmlNanoHTTPClose(ctxt); if (contentType != NULL) xmlFree(contentType); return(-1); } if (contentType != NULL) xmlFree(contentType); output = (char *) xmlMalloc(size + 1); if (output == NULL) { fprintf(stderr, "out of memory\n"); xmlNanoHTTPClose(ctxt); return(-1); } len = xmlNanoHTTPRead(ctxt, output, size); if (len < 0) { fprintf(stderr, "cannot read PROPFIND %s result\n", URL); xmlNanoHTTPClose(ctxt); xmlFree(output); return(-1); } /* !!!!!!!!! handle returns size > size !!!!!!!!!! */ output[len] = 0; xmlNanoHTTPClose(ctxt); *result = output; return(returnCode); } void parsePropfindProp(xmlNodePtr cur, nodeinfoPtr node) { cur = cur->childs; /* * prop ANY */ while (cur != NULL) { if (!strcmp((char *) cur->name, "getlastmodified")) { node->date = (char *) xmlNodeGetContent(cur); } else if (!strcmp((char *) cur->name, "getcontenttype")) { node->content = (char *) xmlNodeGetContent(cur); } else if (!strcmp((char *) cur->name, "getcontentlength")) { node->size = (char *) xmlNodeGetContent(cur); } cur = cur->next; } } void parsePropfindPropstat(xmlNodePtr cur, nodeinfoPtr node) { cur = cur->childs; /* * propstat (prop, status, responsedescription?) */ while (cur != NULL) { if (!strcmp((char *) cur->name, "prop")) { parsePropfindProp(cur, node); } else if (!strcmp((char *) cur->name, "status")) { } else if (!strcmp((char *) cur->name, "responsedescription")) { } cur = cur->next; } } nodeinfoPtr parsePropfindHref(xmlNodePtr cur) { nodeinfoPtr ret; ret = nodeinfoNew(); ret->name = (char *) xmlNodeGetContent(cur); return(ret); } nodeinfoPtr parsePropfindResponse(xmlNodePtr cur) { nodeinfoPtr ret, last, res = NULL; ret = last = NULL; cur = cur->childs; /* * response (href, ((href*, status)|(propstat+)), responsedescription? */ while (cur != NULL) { if (!strcmp((char *) cur->name, "href")) { res = parsePropfindHref(cur); if (res != NULL) { if (ret == NULL) ret = last = res; else last->next = res; while (last->next != NULL) last = last->next; } } else if (!strcmp((char *) cur->name, "propstat")) { parsePropfindPropstat(cur, res); } else if (!strcmp((char *) cur->name, "status")) { } else if (!strcmp((char *) cur->name, "responsedescription")) { } cur = cur->next; } return(ret); } nodeinfoPtr parsePropfindAnswer(xmlNodePtr cur) { nodeinfoPtr ret = NULL, last, res; if (!strcmp((char *) cur->name, "multistatus")) { ret = last = NULL; cur = cur->childs; while (cur != NULL) { if (!strcmp((char *) cur->name, "response")) { res = parsePropfindResponse(cur); if (res != NULL) { if (ret == NULL) ret = last = res; else last->next = res; while (last->next != NULL) last = last->next; } } cur = cur->next; } } return(ret); } nodeinfoPtr propfind(char *file) { nodeinfoPtr ret; xmlDocPtr doc; char URL[1024]; char *xmlResult = NULL; int result; if ((file != NULL) && (!strncmp(file, "http://", 7))) { scanURL(file); } else if (file != NULL) { strcpy(current_path, file); } if (current_file[0] == 0) #ifdef HAVE_SNPRINTF snprintf(URL, sizeof(URL), "%s://%s:%d%s", current_protocol, current_hostname, current_port, current_path); #else sprintf(URL, "%s://%s:%d%s", current_protocol, current_hostname, current_port, current_path); #endif else #ifdef HAVE_SNPRINTF snprintf(URL, sizeof(URL), "%s://%s:%d%s%s", current_protocol, current_hostname, current_port, current_path, current_file); #else sprintf(URL, "%s://%s:%d%s%s", current_protocol, current_hostname, current_port, current_path, current_file); #endif result = propfindQuery(URL, &xmlResult); if (result == -1) return(NULL); if (xmlResult == NULL) return(NULL); doc = xmlParseMemory(xmlResult, strlen(xmlResult)); if (doc == NULL) { fprintf(stdout, "%s\n", xmlResult); xmlFree(xmlResult); return(NULL); } if (debug) fprintf(stdout, "%s\n", xmlResult); ret = parsePropfindAnswer(doc->root); xmlFreeDoc(doc); xmlFree(xmlResult); return(ret); } int cd(char *newpath) { nodeinfoPtr ret; if (newpath == NULL) { strcpy(current_path, "/"); strcpy(current_file, ""); } /* else if */ } int ls(char *newpath) { } int main(int argc, char** argv) { nodeinfoPtr ret; char line[1024], *cur; int i; for (i = 1; i < argc ; i++) { if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) debug++; } for (i = 1; i < argc ; i++) { if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) continue; ret = propfind(argv[i]); nodeinfoListPrint(ret); } /************** int ret; while (1) { ret = fscanf("%s", line); if (!strncmp(line, "cd", 2)) { cur = &line[2]; while ((*cur == ' ') || (*cur == "\t")) cur++; if ((*cur != 0) && (*cur != '\n') && (*cur != '\r')) { cd(cur); } else { cd(NULL); } } else if (!strncmp(line, "ls", 2)) { cur = &line[2]; while ((*cur == ' ') || (*cur == "\t")) cur++; if ((*cur != 0) && (*cur != '\n') && (*cur != '\r')) { ls(cur); } else { ls(NULL); } } } **********/ xmlCleanupParser(); xmlMemoryDump(); return(0); }