--- ./http_config.c Thu Oct 16 06:13:06 1997 +++ ../src2/http_config.c Thu Oct 16 06:12:03 1997 @@ -574,6 +574,18 @@ return (*cmd->func) (parms, mconfig, w, w2, w3); + case TAKE2OR3: + + w = getword_conf (parms->pool, &args); + w2 = getword_conf (parms->pool, &args); + w3 = getword_conf (parms->pool, &args); + + if (*w == '\0' || *w2 == '\0' || *args != 0) + return pstrcat (parms->pool, cmd->name, " takes two or three arguments", + cmd->errmsg ? ", " : NULL, cmd->errmsg, NULL); + + return (*cmd->func) (parms, mconfig, w, w2, w3); + case ITERATE: while (*(w = getword_conf (parms->pool, &args)) != '\0') --- ./http_config.h Thu Oct 16 06:13:06 1997 +++ ../src2/http_config.h Thu Oct 16 06:12:03 1997 @@ -60,6 +60,7 @@ RAW_ARGS, /* cmd_func parses command line itself */ TAKE1, /* one argument only */ TAKE2, /* two arguments only */ + TAKE2OR3, /* two or three arguments */ ITERATE, /* one argument, occuring multiple times * (e.g., IndexIgnore) */ --- ./httpd.h Thu Oct 16 06:13:07 1997 +++ ../src2/httpd.h Thu Oct 16 06:12:04 1997 @@ -188,6 +188,7 @@ /* The default string lengths */ #define MAX_STRING_LEN HUGE_STRING_LEN #define HUGE_STRING_LEN 8192 +#define MAX_PATH_LEN 1024 /* The timeout for waiting for messages */ #define DEFAULT_TIMEOUT 300 @@ -269,6 +270,9 @@ #define SERVER_SUPPORT "http://www.apache.org/" #define DECLINED -1 /* Module declines to handle */ +#define PARTIAL -2 /* Module has done some work, there's more */ + /* to do -- used to indicate more modules */ + /* need to be called */ #define OK 0 /* Module has handled this stage. */ --- ./mod_alias.c Thu Oct 16 06:13:07 1997 +++ ../src2/mod_alias.c Thu Oct 16 06:12:04 1997 @@ -65,6 +65,7 @@ char *real; char *fake; char *handler; + char *user; int redir_status; /* 301, 302, 303, 410, etc */ } alias_entry; @@ -117,7 +118,7 @@ return a; } -const char *add_alias(cmd_parms *cmd, void *dummy, char *f, char *r) +const char *add_alias(cmd_parms *cmd, void *dummy, char *f, char *r, char *u) { server_rec *s = cmd->server; alias_server_conf *conf = @@ -126,7 +127,7 @@ /* XX r can NOT be relative to DocumentRoot here... compat bug. */ - new->fake = f; new->real = r; new->handler = cmd->info; + new->user = u; new->fake = f; new->real = r; new->handler = cmd->info; return NULL; } @@ -169,7 +170,7 @@ else new = push_array (serverconf->redirects); - new->fake = f; new->real = url; + new->user = ""; new->fake = f; new->real = url; new->redir_status = status; return NULL; } @@ -177,8 +178,8 @@ command_rec alias_cmds[] = { { "Alias", add_alias, NULL, RSRC_CONF, TAKE2, "a fakename and a realname"}, -{ "ScriptAlias", add_alias, "cgi-script", RSRC_CONF, TAKE2, - "a fakename and a realname"}, +{ "ScriptAlias", add_alias, "cgi-script", RSRC_CONF, TAKE2OR3, + "a fakename and a realname and an optional user id"}, { "Redirect", add_redirect, (void*)HTTP_MOVED_TEMPORARILY, OR_FILEINFO, TAKE23, "an optional status, then document to be redirected and destination URL" }, @@ -191,10 +192,14 @@ { NULL } }; -int alias_matches (char *uri, char *alias_fakename) +int alias_matches (char *uri, char *alias_fakename, char *wild) { char *end_fakename = alias_fakename + strlen (alias_fakename); char *aliasp = alias_fakename, *urip = uri; + char *wp = wild; + enum { normal, peruser } wild_type; + + wild_type = (uri[1] == '~' ? peruser : normal); while (aliasp < end_fakename) { if (*aliasp == '/') { @@ -206,6 +211,16 @@ while (*aliasp == '/') ++ aliasp; while (*urip == '/') ++ urip; } + else if (wild_type == normal && *aliasp == '*') { + aliasp++; + while (*urip != *aliasp && *urip) + *wp++ = *urip++; + } + else if (wild_type == peruser && *aliasp == '~' && *(aliasp+1) == '/') { + aliasp++; + while (*urip != *aliasp && *urip) + *wp++ = *urip++; + } else { /* Other characters are compared literally */ if (*urip++ != *aliasp++) return 0; @@ -222,6 +237,7 @@ * doubled slashes) */ + *wp = '\0'; return urip - uri; } @@ -229,12 +245,32 @@ { alias_entry *entries = (alias_entry *)aliases->elts; int i; + char wild[MAX_PATH_LEN]; for (i = 0; i < aliases->nelts; ++i) { alias_entry *p = &entries[i]; - int l = alias_matches (r->uri, p->fake); + int l = alias_matches (r->uri, p->fake, wild); if (l > 0) { + char *rp; + char real[MAX_PATH_LEN]; + char per_user_web = 0; + + strcpy(real,p->real); + if (rp = (char *)index(real,'*')) { + strcpy(rp, wild); + strcpy(rp+strlen(wild),p->real+(rp-real+1)); + } + if (real[1] == '~' && wild[0]) { + per_user_web = 1; + strcpy(real+1, wild); + strcpy(real+1+strlen(wild),p->real+2); + } + if (p->user[0]) { + struct stat finfo; + if(stat(real,&finfo) != -1 && + finfo.st_uid != uname2id(p->user)) continue; + } if (p->handler) { /* Set handler, and leave a note for mod_cgi */ r->handler = pstrdup(r->pool, p->handler); table_set (r->notes, "alias-forced-type", p->handler); @@ -246,9 +282,11 @@ char *escurl; escurl = os_escape_path(r->pool, r->uri + l, 1); - return pstrcat(r->pool, p->real, escurl, NULL); - } else - return pstrcat(r->pool, p->real, r->uri + l, NULL); + rp = pstrcat(r->pool, real, escurl, NULL); + } else + rp = pstrcat(r->pool, real, r->uri + l, NULL); + if (per_user_web) return PARTIAL; + return rp; } } @@ -283,6 +321,9 @@ } if ((ret = try_alias_list (r, serverconf->aliases, 0, &status)) != NULL) { + /* a little bit of a kludge, but it forces the + userdir module to get called */ + if (ret == PARTIAL) return DECLINED; r->filename = ret; return OK; }