Ejemplo n.º 1
0
/************************************************************************
*	Function :	membuffer_append
*
*	Parameters :
*		INOUT membuffer* m ; buffer whose memory is to be appended.
*		IN const void* buf ; source buffer whose contents will be 
*					copied
*		IN size_t buf_len ;	length of the source buffer
*
*	Description : Invokes function to appends data from a constant buffer 
*		to the buffer 
*
*	Return : int ;
*
*	Note :
************************************************************************/
int
membuffer_append( INOUT membuffer * m,
                  IN const void *buf,
                  IN size_t buf_len )
{
    assert( m != NULL );

    return membuffer_insert( m, buf, buf_len, m->length );
}
Ejemplo n.º 2
0
/*!
 * \brief Adds "MAN" field in the HTTP header.
 *
 * \return 0 on success, UPNP_E_OUTOFMEMORY on error.
 */
static UPNP_INLINE int add_man_header(
	/* [in,out] HTTP header. */
	membuffer *headers)
{
	size_t n;
	char *soap_action_hdr;
	const char *man_hdr =
		"MAN: \"http://schemas.xmlsoap.org/soap/envelope/\"; ns=01\r\n01-";

	/* change POST to M-POST */
	if (membuffer_insert(headers, "M-", 2, 0) != 0)
		return UPNP_E_OUTOF_MEMORY;
	soap_action_hdr = strstr(headers->buf, "SOAPACTION:");
	/* can't fail */
	assert(soap_action_hdr != NULL);
	/* insert MAN header */
	n = (size_t)(soap_action_hdr - headers->buf);
	if (membuffer_insert(headers, man_hdr, strlen(man_hdr), n))
		return UPNP_E_OUTOF_MEMORY;

	return 0;
}
Ejemplo n.º 3
0
/****************************************************************************
*	Function :	add_man_header
*
*	Parameters :
*			INOUT membuffer* headers :	HTTP header
*
*	Description :	This function adds "MAN" field in the HTTP header
*
*	Return : int
*		returns 0 on success; UPNP_E_OUTOFMEMORY on error
*
*	Note :
****************************************************************************/
static XINLINE int
add_man_header( INOUT membuffer * headers )
{
    char *soap_action_hdr;
    char *man_hdr = "MAN: \"http://schemas.xmlsoap.org/soap/envelope/\"; "
        "ns=01\r\n01-";

    // change POST to M-POST
    if( membuffer_insert( headers, "M-", 2, 0 ) != 0 ) {
        return UPNP_E_OUTOF_MEMORY;
    }

    soap_action_hdr = strstr( headers->buf, "SOAPACTION:" );
    assert( soap_action_hdr != NULL );  // can't fail

    // insert MAN header
    if( membuffer_insert( headers, man_hdr, strlen( man_hdr ),
                          soap_action_hdr - headers->buf ) != 0 ) {
        return UPNP_E_OUTOF_MEMORY;
    }

    return 0;
}
Ejemplo n.º 4
0
/************************************************************************
*	Function :	membuffer_append_str
*
*	Parameters :
*		INOUT membuffer* m ;	buffer whose memory is to be appended.
*		IN const char* c_str ;	source buffer whose contents will be 
*					copied
*
*	Description : Invokes function to appends data from a constant string 
*		to the buffer 	
*
*	Return : int ;
*
*	Note :
************************************************************************/
int
membuffer_append_str( INOUT membuffer * m,
                      IN const char *c_str )
{
    return membuffer_insert( m, c_str, strlen( c_str ), m->length );
}
Ejemplo n.º 5
0
/*!
 * \brief Processes the request and returns the result in the output parameters.
 *
 * \return
 * \li \c HTTP_BAD_REQUEST
 * \li \c HTTP_INTERNAL_SERVER_ERROR
 * \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
 * \li \c HTTP_OK
 */
static int process_request(
	/*! [in] HTTP Request message. */
	http_message_t *req,
	/*! [out] Type of response. */
	enum resp_type *rtype,
	/*! [out] Headers. */
	membuffer *headers,
	/*! [out] Get filename from request document. */
	membuffer *filename,
	/*! [out] Xml alias document from the request document. */
	struct xml_alias_t *alias,
	/*! [out] Send Instruction object where the response is set up. */
	struct SendInstruction *RespInstr)
{
	int code;
	int err_code;

	char *request_doc;
	struct File_Info finfo;
	int using_alias;
	int using_virtual_dir;
	uri_type *url;
	const char *temp_str;
	int resp_major;
	int resp_minor;
	int alias_grabbed;
	size_t dummy;
	char *extra_headers = NULL;
	int extra_func; //chrison

	print_http_headers(req);
	url = &req->uri;
	assert(req->method == HTTPMETHOD_GET ||
	       req->method == HTTPMETHOD_HEAD ||
	       req->method == HTTPMETHOD_POST ||
	       req->method == HTTPMETHOD_SIMPLEGET);
	/* init */
	memset(&finfo, 0, sizeof(finfo));
	request_doc = NULL;
	finfo.content_type = NULL;
	alias_grabbed = FALSE;
	err_code = HTTP_INTERNAL_SERVER_ERROR;	/* default error */
	using_virtual_dir = FALSE;
	using_alias = FALSE;

	http_CalcResponseVersion(req->major_version, req->minor_version,
				 &resp_major, &resp_minor);
	/* */
	/* remove dots */
	/* */
	request_doc = osal_malloc(url->pathquery.size + 1);
	if (request_doc == NULL) {
		goto error_handler;	/* out of mem */
	}
	memcpy(request_doc, url->pathquery.buff, url->pathquery.size);
	request_doc[url->pathquery.size] = '\0';
	dummy = url->pathquery.size;
	remove_escaped_chars(request_doc, &dummy);
	code = remove_dots(request_doc, url->pathquery.size);
	if (code != 0) {
		err_code = HTTP_FORBIDDEN;
		goto error_handler;
	}
	if (*request_doc != '/') {
		/* no slash */
		err_code = HTTP_BAD_REQUEST;
		goto error_handler;
	}
	if (isFileInVirtualDir(request_doc)) {
		using_virtual_dir = TRUE;
		RespInstr->IsVirtualFile = 1;
		if (membuffer_assign_str(filename, request_doc) != 0) {
			goto error_handler;
		}
	} else {
		/* try using alias */
		if (is_valid_alias(&gAliasDoc)) {
			alias_grab(alias);
			alias_grabbed = TRUE;
			using_alias = get_alias(request_doc, alias, &finfo);
			if (using_alias == TRUE) {
				finfo.content_type =
				    ixmlCloneDOMString("text/xml");

				if (finfo.content_type == NULL) {
					goto error_handler;
				}
			}
		}
	}
	if (using_virtual_dir) {
		if (req->method != HTTPMETHOD_POST) {
			/* get file info */
			int		ret;
			if ((ret = virtualDirCallback.
			    get_info(filename->buf, req, &extra_headers, &finfo, &extra_func)) != 0) {
			    switch(ret) {
			    case VHAND_ERR__OUT_OF_SERVICE:
			    	err_code = HTTP_SERVICE_UNAVAILABLE;
			    	break;
			    default:
					err_code = HTTP_NOT_FOUND;
				}
				goto error_handler;
			}
			/* try index.html if req is a dir */
			if (finfo.is_directory) {
				if (filename->buf[filename->length - 1] == '/') {
					temp_str = "index.html";
				} else {
					temp_str = "/index.html";
				}
				if (membuffer_append_str(filename, temp_str) !=
				    0) {
					goto error_handler;
				}
				/* get info */
				if ((virtualDirCallback.
				     get_info(filename->buf, req, &extra_headers, &finfo,&extra_func) != UPNP_E_SUCCESS)
				    || finfo.is_directory) {
					err_code = HTTP_NOT_FOUND;
					goto error_handler;
				}
			}
			/* not readable */
			if (!finfo.is_readable) {
				err_code = HTTP_FORBIDDEN;
				goto error_handler;
			}
			/* finally, get content type */
			/* if ( get_content_type(filename->buf, &content_type) != 0 ) */
			/*{ */
			/*  goto error_handler; */
			/* } */
		}
	} else if (!using_alias) {
		int i;
		if (gDocumentRootDir.length == 0) {
			goto error_handler;
		}
		/* */
		/* get file name */
		/* */

		/* filename str */
		UpnpPrintf(UPNP_WARN, HTTP, __FILE__, __LINE__,"%d GET filename %s\r\n", __LINE__, request_doc);
		// Find symbolic link path
		for (i = 0; _symlink[i].symbol != NULL; i++) {
			if (!strncmp(request_doc, _symlink[i].symbol, strlen(_symlink[i].symbol))) {
				// replace symbol by target
				membuffer_assign_str(filename, request_doc);
				membuffer_delete(filename, 0, strlen(_symlink[i].symbol));
				if (membuffer_insert(filename, _symlink[i].target, strlen(_symlink[i].target), 0) != 0)
					goto error_handler;	// out of mem
				break;
			}
		}
		if (!_symlink[i].symbol) {
			// No match, append default root path
			if (membuffer_assign_str(filename, gDocumentRootDir.buf) != 0 ||
			    membuffer_append_str(filename, request_doc) != 0) {
				goto error_handler;	/* out of mem */
			}
		}
		UpnpPrintf(UPNP_WARN, HTTP, __FILE__, __LINE__,"%d GET filename %s\r\n", __LINE__, filename->buf);
		/* remove trailing slashes */
		while (filename->length > 0 &&
		       filename->buf[filename->length - 1] == '/') {
			membuffer_delete(filename, filename->length - 1, 1);
		}
		if (req->method != HTTPMETHOD_POST) {
			/* get info on file */
			if (get_file_info(filename->buf, &finfo) != 0) {
				err_code = HTTP_NOT_FOUND;
				goto error_handler;
			}
			/* try index.html if req is a dir */
			if (finfo.is_directory) {
				if (filename->buf[filename->length - 1] == '/') {
					temp_str = "index.html";
				} else {
					temp_str = "/index.html";
				}
				if (membuffer_append_str(filename, temp_str) !=
				    0) {
					goto error_handler;
				}
				/* get info */
				if (get_file_info(filename->buf, &finfo) != 0 ||
				    finfo.is_directory) {
					err_code = HTTP_NOT_FOUND;
					goto error_handler;
				}
			}
			/* not readable */
			if (!finfo.is_readable) {
				err_code = HTTP_FORBIDDEN;
				goto error_handler;
			}
		}
		/* finally, get content type */
		/*      if ( get_content_type(filename->buf, &content_type) != 0 ) */
		/*      { */
		/*          goto error_handler; */
		/*      } */
	}
	RespInstr->ReadSendSize = finfo.file_length;
	/* Check other header field. */
	if ((code =
	     CheckOtherHTTPHeaders(req, RespInstr,
				   finfo.file_length)) != HTTP_OK) {
		err_code = code;
		goto error_handler;
	}
	if (req->method == HTTPMETHOD_POST) {
		*rtype = RESP_POST;
		err_code = HTTP_OK;
		goto error_handler;
	}
	/*extra_headers = UpnpFileInfo_get_ExtraHeaders(finfo); */
	if (!extra_headers) {
		extra_headers = "";
	}

	/* Check if chunked encoding should be used. */
	if (using_virtual_dir && finfo.file_length == UPNP_USING_CHUNKED) {
		/* Chunked encoding is only supported by HTTP 1.1 clients */
		if (resp_major == 1 && resp_minor == 1) {
			RespInstr->IsChunkActive = 1;
		} else {
			/* The virtual callback indicates that we should use
			 * chunked encoding however the client doesn't support
			 * it. Return with an internal server error. */
			err_code = HTTP_NOT_ACCEPTABLE;
			goto error_handler;
		}
	}
	if (RespInstr->IsRangeActive && RespInstr->IsChunkActive) {
		/* Content-Range: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
		/* Transfer-Encoding: chunked */
		if (http_MakeMessage(headers, resp_major, resp_minor,
		    "R" "T" "GKLD" "s" "tcS" "Xc" "sCc",
		    HTTP_PARTIAL_CONTENT,	/* status code */
		    finfo.content_type,	/* content type */
		    RespInstr,	/* range info */
		    RespInstr,	/* language info */
		    "LAST-MODIFIED: ",
		    &finfo.last_modified,
		    X_USER_AGENT, extra_headers) != 0) {
			goto error_handler;
		}
	} else if (RespInstr->IsRangeActive && !RespInstr->IsChunkActive) {
		/* Content-Range: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
		/* Transfer-Encoding: chunked */
		if (http_MakeMessage(headers, resp_major, resp_minor,
		    "R" "N" "T" "GLD" "s" "tcS" "Xc" "sCc",
		    HTTP_PARTIAL_CONTENT,	/* status code */
		    RespInstr->ReadSendSize,	/* content length */
		    finfo.content_type,	/* content type */
		    RespInstr,	/* range info */
		    RespInstr,	/* language info */
		    "LAST-MODIFIED: ",
		    &finfo.last_modified,
		    X_USER_AGENT, extra_headers) != 0) {
			goto error_handler;
		}
	} else if (!RespInstr->IsRangeActive && RespInstr->IsChunkActive) {
		/* Content-Range: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
		/* Transfer-Encoding: chunked */
		if (http_MakeMessage(headers, resp_major, resp_minor,
		    "RK" "TLD" "s" "tcS" "Xc" "sCc",
		    HTTP_OK,	/* status code */
		    finfo.content_type,	/* content type */
		    RespInstr,	/* language info */
		    "LAST-MODIFIED: ",
		    &finfo.last_modified,
		    X_USER_AGENT, extra_headers) != 0) {
			goto error_handler;
		}
	} else {
		/* !RespInstr->IsRangeActive && !RespInstr->IsChunkActive */
		if (RespInstr->ReadSendSize != 0) {
			/* Content-Range: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
			/* Transfer-Encoding: chunked */
			if (http_MakeMessage(headers, resp_major, resp_minor,
			    "R" "N" "TLD" "s" "tcS" "Xc" "sCc",
			    HTTP_OK,	/* status code */
			    RespInstr->ReadSendSize,	/* content length */
			    finfo.content_type,	/* content type */
			    RespInstr,	/* language info */
			    "LAST-MODIFIED: ",
			    &finfo.last_modified,
			    X_USER_AGENT,
			    extra_headers) != 0) {
				goto error_handler;
			}
		} else {
			/* Content-Range: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
			/* Transfer-Encoding: chunked */
			if (http_MakeMessage(headers, resp_major, resp_minor,
			    "R" "TLD" "s" "tcS" "Xc" "sCc",
			    HTTP_OK,	/* status code */
			    finfo.content_type,	/* content type */
			    RespInstr,	/* language info */
			    "LAST-MODIFIED: ",
			    &finfo.last_modified,
			    X_USER_AGENT,
			    extra_headers) != 0) {
				goto error_handler;
			}
		}
	}
	if (req->method == HTTPMETHOD_HEAD) {
		*rtype = RESP_HEADERS;
	} else if (using_alias) {
		/* GET xml */
		*rtype = RESP_XMLDOC;
	} else if (using_virtual_dir) {
		*rtype = RESP_WEBDOC;
	} else {
		/* GET filename */
		*rtype = RESP_FILEDOC;
	}
	/* simple get http 0.9 as specified in http 1.0 */
	/* don't send headers */
	if (req->method == HTTPMETHOD_SIMPLEGET) {
		membuffer_destroy(headers);
	}
	err_code = HTTP_OK;

 error_handler:
	osal_free(request_doc);
	ixmlFreeDOMString(finfo.content_type);
	if (err_code != HTTP_OK && alias_grabbed) {
		alias_release(alias);
	}

	return err_code;
}