Annotation of XML/testDAV.c, revision 1.9
1.1 daniel 1: /*
2: * testDAV.c : a small tester program for WebDAV operations
3: *
4: * See Copyright for the status of this software.
5: *
6: * Daniel.Veillard@w3.org
7: */
8:
9: #ifdef WIN32
1.4 daniel 10: #include "win32config.h"
1.1 daniel 11: #else
12: #include "config.h"
13: #endif
14:
1.6 daniel 15: #include "xmlversion.h"
16:
17: #ifdef LIBXML_HTTP_ENABLED
1.1 daniel 18: #include <stdio.h>
19: #include <string.h>
20:
21: #ifdef HAVE_SYS_TYPES_H
22: #include <sys/types.h>
23: #endif
24: #ifdef HAVE_SYS_STAT_H
25: #include <sys/stat.h>
26: #endif
27: #ifdef HAVE_FCNTL_H
28: #include <fcntl.h>
29: #endif
30: #ifdef HAVE_UNISTD_H
31: #include <unistd.h>
32: #endif
33: #ifdef HAVE_STDLIB_H
34: #include <stdlib.h>
35: #endif
36:
1.6 daniel 37: #include <libxml/xmlmemory.h>
38: #include <libxml/nanohttp.h>
39: #include <libxml/tree.h>
40: #include <libxml/parser.h>
1.9 ! veillard 41: #include <libxml/xmlerror.h>
1.1 daniel 42:
43: static int debug = 0;
44:
45: typedef struct nodeinfo {
46: struct nodeinfo *next;
47: char *name;
48: char *size;
49: char *date;
50: char *content;
51: } nodeinfo, *nodeinfoPtr;
52:
53: char current_protocol[20] = "http";
54: char current_hostname[100] = "localhost";
55: char current_path[1024] = "/";
56: char current_file[1024] = "";
57: int current_port = 80;
58:
59: void scanURL(const char *URL) {
60: const char *cur = URL;
61: char buf[4096];
62: int index = 0;
63: int port = 0;
64:
65: buf[index] = 0;
66: while (*cur != 0) {
67: if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) {
68: buf[index] = 0;
69: strcpy(current_protocol, buf);
70: index = 0;
71: cur += 3;
72: break;
73: }
74: buf[index++] = *cur++;
75: }
76: if (*cur == 0) return;
77:
78: buf[index] = 0;
79: while (1) {
80: if (cur[0] == ':') {
81: buf[index] = 0;
82: strcpy(current_hostname, buf);
83: index = 0;
84: cur += 1;
85: while ((*cur >= '0') && (*cur <= '9')) {
86: port *= 10;
87: port += *cur - '0';
88: cur++;
89: }
90: if (port != 0) current_port = port;
91: while ((cur[0] != '/') && (*cur != 0))
92: cur++;
93: break;
94: }
95: if ((*cur == '/') || (*cur == 0)) {
96: buf[index] = 0;
97: strcpy(current_hostname, buf);
98: index = 0;
99: break;
100: }
101: buf[index++] = *cur++;
102: }
103: if (*cur == 0) {
104: strcpy(current_path, "/");
105: strcpy(current_file, "");
106: }else {
107: buf[index] = 0;
108: while (*cur != 0) {
109: if ((cur[0] == '#') || (cur[0] == '?'))
110: break;
111: buf[index++] = *cur++;
112: }
113: buf[index] = 0;
114: while ((index > 0) && (buf[index] != '/')) index--;
115: strcpy(current_file, &buf[index + 1]);
116: buf[index + 1] = 0;
117: strcpy(current_path, buf);
118: }
119: }
120:
121: nodeinfoPtr nodeinfoNew() {
1.2 daniel 122: nodeinfoPtr ret = xmlMalloc(sizeof(nodeinfo));
1.1 daniel 123: if (ret == NULL) return(NULL);
124: memset(ret, 0, sizeof(nodeinfo));
125: return(ret);
126: }
127: void nodeinfoFree(nodeinfoPtr info) {
128: if (info == NULL) return;
1.2 daniel 129: if (info->name) xmlFree(info->name);
130: if (info->date) xmlFree(info->date);
131: if (info->size) xmlFree(info->date);
132: if (info->content) xmlFree(info->content);
1.1 daniel 133: }
134: void nodeinfoListFree(nodeinfoPtr info) {
135: nodeinfoPtr cur = info;
136:
137: while (cur != NULL) {
138: info = info->next;
139: nodeinfoFree(cur);
140: cur = info;
141: }
142: }
143: void nodeinfoPrint(nodeinfoPtr info) {
144: if (info == NULL) return;
1.9 ! veillard 145: if (info->date) xmlGenericError(xmlGenericErrorContext,
! 146: "%s\t", info->date);
! 147: if (info->name) xmlGenericError(xmlGenericErrorContext,
! 148: "%s\t", info->name);
! 149: else xmlGenericError(xmlGenericErrorContext,
! 150: "???\t");
! 151: if (info->size) xmlGenericError(xmlGenericErrorContext,
! 152: "%s\t", info->size);
! 153: if (info->content) xmlGenericError(xmlGenericErrorContext,
! 154: "%s\t", info->content);
! 155: xmlGenericError(xmlGenericErrorContext, "\n");
1.1 daniel 156: }
157: void nodeinfoListPrint(nodeinfoPtr info) {
158: nodeinfoPtr cur = info;
159:
160: while (cur != NULL) {
161: info = info->next;
162: nodeinfoPrint(cur);
163: cur = info;
164: }
165: }
166: int propfindQuery(const char *URL, char **result) {
167: void *ctxt;
168: char *contentType = "text/xml; charset=\"utf-8\"";
169: char *output;
170: int len;
171: int size = 40000;
172: int returnCode;
173: char *verboseQuery =
174: "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\
175: <D:propfind xmlns:D=\"DAV:\">\
176: <D:allprop/>\
177: </D:propfind>";
178:
179:
180: if ((URL == NULL) || (result == NULL)) return(-1);
181:
182: if (URL[strlen(URL) - 1] == '/')
183: ctxt = xmlNanoHTTPMethod(URL, "PROPFIND", NULL,
184: &contentType, "Depth: 1\r\n");
185: else
186: ctxt = xmlNanoHTTPMethod(URL, "PROPFIND", verboseQuery,
187: &contentType, "Depth: 0\r\n");
188: if (ctxt == NULL) {
1.9 ! veillard 189: xmlGenericError(xmlGenericErrorContext,
! 190: "PROPFIND %s failed\n", URL);
1.1 daniel 191: return(-1);
192: }
1.2 daniel 193:
1.1 daniel 194: returnCode = xmlNanoHTTPReturnCode(ctxt);
195: if ((returnCode >= 300) ||
196: ((contentType != NULL) && (strncmp(contentType, "text/xml", 8)))) {
197: xmlNanoHTTPClose(ctxt);
1.2 daniel 198: if (contentType != NULL) xmlFree(contentType);
1.1 daniel 199: return(-1);
200: }
1.2 daniel 201: if (contentType != NULL) xmlFree(contentType);
1.1 daniel 202:
1.2 daniel 203: output = (char *) xmlMalloc(size + 1);
1.1 daniel 204: if (output == NULL) {
1.9 ! veillard 205: xmlGenericError(xmlGenericErrorContext,
! 206: "out of memory\n");
1.1 daniel 207: xmlNanoHTTPClose(ctxt);
208: return(-1);
209: }
210: len = xmlNanoHTTPRead(ctxt, output, size);
211: if (len < 0) {
1.9 ! veillard 212: xmlGenericError(xmlGenericErrorContext,
! 213: "cannot read PROPFIND %s result\n", URL);
1.1 daniel 214: xmlNanoHTTPClose(ctxt);
1.2 daniel 215: xmlFree(output);
1.1 daniel 216: return(-1);
217: }
218: /* !!!!!!!!! handle returns size > size !!!!!!!!!! */
219: output[len] = 0;
220: xmlNanoHTTPClose(ctxt);
221:
222: *result = output;
223: return(returnCode);
224: }
225:
226: void parsePropfindProp(xmlNodePtr cur, nodeinfoPtr node) {
1.5 daniel 227: cur = cur->children;
1.1 daniel 228:
229: /*
230: * prop ANY
231: */
232: while (cur != NULL) {
233: if (!strcmp((char *) cur->name, "getlastmodified")) {
234: node->date = (char *) xmlNodeGetContent(cur);
235: } else if (!strcmp((char *) cur->name, "getcontenttype")) {
236: node->content = (char *) xmlNodeGetContent(cur);
237: } else if (!strcmp((char *) cur->name, "getcontentlength")) {
238: node->size = (char *) xmlNodeGetContent(cur);
239: }
240: cur = cur->next;
241: }
242: }
243:
244: void parsePropfindPropstat(xmlNodePtr cur, nodeinfoPtr node) {
1.5 daniel 245: cur = cur->children;
1.1 daniel 246:
247: /*
248: * propstat (prop, status, responsedescription?)
249: */
250: while (cur != NULL) {
251: if (!strcmp((char *) cur->name, "prop")) {
252: parsePropfindProp(cur, node);
253: } else if (!strcmp((char *) cur->name, "status")) {
254: } else if (!strcmp((char *) cur->name, "responsedescription")) {
255: }
256: cur = cur->next;
257: }
258: }
259:
260: nodeinfoPtr parsePropfindHref(xmlNodePtr cur) {
261: nodeinfoPtr ret;
262:
263: ret = nodeinfoNew();
264: ret->name = (char *) xmlNodeGetContent(cur);
265: return(ret);
266: }
267:
268: nodeinfoPtr parsePropfindResponse(xmlNodePtr cur) {
269: nodeinfoPtr ret, last, res = NULL;
270:
271: ret = last = NULL;
1.5 daniel 272: cur = cur->children;
1.1 daniel 273:
274: /*
275: * response (href, ((href*, status)|(propstat+)), responsedescription?
276: */
277: while (cur != NULL) {
278: if (!strcmp((char *) cur->name, "href")) {
279: res = parsePropfindHref(cur);
280: if (res != NULL) {
281: if (ret == NULL) ret = last = res;
282: else last->next = res;
283: while (last->next != NULL) last = last->next;
284: }
285: } else if (!strcmp((char *) cur->name, "propstat")) {
286: parsePropfindPropstat(cur, res);
287: } else if (!strcmp((char *) cur->name, "status")) {
288: } else if (!strcmp((char *) cur->name, "responsedescription")) {
289: }
290: cur = cur->next;
291: }
292: return(ret);
293: }
294:
295: nodeinfoPtr parsePropfindAnswer(xmlNodePtr cur) {
296: nodeinfoPtr ret = NULL, last, res;
297:
298: if (!strcmp((char *) cur->name, "multistatus")) {
299: ret = last = NULL;
1.5 daniel 300: cur = cur->children;
1.1 daniel 301: while (cur != NULL) {
302: if (!strcmp((char *) cur->name, "response")) {
303: res = parsePropfindResponse(cur);
304: if (res != NULL) {
305: if (ret == NULL) ret = last = res;
306: else last->next = res;
307: while (last->next != NULL) last = last->next;
308: }
309: }
310: cur = cur->next;
311: }
312: }
313: return(ret);
314: }
315:
316: nodeinfoPtr propfind(char *file) {
317: nodeinfoPtr ret;
318: xmlDocPtr doc;
319: char URL[1024];
320: char *xmlResult = NULL;
321: int result;
322:
323: if ((file != NULL) && (!strncmp(file, "http://", 7))) {
324: scanURL(file);
325: } else if (file != NULL) {
326: strcpy(current_path, file);
327: }
328: if (current_file[0] == 0)
1.2 daniel 329: #ifdef HAVE_SNPRINTF
1.1 daniel 330: snprintf(URL, sizeof(URL), "%s://%s:%d%s", current_protocol,
331: current_hostname, current_port, current_path);
1.2 daniel 332: #else
333: sprintf(URL, "%s://%s:%d%s", current_protocol,
334: current_hostname, current_port, current_path);
335: #endif
1.1 daniel 336: else
1.2 daniel 337: #ifdef HAVE_SNPRINTF
1.1 daniel 338: snprintf(URL, sizeof(URL), "%s://%s:%d%s%s", current_protocol,
339: current_hostname, current_port, current_path, current_file);
1.2 daniel 340: #else
341: sprintf(URL, "%s://%s:%d%s%s", current_protocol,
342: current_hostname, current_port, current_path, current_file);
343: #endif
1.1 daniel 344:
1.7 veillard 345: URL[sizeof(URL) - 1] = 0;
1.1 daniel 346: result = propfindQuery(URL, &xmlResult);
347: if (result == -1) return(NULL);
348: if (xmlResult == NULL) return(NULL);
349:
350: doc = xmlParseMemory(xmlResult, strlen(xmlResult));
351: if (doc == NULL) {
352: fprintf(stdout, "%s\n", xmlResult);
1.2 daniel 353: xmlFree(xmlResult);
1.1 daniel 354: return(NULL);
355: }
356:
357: if (debug)
358: fprintf(stdout, "%s\n", xmlResult);
359:
1.5 daniel 360: ret = parsePropfindAnswer(doc->children);
1.1 daniel 361: xmlFreeDoc(doc);
1.2 daniel 362: xmlFree(xmlResult);
1.1 daniel 363: return(ret);
364: }
365:
366: int cd(char *newpath) {
367: if (newpath == NULL) {
368: strcpy(current_path, "/");
369: strcpy(current_file, "");
370: } /* else if */
1.8 veillard 371: return(0);
1.1 daniel 372: }
373:
374: int ls(char *newpath) {
1.8 veillard 375: return(0);
1.1 daniel 376: }
377:
378: int main(int argc, char** argv) {
379: nodeinfoPtr ret;
380: int i;
381:
382: for (i = 1; i < argc ; i++) {
383: if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
384: debug++;
385: }
386: for (i = 1; i < argc ; i++) {
387: if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
388: continue;
389: ret = propfind(argv[i]);
390: nodeinfoListPrint(ret);
391: }
392: /**************
393: int ret;
394: while (1) {
395: ret = fscanf("%s", line);
396: if (!strncmp(line, "cd", 2)) {
397: cur = &line[2];
398: while ((*cur == ' ') || (*cur == "\t")) cur++;
399: if ((*cur != 0) && (*cur != '\n') && (*cur != '\r')) {
400: cd(cur);
401: } else {
402: cd(NULL);
403: }
404: } else if (!strncmp(line, "ls", 2)) {
405: cur = &line[2];
406: while ((*cur == ' ') || (*cur == "\t")) cur++;
407: if ((*cur != 0) && (*cur != '\n') && (*cur != '\r')) {
408: ls(cur);
409: } else {
410: ls(NULL);
411: }
412: }
413: }
414: **********/
1.3 daniel 415: xmlCleanupParser();
1.2 daniel 416: xmlMemoryDump();
1.1 daniel 417: return(0);
418: }
1.6 daniel 419: #else /* !LIBXML_HTTP_ENABLED */
420: #include <stdio.h>
421: int main(int argc, char **argv) {
1.9 ! veillard 422: xmlGenericError(xmlGenericErrorContext,
! 423: "%s : HTTP support not compiled in\n", argv[0]);
1.6 daniel 424: return(0);
425: }
426: #endif /* LIBXML_HTTP_ENABLED */
Webmaster