Esempio n. 1
0
/* Mostly copied from callcgi. */
static void mkcgienv(struct hthead *req, struct charbuf *dst)
{
    int i;
    char *url, *pi, *tmp, *qp, *h, *p;
    
    bufaddenv(dst, "SERVER_SOFTWARE", "ashd/%s", VERSION);
    bufaddenv(dst, "GATEWAY_INTERFACE", "CGI/1.1");
    bufaddenv(dst, "SERVER_PROTOCOL", "%s", req->ver);
    bufaddenv(dst, "REQUEST_METHOD", "%s", req->method);
    bufaddenv(dst, "REQUEST_URI", "%s", req->url);
    url = sstrdup(req->url);
    if((qp = strchr(url, '?')) != NULL)
	*(qp++) = 0;
    /* XXX: This is an ugly hack (I think), but though I can think of
     * several alternatives, none seem to be better. */
    if(*req->rest && (strlen(url) >= strlen(req->rest)) &&
       !strcmp(req->rest, url + strlen(url) - strlen(req->rest))) {
	url[strlen(url) - strlen(req->rest)] = 0;
    }
    if((pi = unquoteurl(req->rest)) == NULL)
	pi = sstrdup(req->rest);
    if(!strcmp(url, "/")) {
	/* This seems to be normal CGI behavior, but see callcgi.c for
	 * details. */
	url[0] = 0;
	pi = sprintf2("/%s", tmp = pi);
	free(tmp);
    }
    bufaddenv(dst, "PATH_INFO", "%s", pi);
    bufaddenv(dst, "SCRIPT_NAME", "%s", url);
    bufaddenv(dst, "QUERY_STRING", "%s", qp?qp:"");
    free(pi);
    free(url);
    if((h = getheader(req, "Host")) != NULL)
	bufaddenv(dst, "SERVER_NAME", "%s", h);
    if((h = getheader(req, "X-Ash-Server-Address")) != NULL)
	bufaddenv(dst, "SERVER_ADDR", "%s", h);
    if((h = getheader(req, "X-Ash-Server-Port")) != NULL)
	bufaddenv(dst, "SERVER_PORT", "%s", h);
    if((h = getheader(req, "X-Ash-Remote-User")) != NULL)
	bufaddenv(dst, "REMOTE_USER", "%s", h);
    if(((h = getheader(req, "X-Ash-Protocol")) != NULL) && !strcmp(h, "https"))
	bufaddenv(dst, "HTTPS", "on");
    if((h = getheader(req, "X-Ash-Address")) != NULL)
	bufaddenv(dst, "REMOTE_ADDR", "%s", h);
    if((h = getheader(req, "X-Ash-Port")) != NULL)
	bufaddenv(dst, "REMOTE_PORT", "%s", h);
    if((h = getheader(req, "Content-Type")) != NULL)
	bufaddenv(dst, "CONTENT_TYPE", "%s", h);
    if((h = getheader(req, "Content-Length")) != NULL)
	bufaddenv(dst, "CONTENT_LENGTH", "%s", h);
    else
	bufaddenv(dst, "CONTENT_LENGTH", "0");
    if((h = getheader(req, "X-Ash-File")) != NULL) {
	h = absolutify(h);
	bufaddenv(dst, "SCRIPT_FILENAME", "%s", h);
	free(h);
    }
    for(i = 0; i < req->noheaders; i++) {
	h = sprintf2("HTTP_%s", req->headers[i][0]);
	for(p = h; *p; p++) {
	    if(isalnum(*p))
		*p = toupper(*p);
	    else
		*p = '_';
	}
	bufcatkv(dst, h, req->headers[i][1]);
	free(h);
    }
}
Esempio n. 2
0
static pid_t forkchild(int inpath, char **prog, char *file, char *method, char *url, char *rest, int *infd, int *outfd)
{
    char *qp, **env, *name;
    int inp[2], outp[2];
    pid_t pid;
    char *pi;
    int (*execfun)(const char *, char *const []);

    pipe(inp);
    pipe(outp);
    if((pid = fork()) < 0) {
	flog(LOG_ERR, "callcgi: could not fork");
	exit(1);
    }
    if(pid == 0) {
	dup2(inp[0], 0);
	dup2(outp[1], 1);
	close(inp[0]);
	close(inp[1]);
	close(outp[0]);
	close(outp[1]);
	if((qp = strchr(url, '?')) != NULL)
	    *(qp++) = 0;
	putenv(sprintf2("SERVER_SOFTWARE=ashd/%s", VERSION));
	putenv("GATEWAY_INTERFACE=CGI/1.1");
	if(getenv("HTTP_VERSION"))
	    putenv(sprintf2("SERVER_PROTOCOL=%s", getenv("HTTP_VERSION")));
	putenv(sprintf2("REQUEST_METHOD=%s", method));
	name = url;
	/* XXX: This is an ugly hack (I think), but though I can think
	 * of several alternatives, none seem to be better. */
	if(*rest && (strlen(url) >= strlen(rest)) &&
	   !strcmp(rest, url + strlen(url) - strlen(rest))) {
	    name = sprintf2("%.*s", (int)(strlen(url) - strlen(rest)), url);
	}
	if((pi = unquoteurl(rest)) == NULL)
	    pi = rest;
	if(!strcmp(name, "/")) {
	    /*
	     * Normal CGI behavior appears to be to always let
	     * PATH_INFO begin with a slash and never let SCRIPT_NAME
	     * end with one. That conflicts, however, with some
	     * behaviors, such as "mounting" CGI applications on a
	     * directory element of the URI space -- a handler
	     * responding to "/foo/" would not be able to tell that it
	     * is not called "/foo", which makes a large difference,
	     * not least in relation to URI reconstruction and
	     * redirections. A common practical case is CGI-handled
	     * index files in directories. Therefore, this only
	     * handles the nonconditional case of the root directory
	     * and leaves other decisions to the previous handler
	     * handing over the request to callcgi. It is unclear if
	     * there is a better way to handle the problem.
	     */
	    name[0] = 0;
	    pi = sprintf2("/%s", pi);
	}
	putenv(sprintf2("PATH_INFO=%s", pi));
	putenv(sprintf2("SCRIPT_NAME=%s", name));
	putenv(sprintf2("QUERY_STRING=%s", qp?qp:""));
	if(getenv("REQ_HOST"))
	    putenv(sprintf2("SERVER_NAME=%s", getenv("REQ_HOST")));
	if(getenv("REQ_X_ASH_SERVER_ADDRESS"))
	    putenv(sprintf2("SERVER_ADDR=%s", getenv("REQ_X_ASH_SERVER_ADDRESS")));
	if(getenv("REQ_X_ASH_SERVER_PORT"))
	    putenv(sprintf2("SERVER_PORT=%s", getenv("REQ_X_ASH_SERVER_PORT")));
	if(getenv("REQ_X_ASH_PROTOCOL") && !strcmp(getenv("REQ_X_ASH_PROTOCOL"), "https"))
	    putenv("HTTPS=on");
	if(getenv("REQ_X_ASH_ADDRESS"))
	    putenv(sprintf2("REMOTE_ADDR=%s", getenv("REQ_X_ASH_ADDRESS")));
	if(getenv("REQ_X_ASH_PORT"))
	    putenv(sprintf2("REMOTE_PORT=%s", getenv("REQ_X_ASH_PORT")));
	if(getenv("REQ_X_ASH_REMOTE_USER"))
	    putenv(sprintf2("REMOTE_USER=%s", getenv("REQ_X_ASH_REMOTE_USER")));
	if(getenv("REQ_CONTENT_TYPE"))
	    putenv(sprintf2("CONTENT_TYPE=%s", getenv("REQ_CONTENT_TYPE")));
	if(getenv("REQ_CONTENT_LENGTH"))
	    putenv(sprintf2("CONTENT_LENGTH=%s", getenv("REQ_CONTENT_LENGTH")));
	for(env = environ; *env; env++) {
	    if(!strncmp(*env, "REQ_", 4))
		putenv(sprintf2("HTTP_%s", (*env) + 4));
	}
	/*
	 * This is (understandably) missing from the CGI
	 * specification, but PHP seems to require it.
	 */
	execfun = inpath?execvp:execv;
	if(file != NULL)
	    putenv(sprintf2("SCRIPT_FILENAME=%s", absolutify(file)));
	execfun(prog[0], prog);
	exit(127);
    }
    close(inp[0]);
    close(outp[1]);
    *infd = inp[1];
    *outfd = outp[0];
    return(pid);
}
Esempio n. 3
0
Referen::Referen(Path path, Path context)
: absPath(absolutify(path, context)),
qualifiedName(qualify(absPath)) {
}