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