static void copy_request(char *rbuf, apr_size_t rbuflen, request_rec *r) { char *p; if (r->the_request == NULL) { apr_cpystrn(rbuf, "NULL", rbuflen); return; /* short circuit below */ } if (r->parsed_uri.password == NULL) { p = r->the_request; } else { /* Don't reveal the password in the server-status view */ p = apr_pstrcat(r->pool, r->method, " ", apr_uri_unparse(r->pool, &r->parsed_uri, APR_URI_UNP_OMITPASSWORD), r->assbackwards ? NULL : " ", r->protocol, NULL); } /* now figure out if we copy over the 1st rbuflen chars or the last */ if (!ap_mod_status_reqtail) { apr_cpystrn(rbuf, p, rbuflen); } else { apr_size_t slen = strlen(p); if (slen < rbuflen) { /* it all fits anyway */ apr_cpystrn(rbuf, p, rbuflen); } else { apr_cpystrn(rbuf, p+(slen-rbuflen+1), rbuflen); } } }
apr_status_t h2_request_rwrite(h2_request *req, request_rec *r) { apr_status_t status; req->config = h2_config_rget(r); req->method = r->method; req->scheme = (r->parsed_uri.scheme? r->parsed_uri.scheme : ap_http_scheme(r)); req->authority = r->hostname; req->path = apr_uri_unparse(r->pool, &r->parsed_uri, APR_URI_UNP_OMITSITEPART); if (!ap_strchr_c(req->authority, ':') && r->server && r->server->port) { apr_port_t defport = apr_uri_port_of_scheme(req->scheme); if (defport != r->server->port) { /* port info missing and port is not default for scheme: append */ req->authority = apr_psprintf(r->pool, "%s:%d", req->authority, (int)r->server->port); } } AP_DEBUG_ASSERT(req->scheme); AP_DEBUG_ASSERT(req->authority); AP_DEBUG_ASSERT(req->path); AP_DEBUG_ASSERT(req->method); status = add_all_h1_header(req, r->pool, r->headers_in); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r, "h2_request(%d): rwrite %s host=%s://%s%s", req->id, req->method, req->scheme, req->authority, req->path); return status; }
static int test_aup(apr_pool_t *p) { int i; apr_status_t rv; apr_uri_t info; struct aup_test *t; const char *failed; int rc = 0; for (i = 0; i < sizeof(aup_tests) / sizeof(aup_tests[0]); i++) { memset(&info, 0, sizeof(info)); t = &aup_tests[i]; rv = apr_uri_parse(p, t->uri, &info); failed = (rv != t->rv) ? "bad rc" : NULL; if (!failed && t->rv == APR_SUCCESS) { if (!same_str(info.scheme, t->scheme)) failed = "bad scheme"; if (!same_str(info.hostinfo, t->hostinfo)) failed = "bad hostinfo"; if (!same_str(info.user, t->user)) failed = "bad user"; if (!same_str(info.password, t->password)) failed = "bad password"; if (!same_str(info.hostname, t->hostname)) failed = "bad hostname"; if (!same_str(info.port_str, t->port_str)) failed = "bad port_str"; if (!same_str(info.path, t->path)) failed = "bad path"; if (!same_str(info.query, t->query)) failed = "bad query"; if (!same_str(info.fragment, t->fragment)) failed = "bad fragment"; if (info.port != t->port) failed = "bad port"; } if (failed) { ++rc; fprintf(stderr, "failure for testcase %d/uri %s: %s\n", i, t->uri, failed); show_info(rv, t->rv, &info); } else if (t->rv == APR_SUCCESS) { const char *s = apr_uri_unparse(p, &info, APR_URI_UNP_REVEALPASSWORD); if (strcmp(s, t->uri)) { fprintf(stderr, "apr_uri_unparsed failed for testcase %d\n", i); fprintf(stderr, " got %s, expected %s\n", s, t->uri); } } } return rc; }
static const char *log_request_line(request_rec *r, char *a) { /* NOTE: If the original request contained a password, we * re-write the request line here to contain XXXXXX instead: * (note the truncation before the protocol string for HTTP/0.9 requests) * (note also that r->the_request contains the unmodified request) */ return ap_escape_logitem(r->pool, (r->parsed_uri.password) ? apr_pstrcat(r->pool, r->method, " ", apr_uri_unparse(r->pool, &r->parsed_uri, 0), r->assbackwards ? NULL : " ", r->protocol, NULL) : r->the_request); }
static char * add_auth_token(apr_pool_t *pool, saxctxt *ctx, apr_uri_t *u) { apr_uri_t u2 = *u; const char *unparsed_uri, *auth_token, *ip; char *timestamp, *forwarded_list, *last; apr_status_t rv; apr_time_exp_t xt; apr_size_t sz; apr_table_t *params; unparsed_uri = apr_uri_unparse(pool, &u2, APR_URI_UNP_OMITQUERY); rv = apr_time_exp_lt(&xt, apr_time_now() + apr_time_from_sec(ctx->cfg->auth_exptime)); timestamp = apr_palloc(pool, TIME_STR_SIZE + 1); rv = apr_strftime(timestamp, &sz, TIME_STR_SIZE, "%FT%T%z", &xt); if (u2.query) u2.query = apr_pstrcat(pool, u2.query, "&vox_timestamp=", timestamp, NULL); else u2.query = apr_pstrcat(pool, "vox_timestamp=", timestamp, NULL); /* Convert the query string to a table */ params = apr_table_make(pool, 1); qs_to_table(u2.query, params, pool); /* Generate the auth token */ forwarded_list = (char *)apr_table_get(ctx->f->r->headers_in, "X-Forwarded-For"); /* If X-Forwarded-For header exists, use first IP in it */ if (forwarded_list && (forwarded_list = apr_pstrdup(pool, forwarded_list)) && (ip = apr_strtok(forwarded_list, ", \t", &last))) auth_token = make_auth_token(ctx->f->r, ip, unparsed_uri, params, ctx->cfg->auth_key); else /* Otherwise, use the normal remote_ip */ auth_token = make_auth_token(ctx->f->r, ctx->f->r->connection->remote_ip, unparsed_uri, params, ctx->cfg->auth_key); if (auth_token) { u2.query = apr_pstrcat(pool, u2.query, "&vox_sig=", auth_token, NULL); ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ctx->f->r->server, "add_auth_token: new query string is %s", u2.query); } return u2.query; }
/* This implements serf_bucket_headers_do_callback_fn_t. */ static int capabilities_headers_iterator_callback(void *baton, const char *key, const char *val) { options_context_t *opt_ctx = baton; svn_ra_serf__session_t *session = opt_ctx->session; if (svn_cstring_casecmp(key, "dav") == 0) { /* Each header may contain multiple values, separated by commas, e.g.: DAV: version-control,checkout,working-resource DAV: merge,baseline,activity,version-controlled-collection DAV: http://subversion.tigris.org/xmlns/dav/svn/depth */ apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE, opt_ctx->pool); opt_ctx->received_dav_header = TRUE; /* Right now we only have a few capabilities to detect, so just seek for them directly. This could be written slightly more efficiently, but that wouldn't be worth it until we have many more capabilities. */ if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals)) { svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_DEPTH, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals)) { /* The server doesn't know what repository we're referring to, so it can't just say capability_yes. */ if (!svn_hash_gets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO)) { svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO, capability_server_yes); } } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals)) { svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals)) { svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals)) { svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INHERITED_PROPS, vals)) { svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_INHERITED_PROPS, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS, vals)) { svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS, vals)) { svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INLINE_PROPS, vals)) { session->supports_inline_props = TRUE; } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_REPLAY_REV_RESOURCE, vals)) { session->supports_rev_rsrc_replay = TRUE; } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF1, vals)) { /* Use compressed svndiff1 format for servers that properly advertise this capability (Subversion 1.10 and greater). */ session->supports_svndiff1 = TRUE; } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LIST, vals)) { svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_LIST, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF2, vals)) { /* Same for svndiff2. */ session->supports_svndiff2 = TRUE; } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PUT_RESULT_CHECKSUM, vals)) { session->supports_put_result_checksum = TRUE; } } /* SVN-specific headers -- if present, server supports HTTP protocol v2 */ else if (!svn_ctype_casecmp(key[0], 'S') && !svn_ctype_casecmp(key[1], 'V') && !svn_ctype_casecmp(key[2], 'N')) { /* If we've not yet seen any information about supported POST requests, we'll initialize the list/hash with "create-txn" (which we know is supported by virtue of the server speaking HTTPv2 at all. */ if (! session->supported_posts) { session->supported_posts = apr_hash_make(session->pool); apr_hash_set(session->supported_posts, "create-txn", 10, (void *)1); } if (svn_cstring_casecmp(key, SVN_DAV_ROOT_URI_HEADER) == 0) { session->repos_root = session->session_url; session->repos_root.path = (char *)svn_fspath__canonicalize(val, session->pool); session->repos_root_str = svn_urlpath__canonicalize( apr_uri_unparse(session->pool, &session->repos_root, 0), session->pool); } else if (svn_cstring_casecmp(key, SVN_DAV_ME_RESOURCE_HEADER) == 0) { #ifdef SVN_DEBUG char *ignore_v2_env_var = getenv(SVN_IGNORE_V2_ENV_VAR); if (!(ignore_v2_env_var && apr_strnatcasecmp(ignore_v2_env_var, "yes") == 0)) session->me_resource = apr_pstrdup(session->pool, val); #else session->me_resource = apr_pstrdup(session->pool, val); #endif } else if (svn_cstring_casecmp(key, SVN_DAV_REV_STUB_HEADER) == 0) { session->rev_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_REV_ROOT_STUB_HEADER) == 0) { session->rev_root_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_TXN_STUB_HEADER) == 0) { session->txn_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_TXN_ROOT_STUB_HEADER) == 0) { session->txn_root_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_STUB_HEADER) == 0) { session->vtxn_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_ROOT_STUB_HEADER) == 0) { session->vtxn_root_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_REPOS_UUID_HEADER) == 0) { session->uuid = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_YOUNGEST_REV_HEADER) == 0) { opt_ctx->youngest_rev = SVN_STR_TO_REV(val); } else if (svn_cstring_casecmp(key, SVN_DAV_ALLOW_BULK_UPDATES) == 0) { session->server_allows_bulk = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_SUPPORTED_POSTS_HEADER) == 0) { /* May contain multiple values, separated by commas. */ int i; apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE, session->pool); for (i = 0; i < vals->nelts; i++) { const char *post_val = APR_ARRAY_IDX(vals, i, const char *); svn_hash_sets(session->supported_posts, post_val, (void *)1); } } else if (svn_cstring_casecmp(key, SVN_DAV_REPOSITORY_MERGEINFO) == 0)
svn_error_t *svn_ra_open4(svn_ra_session_t **session_p, const char **corrected_url_p, const char *repos_URL, const char *uuid, const svn_ra_callbacks2_t *callbacks, void *callback_baton, apr_hash_t *config, apr_pool_t *pool) { apr_pool_t *sesspool = svn_pool_create(pool); svn_ra_session_t *session; const struct ra_lib_defn *defn; const svn_ra__vtable_t *vtable = NULL; svn_config_t *servers = NULL; const char *server_group; apr_uri_t repos_URI; apr_status_t apr_err; #ifdef CHOOSABLE_DAV_MODULE const char *http_library = DEFAULT_HTTP_LIBRARY; #endif /* Auth caching parameters. */ svn_boolean_t store_passwords = SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS; svn_boolean_t store_auth_creds = SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS; const char *store_plaintext_passwords = SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS; svn_boolean_t store_pp = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP; const char *store_pp_plaintext = SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT; const char *corrected_url; /* Initialize the return variable. */ *session_p = NULL; apr_err = apr_uri_parse(sesspool, repos_URL, &repos_URI); /* ### Should apr_uri_parse leave hostname NULL? It doesn't * for "file:///" URLs, only for bogus URLs like "bogus". * If this is the right behavior for apr_uri_parse, maybe we * should have a svn_uri_parse wrapper. */ if (apr_err != APR_SUCCESS || repos_URI.hostname == NULL) return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, _("Illegal repository URL '%s'"), repos_URL); if (callbacks->auth_baton) { /* The 'store-passwords' and 'store-auth-creds' parameters used to * live in SVN_CONFIG_CATEGORY_CONFIG. For backward compatibility, * if values for these parameters have already been set by our * callers, we use those values as defaults. * * Note that we can only catch the case where users explicitly set * "store-passwords = no" or 'store-auth-creds = no". * * However, since the default value for both these options is * currently (and has always been) "yes", users won't know * the difference if they set "store-passwords = yes" or * "store-auth-creds = yes" -- they'll get the expected behaviour. */ if (svn_auth_get_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL) store_passwords = FALSE; if (svn_auth_get_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL) store_auth_creds = FALSE; } if (config) { /* Grab the 'servers' config. */ servers = apr_hash_get(config, SVN_CONFIG_CATEGORY_SERVERS, APR_HASH_KEY_STRING); if (servers) { /* First, look in the global section. */ SVN_ERR(svn_config_get_bool (servers, &store_passwords, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_STORE_PASSWORDS, store_passwords)); SVN_ERR(svn_config_get_yes_no_ask (servers, &store_plaintext_passwords, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS, SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS)); SVN_ERR(svn_config_get_bool (servers, &store_pp, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP, store_pp)); SVN_ERR(svn_config_get_yes_no_ask (servers, &store_pp_plaintext, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT, SVN_CONFIG_DEFAULT_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT)); SVN_ERR(svn_config_get_bool (servers, &store_auth_creds, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_STORE_AUTH_CREDS, store_auth_creds)); /* Find out where we're about to connect to, and * try to pick a server group based on the destination. */ server_group = svn_config_find_group(servers, repos_URI.hostname, SVN_CONFIG_SECTION_GROUPS, sesspool); if (server_group) { /* Override global auth caching parameters with the ones * for the server group, if any. */ SVN_ERR(svn_config_get_bool(servers, &store_auth_creds, server_group, SVN_CONFIG_OPTION_STORE_AUTH_CREDS, store_auth_creds)); SVN_ERR(svn_config_get_bool(servers, &store_passwords, server_group, SVN_CONFIG_OPTION_STORE_PASSWORDS, store_passwords)); SVN_ERR(svn_config_get_yes_no_ask (servers, &store_plaintext_passwords, server_group, SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS, store_plaintext_passwords)); SVN_ERR(svn_config_get_bool (servers, &store_pp, server_group, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP, store_pp)); SVN_ERR(svn_config_get_yes_no_ask (servers, &store_pp_plaintext, server_group, SVN_CONFIG_OPTION_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT, store_pp_plaintext)); } #ifdef CHOOSABLE_DAV_MODULE /* Now, which DAV-based RA method do we want to use today? */ http_library = svn_config_get_server_setting(servers, server_group, /* NULL is OK */ SVN_CONFIG_OPTION_HTTP_LIBRARY, DEFAULT_HTTP_LIBRARY); if (strcmp(http_library, "neon") != 0 && strcmp(http_library, "serf") != 0) return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL, _("Invalid config: unknown HTTP library " "'%s'"), http_library); #endif } } if (callbacks->auth_baton) { /* Save auth caching parameters in the auth parameter hash. */ if (! store_passwords) svn_auth_set_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, ""); svn_auth_set_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS, store_plaintext_passwords); if (! store_pp) svn_auth_set_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_DONT_STORE_SSL_CLIENT_CERT_PP, ""); svn_auth_set_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT, store_pp_plaintext); if (! store_auth_creds) svn_auth_set_parameter(callbacks->auth_baton, SVN_AUTH_PARAM_NO_AUTH_CACHE, ""); } /* Find the library. */ for (defn = ra_libraries; defn->ra_name != NULL; ++defn) { const char *scheme; if ((scheme = has_scheme_of(defn->schemes, repos_URL))) { svn_ra__init_func_t initfunc = defn->initfunc; #ifdef CHOOSABLE_DAV_MODULE if (defn->schemes == dav_schemes && strcmp(defn->ra_name, http_library) != 0) continue; #endif if (! initfunc) SVN_ERR(load_ra_module(&initfunc, NULL, defn->ra_name, sesspool)); if (! initfunc) /* Library not found. */ continue; SVN_ERR(initfunc(svn_ra_version(), &vtable, sesspool)); SVN_ERR(check_ra_version(vtable->get_version(), scheme)); if (! has_scheme_of(vtable->get_schemes(sesspool), repos_URL)) /* Library doesn't support the scheme at runtime. */ continue; break; } } if (vtable == NULL) return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, _("Unrecognized URL scheme for '%s'"), repos_URL); /* Create the session object. */ session = apr_pcalloc(sesspool, sizeof(*session)); session->vtable = vtable; session->pool = sesspool; /* Ask the library to open the session. */ SVN_ERR_W(vtable->open_session(session, &corrected_url, repos_URL, callbacks, callback_baton, config, sesspool), apr_psprintf(pool, "Unable to connect to a repository at URL '%s'", repos_URL)); /* If the session open stuff detected a server-provided URL correction (a 301 or 302 redirect response during the initial OPTIONS request), then kill the session so the caller can decide what to do. */ if (corrected_url_p && corrected_url) { if (! svn_path_is_url(corrected_url)) { /* RFC1945 and RFC2616 state that the Location header's value (from whence this CORRECTED_URL ultimately comes), if present, must be an absolute URI. But some Apache versions (those older than 2.2.11, it seems) transmit only the path portion of the URI. See issue #3775 for details. */ apr_uri_t corrected_URI = repos_URI; corrected_URI.path = (char *)corrected_url; corrected_url = apr_uri_unparse(pool, &corrected_URI, 0); } *corrected_url_p = svn_uri_canonicalize(corrected_url, pool); svn_pool_destroy(sesspool); return SVN_NO_ERROR; } /* Check the UUID. */ if (uuid) { const char *repository_uuid; SVN_ERR(vtable->get_uuid(session, &repository_uuid, pool)); if (strcmp(uuid, repository_uuid) != 0) { /* Duplicate the uuid as it is allocated in sesspool */ repository_uuid = apr_pstrdup(pool, repository_uuid); svn_pool_destroy(sesspool); return svn_error_createf(SVN_ERR_RA_UUID_MISMATCH, NULL, _("Repository UUID '%s' doesn't match " "expected UUID '%s'"), repository_uuid, uuid); } } *session_p = session; return SVN_NO_ERROR; }
/* This implements serf_bucket_headers_do_callback_fn_t. */ static int capabilities_headers_iterator_callback(void *baton, const char *key, const char *val) { options_context_t *opt_ctx = baton; svn_ra_serf__session_t *session = opt_ctx->session; if (svn_cstring_casecmp(key, "dav") == 0) { /* Each header may contain multiple values, separated by commas, e.g.: DAV: version-control,checkout,working-resource DAV: merge,baseline,activity,version-controlled-collection DAV: http://subversion.tigris.org/xmlns/dav/svn/depth */ apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE, opt_ctx->pool); /* Right now we only have a few capabilities to detect, so just seek for them directly. This could be written slightly more efficiently, but that wouldn't be worth it until we have many more capabilities. */ if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals)) { apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_DEPTH, APR_HASH_KEY_STRING, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals)) { /* The server doesn't know what repository we're referring to, so it can't just say capability_yes. */ apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO, APR_HASH_KEY_STRING, capability_server_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals)) { apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS, APR_HASH_KEY_STRING, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals)) { apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS, APR_HASH_KEY_STRING, capability_yes); } if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals)) { apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY, APR_HASH_KEY_STRING, capability_yes); } } /* SVN-specific headers -- if present, server supports HTTP protocol v2 */ else if (strncmp(key, "SVN", 3) == 0) { /* If we've not yet seen any information about supported POST requests, we'll initialize the list/hash with "create-txn" (which we know is supported by virtue of the server speaking HTTPv2 at all. */ if (! session->supported_posts) { session->supported_posts = apr_hash_make(session->pool); apr_hash_set(session->supported_posts, "create-txn", 10, (void *)1); } if (svn_cstring_casecmp(key, SVN_DAV_ROOT_URI_HEADER) == 0) { session->repos_root = session->session_url; session->repos_root.path = (char *)svn_fspath__canonicalize(val, session->pool); session->repos_root_str = svn_urlpath__canonicalize( apr_uri_unparse(session->pool, &session->repos_root, 0), session->pool); } else if (svn_cstring_casecmp(key, SVN_DAV_ME_RESOURCE_HEADER) == 0) { #ifdef SVN_DEBUG char *ignore_v2_env_var = getenv(SVN_IGNORE_V2_ENV_VAR); if (!(ignore_v2_env_var && apr_strnatcasecmp(ignore_v2_env_var, "yes") == 0)) session->me_resource = apr_pstrdup(session->pool, val); #else session->me_resource = apr_pstrdup(session->pool, val); #endif } else if (svn_cstring_casecmp(key, SVN_DAV_REV_STUB_HEADER) == 0) { session->rev_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_REV_ROOT_STUB_HEADER) == 0) { session->rev_root_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_TXN_STUB_HEADER) == 0) { session->txn_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_TXN_ROOT_STUB_HEADER) == 0) { session->txn_root_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_STUB_HEADER) == 0) { session->vtxn_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_VTXN_ROOT_STUB_HEADER) == 0) { session->vtxn_root_stub = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_REPOS_UUID_HEADER) == 0) { session->uuid = apr_pstrdup(session->pool, val); } else if (svn_cstring_casecmp(key, SVN_DAV_YOUNGEST_REV_HEADER) == 0) { opt_ctx->youngest_rev = SVN_STR_TO_REV(val); } else if (svn_cstring_casecmp(key, SVN_DAV_SUPPORTED_POSTS_HEADER) == 0) { /* May contain multiple values, separated by commas. */ int i; apr_array_header_t *vals = svn_cstring_split(val, ",", TRUE, opt_ctx->pool); for (i = 0; i < vals->nelts; i++) { const char *post_val = APR_ARRAY_IDX(vals, i, const char *); apr_hash_set(session->supported_posts, post_val, APR_HASH_KEY_STRING, (void *)1); } } }
AP_DECLARE(void) ap_add_common_vars(request_rec *r) { apr_table_t *e; server_rec *s = r->server; conn_rec *c = r->connection; core_dir_config *conf = (core_dir_config *)ap_get_core_module_config(r->per_dir_config); const char *env_temp; const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in); const apr_table_entry_t *hdrs = (const apr_table_entry_t *) hdrs_arr->elts; int i; apr_port_t rport; char *q; /* use a temporary apr_table_t which we'll overlap onto * r->subprocess_env later * (exception: if r->subprocess_env is empty at the start, * write directly into it) */ if (apr_is_empty_table(r->subprocess_env)) { e = r->subprocess_env; } else { e = apr_table_make(r->pool, 25 + hdrs_arr->nelts); } /* First, add environment vars from headers... this is as per * CGI specs, though other sorts of scripting interfaces see * the same vars... */ for (i = 0; i < hdrs_arr->nelts; ++i) { if (!hdrs[i].key) { continue; } /* A few headers are special cased --- Authorization to prevent * rogue scripts from capturing passwords; content-type and -length * for no particular reason. */ if (!strcasecmp(hdrs[i].key, "Content-type")) { apr_table_addn(e, "CONTENT_TYPE", hdrs[i].val); } else if (!strcasecmp(hdrs[i].key, "Content-length")) { apr_table_addn(e, "CONTENT_LENGTH", hdrs[i].val); } /* * You really don't want to disable this check, since it leaves you * wide open to CGIs stealing passwords and people viewing them * in the environment with "ps -e". But, if you must... */ #ifndef SECURITY_HOLE_PASS_AUTHORIZATION else if (!strcasecmp(hdrs[i].key, "Authorization") || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) { if (conf->cgi_pass_auth == AP_CGI_PASS_AUTH_ON) { add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val); } } #endif else add_unless_null(e, http2env(r, hdrs[i].key), hdrs[i].val); } env_temp = apr_table_get(r->subprocess_env, "PATH"); if (env_temp == NULL) { env_temp = getenv("PATH"); } if (env_temp == NULL) { env_temp = DEFAULT_PATH; } apr_table_addn(e, "PATH", apr_pstrdup(r->pool, env_temp)); #if defined(WIN32) env2env(e, "SystemRoot"); env2env(e, "COMSPEC"); env2env(e, "PATHEXT"); env2env(e, "WINDIR"); #elif defined(OS2) env2env(e, "COMSPEC"); env2env(e, "ETC"); env2env(e, "DPATH"); env2env(e, "PERLLIB_PREFIX"); #elif defined(BEOS) env2env(e, "LIBRARY_PATH"); #elif defined(DARWIN) env2env(e, "DYLD_LIBRARY_PATH"); #elif defined(_AIX) env2env(e, "LIBPATH"); #elif defined(__HPUX__) /* HPUX PARISC 2.0W knows both, otherwise redundancy is harmless */ env2env(e, "SHLIB_PATH"); env2env(e, "LD_LIBRARY_PATH"); #else /* Some Unix */ env2env(e, "LD_LIBRARY_PATH"); #endif apr_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r)); apr_table_addn(e, "SERVER_SOFTWARE", ap_get_server_banner()); apr_table_addn(e, "SERVER_NAME", ap_escape_html(r->pool, ap_get_server_name_for_url(r))); apr_table_addn(e, "SERVER_ADDR", r->connection->local_ip); /* Apache */ apr_table_addn(e, "SERVER_PORT", apr_psprintf(r->pool, "%u", ap_get_server_port(r))); add_unless_null(e, "REMOTE_HOST", ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST, NULL)); apr_table_addn(e, "REMOTE_ADDR", r->useragent_ip); apr_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */ apr_table_setn(e, "REQUEST_SCHEME", ap_http_scheme(r)); apr_table_addn(e, "CONTEXT_PREFIX", ap_context_prefix(r)); apr_table_addn(e, "CONTEXT_DOCUMENT_ROOT", ap_context_document_root(r)); apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */ if (apr_table_get(r->notes, "proxy-noquery") && (q = ap_strchr(r->filename, '?'))) { *q = '\0'; apr_table_addn(e, "SCRIPT_FILENAME", apr_pstrdup(r->pool, r->filename)); *q = '?'; } else { apr_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */ } rport = c->client_addr->port; apr_table_addn(e, "REMOTE_PORT", apr_itoa(r->pool, rport)); if (r->user) { apr_table_addn(e, "REMOTE_USER", r->user); } else if (r->prev) { request_rec *back = r->prev; while (back) { if (back->user) { apr_table_addn(e, "REDIRECT_REMOTE_USER", back->user); break; } back = back->prev; } } add_unless_null(e, "AUTH_TYPE", r->ap_auth_type); env_temp = ap_get_remote_logname(r); if (env_temp) { apr_table_addn(e, "REMOTE_IDENT", apr_pstrdup(r->pool, env_temp)); } /* Apache custom error responses. If we have redirected set two new vars */ if (r->prev) { /* PR#57785: reconstruct full URL here */ apr_uri_t *uri = &r->prev->parsed_uri; if (!uri->scheme) { uri->scheme = (char*)ap_http_scheme(r->prev); } if (!uri->port) { uri->port = ap_get_server_port(r->prev); uri->port_str = apr_psprintf(r->pool, "%u", uri->port); } if (!uri->hostname) { uri->hostname = (char*)ap_get_server_name_for_url(r->prev); } add_unless_null(e, "REDIRECT_QUERY_STRING", r->prev->args); add_unless_null(e, "REDIRECT_URL", apr_uri_unparse(r->pool, uri, 0)); } if (e != r->subprocess_env) { apr_table_overlap(r->subprocess_env, e, APR_OVERLAP_TABLES_SET); } }
static int webid_auth_checker(request_rec *r) { int is_initial_req, req_access, req_method, ret; const char *req_dest; request_rec *r_dest; apr_uri_t apr_uri; if (r->filename == NULL) { ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "Module bug? Request filename is missing for URI %s", r->uri); return http_status_code(r, OK); } if (r->user == NULL || strlen(r->user) == 0) { return http_status_code(r, HTTP_FORBIDDEN); } // req_access: Read, Write, or Control is_initial_req = ap_is_initial_req(r); req_access = WEBID_ACCESS_INVALID; req_method = (AP_METHOD_BIT << r->method_number); if (is_initial_req && r->method_number == M_COPY) { // allow COPY of a readonly source URI // - target URI check happens by subrequest req_access = WEBID_ACCESS_READ; } else if (req_method == (req_method & WEBID_M_READ)) { // check the acl:Read method bitmask req_access = WEBID_ACCESS_READ; } else if (req_method == (req_method & WEBID_M_WRITE)) { // check the acl:Write method bitmask // - writes to ACL URIs are acl:Control (handled internally) req_access = WEBID_ACCESS_WRITE; } else { // unhandled methods require acl:Control req_access = WEBID_ACCESS_CONTROL; } ret = HTTP_FORBIDDEN; if (is_initial_req && (r->method_number == M_COPY || r->method_number == M_MOVE)) { req_dest = apr_table_get(r->headers_in, "Destination"); if (req_dest == NULL) { const char *nscp_host = apr_table_get(r->headers_in, "Host"); const char *nscp_path = apr_table_get(r->headers_in, "New-uri"); if (nscp_host != NULL && nscp_path != NULL) req_dest = apr_psprintf(r->pool, "http://%s%s", nscp_host, nscp_path); } if (req_dest != NULL) { if ((apr_uri_parse(r->pool, req_dest, &apr_uri) == APR_SUCCESS) && (apr_uri.scheme != NULL && strcmp(apr_uri.scheme, ap_http_scheme(r)) == 0) && (apr_uri.hostname != NULL && strcmp(apr_uri.hostname, ap_get_server_name(r)) == 0)) { req_dest = apr_uri_unparse(r->pool, &apr_uri, APR_URI_UNP_OMITSITEPART); r_dest = ap_sub_req_method_uri(r->method, req_dest, r, NULL); if ((ret = check_request_acl(r, req_access)) == OK) ret = check_request_acl(r_dest, WEBID_ACCESS_WRITE); } else { ret = HTTP_BAD_GATEWAY; } } } else { ret = check_request_acl(r, req_access); } return http_status_code(r, ret); }
CStringA CPathUtils::GetAbsoluteURL ( const CStringA& URL , const CStringA& repositoryRootURL , const CStringA& parentPathURL) { CStringA errorResult; SVNPool pool; /* If the URL is already absolute, there is nothing to do. */ const char *canonicalized_url = svn_uri_canonicalize (URL, pool); if (svn_path_is_url (canonicalized_url)) return canonicalized_url; /* Parse the parent directory URL into its parts. */ apr_uri_t parent_dir_parsed_uri; if (apr_uri_parse (pool, parentPathURL, &parent_dir_parsed_uri)) return errorResult; /* If the parent directory URL is at the server root, then the URL may have no / after the hostname so apr_uri_parse() will leave the URL's path as NULL. */ if (! parent_dir_parsed_uri.path) parent_dir_parsed_uri.path = apr_pstrmemdup (pool, "/", 1); /* Handle URLs relative to the current directory or to the repository root. The backpaths may only remove path elements, not the hostname. This allows an external to refer to another repository in the same server relative to the location of this repository, say using SVNParentPath. */ if ((0 == strncmp("../", URL, 3)) || (0 == strncmp("^/", URL, 2))) { apr_array_header_t *base_components = NULL; apr_array_header_t *relative_components = NULL; /* Decompose either the parent directory's URL path or the repository root's URL path into components. */ if (0 == strncmp ("../", URL, 3)) { base_components = svn_path_decompose (parent_dir_parsed_uri.path, pool); relative_components = svn_path_decompose (canonicalized_url, pool); } else { apr_uri_t repos_root_parsed_uri; if (apr_uri_parse(pool, repositoryRootURL, &repos_root_parsed_uri)) return errorResult; /* If the repository root URL is at the server root, then the URL may have no / after the hostname so apr_uri_parse() will leave the URL's path as NULL. */ if (! repos_root_parsed_uri.path) repos_root_parsed_uri.path = apr_pstrmemdup (pool, "/", 1); base_components = svn_path_decompose (repos_root_parsed_uri.path, pool); relative_components = svn_path_decompose (canonicalized_url + 2, pool); } for (int i = 0; i < relative_components->nelts; ++i) { const char *component = APR_ARRAY_IDX(relative_components, i, const char *); if (0 == strcmp("..", component)) { /* Constructing the final absolute URL together with apr_uri_unparse() requires that the path be absolute, so only pop a component if the component being popped is not the component for the root directory. */ if (base_components->nelts > 1) apr_array_pop (base_components); } else APR_ARRAY_PUSH (base_components, const char *) = component; } parent_dir_parsed_uri.path = (char *)svn_path_compose(base_components, pool); parent_dir_parsed_uri.query = NULL; parent_dir_parsed_uri.fragment = NULL; return apr_uri_unparse (pool, &parent_dir_parsed_uri, 0); }
static svn_error_t * resolve_relative_external_url(const char **resolved_url, const svn_wc_external_item2_t *item, const char *repos_root_url, const char *parent_dir_url, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { const char *url = item->url; apr_uri_t parent_dir_uri; apr_status_t status; *resolved_url = item->url; /* If the URL is already absolute, there is nothing to do. */ if (svn_path_is_url(url)) { /* "http://server/path" */ *resolved_url = svn_uri_canonicalize(url, result_pool); return SVN_NO_ERROR; } if (url[0] == '/') { /* "/path", "//path", and "///path" */ int num_leading_slashes = 1; if (url[1] == '/') { num_leading_slashes++; if (url[2] == '/') num_leading_slashes++; } /* "//schema-relative" and in some cases "///schema-relative". This last format is supported on file:// schema relative. */ url = apr_pstrcat(scratch_pool, apr_pstrndup(scratch_pool, url, num_leading_slashes), svn_relpath_canonicalize(url + num_leading_slashes, scratch_pool), (char*)NULL); } else { /* "^/path" and "../path" */ url = svn_relpath_canonicalize(url, scratch_pool); } /* Parse the parent directory URL into its parts. */ status = apr_uri_parse(scratch_pool, parent_dir_url, &parent_dir_uri); if (status) return svn_error_createf(SVN_ERR_BAD_URL, 0, "Illegal parent directory URL '%s'", parent_dir_url); /* If the parent directory URL is at the server root, then the URL may have no / after the hostname so apr_uri_parse() will leave the URL's path as NULL. */ if (! parent_dir_uri.path) parent_dir_uri.path = apr_pstrmemdup(scratch_pool, "/", 1); parent_dir_uri.query = NULL; parent_dir_uri.fragment = NULL; /* Handle URLs relative to the current directory or to the repository root. The backpaths may only remove path elements, not the hostname. This allows an external to refer to another repository in the same server relative to the location of this repository, say using SVNParentPath. */ if ((0 == strncmp("../", url, 3)) || (0 == strncmp("^/", url, 2))) { apr_array_header_t *base_components; apr_array_header_t *relative_components; int i; /* Decompose either the parent directory's URL path or the repository root's URL path into components. */ if (0 == strncmp("../", url, 3)) { base_components = svn_path_decompose(parent_dir_uri.path, scratch_pool); relative_components = svn_path_decompose(url, scratch_pool); } else { apr_uri_t repos_root_uri; status = apr_uri_parse(scratch_pool, repos_root_url, &repos_root_uri); if (status) return svn_error_createf(SVN_ERR_BAD_URL, 0, "Illegal repository root URL '%s'", repos_root_url); /* If the repository root URL is at the server root, then the URL may have no / after the hostname so apr_uri_parse() will leave the URL's path as NULL. */ if (! repos_root_uri.path) repos_root_uri.path = apr_pstrmemdup(scratch_pool, "/", 1); base_components = svn_path_decompose(repos_root_uri.path, scratch_pool); relative_components = svn_path_decompose(url + 2, scratch_pool); } for (i = 0; i < relative_components->nelts; ++i) { const char *component = APR_ARRAY_IDX(relative_components, i, const char *); if (0 == strcmp("..", component)) { /* Constructing the final absolute URL together with apr_uri_unparse() requires that the path be absolute, so only pop a component if the component being popped is not the component for the root directory. */ if (base_components->nelts > 1) apr_array_pop(base_components); } else APR_ARRAY_PUSH(base_components, const char *) = component; } parent_dir_uri.path = (char *)svn_path_compose(base_components, scratch_pool); *resolved_url = svn_uri_canonicalize(apr_uri_unparse(scratch_pool, &parent_dir_uri, 0), result_pool); return SVN_NO_ERROR; }
/* compute a new uri based on the old one and the current request such that the uri maps to the same location on a different server. there are three cases: 1. globally absolute: method://old-server(:port)/path/to/file 2. locally absolute: /path/to/file 3. relative: path/to/file we handle the cases as follows: 1. check from_servers to ensure that old-server(:port) is listed; if not, we check if old-server is the current servername; if not, we _do not_ replace the server in the url; note that we _do not_ try to match urls of the form method://username:password@old-server(:port)/path/to/file 2. just drop in to_server in the beginning 3. figure out the current request_uri, and replace the most specific filename with path/to/file */ static char * remap_url(saxctxt *ctx, char *uri, int add_auth, int add_qstring_ignore) { apr_uri_t u, u2; int i; char *s; apr_pool_t *pool = ctx->f->r->pool; ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctx->f->r->server, "remap_url: remapping %s (add_auth = %d, add_qstring_ignore = %d)", uri, add_auth, add_qstring_ignore); if(apr_uri_parse(pool, uri, &u) != APR_SUCCESS) return NULL; /* only CDNify HTTP and HTTPS requests for now */ if(u.scheme && strcasecmp(u.scheme, "http") != 0 && strcasecmp(u.scheme, "https") != 0) return NULL; if(u.hostinfo) { /* case 1 */ const char *hostinfo = (u.port_str && u.scheme && u.port != apr_uri_port_of_scheme(u.scheme)) ? u.hostinfo : u.hostname; /* does this hostinfo match the current ServerName or one of the ServerAliases? */ if(matches_aliases(ctx->f->r->server, hostinfo)) goto set_hostname_and_return; /* if not, cycle through from_servers and see if one of them matches */ if(ctx->cfg->from_servers) { tattr *from = (tattr *)ctx->cfg->from_servers->elts; for(i = 0; i < ctx->cfg->from_servers->nelts; ++i) if(!strcasecmp(hostinfo, from[i].val)) goto set_hostname_and_return; } } else if(u.path && u.path[0] == '/') { /* case 2 */ goto set_hostname_and_return; } else if(u.path) { /* case 3 */ /* * first figure out the local absolute path, minus the filename, * from r->uri; then, tack the relative uri onto the end */ char *my_uri = apr_pstrdup(pool, ctx->f->r->uri); s = strrchr(my_uri, '/'); if(s) { *(s+1) = '\0'; u.path = apr_pstrcat(pool, my_uri, u.path, NULL); } goto set_hostname_and_return; } return NULL; set_hostname_and_return: if(apr_uri_parse(pool, (char *)ctx->cfg->to_server, &u2) != APR_SUCCESS) return NULL; u.scheme = u2.scheme; u.hostname = u2.hostname; u.port_str = u2.port_str; u.port = u2.port; if(add_qstring_ignore) u.query = add_qstring_ignore_token(pool, ctx, &u); if(add_auth) u.query = add_auth_token(pool, ctx, &u); return apr_uri_unparse(pool, &u, 0); }
cookie_t * chxj_save_cookie(request_rec *r) { int ii; apr_array_header_t *headers; apr_table_entry_t *hentryp; apr_array_header_t *err_headers; apr_table_entry_t *err_hentryp; char *old_cookie_id; char *store_string; mod_chxj_config *dconf; chxjconvrule_entry *entryp; apr_table_t *new_cookie_table; int has_cookie = 0; cookie_t *cookie; cookie_t *old_cookie; char *refer_string; apr_uri_t parsed_uri; int has_refer; DBG(r, "start chxj_save_cookie()"); cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t)); cookie->cookie_id = NULL; has_cookie = 0; has_refer = 0; dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); entryp = chxj_apply_convrule(r, dconf->convrules); if (! entryp) { DBG(r, "end chxj_save_cookie() no pattern"); return NULL; } if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) { DBG(r, "end chxj_save_cookie() CookieOff"); return NULL; } headers = (apr_array_header_t*)apr_table_elts(r->headers_out); hentryp = (apr_table_entry_t*)headers->elts; err_headers = (apr_array_header_t*)apr_table_elts(r->err_headers_out); err_hentryp = (apr_table_entry_t*)err_headers->elts; new_cookie_table = apr_table_make(r->pool, 0); for (ii=0; ii<headers->nelts; ii++) { if (strcasecmp(hentryp[ii].key, "Set-Cookie") == 0) { DBG(r, "====================================="); DBG(r, "cookie=[%s:%s]", hentryp[ii].key, hentryp[ii].val); char* key; char* val; char* buff; buff = apr_pstrdup(r->pool, hentryp[ii].val); val = strchr(buff, '='); if (val) { key = buff; *val++ = 0; apr_table_add(new_cookie_table, key, val); if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++; } has_cookie = 1; DBG(r, "====================================="); } } for (ii=0; ii<err_headers->nelts; ii++) { if (strcasecmp(err_hentryp[ii].key, "Set-Cookie") == 0) { DBG(r, "====================================="); DBG(r, "cookie=[%s:%s]", err_hentryp[ii].key, err_hentryp[ii].val); char* key; char* val; char* buff; buff = apr_pstrdup(r->pool, err_hentryp[ii].val); val = strchr(buff, '='); if (val) { key = buff; *val++ = 0; apr_table_add(new_cookie_table, key, val); if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++; } has_cookie = 1; DBG(r, "====================================="); } } apr_table_unset(r->headers_out, "Set-Cookie"); apr_table_unset(r->err_headers_out, "Set-Cookie"); if (! has_refer) { apr_uri_parse(r->pool,r->uri, &parsed_uri); refer_string = apr_psprintf(r->pool, "%s://%s%s", chxj_run_http_scheme(r), r->hostname, apr_uri_unparse(r->pool, &parsed_uri, APR_URI_UNP_OMITSITEPART)); if (r->args && strlen(r->args)) { refer_string = apr_pstrcat(r->pool, refer_string, "?", r->args, NULL); } apr_table_setn(new_cookie_table, REFERER_COOKIE_KEY, refer_string); DBG(r, "ADD REFER[%s]", refer_string); has_cookie++; } /* * check input parameters */ old_cookie_id = (char*)apr_table_get(r->headers_in, "CHXJ_COOKIE_ID"); if (old_cookie_id) { old_cookie = chxj_load_cookie(r, old_cookie_id); if (old_cookie && old_cookie->cookie_headers) { hentryp = (apr_table_entry_t*)old_cookie->cookie_headers->elts; for (ii=0; ii<old_cookie->cookie_headers->nelts; ii++) { if (hentryp && apr_table_get(new_cookie_table, hentryp[ii].key) == NULL) { apr_table_add(new_cookie_table, hentryp[ii].key, hentryp[ii].val); has_cookie = 1; } } chxj_delete_cookie(r, old_cookie_id); chxj_delete_cookie_expire(r, old_cookie_id); } } if (! has_cookie) { DBG(r, "no cookie"); DBG(r, "end chxj_save_cookie()"); return NULL; } /* * create val */ cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(new_cookie_table); store_string = apr_palloc(r->pool, 1); store_string[0] = 0; hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts; for (ii=0; ii<cookie->cookie_headers->nelts; ii++) { if (ii) store_string = apr_pstrcat(r->pool, store_string, "\n", NULL); store_string = apr_pstrcat(r->pool, store_string, hentryp[ii].key, "=", hentryp[ii].val, NULL); } if (old_cookie_id && IS_COOKIE_LAZY(dconf)) { DBG(r, "LAZY COOKIE save"); cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id); } else { DBG(r, "NO LAZY COOKIE save. old_cookie_id:[%s] LAZY:[%d]", old_cookie_id,IS_COOKIE_LAZY(dconf)); cookie->cookie_id = alloc_cookie_id(r); } { int done_proc = 0; #if defined(USE_MYSQL_COOKIE) if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) { if (! chxj_save_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) { ERR(r, "%s:%d faild: chxj_save_cookie_mysql() cookie_id:[%s]", APLOG_MARK,cookie->cookie_id); cookie = NULL; goto on_error; } done_proc = 1; } #endif #if defined(USE_MEMCACHE_COOKIE) if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) { if (! chxj_save_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) { ERR(r, "%s:%d failed: chxj_save_cookie_memcache() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id); cookie = NULL; goto on_error; } done_proc = 1; } #endif if (IS_COOKIE_STORE_DBM(dconf->cookie_store_type) || ! done_proc) { if (! chxj_save_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) { ERR(r, "%s:%d failed: chxj_save_cookie_dbm() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id); cookie = NULL; goto on_error; } } } if (cookie) { chxj_save_cookie_expire(r, cookie); } on_error: DBG(r, "end chxj_save_cookie()"); return cookie; }