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