Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 2D52910E0D for ; Wed, 11 Feb 2015 13:29:37 +0000 (UTC) Received: (qmail 50402 invoked by uid 500); 11 Feb 2015 13:29:32 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 50345 invoked by uid 500); 11 Feb 2015 13:29:32 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 50233 invoked by uid 99); 11 Feb 2015 13:29:32 -0000 Received: from eris.apache.org (HELO hades.apache.org) (140.211.11.105) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 11 Feb 2015 13:29:32 +0000 Received: from hades.apache.org (localhost [127.0.0.1]) by hades.apache.org (ASF Mail Server at hades.apache.org) with ESMTP id C14C4AC0175 for ; Wed, 11 Feb 2015 13:29:31 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1658954 [2/22] - in /subversion/branches/reuse-ra-session: ./ build/generator/ build/generator/templates/ subversion/bindings/javahl/native/ subversion/bindings/javahl/native/jniwrapper/ subversion/bindings/swig/ subversion/include/ subver... Date: Wed, 11 Feb 2015 13:29:28 -0000 To: commits@subversion.apache.org From: ivan@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20150211132931.C14C4AC0175@hades.apache.org> Modified: subversion/branches/reuse-ra-session/subversion/libsvn_ra/ra_loader.c URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_ra/ra_loader.c?rev=1658954&r1=1658953&r2=1658954&view=diff ============================================================================== --- subversion/branches/reuse-ra-session/subversion/libsvn_ra/ra_loader.c (original) +++ subversion/branches/reuse-ra-session/subversion/libsvn_ra/ra_loader.c Wed Feb 11 13:29:26 2015 @@ -52,6 +52,7 @@ #include "ra_loader.h" #include "deprecated.h" +#include "private/svn_auth_private.h" #include "private/svn_ra_private.h" #include "svn_private_config.h" @@ -273,22 +274,12 @@ svn_error_t *svn_ra_open4(svn_ra_session 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 = NULL; apr_uri_t repos_URI; apr_status_t apr_err; svn_error_t *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; /* Initialize the return variable. */ *session_p = NULL; @@ -304,100 +295,27 @@ svn_error_t *svn_ra_open4(svn_ra_session 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; - } + SVN_ERR(svn_auth__apply_config_for_server(callbacks->auth_baton, config, + repos_URI.hostname, sesspool)); +#ifdef CHOOSABLE_DAV_MODULE if (config) { + svn_config_t *servers = NULL; + const char *server_group = NULL; + /* Grab the 'servers' config. */ servers = svn_hash_gets(config, SVN_CONFIG_CATEGORY_SERVERS); 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, @@ -410,38 +328,9 @@ svn_error_t *svn_ra_open4(svn_ra_session _("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, ""); - - if (server_group) - svn_auth_set_parameter(callbacks->auth_baton, - SVN_AUTH_PARAM_SERVER_GROUP, server_group); - } +#endif /* Find the library. */ for (defn = ra_libraries; defn->ra_name != NULL; ++defn) Modified: subversion/branches/reuse-ra-session/subversion/libsvn_ra_svn/editorp.c URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_ra_svn/editorp.c?rev=1658954&r1=1658953&r2=1658954&view=diff ============================================================================== --- subversion/branches/reuse-ra-session/subversion/libsvn_ra_svn/editorp.c (original) +++ subversion/branches/reuse-ra-session/subversion/libsvn_ra_svn/editorp.c Wed Feb 11 13:29:26 2015 @@ -91,7 +91,7 @@ typedef struct ra_svn_driver_state_t { different purpose instead: at apply-textdelta time, we set it to a subpool of the file pool, which is destroyed in textdelta-end. */ typedef struct ra_svn_token_entry_t { - const char *token; + svn_string_t *token; void *baton; svn_boolean_t is_file; svn_stream_t *dstream; /* svndiff stream for apply_textdelta */ @@ -465,27 +465,31 @@ void svn_ra_svn_get_editor(const svn_del /* Store a token entry. The token string will be copied into pool. */ static ra_svn_token_entry_t *store_token(ra_svn_driver_state_t *ds, - void *baton, const char *token, + void *baton, + svn_string_t *token, svn_boolean_t is_file, apr_pool_t *pool) { ra_svn_token_entry_t *entry; entry = apr_palloc(pool, sizeof(*entry)); - entry->token = apr_pstrdup(pool, token); + entry->token = svn_string_dup(token, pool); entry->baton = baton; entry->is_file = is_file; entry->dstream = NULL; entry->pool = pool; - svn_hash_sets(ds->tokens, entry->token, entry); + + apr_hash_set(ds->tokens, entry->token->data, entry->token->len, entry); + return entry; } -static svn_error_t *lookup_token(ra_svn_driver_state_t *ds, const char *token, +static svn_error_t *lookup_token(ra_svn_driver_state_t *ds, + svn_string_t *token, svn_boolean_t is_file, ra_svn_token_entry_t **entry) { - *entry = svn_hash_gets(ds->tokens, token); + *entry = apr_hash_get(ds->tokens, token->data, token->len); if (!*entry || (*entry)->is_file != is_file) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Invalid file or dir token during edit")); @@ -511,10 +515,10 @@ static svn_error_t *ra_svn_handle_open_r { svn_revnum_t rev; apr_pool_t *subpool; - const char *token; + svn_string_t *token; void *root_baton; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)c", &rev, &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)s", &rev, &token)); subpool = svn_pool_create(ds->pool); SVN_CMD_ERR(ds->editor->open_root(ds->edit_baton, rev, subpool, &root_baton)); @@ -527,11 +531,12 @@ static svn_error_t *ra_svn_handle_delete const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *path, *token; + const char *path; + svn_string_t *token; svn_revnum_t rev; ra_svn_token_entry_t *entry; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)c", + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)s", &path, &rev, &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); path = svn_relpath_canonicalize(path, pool); @@ -544,13 +549,14 @@ static svn_error_t *ra_svn_handle_add_di const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *path, *token, *child_token, *copy_path; + const char *path, *copy_path; + svn_string_t *token, *child_token; svn_revnum_t copy_rev; ra_svn_token_entry_t *entry; apr_pool_t *subpool; void *child_baton; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccc(?cr)", &path, &token, + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?cr)", &path, &token, &child_token, ©_path, ©_rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); subpool = svn_pool_create(entry->pool); @@ -577,13 +583,14 @@ static svn_error_t *ra_svn_handle_open_d const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *path, *token, *child_token; + const char *path; + svn_string_t *token, *child_token; svn_revnum_t rev; ra_svn_token_entry_t *entry; apr_pool_t *subpool; void *child_baton; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccc(?r)", &path, &token, + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?r)", &path, &token, &child_token, &rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); subpool = svn_pool_create(entry->pool); @@ -599,11 +606,12 @@ static svn_error_t *ra_svn_handle_change const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *token, *name; + svn_string_t *token; + const char *name; svn_string_t *value; ra_svn_token_entry_t *entry; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cc(?s)", &token, &name, + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "sc(?s)", &token, &name, &value)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); SVN_CMD_ERR(ds->editor->change_dir_prop(entry->baton, name, value, @@ -616,11 +624,11 @@ static svn_error_t *ra_svn_handle_close_ const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *token; + svn_string_t *token; ra_svn_token_entry_t *entry; /* Parse and look up the directory token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s", &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); /* Close the directory and destroy the baton. */ @@ -636,11 +644,11 @@ static svn_error_t *ra_svn_handle_absent ra_svn_driver_state_t *ds) { const char *path; - const char *token; + svn_string_t *token; ra_svn_token_entry_t *entry; /* Parse parameters and look up the directory token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cc", &path, &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cs", &path, &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); /* Call the editor. */ @@ -653,15 +661,19 @@ static svn_error_t *ra_svn_handle_add_fi const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *path, *token, *file_token, *copy_path; + const char *path, *copy_path; + svn_string_t *token, *file_token; svn_revnum_t copy_rev; ra_svn_token_entry_t *entry, *file_entry; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccc(?cr)", &path, &token, + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?cr)", &path, &token, &file_token, ©_path, ©_rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); ds->file_refs++; - path = svn_relpath_canonicalize(path, pool); + + /* The PATH should be canonical .. but never trust incoming data. */ + if (!svn_relpath_is_canonical(path)) + path = svn_relpath_canonicalize(path, pool); /* Some operations pass COPY_PATH as a full URL (commits, etc.). Others (replay, e.g.) deliver an fspath. That's ... annoying. */ @@ -684,15 +696,20 @@ static svn_error_t *ra_svn_handle_open_f const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *path, *token, *file_token; + const char *path; + svn_string_t *token, *file_token; svn_revnum_t rev; ra_svn_token_entry_t *entry, *file_entry; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccc(?r)", &path, &token, + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?r)", &path, &token, &file_token, &rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); ds->file_refs++; - path = svn_relpath_canonicalize(path, pool); + + /* The PATH should be canonical .. but never trust incoming data. */ + if (!svn_relpath_is_canonical(path)) + path = svn_relpath_canonicalize(path, pool); + file_entry = store_token(ds, NULL, file_token, TRUE, ds->file_pool); SVN_CMD_ERR(ds->editor->open_file(path, entry->baton, rev, ds->file_pool, &file_entry->baton)); @@ -704,14 +721,14 @@ static svn_error_t *ra_svn_handle_apply_ const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *token; + svn_string_t *token; ra_svn_token_entry_t *entry; svn_txdelta_window_handler_t wh; void *wh_baton; char *base_checksum; /* Parse arguments and look up the token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?c)", + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s(?c)", &token, &base_checksum)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); if (entry->dstream) @@ -729,12 +746,12 @@ static svn_error_t *ra_svn_handle_textde const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *token; + svn_string_t *token; ra_svn_token_entry_t *entry; svn_string_t *str; /* Parse arguments and look up the token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cs", &token, &str)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ss", &token, &str)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); if (!entry->dstream) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -748,11 +765,11 @@ static svn_error_t *ra_svn_handle_textde const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *token; + svn_string_t *token; ra_svn_token_entry_t *entry; /* Parse arguments and look up the token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s", &token)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); if (!entry->dstream) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -768,11 +785,11 @@ static svn_error_t *ra_svn_handle_change const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *token, *name; - svn_string_t *value; + const char *name; + svn_string_t *token, *value; ra_svn_token_entry_t *entry; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cc(?s)", &token, &name, + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "sc(?s)", &token, &name, &value)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); SVN_CMD_ERR(ds->editor->change_file_prop(entry->baton, name, value, pool)); @@ -784,12 +801,12 @@ static svn_error_t *ra_svn_handle_close_ const apr_array_header_t *params, ra_svn_driver_state_t *ds) { - const char *token; + svn_string_t *token; ra_svn_token_entry_t *entry; const char *text_checksum; /* Parse arguments and look up the file token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?c)", + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s(?c)", &token, &text_checksum)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); @@ -807,11 +824,11 @@ static svn_error_t *ra_svn_handle_absent ra_svn_driver_state_t *ds) { const char *path; - const char *token; + svn_string_t *token; ra_svn_token_entry_t *entry; /* Parse parameters and look up the parent directory token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cc", &path, &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cs", &path, &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); /* Call the editor. */ Modified: subversion/branches/reuse-ra-session/subversion/libsvn_ra_svn/marshal.c URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_ra_svn/marshal.c?rev=1658954&r1=1658953&r2=1658954&view=diff ============================================================================== --- subversion/branches/reuse-ra-session/subversion/libsvn_ra_svn/marshal.c (original) +++ subversion/branches/reuse-ra-session/subversion/libsvn_ra_svn/marshal.c Wed Feb 11 13:29:26 2015 @@ -1433,7 +1433,7 @@ svn_ra_svn__parse_proplist(const apr_arr apr_pool_t *pool, apr_hash_t **props) { - char *name; + svn_string_t *name; svn_string_t *value; svn_ra_svn_item_t *elt; int i; @@ -1445,9 +1445,9 @@ svn_ra_svn__parse_proplist(const apr_arr if (elt->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Proplist element not a list")); - SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, pool, "cs", + SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, pool, "ss", &name, &value)); - svn_hash_sets(*props, name, value); + apr_hash_set(*props, name->data, name->len, value); } return SVN_NO_ERROR; Modified: subversion/branches/reuse-ra-session/subversion/libsvn_repos/log.c URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_repos/log.c?rev=1658954&r1=1658953&r2=1658954&view=diff ============================================================================== --- subversion/branches/reuse-ra-session/subversion/libsvn_repos/log.c (original) +++ subversion/branches/reuse-ra-session/subversion/libsvn_repos/log.c Wed Feb 11 13:29:26 2015 @@ -1144,7 +1144,16 @@ fill_log_entry(svn_log_entry_t *log_entr int i; /* Requested only some revprops... */ - + + /* Make "svn:author" and "svn:date" available as svn_string_t + for efficient comparison via svn_string_compare(). Note that + we want static initialization here and must therefore emulate + strlen(x) by sizeof(x)-1. */ + static const svn_string_t svn_prop_revision_author + = {SVN_PROP_REVISION_AUTHOR, sizeof(SVN_PROP_REVISION_AUTHOR)-1}; + static const svn_string_t svn_prop_revision_date + = {SVN_PROP_REVISION_DATE, sizeof(SVN_PROP_REVISION_DATE)-1}; + /* often only the standard revprops got requested and delivered. In that case, we can simply pass the hash on. */ if (revprops->nelts == apr_hash_count(r_props) && !censor_revprops) @@ -1172,10 +1181,8 @@ fill_log_entry(svn_log_entry_t *log_entr svn_string_t *value = apr_hash_get(r_props, name->data, name->len); if (censor_revprops - && !(strncmp(name->data, SVN_PROP_REVISION_AUTHOR, - name->len) == 0 - || strncmp(name->data, SVN_PROP_REVISION_DATE, - name->len) == 0)) + && !svn_string_compare(name, &svn_prop_revision_author) + && !svn_string_compare(name, &svn_prop_revision_date)) /* ... but we can only return author/date. */ continue; if (log_entry->revprops == NULL) Modified: subversion/branches/reuse-ra-session/subversion/libsvn_repos/repos.c URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_repos/repos.c?rev=1658954&r1=1658953&r2=1658954&view=diff ============================================================================== --- subversion/branches/reuse-ra-session/subversion/libsvn_repos/repos.c (original) +++ subversion/branches/reuse-ra-session/subversion/libsvn_repos/repos.c Wed Feb 11 13:29:26 2015 @@ -291,10 +291,76 @@ create_locks(svn_repos_t *repos, apr_poo "# For similar reasons, you should also add a trailing @ to URLs which" NL \ "# are passed to SVN commands accepting URLs with peg revisions." NL +/* Return template text for a hook script named SCRIPT_NAME. Include + * DESCRIPTION and SCRIPT in the template text. + */ +static const char * +hook_template_text(const char *script_name, + const char *description, + const char *script, + apr_pool_t *result_pool) +{ + return apr_pstrcat(result_pool, +"#!/bin/sh" NL +"" NL, + description, +"#" NL +"# The default working directory for the invocation is undefined, so" NL +"# the program should set one explicitly if it cares." NL +"#" NL +"# On a Unix system, the normal procedure is to have '", script_name, "'" NL +"# invoke other programs to do the real work, though it may do the" NL +"# work itself too." NL +"#" NL +"# Note that '", script_name, "' must be executable by the user(s) who will" NL +"# invoke it (typically the user httpd runs as), and that user must" NL +"# have filesystem-level permission to access the repository." NL +"#" NL +"# On a Windows system, you should name the hook program" NL +"# '", script_name, ".bat' or '", script_name, ".exe'," NL +"# but the basic idea is the same." NL +"#" NL +HOOKS_ENVIRONMENT_TEXT +"#" NL +HOOKS_QUOTE_ARGUMENTS_TEXT +"#" NL +"# Here is an example hook script, for a Unix /bin/sh interpreter." NL +PREWRITTEN_HOOKS_TEXT +"" NL +"" NL, + script, + SVN_VA_NULL); +} + +/* Write a template file for a hook script named SCRIPT_NAME (appending + * '.tmpl' to that name) in REPOS. Include DESCRIPTION and SCRIPT in the + * template text. + */ +static svn_error_t * +write_hook_template_file(svn_repos_t *repos, const char *script_name, + const char *description, + const char *script, + apr_pool_t *pool) +{ + const char *template_path + = svn_dirent_join(repos->hook_path, + apr_psprintf(pool, "%s%s", + script_name, SVN_REPOS__HOOK_DESC_EXT), + pool); + const char *contents + = hook_template_text(script_name, description, script, pool); + + SVN_ERR(svn_io_file_create(template_path, contents, pool)); + SVN_ERR(svn_io_set_file_executable(template_path, TRUE, FALSE, pool)); + return SVN_NO_ERROR; +} + +/* Write the hook template files in REPOS. + */ static svn_error_t * create_hooks(svn_repos_t *repos, apr_pool_t *pool) { - const char *this_path, *contents; + const char *description, *script; /* Create the hook directory. */ SVN_ERR_W(create_repos_dir(repos->hook_path, pool), @@ -303,16 +369,9 @@ create_hooks(svn_repos_t *repos, apr_poo /*** Write a default template for each standard hook file. */ /* Start-commit hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_start_commit_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_START_COMMIT - contents = -"#!/bin/sh" NL -"" NL + description = "# START-COMMIT HOOK" NL "#" NL "# The start-commit hook is invoked immediately after a Subversion txn is" NL @@ -343,33 +402,10 @@ create_hooks(svn_repos_t *repos, apr_poo "# make security assumptions based on the capabilities list, nor should" NL "# you assume that clients reliably report every capability they have." NL "#" NL -"# The working directory for this hook program's invocation is undefined," NL -"# so the program should set one explicitly if it cares." NL -"#" NL "# If the hook program exits with success, the commit continues; but" NL "# if it exits with failure (non-zero), the commit is stopped before" NL -"# a Subversion txn is created, and STDERR is returned to the client." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"# " NL -HOOKS_ENVIRONMENT_TEXT -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter." NL -PREWRITTEN_HOOKS_TEXT -"" NL -"" NL +"# a Subversion txn is created, and STDERR is returned to the client." NL; + script = "REPOS=\"$1\"" NL "USER=\"$2\"" NL "" NL @@ -379,25 +415,17 @@ PREWRITTEN_HOOKS_TEXT "# All checks passed, so allow the commit." NL "exit 0" NL; -#undef SCRIPT_NAME + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating start-commit hook")); - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - _("Creating start-commit hook")); +#undef SCRIPT_NAME - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end start-commit hook */ /* Pre-commit hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_pre_commit_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_PRE_COMMIT - contents = -"#!/bin/sh" NL -"" NL + description = "# PRE-COMMIT HOOK" NL "#" NL "# The pre-commit hook is invoked before a Subversion txn is" NL @@ -419,18 +447,11 @@ PREWRITTEN_HOOKS_TEXT "# by the separator character '|', followed by the lock token string," NL "# followed by a newline." NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# If the hook program exits with success, the txn is committed; but" NL "# if it exits with failure (non-zero), the txn is aborted, no commit" NL "# takes place, and STDERR is returned to the client. The hook" NL "# program can use the 'svnlook' utility to help it examine the txn." NL "#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL "# *** NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT ***" NL "# *** FOR REVISION PROPERTIES (like svn:log or svn:author). ***" NL "#" NL @@ -439,24 +460,8 @@ PREWRITTEN_HOOKS_TEXT "# hooks should not modify the versioned data in txns, or else come" NL "# up with a mechanism to make it safe to do so (by informing the" NL "# committing client of the changes). However, right now neither" NL -"# mechanism is implemented, so hook writers just have to be careful." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"#" NL -HOOKS_ENVIRONMENT_TEXT -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter." NL -PREWRITTEN_HOOKS_TEXT -"" NL -"" NL +"# mechanism is implemented, so hook writers just have to be careful." NL; + script = "REPOS=\"$1\"" NL "TXN=\"$2\"" NL "" NL @@ -473,26 +478,17 @@ PREWRITTEN_HOOKS_TEXT "# All checks passed, so allow the commit." NL "exit 0" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - _("Creating pre-commit hook")); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating pre-commit hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end pre-commit hook */ +#undef SCRIPT_NAME /* Pre-revprop-change hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_pre_revprop_change_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_PRE_REVPROP_CHANGE - contents = -"#!/bin/sh" NL -"" NL + description = "# PRE-REVPROP-CHANGE HOOK" NL "#" NL "# The pre-revprop-change hook is invoked before a revision property" NL @@ -520,28 +516,8 @@ PREWRITTEN_HOOKS_TEXT "# will behave as if the hook were present, but failed. The reason" NL "# for this is that revision properties are UNVERSIONED, meaning that" NL "# a successful propchange is destructive; the old value is gone" NL -"# forever. We recommend the hook back up the old value somewhere." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"#" NL -HOOKS_ENVIRONMENT_TEXT -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter." NL -PREWRITTEN_HOOKS_TEXT -"" NL -"" NL +"# forever. We recommend the hook back up the old value somewhere." NL; + script = "REPOS=\"$1\"" NL "REV=\"$2\"" NL "USER=\"$3\"" NL @@ -553,26 +529,17 @@ PREWRITTEN_HOOKS_TEXT "echo \"Changing revision properties other than svn:log is prohibited\" >&2" NL "exit 1" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - _("Creating pre-revprop-change hook")); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating pre-revprop-change hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end pre-revprop-change hook */ +#undef SCRIPT_NAME /* Pre-lock hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_pre_lock_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_PRE_LOCK - contents = -"#!/bin/sh" NL -"" NL + description = "# PRE-LOCK HOOK" NL "#" NL "# The pre-lock hook is invoked before an exclusive lock is" NL @@ -591,29 +558,10 @@ PREWRITTEN_HOOKS_TEXT "# this feature, you must guarantee the tokens generated are unique across" NL "# the repository each time." NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# If the hook program exits with success, the lock is created; but" NL "# if it exits with failure (non-zero), the lock action is aborted" NL -"# and STDERR is returned to the client." NL -"" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"#" NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter:" NL -"" NL +"# and STDERR is returned to the client." NL; + script = "REPOS=\"$1\"" NL "PATH=\"$2\"" NL "USER=\"$3\"" NL @@ -647,26 +595,17 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "echo \"Error: $PATH already locked by ${LOCK_OWNER}.\" 1>&2" NL "exit 1" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - "Creating pre-lock hook"); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating pre-lock hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end pre-lock hook */ +#undef SCRIPT_NAME /* Pre-unlock hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_pre_unlock_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_PRE_UNLOCK - contents = -"#!/bin/sh" NL -"" NL + description = "# PRE-UNLOCK HOOK" NL "#" NL "# The pre-unlock hook is invoked before an exclusive lock is" NL @@ -680,29 +619,10 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "# [4] TOKEN (the lock token to be destroyed)" NL "# [5] BREAK-UNLOCK (1 if the user is breaking the lock, else 0)" NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# If the hook program exits with success, the lock is destroyed; but" NL "# if it exits with failure (non-zero), the unlock action is aborted" NL -"# and STDERR is returned to the client." NL -"" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"#" NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter:" NL -"" NL +"# and STDERR is returned to the client." NL; + script = "REPOS=\"$1\"" NL "PATH=\"$2\"" NL "USER=\"$3\"" NL @@ -733,27 +653,17 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "echo \"Error: $PATH locked by ${LOCK_OWNER}.\" 1>&2" NL "exit 1" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - "Creating pre-unlock hook"); - - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end pre-unlock hook */ + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating pre-unlock hook")); +#undef SCRIPT_NAME /* Post-commit hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_post_commit_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_POST_COMMIT - contents = -"#!/bin/sh" NL -"" NL + description = "# POST-COMMIT HOOK" NL "#" NL "# The post-commit hook is invoked after a commit. Subversion runs" NL @@ -765,60 +675,28 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "# [2] REV (the number of the revision just committed)" NL "# [3] TXN-NAME (the name of the transaction that has become REV)" NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# Because the commit has already completed and cannot be undone," NL "# the exit code of the hook program is ignored. The hook program" NL "# can use the 'svnlook' utility to help it examine the" NL -"# newly-committed tree." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"# " NL -HOOKS_ENVIRONMENT_TEXT -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter." NL -PREWRITTEN_HOOKS_TEXT -"" NL -"" NL +"# newly-committed tree." NL; + script = "REPOS=\"$1\"" NL "REV=\"$2\"" NL "TXN_NAME=\"$3\"" NL NL "mailer.py commit \"$REPOS\" \"$REV\" /path/to/mailer.conf" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - _("Creating post-commit hook")); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating post-commit hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end post-commit hook */ +#undef SCRIPT_NAME /* Post-lock hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_post_lock_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_POST_LOCK - contents = -"#!/bin/sh" NL -"" NL + description = "# POST-LOCK HOOK" NL "#" NL "# The post-lock hook is run after a path is locked. Subversion runs" NL @@ -831,57 +709,29 @@ PREWRITTEN_HOOKS_TEXT "#" NL "# The paths that were just locked are passed to the hook via STDIN." NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# Because the locks have already been created and cannot be undone," NL "# the exit code of the hook program is ignored. The hook program" NL "# can use the 'svnlook' utility to examine the paths in the repository" NL "# but since the hook is invoked asyncronously the newly-created locks" NL -"# may no longer be present." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter:" NL -"" NL +"# may no longer be present." NL; + script = "REPOS=\"$1\"" NL "USER=\"$2\"" NL "" NL "# Send email to interested parties, let them know a lock was created:" NL "mailer.py lock \"$REPOS\" \"$USER\" /path/to/mailer.conf" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - "Creating post-lock hook"); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating post-lock hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end post-lock hook */ +#undef SCRIPT_NAME /* Post-unlock hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_post_unlock_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_POST_UNLOCK - contents = -"#!/bin/sh" NL -"" NL + description = "# POST-UNLOCK HOOK" NL "#" NL "# The post-unlock hook runs after a path is unlocked. Subversion runs" NL @@ -894,54 +744,26 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "#" NL "# The paths that were just unlocked are passed to the hook via STDIN." NL "#" NL -"# The default working directory for the invocation is undefined, so" NL -"# the program should set one explicitly if it cares." NL -"#" NL "# Because the lock has already been destroyed and cannot be undone," NL -"# the exit code of the hook program is ignored." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter:" NL -"" NL +"# the exit code of the hook program is ignored." NL; + script = "REPOS=\"$1\"" NL "USER=\"$2\"" NL "" NL "# Send email to interested parties, let them know a lock was removed:" NL "mailer.py unlock \"$REPOS\" \"$USER\" /path/to/mailer.conf" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - "Creating post-unlock hook"); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating post-unlock hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end post-unlock hook */ +#undef SCRIPT_NAME /* Post-revprop-change hook. */ - { - this_path = apr_psprintf(pool, "%s%s", - svn_repos_post_revprop_change_hook(repos, pool), - SVN_REPOS__HOOK_DESC_EXT); - #define SCRIPT_NAME SVN_REPOS__HOOK_POST_REVPROP_CHANGE - contents = -"#!/bin/sh" NL -"" NL + description = "# POST-REVPROP-CHANGE HOOK" NL "#" NL "# The post-revprop-change hook is invoked after a revision property" NL @@ -961,28 +783,8 @@ HOOKS_QUOTE_ARGUMENTS_TEXT "# Because the propchange has already completed and cannot be undone," NL "# the exit code of the hook program is ignored. The hook program" NL "# can use the 'svnlook' utility to help it examine the" NL -"# new property value." NL -"#" NL -"# On a Unix system, the normal procedure is to have '"SCRIPT_NAME"'" NL -"# invoke other programs to do the real work, though it may do the" NL -"# work itself too." NL -"#" NL -"# Note that '"SCRIPT_NAME"' must be executable by the user(s) who will" NL -"# invoke it (typically the user httpd runs as), and that user must" NL -"# have filesystem-level permission to access the repository." NL -"#" NL -"# On a Windows system, you should name the hook program" NL -"# '"SCRIPT_NAME".bat' or '"SCRIPT_NAME".exe'," NL -"# but the basic idea is the same." NL -"# " NL -HOOKS_ENVIRONMENT_TEXT -"# " NL -HOOKS_QUOTE_ARGUMENTS_TEXT -"# " NL -"# Here is an example hook script, for a Unix /bin/sh interpreter." NL -PREWRITTEN_HOOKS_TEXT -"" NL -"" NL +"# new property value." NL; + script = "REPOS=\"$1\"" NL "REV=\"$2\"" NL "USER=\"$3\"" NL @@ -992,13 +794,11 @@ PREWRITTEN_HOOKS_TEXT "mailer.py propchange2 \"$REPOS\" \"$REV\" \"$USER\" \"$PROPNAME\" " "\"$ACTION\" /path/to/mailer.conf" NL; -#undef SCRIPT_NAME - - SVN_ERR_W(svn_io_file_create(this_path, contents, pool), - _("Creating post-revprop-change hook")); + SVN_ERR_W(write_hook_template_file(repos, SCRIPT_NAME, + description, script, pool), + _("Creating post-revprop-change hook")); - SVN_ERR(svn_io_set_file_executable(this_path, TRUE, FALSE, pool)); - } /* end post-revprop-change hook */ +#undef SCRIPT_NAME return SVN_NO_ERROR; } Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/auth.c URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/auth.c?rev=1658954&r1=1658953&r2=1658954&view=diff ============================================================================== --- subversion/branches/reuse-ra-session/subversion/libsvn_subr/auth.c (original) +++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/auth.c Wed Feb 11 13:29:26 2015 @@ -685,3 +685,167 @@ svn_auth_get_platform_specific_client_pr return SVN_NO_ERROR; } + +svn_error_t * +svn_auth__apply_config_for_server(svn_auth_baton_t *auth_baton, + apr_hash_t *config, + const char *server_name, + apr_pool_t *scratch_pool) +{ + 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; + svn_config_t *servers = NULL; + const char *server_group = NULL; + + /* 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(auth_baton, + SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL) + store_passwords = FALSE; + + if (svn_auth_get_parameter(auth_baton, + SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL) + store_auth_creds = FALSE; + + /* All the svn_auth_set_parameter() calls below this not only affect the + to be created ra session, but also all the ra sessions that are already + use this auth baton! + + Please try to key things based on the realm string instead of this + construct. + */ + + if (config) + { + /* Grab the 'servers' config. */ + servers = svn_hash_gets(config, SVN_CONFIG_CATEGORY_SERVERS); + 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, server_name, + SVN_CONFIG_SECTION_GROUPS, + scratch_pool); + + 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)); + } + } + } + + /* Save auth caching parameters in the auth parameter hash. */ + if (! store_passwords) + svn_auth_set_parameter(auth_baton, + SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, ""); + + svn_auth_set_parameter(auth_baton, + SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS, + store_plaintext_passwords); + + if (! store_pp) + svn_auth_set_parameter(auth_baton, + SVN_AUTH_PARAM_DONT_STORE_SSL_CLIENT_CERT_PP, + ""); + + svn_auth_set_parameter(auth_baton, + SVN_AUTH_PARAM_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT, + store_pp_plaintext); + + if (! store_auth_creds) + svn_auth_set_parameter(auth_baton, + SVN_AUTH_PARAM_NO_AUTH_CACHE, ""); + + /* ### This setting may have huge side-effects when the auth baton is shared + ### between different ra sessions, as it will change which server settings + ### will be used for all future auth requests. + ### + ### E.g. when you connect using a ssl client cert that is specified in the + ### config file, you might have it when you first connect... but if you + ### then connect to another repository, you might not see the same + ### settings when the SSL connection is built up again later on. + ### + ### Most current usages should probably have been keyed on the realm + ### string instead of this magic flag that changes when multiple repositories + ### are used. + ### + ### This especially affects long living ra sessions, such as those on the + ### reuse-ra-session branch. + */ + if (server_group) + svn_auth_set_parameter(auth_baton, + SVN_AUTH_PARAM_SERVER_GROUP, + apr_pstrdup(auth_baton->pool, server_group)); + + return SVN_NO_ERROR; +} Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509.h URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509.h?rev=1658954&r1=1658953&r2=1658954&view=diff ============================================================================== --- subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509.h (original) +++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509.h Wed Feb 11 13:29:26 2015 @@ -108,15 +108,19 @@ typedef struct _x509_cert { } x509_cert; +struct svn_x509_name_attr_t { + unsigned char *oid; + apr_size_t oid_len; + const char *utf8_value; +}; + /* * Certificate info, returned from the parser */ struct svn_x509_certinfo_t { - apr_array_header_t *issuer_oids; - apr_hash_t *issuer; - apr_array_header_t *subject_oids; - apr_hash_t *subject; + apr_array_header_t *issuer; + apr_array_header_t *subject; apr_time_t valid_from; apr_time_t valid_to; svn_checksum_t *digest; Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509info.c URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509info.c?rev=1658954&r1=1658953&r2=1658954&view=diff ============================================================================== --- subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509info.c (original) +++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509info.c Wed Feb 11 13:29:26 2015 @@ -34,6 +34,33 @@ +svn_x509_name_attr_t * +svn_x509_name_attr_dup(const svn_x509_name_attr_t *attr, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_x509_name_attr_t *result = apr_palloc(result_pool, sizeof(*result)); + result->oid_len = attr->oid_len; + result->oid = apr_palloc(result_pool, result->oid_len); + memcpy(result->oid, attr->oid, result->oid_len); + result->utf8_value = apr_pstrdup(result_pool, attr->utf8_value); + + return result; +} + +const unsigned char * +svn_x509_name_attr_get_oid(const svn_x509_name_attr_t *attr, apr_size_t *len) +{ + *len = attr->oid_len; + return attr->oid; +} + +const char * +svn_x509_name_attr_get_value(const svn_x509_name_attr_t *attr) +{ + return attr->utf8_value; +} + /* Array elements are assumed to be nul-terminated C strings. */ static apr_array_header_t * deep_copy_array(apr_array_header_t *s, apr_pool_t *result_pool) @@ -56,31 +83,24 @@ deep_copy_array(apr_array_header_t *s, a return d; } -/* Hash key and value are assumed to be nul-terminated C strings. */ -static apr_hash_t *deep_copy_hash(apr_hash_t *s, - apr_pool_t *scratch_pool, - apr_pool_t *result_pool) +/* Copy an array with elements that are svn_x509_name_attr_t's */ +static apr_array_header_t * +deep_copy_name_attrs(apr_array_header_t *s, apr_pool_t *result_pool) { - apr_hash_t *d; - apr_hash_index_t *i; + int i; + apr_array_header_t *d; if (!s) return NULL; - d = apr_hash_make(result_pool); - i = apr_hash_first(scratch_pool, s); + d = apr_array_copy(result_pool, s); - /* Make a deep copy of the hash keys and values. */ - while (i) + /* Make a deep copy of the svn_x509_name_attr_t's in the array. */ + for (i = 0; i < s->nelts; ++i) { - const void *key; - void *val; - apr_ssize_t klen; - - apr_hash_this(i, &key, &klen, &val); - apr_hash_set(d, apr_pstrndup(result_pool, key, klen), klen, - apr_pstrdup(result_pool, val)); - i = apr_hash_next(i); + APR_ARRAY_IDX(d, i, const svn_x509_name_attr_t *) = + svn_x509_name_attr_dup(APR_ARRAY_IDX(s, i, svn_x509_name_attr_t *), + result_pool, result_pool); } return d; @@ -92,10 +112,8 @@ svn_x509_certinfo_dup(const svn_x509_cer apr_pool_t *scratch_pool) { svn_x509_certinfo_t *result = apr_palloc(result_pool, sizeof(*result)); - result->subject_oids = deep_copy_array(certinfo->subject_oids, result_pool); - result->subject = deep_copy_hash(certinfo->subject, scratch_pool, result_pool); - result->issuer_oids = deep_copy_array(certinfo->issuer_oids, result_pool); - result->issuer = deep_copy_hash(certinfo->issuer, scratch_pool, result_pool); + result->subject = deep_copy_name_attrs(certinfo->subject, result_pool); + result->issuer = deep_copy_name_attrs(certinfo->issuer, result_pool); result->valid_from = certinfo->valid_from; result->valid_to = certinfo->valid_to; result->digest = svn_checksum_dup(certinfo->digest, result_pool); @@ -105,49 +123,134 @@ svn_x509_certinfo_dup(const svn_x509_cer } typedef struct asn1_oid { - const char *oid_string; + const unsigned char *oid; + const ptrdiff_t oid_len; const char *short_label; const char *long_label; } asn1_oid; +#define CONSTANT_PAIR(c) (unsigned char *)(c), sizeof((c)) - 1 + static const asn1_oid asn1_oids[] = { - { SVN_X509_OID_COMMON_NAME, "CN", "commonName" }, - { SVN_X509_OID_COUNTRY, "C", "countryName" }, - { SVN_X509_OID_LOCALITY, "L", "localityName" }, - { SVN_X509_OID_STATE, "ST", "stateOrProvinceName" }, - { SVN_X509_OID_ORGANIZATION, "O", "organizationName" }, - { SVN_X509_OID_ORG_UNIT, "OU", "organizationalUnitName"}, - { SVN_X509_OID_EMAIL, NULL, "emailAddress" }, + { CONSTANT_PAIR(SVN_X509_OID_COMMON_NAME), "CN", "commonName" }, + { CONSTANT_PAIR(SVN_X509_OID_COUNTRY), "C", "countryName" }, + { CONSTANT_PAIR(SVN_X509_OID_LOCALITY), "L", "localityName" }, + { CONSTANT_PAIR(SVN_X509_OID_STATE), "ST", "stateOrProvinceName" }, + { CONSTANT_PAIR(SVN_X509_OID_ORGANIZATION), "O", "organizationName" }, + { CONSTANT_PAIR(SVN_X509_OID_ORG_UNIT), "OU", "organizationalUnitName"}, + { CONSTANT_PAIR(SVN_X509_OID_EMAIL), NULL, "emailAddress" }, { NULL }, }; -static const asn1_oid *oid_string_to_asn1_oid(const char *oid_string) +/* Given an OID return a null-terminated C string representation. + * For example an OID with the bytes "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01" + * would be converted to the string "1.2.840.113549.1.9.1". */ +const char * +svn_x509_oid_to_string(const unsigned char *oid, apr_size_t oid_len, + apr_pool_t *scratch_pool, apr_pool_t *result_pool) { - const asn1_oid *oid; + svn_stringbuf_t *out = svn_stringbuf_create_empty(result_pool); + const unsigned char *p = oid; + const unsigned char *end = p + oid_len; + const char *temp; + + while (p != end) { + if (p == oid) + { + /* Handle decoding the first two values of the OID. These values + * are encoded by taking the first value and adding 40 to it and + * adding the result to the second value, then placing this single + * value in the first byte of the output. This is unambiguous since + * the first value is apparently limited to 0, 1 or 2 and the second + * is limited to 0 to 39. */ + temp = apr_psprintf(scratch_pool, "%d.%d", *p / 40, *p % 40); + p++; + } + else if (*p < 128) + { + /* The remaining values if they're less than 128 are just + * the number one to one encoded */ + temp = apr_psprintf(scratch_pool, ".%d", *p); + p++; + } + else + { + /* Values greater than 128 are encoded as a series of 7 bit values + * with the left most bit set to indicate this encoding with the + * last octet missing the left most bit to finish out the series.. */ + unsigned int collector = 0; + svn_boolean_t dot = FALSE; + + do { + if (collector == 0 && *p == 0x80) + { + /* include leading zeros in the string representation + technically not legal, but this seems nicer than just + returning NULL */ + if (!dot) + { + svn_stringbuf_appendbyte(out, '.'); + dot = TRUE; + } + svn_stringbuf_appendbyte(out, '0'); + } + else if (collector > UINT_MAX >> 7) + { + /* overflow */ + return NULL; + } + collector = collector << 7 | (*(p++) & 0x7f); + } while (p != end && *p > 127); + if (collector > UINT_MAX >> 7) + return NULL; /* overflow */ + collector = collector << 7 | *(p++); + temp = apr_psprintf(scratch_pool, "%s%d", dot ? "" : ".", collector); + } + svn_stringbuf_appendcstr(out, temp); + } - for (oid = asn1_oids; oid->oid_string; oid++) + if (svn_stringbuf_isempty(out)) + return NULL; + + return out->data; +} + +static const asn1_oid *oid_to_asn1_oid(unsigned char *oid, apr_size_t oid_len) +{ + const asn1_oid *entry; + + for (entry = asn1_oids; entry->oid; entry++) { - if (strcmp(oid_string, oid->oid_string) == 0) - return oid; + if (oid_len == entry->oid_len && + memcmp(oid, entry->oid, oid_len) == 0) + return entry; } return NULL; } -static const char *oid_string_to_best_label(const char *oid_string) +static const char *oid_to_best_label(unsigned char *oid, apr_size_t oid_len, + apr_pool_t *result_pool) { - const asn1_oid *oid = oid_string_to_asn1_oid(oid_string); + const asn1_oid *entry = oid_to_asn1_oid(oid, oid_len); - if (oid) + if (entry) { - if (oid->short_label) - return oid->short_label; + if (entry->short_label) + return entry->short_label; - if (oid->long_label) - return oid->long_label; + if (entry->long_label) + return entry->long_label; + } + else + { + const char *oid_string = svn_x509_oid_to_string(oid, oid_len, + result_pool, result_pool); + if (oid_string) + return oid_string; } - return oid_string; + return "??"; } /* @@ -156,23 +259,22 @@ static const char *oid_string_to_best_la * If CN is not NULL, return any common name in CN */ static const char * -get_dn(apr_array_header_t *oids, - apr_hash_t *hash, +get_dn(apr_array_header_t *name, apr_pool_t *result_pool) { svn_stringbuf_t *buf = svn_stringbuf_create_empty(result_pool); int n; - for (n = 0; n < oids->nelts; n++) + for (n = 0; n < name->nelts; n++) { - const char *field = APR_ARRAY_IDX(oids, n, const char *); + const svn_x509_name_attr_t *attr = APR_ARRAY_IDX(name, n, svn_x509_name_attr_t *); if (n > 0) svn_stringbuf_appendcstr(buf, ", "); - svn_stringbuf_appendcstr(buf, oid_string_to_best_label(field)); + svn_stringbuf_appendcstr(buf, oid_to_best_label(attr->oid, attr->oid_len, result_pool)); svn_stringbuf_appendbyte(buf, '='); - svn_stringbuf_appendcstr(buf, svn_hash_gets(hash, field)); + svn_stringbuf_appendcstr(buf, attr->utf8_value); } return buf->data; @@ -182,40 +284,26 @@ const char * svn_x509_certinfo_get_subject(const svn_x509_certinfo_t *certinfo, apr_pool_t *result_pool) { - return get_dn(certinfo->subject_oids, certinfo->subject, result_pool); + return get_dn(certinfo->subject, result_pool); } const apr_array_header_t * -svn_x509_certinfo_get_subject_oids(const svn_x509_certinfo_t *certinfo) +svn_x509_certinfo_get_subject_attrs(const svn_x509_certinfo_t *certinfo) { - return certinfo->subject_oids; -} - -const char * -svn_x509_certinfo_get_subject_attr(const svn_x509_certinfo_t *certinfo, - const char *oid) -{ - return svn_hash_gets(certinfo->subject, oid); + return certinfo->subject; } const char * svn_x509_certinfo_get_issuer(const svn_x509_certinfo_t *certinfo, apr_pool_t *result_pool) { - return get_dn(certinfo->issuer_oids, certinfo->issuer, result_pool); + return get_dn(certinfo->issuer, result_pool); } const apr_array_header_t * -svn_x509_certinfo_get_issuer_oids(const svn_x509_certinfo_t *certinfo) -{ - return certinfo->issuer_oids; -} - -const char * -svn_x509_certinfo_get_issuer_attr(const svn_x509_certinfo_t *certinfo, - const char *oid) +svn_x509_certinfo_get_issuer_attrs(const svn_x509_certinfo_t *certinfo) { - return svn_hash_gets(certinfo->issuer, oid); + return certinfo->issuer; } apr_time_t @@ -241,3 +329,4 @@ svn_x509_certinfo_get_hostnames(const sv { return certinfo->hostnames; } + Modified: subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509parse.c URL: http://svn.apache.org/viewvc/subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509parse.c?rev=1658954&r1=1658953&r2=1658954&view=diff ============================================================================== --- subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509parse.c (original) +++ subversion/branches/reuse-ra-session/subversion/libsvn_subr/x509parse.c Wed Feb 11 13:29:26 2015 @@ -903,90 +903,27 @@ x509name_to_utf8_string(const x509_name return nul_escape(utf8_string, result_pool); } -/* Given an OID return a null-terminated C string representation in *RESULT. - * For example an OID with the bytes "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01" - * would be converted to the string "1.2.840.113549.1.9.1". */ static svn_error_t * -asn1_oid_to_string(const char **result, const x509_buf *oid, - apr_pool_t *scratch_pool, apr_pool_t *result_pool) -{ - svn_stringbuf_t *out = svn_stringbuf_create_empty(result_pool); - const unsigned char *p = oid->p; - const unsigned char *end = p + oid->len; - const char *temp; - - *result = NULL; - - if (oid->tag != ASN1_OID) - return svn_error_create(SVN_ERR_ASN1_UNEXPECTED_TAG, NULL, NULL); - - if (oid->len <= 0) - return svn_error_create(SVN_ERR_ASN1_OUT_OF_DATA, NULL, NULL); - - while (p != end) { - if (p == oid->p) - { - /* Handle decoding the first two values of the OID. These values - * are encoded by taking the first value and adding 40 to it and - * adding the result to the second value, then placing this single - * value in the first byte of the output. This is unambiguous since - * the first value is apparently limited to 0, 1 or 2 and the second - * is limited to 0 to 39. */ - temp = apr_psprintf(scratch_pool, "%d.%d", *p / 40, *p % 40); - p++; - } - else if (*p < 128) - { - /* The remaining values if they're less than 128 are just - * the number one to one encoded */ - temp = apr_psprintf(scratch_pool, ".%d", *p); - p++; - } - else - { - /* Values greater than 128 are encoded as a series of 7 bit values - * with the left most bit set to indicate this encoding with the - * last octet missing the left most bit to finish out the series.. */ - int collector = 0; - - do { - collector = collector << 7 | (*(p++) & 0x7f); - } while (p != end && *p > 127); - collector = collector << 7 | *(p++); - temp = apr_psprintf(scratch_pool, ".%d", collector); - } - svn_stringbuf_appendcstr(out, temp); - } - - *result = out->data; - return SVN_NO_ERROR; -} - -static svn_error_t * -x509_name_to_certinfo(apr_array_header_t **oids, - apr_hash_t **hash, +x509_name_to_certinfo(apr_array_header_t **result, const x509_name *dn, apr_pool_t *scratch_pool, apr_pool_t *result_pool) { const x509_name *name = dn; - *oids = apr_array_make(result_pool, 6, sizeof(const char *)); - *hash = apr_hash_make(result_pool); + *result = apr_array_make(result_pool, 6, sizeof(svn_x509_name_attr_t *)); while (name != NULL) { - const char *oid_string; - const char *utf8_value; + svn_x509_name_attr_t *attr = apr_palloc(result_pool, sizeof(svn_x509_name_attr_t)); - SVN_ERR(asn1_oid_to_string(&oid_string, &name->oid, - scratch_pool, result_pool)); - APR_ARRAY_PUSH(*oids, const char *) = oid_string; - utf8_value = x509name_to_utf8_string(name, result_pool); - if (utf8_value) - svn_hash_sets(*hash, oid_string, utf8_value); - else + attr->oid_len = name->oid.len; + attr->oid = apr_palloc(result_pool, attr->oid_len); + memcpy(attr->oid, name->oid.p, attr->oid_len); + attr->utf8_value = x509name_to_utf8_string(name, result_pool); + if (!attr->utf8_value) /* this should never happen */ - svn_hash_sets(*hash, oid_string, "??"); + attr->utf8_value = apr_pstrdup(result_pool, "??"); + APR_ARRAY_PUSH(*result, const svn_x509_name_attr_t *) = attr; name = name->next; } @@ -1028,6 +965,23 @@ is_hostname(const char *str) return TRUE; } +static const char * +x509parse_get_cn(apr_array_header_t *subject) +{ + int i; + + for (i = 0; i < subject->nelts; ++i) + { + const svn_x509_name_attr_t *attr = APR_ARRAY_IDX(subject, i, const svn_x509_name_attr_t *); + if (equal(attr->oid, attr->oid_len, + SVN_X509_OID_COMMON_NAME, sizeof(SVN_X509_OID_COMMON_NAME) - 1)) + return attr->utf8_value; + } + + return NULL; +} + + static void x509parse_get_hostnames(svn_x509_certinfo_t *ci, x509_cert *crt, apr_pool_t *result_pool, apr_pool_t *scratch_pool) @@ -1058,8 +1012,7 @@ x509parse_get_hostnames(svn_x509_certinf /* no SAN then get the hostname from the CommonName on the cert */ const char *utf8_value; - utf8_value = svn_x509_certinfo_get_subject_attr(ci, - SVN_X509_OID_COMMON_NAME); + utf8_value = x509parse_get_cn(ci->subject); if (utf8_value && is_hostname(utf8_value)) { @@ -1220,11 +1173,11 @@ svn_x509_parse_cert(svn_x509_certinfo_t ci = apr_pcalloc(result_pool, sizeof(*ci)); /* Get the subject name */ - SVN_ERR(x509_name_to_certinfo(&ci->subject_oids, &ci->subject, &crt->subject, + SVN_ERR(x509_name_to_certinfo(&ci->subject, &crt->subject, scratch_pool, result_pool)); /* Get the issuer name */ - SVN_ERR(x509_name_to_certinfo(&ci->issuer_oids, &ci->issuer, &crt->issuer, + SVN_ERR(x509_name_to_certinfo(&ci->issuer, &crt->issuer, scratch_pool, result_pool)); /* Copy the validity range */