📄 mod_rewrite.c
字号:
} return 0;}/* * substitute the prefix path 'match' in 'input' with 'subst' (RewriteBase) */static char *subst_prefix_path(request_rec *r, char *input, char *match, const char *subst){ apr_size_t len = strlen(match); if (len && match[len - 1] == '/') { --len; } if (!strncmp(input, match, len) && input[len++] == '/') { apr_size_t slen, outlen; char *output; rewritelog((r, 5, NULL, "strip matching prefix: %s -> %s", input, input+len)); slen = strlen(subst); if (slen && subst[slen - 1] != '/') { ++slen; } outlen = strlen(input) + slen - len; output = apr_palloc(r->pool, outlen + 1); /* don't forget the \0 */ memcpy(output, subst, slen); if (slen && !output[slen-1]) { output[slen-1] = '/'; } memcpy(output+slen, input+len, outlen - slen); output[outlen] = '\0'; rewritelog((r, 4, NULL, "add subst prefix: %s -> %s", input+len, output)); return output; } /* prefix didn't match */ return input;}/* * +-------------------------------------------------------+ * | | * | caching support * | | * +-------------------------------------------------------+ */static void set_cache_value(const char *name, apr_time_t t, char *key, char *val){ cachedmap *map; if (cachep) {#if APR_HAS_THREADS apr_thread_mutex_lock(cachep->lock);#endif map = apr_hash_get(cachep->maps, name, APR_HASH_KEY_STRING); if (!map) { apr_pool_t *p; if (apr_pool_create(&p, cachep->pool) != APR_SUCCESS) {#if APR_HAS_THREADS apr_thread_mutex_unlock(cachep->lock);#endif return; } map = apr_palloc(cachep->pool, sizeof(cachedmap)); map->pool = p; map->entries = apr_hash_make(map->pool); map->mtime = t; apr_hash_set(cachep->maps, name, APR_HASH_KEY_STRING, map); } else if (map->mtime != t) { apr_pool_clear(map->pool); map->entries = apr_hash_make(map->pool); map->mtime = t; } /* Now we should have a valid map->entries hash, where we * can store our value. * * We need to copy the key and the value into OUR pool, * so that we don't leave it during the r->pool cleanup. */ apr_hash_set(map->entries, apr_pstrdup(map->pool, key), APR_HASH_KEY_STRING, apr_pstrdup(map->pool, val));#if APR_HAS_THREADS apr_thread_mutex_unlock(cachep->lock);#endif } return;}static char *get_cache_value(const char *name, apr_time_t t, char *key, apr_pool_t *p){ cachedmap *map; char *val = NULL; if (cachep) {#if APR_HAS_THREADS apr_thread_mutex_lock(cachep->lock);#endif map = apr_hash_get(cachep->maps, name, APR_HASH_KEY_STRING); if (map) { /* if this map is outdated, forget it. */ if (map->mtime != t) { apr_pool_clear(map->pool); map->entries = apr_hash_make(map->pool); map->mtime = t; } else { val = apr_hash_get(map->entries, key, APR_HASH_KEY_STRING); if (val) { /* copy the cached value into the supplied pool, * where it belongs (r->pool usually) */ val = apr_pstrdup(p, val); } } }#if APR_HAS_THREADS apr_thread_mutex_unlock(cachep->lock);#endif } return val;}static int init_cache(apr_pool_t *p){ cachep = apr_palloc(p, sizeof(cache)); if (apr_pool_create(&cachep->pool, p) != APR_SUCCESS) { cachep = NULL; /* turns off cache */ return 0; } cachep->maps = apr_hash_make(cachep->pool);#if APR_HAS_THREADS (void)apr_thread_mutex_create(&(cachep->lock), APR_THREAD_MUTEX_DEFAULT, p);#endif return 1;}/* * +-------------------------------------------------------+ * | | * | Map Functions * | | * +-------------------------------------------------------+ *//* * General Note: key is already a fresh string, created (expanded) just * for the purpose to be passed in here. So one can modify key itself. */static char *rewrite_mapfunc_toupper(request_rec *r, char *key){ char *p; for (p = key; *p; ++p) { *p = apr_toupper(*p); } return key;}static char *rewrite_mapfunc_tolower(request_rec *r, char *key){ ap_str_tolower(key); return key;}static char *rewrite_mapfunc_escape(request_rec *r, char *key){ return ap_escape_uri(r->pool, key);}static char *rewrite_mapfunc_unescape(request_rec *r, char *key){ ap_unescape_url(key); return key;}static char *select_random_value_part(request_rec *r, char *value){ char *p = value; unsigned n = 1; /* count number of distinct values */ while ((p = ap_strchr(p, '|')) != NULL) { ++n; ++p; } if (n > 1) { /* initialize random generator * * XXX: Probably this should be wrapped into a thread mutex, * shouldn't it? Is it worth the effort? */ if (!rewrite_rand_init_done) { srand((unsigned)(getpid())); rewrite_rand_init_done = 1; } /* select a random subvalue */ n = (int)(((double)(rand() % RAND_MAX) / RAND_MAX) * n + 1); /* extract it from the whole string */ while (--n && (value = ap_strchr(value, '|')) != NULL) { ++value; } if (value) { /* should not be NULL, but ... */ p = ap_strchr(value, '|'); if (p) { *p = '\0'; } } } return value;}/* child process code */static void rewrite_child_errfn(apr_pool_t *p, apr_status_t err, const char *desc){ ap_log_error(APLOG_MARK, APLOG_ERR, err, NULL, "%s", desc);}static apr_status_t rewritemap_program_child(apr_pool_t *p, const char *progname, char **argv, apr_file_t **fpout, apr_file_t **fpin){ apr_status_t rc; apr_procattr_t *procattr; apr_proc_t *procnew; if ( APR_SUCCESS == (rc=apr_procattr_create(&procattr, p)) && APR_SUCCESS == (rc=apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_FULL_BLOCK, APR_NO_PIPE)) && APR_SUCCESS == (rc=apr_procattr_dir_set(procattr, ap_make_dirstr_parent(p, argv[0]))) && APR_SUCCESS == (rc=apr_procattr_cmdtype_set(procattr, APR_PROGRAM)) && APR_SUCCESS == (rc=apr_procattr_child_errfn_set(procattr, rewrite_child_errfn)) && APR_SUCCESS == (rc=apr_procattr_error_check_set(procattr, 1))) { procnew = apr_pcalloc(p, sizeof(*procnew)); rc = apr_proc_create(procnew, argv[0], (const char **)argv, NULL, procattr, p); if (rc == APR_SUCCESS) { apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT); if (fpin) { (*fpin) = procnew->in; } if (fpout) { (*fpout) = procnew->out; } } } return (rc);}static apr_status_t run_rewritemap_programs(server_rec *s, apr_pool_t *p){ rewrite_server_conf *conf; apr_hash_index_t *hi; apr_status_t rc; int lock_warning_issued = 0; conf = ap_get_module_config(s->module_config, &rewrite_module); /* If the engine isn't turned on, * don't even try to do anything. */ if (conf->state == ENGINE_DISABLED) { return APR_SUCCESS; } for (hi = apr_hash_first(p, conf->rewritemaps); hi; hi = apr_hash_next(hi)){ apr_file_t *fpin = NULL; apr_file_t *fpout = NULL; rewritemap_entry *map; void *val; apr_hash_this(hi, NULL, NULL, &val); map = val; if (map->type != MAPTYPE_PRG) { continue; } if (!(map->argv[0]) || !*(map->argv[0]) || map->fpin || map->fpout) { continue; } if (!lock_warning_issued && (!lockname || !*lockname)) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, "mod_rewrite: Running external rewrite maps " "without defining a RewriteLock is DANGEROUS!"); ++lock_warning_issued; } rc = rewritemap_program_child(p, map->argv[0], map->argv, &fpout, &fpin); if (rc != APR_SUCCESS || fpin == NULL || fpout == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, rc, s, "mod_rewrite: could not start RewriteMap " "program %s", map->checkfile); return rc; } map->fpin = fpin; map->fpout = fpout; } return APR_SUCCESS;}/* * +-------------------------------------------------------+ * | | * | Lookup functions * | | * +-------------------------------------------------------+ */static char *lookup_map_txtfile(request_rec *r, const char *file, char *key){ apr_file_t *fp = NULL; char line[REWRITE_MAX_TXT_MAP_LINE + 1]; /* +1 for \0 */ char *value, *keylast; if (apr_file_open(&fp, file, APR_READ|APR_BUFFERED, APR_OS_DEFAULT, r->pool) != APR_SUCCESS) { return NULL; } keylast = key + strlen(key); value = NULL; while (apr_file_gets(line, sizeof(line), fp) == APR_SUCCESS) { char *p, *c; /* ignore comments and lines starting with whitespaces */ if (*line == '#' || apr_isspace(*line)) { continue; } p = line; c = key; while (c < keylast && *p == *c && !apr_isspace(*p)) { ++p; ++c; } /* key doesn't match - ignore. */ if (c != keylast || !apr_isspace(*p)) { continue; } /* jump to the value */ while (*p && apr_isspace(*p)) { ++p; } /* no value? ignore */ if (!*p) { continue; } /* extract the value and return. */ c = p; while (*p && !apr_isspace(*p)) { ++p; } value = apr_pstrmemdup(r->pool, c, p - c); break; } apr_file_close(fp); return value;}static char *lookup_map_dbmfile(request_rec *r, const char *file, const char *dbmtype, char *key){ apr_dbm_t *dbmfp = NULL; apr_datum_t dbmkey; apr_datum_t dbmval; char *value; if (apr_dbm_open_ex(&dbmfp, dbmtype, file, APR_DBM_READONLY, APR_OS_DEFAULT, r->pool) != APR_SUCCESS) { return NULL; } dbmkey.dptr = key; dbmkey.dsize = strlen(key); if (apr_dbm_fetch(dbmfp, dbmkey, &dbmval) == APR_SUCCESS && dbmval.dptr) { value = apr_pstrmemdup(r->pool, dbmval.dptr, dbmval.dsize); } else { value = NULL; } apr_dbm_close(dbmfp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -