static int mva_translate(request_rec *r) { mva_sconf_t *conf; const char *name, *map, *uri; mva_mode_e mode; const char *cgi; conf = (mva_sconf_t *) ap_get_module_config(r->server->module_config, &vhost_bytemark_module); cgi = NULL; if (conf->cgi_root) { cgi = strstr(r->uri, "cgi-bin/"); if (cgi && (cgi != r->uri + strspn(r->uri, "/"))) { cgi = NULL; } } if (cgi) { mode = conf->cgi_root_mode; map = conf->cgi_root; uri = cgi + strlen("cgi-bin"); } else if (r->uri[0] == '/') { mode = conf->doc_root_mode; map = conf->doc_root; uri = r->uri; } else { return DECLINED; } if (mode == VHOST_ALIAS_NAME) { name = ap_get_server_name(r); } else if (mode == VHOST_ALIAS_IP) { name = r->connection->local_ip; } else { return DECLINED; } /* ### There is an optimization available here to determine the * absolute portion of the path from the server config phase, * through the first % segment, and note that portion of the path * canonical_path buffer. */ r->canonical_filename = ""; vhost_alias_interpolate(r, conf, name, map, uri); if (cgi) { /* see is_scriptaliased() in mod_cgi */ r->handler = "cgi-script"; apr_table_setn(r->notes, "alias-forced-type", r->handler); ap_set_context_info(r, "/cgi-bin", NULL); } return OK; }
static int translate_userdir(request_rec *r) { ap_conf_vector_t *server_conf; const userdir_config *s_cfg; const char *userdirs; const char *user, *dname; char *redirect; apr_finfo_t statbuf; /* * If the URI doesn't match our basic pattern, we've nothing to do with * it. */ if (r->uri[0] != '/' || r->uri[1] != '~') { return DECLINED; } server_conf = r->server->module_config; s_cfg = ap_get_module_config(server_conf, &userdir_module); userdirs = s_cfg->userdir; if (userdirs == NULL) { return DECLINED; } dname = r->uri + 2; user = ap_getword(r->pool, &dname, '/'); /* * The 'dname' funny business involves backing it up to capture the '/' * delimiting the "/~user" part from the rest of the URL, in case there * was one (the case where there wasn't being just "GET /~user HTTP/1.0", * for which we don't want to tack on a '/' onto the filename). */ if (dname[-1] == '/') { --dname; } /* * If there's no username, it's not for us. Ignore . and .. as well. */ if (user[0] == '\0' || (user[1] == '.' && (user[2] == '\0' || (user[2] == '.' && user[3] == '\0')))) { return DECLINED; } /* * Nor if there's an username but it's in the disabled list. */ if (apr_table_get(s_cfg->disabled_users, user) != NULL) { return DECLINED; } /* * If there's a global interdiction on UserDirs, check to see if this * name is one of the Blessed. */ if (s_cfg->globally_disabled == O_DISABLE && apr_table_get(s_cfg->enabled_users, user) == NULL) { return DECLINED; } /* * Special cases all checked, onward to normal substitution processing. */ while (*userdirs) { const char *userdir = ap_getword_conf(r->pool, &userdirs); char *filename = NULL, *prefix = NULL; apr_status_t rv; int is_absolute = ap_os_is_path_absolute(r->pool, userdir); if (ap_strchr_c(userdir, '*')) prefix = ap_getword(r->pool, &userdir, '*'); if (userdir[0] == '\0' || is_absolute) { if (prefix) { #ifdef HAVE_DRIVE_LETTERS /* * Crummy hack. Need to figure out whether we have been * redirected to a URL or to a file on some drive. Since I * know of no protocols that are a single letter, ignore * a : as the first or second character, and assume a file * was specified */ if (strchr(prefix + 2, ':')) #else if (strchr(prefix, ':') && !is_absolute) #endif /* HAVE_DRIVE_LETTERS */ { redirect = apr_pstrcat(r->pool, prefix, user, userdir, dname, NULL); apr_table_setn(r->headers_out, "Location", redirect); return HTTP_MOVED_TEMPORARILY; } else filename = apr_pstrcat(r->pool, prefix, user, userdir, NULL); } else filename = apr_pstrcat(r->pool, userdir, "/", user, NULL); } else if (prefix && ap_strchr_c(prefix, ':')) { redirect = apr_pstrcat(r->pool, prefix, user, dname, NULL); apr_table_setn(r->headers_out, "Location", redirect); return HTTP_MOVED_TEMPORARILY; } else { #if APR_HAS_USER char *homedir; if (apr_uid_homepath_get(&homedir, user, r->pool) == APR_SUCCESS) { filename = apr_pstrcat(r->pool, homedir, "/", userdir, NULL); } #else return DECLINED; #endif } /* * Now see if it exists, or we're at the last entry. If we are at the * last entry, then use the filename generated (if there is one) * anyway, in the hope that some handler might handle it. This can be * used, for example, to run a CGI script for the user. */ if (filename && (!*userdirs || ((rv = apr_stat(&statbuf, filename, APR_FINFO_MIN, r->pool)) == APR_SUCCESS || rv == APR_INCOMPLETE))) { r->filename = apr_pstrcat(r->pool, filename, dname, NULL); ap_set_context_info(r, apr_pstrmemdup(r->pool, r->uri, dname - r->uri), filename); /* XXX: Does this walk us around FollowSymLink rules? * When statbuf contains info on r->filename we can save a syscall * by copying it to r->finfo */ if (*userdirs && dname[0] == 0) r->finfo = statbuf; /* For use in the get_suexec_identity phase */ apr_table_setn(r->notes, "mod_userdir_user", user); return OK; } } return DECLINED; }
static void vhost_alias_interpolate(request_rec *r, mva_sconf_t *conf, const char *name, const char *map, const char *uri) { /* 0..9 9..0 */ enum { MAXDOTS = 19 }; const char *dots[MAXDOTS+1]; int ndots; char buf[HUGE_STRING_LEN]; char *dest; const char *docroot; int N, M, Np, Mp, Nd, Md; const char *start, *end; const char *p; ndots = 0; dots[ndots++] = name-1; /* slightly naughty */ for (p = name; *p; ++p){ if (*p == '.' && ndots < MAXDOTS) { dots[ndots++] = p; } } dots[ndots] = p; r->filename = NULL; dest = buf; while (*map) { if (*map != '%') { /* normal characters */ vhost_alias_checkspace(r, buf, &dest, 1); *dest++ = *map++; continue; } /* we are in a format specifier */ ++map; /* %% -> % */ if (*map == '%') { ++map; vhost_alias_checkspace(r, buf, &dest, 1); *dest++ = '%'; continue; } /* port number */ if (*map == 'p') { ++map; /* no. of decimal digits in a short plus one */ vhost_alias_checkspace(r, buf, &dest, 7); dest += apr_snprintf(dest, 7, "%d", ap_get_server_port(r)); continue; } /* deal with %-N+.-M+ -- syntax is already checked */ M = 0; /* value */ Np = Mp = 0; /* is there a plus? */ Nd = Md = 0; /* is there a dash? */ if (*map == '-') ++map, Nd = 1; N = *map++ - '0'; if (*map == '+') ++map, Np = 1; if (*map == '.') { ++map; if (*map == '-') { ++map, Md = 1; } M = *map++ - '0'; if (*map == '+') { ++map, Mp = 1; } } /* note that N and M are one-based indices, not zero-based */ start = dots[0]+1; /* ptr to the first character */ end = dots[ndots]; /* ptr to the character after the last one */ if (N != 0) { if (N > ndots) { start = "_"; end = start+1; } else if (!Nd) { start = dots[N-1]+1; if (!Np) { end = dots[N]; } } else { if (!Np) { start = dots[ndots-N]+1; } end = dots[ndots-N+1]; } } if (M != 0) { if (M > end - start) { start = "_"; end = start+1; } else if (!Md) { start = start+M-1; if (!Mp) { end = start+1; } } else { if (!Mp) { start = end-M; } end = end-M+1; } } vhost_alias_checkspace(r, buf, &dest, end - start); for (p = start; p < end; ++p) { *dest++ = apr_tolower(*p); } } /* no double slashes */ if (dest - buf > 0 && dest[-1] == '/') { --dest; } *dest = '\0'; /* * A this point we either have a document root which points to something * on disk - or not. * * If the document root doesn't exist on disk we can *attempt* to remap * that to the real file. * * If this remapping fails we don't care as the result will be a 404, * and that would have happened anyway. * */ { struct stat buffer; /** * If we have: * * A document root * Which doesn't exist. * * Then: * * Attempt to fix. * */ if ( ( NULL != buf ) && ( stat( buf, &buffer ) < 0 ) ) { /** * Here we strip out the first part of the name * after the /srv prefix which will result in * a request being rewritten from (for example) * * /srv/test.example.com/public/htdocs * * to: * * /srv/example.com/public/htdocs * */ update_vhost_request( buf ); } } if (r->filename) docroot = apr_pstrcat(r->pool, r->filename, buf, NULL); else docroot = apr_pstrdup(r->pool, buf); r->filename = apr_pstrcat(r->pool, docroot, uri, NULL); ap_set_context_info(r, NULL, docroot); ap_set_document_root(r, docroot); }
static void vhost_alias_interpolate(request_rec *r, const char *name, const char *map, const char *uri) { /* 0..9 9..0 */ enum { MAXDOTS = 19 }; const char *dots[MAXDOTS+1]; int ndots; char buf[HUGE_STRING_LEN]; char *dest; const char *docroot; int N, M, Np, Mp, Nd, Md; const char *start, *end; const char *p; ndots = 0; dots[ndots++] = name-1; /* slightly naughty */ for (p = name; *p; ++p){ if (*p == '.' && ndots < MAXDOTS) { dots[ndots++] = p; } } dots[ndots] = p; r->filename = NULL; dest = buf; while (*map) { if (*map != '%') { /* normal characters */ vhost_alias_checkspace(r, buf, &dest, 1); *dest++ = *map++; continue; } /* we are in a format specifier */ ++map; /* %% -> % */ if (*map == '%') { ++map; vhost_alias_checkspace(r, buf, &dest, 1); *dest++ = '%'; continue; } /* port number */ if (*map == 'p') { ++map; /* no. of decimal digits in a short plus one */ vhost_alias_checkspace(r, buf, &dest, 7); dest += apr_snprintf(dest, 7, "%d", ap_get_server_port(r)); continue; } /* deal with %-N+.-M+ -- syntax is already checked */ M = 0; /* value */ Np = Mp = 0; /* is there a plus? */ Nd = Md = 0; /* is there a dash? */ if (*map == '-') ++map, Nd = 1; N = *map++ - '0'; if (*map == '+') ++map, Np = 1; if (*map == '.') { ++map; if (*map == '-') { ++map, Md = 1; } M = *map++ - '0'; if (*map == '+') { ++map, Mp = 1; } } /* note that N and M are one-based indices, not zero-based */ start = dots[0]+1; /* ptr to the first character */ end = dots[ndots]; /* ptr to the character after the last one */ if (N != 0) { if (N > ndots) { start = "_"; end = start+1; } else if (!Nd) { start = dots[N-1]+1; if (!Np) { end = dots[N]; } } else { if (!Np) { start = dots[ndots-N]+1; } end = dots[ndots-N+1]; } } if (M != 0) { if (M > end - start) { start = "_"; end = start+1; } else if (!Md) { start = start+M-1; if (!Mp) { end = start+1; } } else { if (!Mp) { start = end-M; } end = end-M+1; } } vhost_alias_checkspace(r, buf, &dest, end - start); for (p = start; p < end; ++p) { *dest++ = apr_tolower(*p); } } /* no double slashes */ if (dest - buf > 0 && dest[-1] == '/') { --dest; } *dest = '\0'; if (r->filename) docroot = apr_pstrcat(r->pool, r->filename, buf, NULL); else docroot = apr_pstrdup(r->pool, buf); r->filename = apr_pstrcat(r->pool, docroot, uri, NULL); ap_set_context_info(r, NULL, docroot); ap_set_document_root(r, docroot); }