Ejemplo n.º 1
0
/*
** LOCK requests
*/
PRIVATE BOOL lock_request (Cmdline * arg) {

    HTDAVHeaders * headers = HTDAVHeaders_new();
    HTRequest * request = create_request ();
    HTAnchor * dst = HTAnchor_findAddress(arg->request_uri);
    HTParentAnchor * src = NULL;
    HTParentAnchor * base = NULL;
    BOOL status = NO;
    char * data = NULL;
        
    if (arg->I) {
        HTPrint ("Adding If header %s\n",arg->I);
        HTDAV_setIfHeader (headers,arg->I);
    }

    if (arg->arg1)  {
        data = create_body (arg->arg1);
        HTPrint ("xml body  %s\n",data);
           
        /* chose the func */
        if (arg->func==1) {
            src = HTTmpAnchor(NULL);
            HTAnchor_setDocument(src, data);
            HTAnchor_setFormat(src, HTAtom_for ("text/xml"));
            HTAnchor_setLength(src, strlen(data));
        } 
    }

    if (arg->base_str && *(arg->base_str)) 
        base = (HTParentAnchor *) HTAnchor_findAddress(arg->base_str);

    if (arg->D) HTDAV_setDepthHeader (headers,arg->D);
    if (arg->T) HTDAV_setTimeoutHeader (headers,arg->T);

    HTPrint ("function %d src? %s\n",arg->func,(src)?"yes":"no");

    switch (arg->func) {
        case 1: status = HTLOCKDocumentAnchor (request,dst,src,headers);
                break;
        case 2: status = HTLOCKAnchor (request,dst,data,headers);
                break;
        case 3: status = HTLOCKAbsolute (request,arg->request_uri,data,headers);
                break;
        case 4: status = HTLOCKRelative (request,arg->request_uri,base,data,headers);
                break;
    }

    return status;
}
Ejemplo n.º 2
0
/*
** MOVE requests
*/
PRIVATE BOOL move_request ( Cmdline * arg ) { 
        
    HTDAVHeaders * headers = HTDAVHeaders_new();
    HTRequest * request = create_request ();
    HTAnchor * src = HTAnchor_findAddress(arg->request_uri);
    HTParentAnchor * body = NULL;
    HTParentAnchor * base = NULL;
    BOOL status = NO;
        
    if (arg->arg1) {
       HTPrint ("Adding Destination header %s\n",arg->arg1);
       HTDAV_setDestinationHeader (headers,arg->arg1);
    }
        
    if (arg->I) {
       HTPrint ("Adding If header %s\n",arg->I);
       HTDAV_setIfHeader (headers,arg->I);
    }

    /* chose the func */
    if (arg->func==2 && arg->arg2 ) {
        body = HTTmpAnchor(NULL);
        HTAnchor_setDocument(body, arg->arg2);
        HTAnchor_setFormat(body, HTAtom_for ("text/xml"));
        HTAnchor_setLength(body, strlen(arg->arg2));                
     } 

    if (arg->base_str && *(arg->base_str)) 
        base = (HTParentAnchor *) HTAnchor_findAddress(arg->base_str);

    if (arg->D) HTDAV_setDepthHeader (headers,arg->D);
    if (arg->O == 'T') HTDAV_setOverwriteHeader (headers,YES);
    else if (arg->O == 'F') HTDAV_setOverwriteHeader (headers,NO);

    switch (arg->func) {
        case 1: status = HTMOVEAnchor (request,src,arg->arg2,headers);
                break;
        case 2: status = HTMOVEDocumentAnchor (request,src,body,headers);
                break;
        case 3: status = HTMOVEAbsolute (request,arg->request_uri,arg->arg2, headers);
                break;
        case 4: status = HTMOVERelative (request,arg->request_uri,base,arg->arg2,headers);
                break;
    }

    return status;
}
Ejemplo n.º 3
0
/*
** PROPPATCH requests
*/
PRIVATE BOOL proppatch_request (Cmdline * arg) {
    BOOL status = NO;
    HTDAVHeaders * headers = HTDAVHeaders_new();
    HTRequest * request = create_request ();
    HTAnchor * dst = HTAnchor_findAddress(arg->request_uri);
    HTParentAnchor *base = NULL;
    HTParentAnchor *src = NULL;
    char * xmlbody = NULL;
    
    if (arg->arg1 && *(arg->arg1)) 
        xmlbody = arg->arg1;        
    else 
        return NO;
    
    HTPrint ("xml body **%s**\n",xmlbody);        
    
    if (arg->func==2) {
        src = HTTmpAnchor(NULL);
        HTAnchor_setDocument(src, xmlbody);
        HTAnchor_setFormat(src, HTAtom_for ("text/xml"));
        HTAnchor_setLength(src, strlen(xmlbody));                
    } 

    if (arg->base_str && *(arg->base_str)) 
        base = (HTParentAnchor *) HTAnchor_findAddress(arg->base_str);

    HTPrint ("setting headers\n");
    if (arg->I && *(arg->I)) {           
        HTPrint ("Adding If header %s\n",arg->I);
        HTDAV_setIfHeader (headers,arg->I);
    }

    HTPrint ("Chosing func\n");
    switch (arg->func) {
        case 1: status = HTPROPPATCHAnchor (request,dst,xmlbody,headers);
                break; 
        case 2: status = HTPROPPATCHDocumentAnchor (request,dst,src,headers);
                break; 
        case 3: status = HTPROPPATCHAbsolute (request,arg->request_uri,xmlbody,headers);
                break; 
        case 4: status = HTPROPPATCHRelative (request,arg->request_uri,base,xmlbody,headers);
                break; 
    }    

    return status;
}
Ejemplo n.º 4
0
/*
** PROPFIND requests
*/
PRIVATE BOOL propfind_request (Cmdline * arg) {
    BOOL status = NO;
    HTDAVHeaders * headers = HTDAVHeaders_new();
    HTRequest * request = create_request ();
    HTAnchor * dst = HTAnchor_findAddress(arg->request_uri);
    HTParentAnchor *base = NULL;
    HTParentAnchor *src = NULL;
    char * xmlbody = NULL;

    /* chose the func */
    HTPrint ("should we set the xml body?\n");
    if (arg->arg1 && *(arg->arg1)) {
        if (!strcasecomp (arg->arg1,"allprop") || !strcasecomp (arg->arg1,"propname")) 
            xmlbody = create_propbody (arg->arg1);
        else
            xmlbody = arg->arg1;
        HTPrint ("xml body %s\n",xmlbody);        
    }        
    
    if (arg->func==2 && xmlbody && *xmlbody) {
        src = HTTmpAnchor(NULL);
        HTAnchor_setDocument(src, xmlbody);
        HTAnchor_setFormat(src, HTAtom_for ("text/xml"));
        HTAnchor_setLength(src, strlen(xmlbody));                
    } 

    if (arg->base_str && *(arg->base_str)) 
        base = (HTParentAnchor *) HTAnchor_findAddress(arg->base_str);

    HTPrint ("setting headers\n");
    if (arg->D) HTDAV_setDepthHeader (headers,arg->D);


    switch (arg->func) {
        case 1: status = HTPROPFINDAnchor (request,dst,xmlbody,headers);
                break; 
        case 2: status = HTPROPFINDDocumentAnchor (request,dst,src,headers);
                break; 
        case 3: status = HTPROPFINDAbsolute (request,arg->request_uri,xmlbody,headers);
                break; 
        case 4: status = HTPROPFINDRelative (request,arg->request_uri,base,xmlbody,headers);
                break; 
    }    

    return status;
}
Ejemplo n.º 5
0
PRIVATE int buf_free (HTStream * me)
{
    int status = HT_OK;

    /*
    **  If the buffer has not been flushed explicit and we are a pipe buffer
    **  then we don't free it.
    */ 
    if (me->mode & HT_BM_PIPE && me->state != HT_BS_TRANSPARENT) {
	HTTRACE(STREAM_TRACE, "PipeBuffer Waiting to be flushed\n");
	return HT_OK;
    }

    /*
    **  Should we count the content length and assign it to the
    **  anchor?
    */
    if (me->mode & HT_BM_COUNT && me->request) {
	HTParentAnchor * anchor = HTRequest_anchor(me->request);
	HTTRACE(STREAM_TRACE, "Buffer........ Calculated content-length: %d\n" _ me->conlen);
	HTAnchor_setLength(anchor, me->conlen);
    }

    /*
    **  Flush the buffered data - even if we are paused. That is, we always
    **  flush - except if we have already flushed the buffer, of course.
    **  Also, we don't flush if we are a PIPE buffer. Then the flush MUST be
    **  called explicitly and the buffer can not be freed before this 
    **  happens.
    */
    if ((status = buf_flush(me)) != HT_OK)
	return status;
    if ((status = (*me->target->isa->_free)(me->target)) != HT_OK)
	return status;
    HT_FREE(me);
    return status;
}
Ejemplo n.º 6
0
PRIVATE int FileEvent (SOCKET soc, void * pVoid, HTEventType type)
{
    file_info *file = pVoid;			      /* Specific access information */
    int status = HT_ERROR;
    HTNet * net = file->net;
    HTRequest * request = HTNet_request(net);
    HTParentAnchor * anchor = HTRequest_anchor(request);

    /*
    ** Initiate a new file structure and bind to request structure
    ** This is actually state FILE_BEGIN, but it can't be in the state
    ** machine as we need the structure first.
    */
    if (type == HTEvent_CLOSE) {				      /* Interrupted */
	HTRequest_addError(request, ERR_FATAL, NO, HTERR_INTERRUPTED,
			   NULL, 0, "HTLoadFile");
	FileCleanup(request, HT_INTERRUPTED);
	return HT_OK;
    }


    /* Now jump into the machine. We know the state from the previous run */
    while (1) {
	switch (file->state) {
	case FS_BEGIN:

	    /* We only support safe (GET, HEAD, etc) methods for the moment */
	    if (!HTMethod_isSafe(HTRequest_method(request))) {
		HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_ALLOWED,
				   NULL, 0, "HTLoadFile");
		file->state = FS_ERROR;
		break;
	    }

	    /* Check whether we have access to local disk at all */
	    if (HTLib_secure()) {
		HTTRACE(PROT_TRACE, "LoadFile.... No access to local file system\n");
		file->state = FS_TRY_FTP;
		break;
	    }
	    file->local = HTWWWToLocal(HTAnchor_physical(anchor), "",
				       HTRequest_userProfile(request));
	    if (!file->local) {
		file->state = FS_TRY_FTP;
		break;
	    }

	    /* Create a new host object and link it to the net object */
	    {
		HTHost * host = NULL;
		if ((host = HTHost_new("localhost", 0)) == NULL) return HT_ERROR;
		HTNet_setHost(net, host);
		if (HTHost_addNet(host, net) == HT_PENDING) {
		    HTTRACE(PROT_TRACE, "HTLoadFile.. Pending...\n");
		    /* move to the hack state */
		    file->state = FS_PENDING;
		    return HT_OK;
		}
	    }
	    file->state = FS_DO_CN;
	    break;

	case FS_PENDING:
	    /*
	    ** 2000/08/10 JK : This is a funny state. Because of the
	    ** internal libwww stacks, when doing multiple local
	    ** requests (e.g., while using the Robot), we need to ask
	    ** again for the host object. If we had jumped directly to
	    ** the FS_DO_CN state, libwww would have blocked because
	    ** of socket starvation.
	    ** This state is similar to FS_BEGINNING, but just requests 
	    ** the host object. 
	    ** YES. THIS IS AN UGLY HACK!!
	    */
	    {
		HTHost * host = NULL;
		if ((host = HTHost_new("localhost", 0)) == NULL) return HT_ERROR;
		HTNet_setHost(net, host);
		if (HTHost_addNet(host, net) == HT_PENDING) {
		    HTTRACE(PROT_TRACE, "HTLoadFile.. Pending...\n");
		    file->state = FS_PENDING;
		    return HT_OK;
		}
	    }
	    file->state = FS_DO_CN;
	    break;

	case FS_DO_CN:
	    /*
	    ** If we have to do content negotiation then find the object that
	    ** fits best into either what the client has indicated in the
	    ** accept headers or what the client has registered on its own.
	    ** The object chosen can in fact be a directory! However, content
	    ** negotiation only makes sense if we can read the directory!
	    ** We stat the file in order to find the size and to see it if
	    ** exists.
	    */
	    if (HTRequest_negotiation(request) &&
		HTMethod_isSafe(HTRequest_method(request))) {
 		char * conneg = HTMulti(request, file->local,&file->stat_info);
		if (conneg) {
		    HT_FREE(file->local);
		    file->local = conneg;
		    HTAnchor_setPhysical(anchor, conneg);
		    HTTRACE(PROT_TRACE, "Load File... Found `%s\'\n" _ conneg);
		} else {
		    HTTRACE(PROT_TRACE, "Load File... Not found - even tried content negotiation\n");
		    HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_FOUND,
				       NULL, 0, "HTLoadFile");
		    file->state = FS_ERROR;
		    break;
		}
	    } else {
		if (HT_STAT(file->local, &file->stat_info) == -1) {
		    HTTRACE(PROT_TRACE, "Load File... Not found `%s\'\n" _ file->local);
		    HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_FOUND,
				       NULL, 0, "HTLoadFile");
		    file->state = FS_ERROR;
		    break;
		}
	    }

	    /*
	    ** Check to see if the 'localname' is in fact a directory.
	    ** Note that we can't do a HEAD on a directory
	    */
	    if (((file->stat_info.st_mode) & S_IFMT) == S_IFDIR) {
		if (HTRequest_method(request) == METHOD_GET)
		    file->state = FS_PARSE_DIR;
		else {
		    HTRequest_addError(request, ERR_INFO, NO, HTERR_NO_CONTENT,
				       NULL, 0, "HTLoadFile");
		    file->state = FS_NO_DATA;
		}
		break;
	    }

	    /*
	    ** If empty file then only serve it if it is editable. We also get
	    ** the bindings for the file suffixes in lack of better bindings
	    */
	    {
		BOOL editable = HTEditable(file->local, &file->stat_info);
		if (file_suffix_binding) HTBind_getAnchorBindings(anchor);
		if (editable) HTAnchor_appendAllow(anchor, METHOD_PUT);

		/* Set the file size */
		if (file->stat_info.st_size)
		    HTAnchor_setLength(anchor, file->stat_info.st_size);

		/* Set the file last modified time stamp */
		if (file->stat_info.st_mtime > 0)
		    HTAnchor_setLastModified(anchor, file->stat_info.st_mtime);

		/* Check to see if we can edit it */
		if (!editable && !file->stat_info.st_size) {
		    HTRequest_addError(request, ERR_INFO, NO, HTERR_NO_CONTENT,
				       NULL, 0, "HTLoadFile");
		    file->state = FS_NO_DATA;
		} else {
		    file->state = (HTRequest_method(request)==METHOD_GET) ? 
			FS_NEED_OPEN_FILE : FS_GOT_DATA;
		}
	    }
	    break;

	  case FS_NEED_OPEN_FILE:
	    status = HTFileOpen(net, file->local, HT_FB_RDONLY);
	    if (status == HT_OK) {
		/* 
		** Create the stream pipe FROM the channel to the application.
		** The target for the input stream pipe is set up using the
		** stream stack.
		*/
		{
		    HTStream * rstream = HTStreamStack(HTAnchor_format(anchor),
						       HTRequest_outputFormat(request),
						       HTRequest_outputStream(request),
						       request, YES);
		    HTNet_setReadStream(net, rstream);
		    HTRequest_setOutputConnected(request, YES);
		}

		/*
		** Create the stream pipe TO the channel from the application
		** and hook it up to the request object
		*/
		{
		    HTOutputStream * output = HTNet_getOutput(net, NULL, 0);
		    HTRequest_setInputStream(request, (HTStream *) output);
		}

		/*
		** Set up concurrent read/write if this request isn't the
		** source for a PUT or POST. As source we don't start reading
		** before all destinations are ready. If destination then
		** register the input stream and get ready for read
		*/
		if (HTRequest_isSource(request) && !HTRequest_destinationsReady(request))
		    return HT_OK;
		HTRequest_addError(request, ERR_INFO, NO, HTERR_OK, NULL, 0,
				   "HTLoadFile");
		file->state = FS_NEED_BODY;

		/* If we are _not_ using preemptive mode and we are Unix fd's
		** then return here to get the same effect as when we are
		** connecting to a socket. That way, HTFile acts just like any
		** other protocol module even though we are in fact doing
		** blocking connect
		*/
		if (HTEvent_isCallbacksRegistered()) {
		    if (!HTRequest_preemptive(request)) {
			if (!HTNet_preemptive(net)) {
			    HTTRACE(PROT_TRACE, "HTLoadFile.. Returning\n");
			    HTHost_register(HTNet_host(net), net, HTEvent_READ);
			} else if (!file->timer) {
			    HTTRACE(PROT_TRACE, "HTLoadFile.. Returning\n");
			    file->timer =
				HTTimer_new(NULL, ReturnEvent, file, 1, YES, NO);
			}
			return HT_OK;
		    }
		}
	    } else if (status == HT_WOULD_BLOCK || status == HT_PENDING)
		return HT_OK;
	    else {
		HTRequest_addError(request, ERR_INFO, NO, HTERR_INTERNAL,
				   NULL, 0, "HTLoadFile");
		file->state = FS_ERROR;		       /* Error or interrupt */
	    }
	    break;

	  case FS_NEED_BODY:
	    status = HTHost_read(HTNet_host(net), net);
	    if (status == HT_WOULD_BLOCK)
		return HT_OK;
	    else if (status == HT_LOADED || status == HT_CLOSED) {
		file->state = FS_GOT_DATA;
	    } else {
		HTRequest_addError(request, ERR_INFO, NO, HTERR_FORBIDDEN,
				   NULL, 0, "HTLoadFile");
		file->state = FS_ERROR;
	    }
	    break;

	  case FS_PARSE_DIR:
	    status = HTFile_readDir(request, file);
	    if (status == HT_LOADED)
		file->state = FS_GOT_DATA;
	    else
		file->state = FS_ERROR;
	    break;

	  case FS_TRY_FTP:
	    {
		char *url = HTAnchor_physical(anchor);
		HTAnchor *anchor;
		char *newname = NULL;
		StrAllocCopy(newname, "ftp:");
		if (!strncmp(url, "file:", 5))
		    StrAllocCat(newname, url+5);
		else
		    StrAllocCat(newname, url);
		anchor = HTAnchor_findAddress(newname);
		HTRequest_setAnchor(request, anchor);
		HT_FREE(newname);
		FileCleanup(request, HT_IGNORE);
		return HTLoad(request, YES);
	    }
	    break;

	  case FS_GOT_DATA:
	    FileCleanup(request, HT_LOADED);
	    return HT_OK;
	    break;

	  case FS_NO_DATA:
	    FileCleanup(request, HT_NO_DATA);
	    return HT_OK;
	    break;

	  case FS_RETRY:
	    FileCleanup(request, HT_RETRY);
	    return HT_OK;
	    break;

	  case FS_ERROR:
	    FileCleanup(request, HT_ERROR);
	    return HT_OK;
	    break;
	}
    } /* End of while(1) */
}
Ejemplo n.º 7
0
int main (int argc, char ** argv)
{
    HTRequest * request = NULL;
    HTParentAnchor * src = NULL;
    HTAnchor * dst = NULL;
    char * dst_str = NULL;
    char * data = NULL;
    BOOL status = NO;

    /* Create a new premptive client */
    HTProfile_newNoCacheClient("libwww-POST", "1.0");

    /* Need our own trace and print functions */
    HTPrint_setCallback(printer);
    HTTrace_setCallback(tracer);

    /* Add our own filter to update the history list */
    HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);

    /* Handle command line args */
    if (argc >= 3) {
	dst_str = argv[1];
	data = argv[2];
    } else {
	HTPrint("Type the URI of the destination you want to POST to and the contents that you want to post.\n");
	HTPrint("\t%s <destination> <data>\n", argv[0]);
	HTPrint("For example, %s http://myserver/destination.html \"This is some testdata\"\n",
	       argv[0]);
	return -1;
    }

    if (data && *data && dst_str && *dst_str) {

	/* Make source relative to where we are */
	char * cwd = HTGetCurrentDirectoryURL();

	HTPrint("Posting to %s\n", dst_str);

	/* Create a request */
	request = HTRequest_new();

	/* Get an anchor object for the destination URI */
	dst = HTAnchor_findAddress(dst_str);

	/*
	** Dream up a source anchor (an editor can for example use this).
	** After creation we associate the data that we want to post and
	** set some metadata about what the data is. More formats can be found
	** ../src/HTFormat.html
	*/
	src = HTTmpAnchor(NULL);
	HTAnchor_setDocument(src, data);
	HTAnchor_setFormat(src, WWW_PLAINTEXT);

	/*
	** If not posting to an HTTP/1.1 server then content length MUST be
	** there. If HTTP/1.1 then it doesn't matter as we just use chunked
	** encoding under the covers
	*/
	HTAnchor_setLength(src, strlen(data));

	/* POST the source to the dest */
	status = HTPostAnchor(src, dst, request);

	/* We don't need these anymore */
	HT_FREE(cwd);

	/* Go into the event loop... */
	if (status == YES) HTEventList_loop(request);

    }

    return 0;
}