예제 #1
0
static QString *read_line(FILE *file, char *key)
{
    char value[128];

    if (fscanf(file, "%127s%127s", key, value) == EOF) {
        return NULL;
    }
    remove_dots(key);
    return qstring_from_str(value);
}
예제 #2
0
파일: webserver.c 프로젝트: MaTriXy/libupnp
/*!
 * \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_FORBIDDEN
 * \li \c HTTP_NOT_FOUND
 * \li \c HTTP_NOT_ACCEPTABLE
 * \li \c HTTP_OK
 */
static int process_request(
	/*! [in] HTTP Request message. */
	http_message_t *req,
	/*! [out] Tpye 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;
	const char *extra_headers = NULL;

	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 = 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 */
			if (virtualDirCallback.
			    get_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 ((virtualDirCallback.
				     get_info(filename->buf,
					      &finfo) != 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) {
		if (gDocumentRootDir.length == 0) {
			goto error_handler;
		}
		/* */
		/* get file name */
		/* */

		/* filename str */
		if (membuffer_assign_str(filename, gDocumentRootDir.buf) != 0 ||
		    membuffer_append_str(filename, request_doc) != 0) {
			goto error_handler;	/* out of mem */
		}
		/* 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 */
		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) {
		/* 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) {
			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 {
			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:
	free(request_doc);
	ixmlFreeDOMString(finfo.content_type);
	if (err_code != HTTP_OK && alias_grabbed) {
		alias_release(alias);
	}

	return err_code;
}
예제 #3
0
char *resolve_rel_url(char *base_url, char *rel_url)
{
    uri_type base;
    uri_type rel;
    int rv;

    if (!base_url) {
        if (!rel_url)
            return NULL;
        return strdup(rel_url);
    }

    size_t len_rel = strlen(rel_url);
    if (parse_uri(rel_url, len_rel, &rel) != HTTP_SUCCESS)
        return NULL;
    if (rel.type == (enum uriType)ABSOLUTE)
        return strdup(rel_url);

    size_t len_base = strlen(base_url);
    if ((parse_uri(base_url, len_base, &base) != HTTP_SUCCESS)
            || (base.type != (enum uriType)ABSOLUTE))
        return NULL;
    if (len_rel == (size_t)0)
        return strdup(base_url);

    size_t len = len_base + len_rel + (size_t)2;
    char *out = (char *)malloc(len);
    if (out == NULL)
        return NULL;
    memset(out, 0, len);
    char *out_finger = out;

    /* scheme */
    rv = snprintf(out_finger, len, "%.*s:", (int)base.scheme.size, base.scheme.buff);
    if (rv < 0 || rv >= len)
        goto error;
    out_finger += rv;
    len -= rv;

    /* authority */
    if (rel.hostport.text.size > (size_t)0) {
        rv = snprintf(out_finger, len, "%s", rel_url);
        if (rv < 0 || rv >= len)
            goto error;
        return out;
    }
    if (base.hostport.text.size > (size_t)0) {
	rv = snprintf(out_finger, len, "//%.*s", (int)base.hostport.text.size, base.hostport.text.buff);
	if (rv < 0 || rv >= len)
	    goto error;
	out_finger += rv;
	len -= rv;
    }

    /* path */
    char *path = out_finger;
    if (rel.path_type == (enum pathType)ABS_PATH) {
	rv = snprintf(out_finger, len, "%s", rel_url);
    } else if (base.pathquery.size == (size_t)0) {
	rv = snprintf(out_finger, len, "/%s", rel_url);
    } else {
	if (rel.pathquery.size == (size_t)0) {
	    rv = snprintf(out_finger, len, "%.*s", (int)base.pathquery.size, base.pathquery.buff);
	} else {
	    if (len < base.pathquery.size)
		goto error;
	    size_t i = (size_t)0, prefix = (size_t)1;
	    while (i < base.pathquery.size) {
		out_finger[i] = base.pathquery.buff[i];
		switch (base.pathquery.buff[i++]) {
		    case '/':
			prefix = i;
			/* fall-through */
		    default:
			continue;
		    case '?': /* query */
			if (rel.pathquery.buff[0] == '?')
			    prefix = --i;
		}
		break;
	    }
	    out_finger += prefix;
	    len -= prefix;
	    rv = snprintf(out_finger, len, "%.*s", (int)rel.pathquery.size, rel.pathquery.buff);
	}
	if (rv < 0 || rv >= len)
	    goto error;
	out_finger += rv;
	len -= rv;

	/* fragment */
	if (rel.fragment.size > (size_t)0)
	    rv = snprintf(out_finger, len, "#%.*s", (int)rel.fragment.size, rel.fragment.buff);
	else if (base.fragment.size > (size_t)0)
	    rv = snprintf(out_finger, len, "#%.*s", (int)base.fragment.size, base.fragment.buff);
	else
	    rv = 0;
    }
    if (rv < 0 || rv >= len)
	goto error;
    out_finger += rv;
    len -= rv;

    if (remove_dots(path, out_finger - path) != UPNP_E_SUCCESS)
	goto error;

    return out;

error:
    free(out);
    return NULL;
}
예제 #4
0
void
main (int argc, char **argv)
{
  puts (remove_dots ("/w/kpathsea"));
  puts (remove_dots ("/w//kpathsea"));
  puts (remove_dots ("/w/./kpathsea"));
  puts (remove_dots ("."));
  puts (remove_dots ("./"));
  puts (remove_dots ("./."));
  puts (remove_dots ("../kpathsea"));
  puts (remove_dots ("/kpathsea/../foo"));
  puts (remove_dots ("/../w/kpathsea"));
  puts (remove_dots ("/../w/kpathsea/."));
  puts (remove_dots ("/te/share/texmf/../../../../bin/gnu"));
}
예제 #5
0
static string
selfdir P1C(const_string, argv0)
{
  string ret = NULL;
  string self = NULL;
  
  if (kpse_absolute_p (argv0, true)) {
    self = xstrdup (argv0);
  } else {
#ifdef AMIGA
#include <dos.h>
#include <proto/dos.h>
#include <proto/exec.h>
    BPTR lock;
    struct DosLibrary *DOSBase
      = (struct DosLibrary *) OpenLibrary ("dos.library", 0L);
    assert (DOSBase);

    self = xmalloc (BUFSIZ);
    lock = findpath (argv0);
    if (lock != ((BPTR) -1)) {
      if (getpath (lock, self) == -1) {
        *self = '\0';
      } else {
        strcat (self,DIR_SEP_STRING);
        strcat (self,argv0); 
      }
      UnLock (lock);
    }
    CloseLibrary((struct Library *) DOSBase);
#else /* not AMIGA */
    string elt;
    struct stat s;

    /* Have to check PATH.  But don't call kpse_path_search since we don't
       want to search any ls-R's or do anything special with //'s.  */
    for (elt = kpse_path_element (getenv ("PATH")); !self && elt;
         elt = kpse_path_element (NULL)) {
      string name;
      
      /* UNIX tradition interprets the empty path element as "." */
      if (*elt == 0) elt = ".";
      
      name = concat3 (elt, DIR_SEP_STRING, argv0);

      /* In order to do this perfectly, we'd have to check the owner bits only
         if we are the file owner, and the group bits only if we belong
         to the file group.  That's a lot of work, though, and it's not
         likely that kpathsea will ever be used with a program that's
         only executable by some classes and not others.  See the
         `file_status' function in execute_cmd.c in bash for what's
         necessary if we were to do it right.  */
      if (stat (name, &s) == 0 && s.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) {
        /* Do not stop at directories. */
        if (!S_ISDIR(s.st_mode)) 
          self = name;
      }
    }
#endif /* not AMIGA */
  }
  
  /* If argv0 is somehow dir/exename, `self' will still be NULL.  */
  if (!self)
    self = concat3 (".", DIR_SEP_STRING, argv0);
    
  ret = xdirname (remove_dots (expand_symlinks (self)));

  free (self);
  
  return ret;
}
예제 #6
0
/************************************************************************
*	Function :	resolve_rel_url
*
*	Parameters :
*		char * base_url ;	Base URL
*		char * rel_url ;	Relative URL
*
*	Description : resolves a relative url with a base url returning a NEW 
*		(dynamically allocated with malloc) full url. If the base_url is 
*		NULL, then a copy of the  rel_url is passed back if the rel_url 
*		is absolute then a copy of the rel_url is passed back if neither 
*		the base nor the rel_url are Absolute then NULL is returned.
*		otherwise it tries and resolves the relative url with the base 
*		as described in: http://www.ietf.org/rfc/rfc2396.txt (RFCs 
*		explaining URIs) 
*       : resolution of '..' is NOT implemented, but '.' is resolved 
*
*	Return : char * ;
*
*	Note :
************************************************************************/
char *
resolve_rel_url( char *base_url,
                 char *rel_url )
{
    uri_type base;
    uri_type rel;
    char temp_path = '/';

    int i = 0;
    char *finger = NULL;

    char *last_slash = NULL;

    char *out = NULL;
    char *out_finger = NULL;

    if( base_url && rel_url ) {
        out =
            ( char * )malloc( strlen( base_url ) + strlen( rel_url ) + 2 );
        out_finger = out;
    } else {
        if( rel_url )
            return strdup( rel_url );
        else
            return NULL;
    }

    if( out == NULL ) {
        return NULL;
    }

    if( ( parse_uri( rel_url, strlen( rel_url ), &rel ) ) == HTTP_SUCCESS ) {

        if( rel.type == ABSOLUTE ) {

            strcpy( out, rel_url );
        } else {

            if( ( parse_uri( base_url, strlen( base_url ), &base ) ==
                  HTTP_SUCCESS )
                && ( base.type == ABSOLUTE ) ) {

                if( strlen( rel_url ) == 0 ) {
                    strcpy( out, base_url );
                } else {
                    memcpy( out, base.scheme.buff, base.scheme.size );
                    out_finger += base.scheme.size;
                    ( *out_finger ) = ':';
                    out_finger++;

                    if( rel.hostport.text.size > 0 ) {
                        sprintf( out_finger, "%s", rel_url );
                    } else {
                        if( base.hostport.text.size > 0 ) {
                            memcpy( out_finger, "//", 2 );
                            out_finger += 2;
                            memcpy( out_finger, base.hostport.text.buff,
                                    base.hostport.text.size );
                            out_finger += base.hostport.text.size;
                        }

                        if( rel.path_type == ABS_PATH ) {
                            strcpy( out_finger, rel_url );

                        } else {

                            if( base.pathquery.size == 0 ) {
                                base.pathquery.size = 1;
                                base.pathquery.buff = &temp_path;
                            }

                            finger = out_finger;
                            last_slash = finger;
                            i = 0;

                            while( ( i < base.pathquery.size ) &&
                                   ( base.pathquery.buff[i] != '?' ) ) {
                                ( *finger ) = base.pathquery.buff[i];
                                if( base.pathquery.buff[i] == '/' )
                                    last_slash = finger + 1;
                                i++;
                                finger++;

                            }
                            i = 0;
                            strcpy( last_slash, rel_url );
                            if( remove_dots( out_finger,
                                             strlen( out_finger ) ) !=
                                UPNP_E_SUCCESS ) {
                                free( out );
                                //free(rel_url);
                                return NULL;
                            }
                        }

                    }
                }
            } else {
                free( out );
                //free(rel_url);
                return NULL;
            }
        }
    } else {
        free( out );
        //free(rel_url);            
        return NULL;
    }

    //free(rel_url);
    return out;
}
예제 #7
0
int
main (int argc, char **argv)
{
  kpathsea kpse = xcalloc(1, sizeof(kpathsea_instance));
  kpathsea_set_program_name(kpse, argv[0], NULL);
  puts (remove_dots (kpse,"/w/kpathsea"));
  puts (remove_dots (kpse,"/w//kpathsea"));
  puts (remove_dots (kpse,"/w/./kpathsea"));
  puts (remove_dots (kpse,"."));
  puts (remove_dots (kpse,"./"));
  puts (remove_dots (kpse,"./."));
  puts (remove_dots (kpse,"../kpathsea"));
  puts (remove_dots (kpse,"/kpathsea/../foo"));
  puts (remove_dots (kpse,"/../w/kpathsea"));
  puts (remove_dots (kpse,"/../w/kpathsea/."));
  puts (remove_dots (kpse,"/te/share/texmf/../../../../bin/gnu"));
}