File:  [Public] / XML / testDAV.c
Revision 1.3: download - view: text, annotated - select for diffs
Wed Dec 1 09:13:12 1999 UTC (24 years, 6 months ago) by daniel
Branches: MAIN
CVS tags: HEAD
General cleanup, added xmlCleanupPredefinedEntities(), Daniel

/*
 * 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 <io.h>
#else
#include "config.h"
#endif

#include <stdio.h>
#include <string.h>

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#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 = 
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\
<D:propfind xmlns:D=\"DAV:\">\
    <D:allprop/>\
</D:propfind>";


    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);
}

Webmaster