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