--- subversion-1.10.6/subversion/svnlook/svnlook.c +++ subversion-1.10.6/subversion/svnlook/svnchild_ok.c @@ -86,0 +87 @@ static svn_opt_subcommand_t + subcommand_search, @@ -99,0 +101,2 @@ enum + svnlook__found_count, + svnlook__match_count, @@ -106 +109,3 @@ enum - svnlook__no_newline + svnlook__no_newline, + svnlook__authz_path, + svnlook__user_name @@ -131,0 +137,10 @@ static const apr_getopt_option_t options_table[] = + {"username", svnlook__user_name, 1, N_("username to check auth")}, + + {"authz-path", svnlook__authz_path, 1, N_("path to the authz file")}, + + {"limit-found", svnlook__found_count, 1, + N_("maximum number of search entries, default is 50000. set -1 to unlimit.")}, + + {"limit-match", svnlook__match_count, 1, + N_("maximum number of match entries, default is 100. set -1 to unlimit.")}, + @@ -307,0 +323,6 @@ static const svn_opt_subcommand_desc2_t cmd_table[ + {"search", subcommand_search, {0}, + N_("usage: svnlook search REPOS_PATH [PATH_IN_REPOS] [SEARCH_STRING]\n\n" + "Print the found node, starting at PATH_IN_REPOS (if supplied, at the root\n" + "of the tree otherwise).\n"), + {'r', 'N', svnlook__found_count,svnlook__match_count,svnlook__user_name,svnlook__authz_path ,'M'} }, + @@ -340,0 +362,2 @@ struct svnlook_opt_state + long found_count; + long match_count; @@ -350,0 +374,2 @@ struct svnlook_opt_state + const char *authz_file; + const char *user_name; @@ -376 +401,2 @@ typedef struct svnlook_ctxt_t - + + @@ -1145,0 +1172,18 @@ print_diff_tree(svn_stream_t *out_stream, +static svn_error_t * +print_node_search(svn_fs_root_t *root, + const char *path /* UTF-8! */, + const char *search_str, + svn_boolean_t is_dir, + int indentation, + svn_boolean_t recurse, + apr_pool_t *pool, + void *baton, + long *found_count, long *match_count,int parent_dir_len, + svn_authz_t *authz, + const char *user_name, + svn_boolean_t check_auth) +{ + apr_pool_t *subpool; + apr_hash_t *entries; + svn_boolean_t subdir_check_auth = check_auth; + int len = strlen(path); @@ -1146,0 +1191,85 @@ print_diff_tree(svn_stream_t *out_stream, + SVN_ERR(check_cancel(NULL)); + + if (! is_dir) + return SVN_NO_ERROR; + + /* Recursively handle the node's children. */ + if (recurse || (indentation == 0)) + { + apr_array_header_t *sorted_entries; + int i; + + SVN_ERR(svn_fs_dir_entries(&entries, root, path, pool)); + sorted_entries = svn_sort__hash(entries, + svn_sort_compare_items_lexically, pool); + + subpool = svn_pool_create(pool); + for (i = 0; i < sorted_entries->nelts; i++) + { + + if(*found_count <= 0 || *match_count <= 0 ) + { + svn_pool_destroy(subpool); + return SVN_NO_ERROR; + } + + svn_sort__item_t item = APR_ARRAY_IDX(sorted_entries, i, + svn_sort__item_t); + svn_fs_dirent_t *entry = item.value; + + if(check_auth) + { + svn_boolean_t read_access = FALSE; + svn_repos_authz_check_access(authz, NULL, (*path == '/') + ? svn_fspath__join(path, entry->name, pool) + : svn_relpath_join(path, entry->name, pool), user_name, + svn_authz_read, &read_access, + pool); + + + if(!read_access) + continue; + + if(entry->kind == svn_node_dir ) + { + /*如果有递归权限,则不进行子目录的权限校验 */ + svn_repos_authz_check_access(authz, NULL, path, user_name, + svn_authz_read| svn_authz_recursive, &read_access, + pool); + if(read_access) + subdir_check_auth = FALSE; + else + subdir_check_auth = TRUE; + } + } + + if(strstri(entry->name,search_str)) + { + /* Print the match node. */ + SVN_ERR(svn_cmdline_printf(pool, "%s%s%s\n", + path + parent_dir_len , + (( entry->kind == svn_node_dir) && *(path+len-1) == "/" ? "" : "/" ), + entry->name )); + *match_count = (*match_count) - 1; + } + *found_count = (*found_count) - 1; + + if(entry->kind == svn_node_dir ) + { + svn_pool_clear(subpool); + SVN_ERR(print_node_search(root, + (*path == '/') + ? svn_fspath__join(path, entry->name, pool) + : svn_relpath_join(path, entry->name, pool), + search_str, TRUE, + indentation + 1, recurse, subpool,baton, + found_count,match_count,parent_dir_len, + authz,user_name, subdir_check_auth)); + } + } + svn_pool_destroy(subpool); + } + return SVN_NO_ERROR; +} + + @@ -2100 +2230,54 @@ get_ctxt_baton(svnlook_ctxt_t **baton_p, - +static svn_error_t * +do_node_search(svnlook_ctxt_t *c, + const char *path, + const char *search_str, + svn_boolean_t recurse, + apr_pool_t *pool, + void *baton , + long found_count, + long match_count, + const char *authz_file, + const char *user_name ) +{ + svn_fs_root_t *root; + const svn_fs_id_t *id; + svn_boolean_t is_dir; + svn_boolean_t check_auth = FALSE; + svn_authz_t *authz; + int parent_dir_len = strlen(path); + svn_repos_authz_access_t request; + svn_boolean_t read_access = FALSE; + + SVN_ERR(get_root(&root, c, pool)); + SVN_ERR(svn_fs_node_id(&id, root, path, pool)); + + if(authz_file && user_name) + { + SVN_ERR(svn_repos_authz_read2(&authz, authz_file, + NULL,TRUE, pool)); + check_auth = TRUE; + request = svn_authz_read; + svn_repos_authz_check_access(authz, NULL, path, user_name, + request, &read_access, + pool); + if(!read_access) + return SVN_NO_ERROR; + + /*If there are recursive permissions, no permission verification of subdirectories is performed */ + request |= svn_authz_recursive; + svn_repos_authz_check_access(authz, NULL, path, user_name, + request, &read_access, + pool); + if(read_access) + { + check_auth = FALSE; + } + + } + + SVN_ERR(svn_fs_is_dir(&is_dir, root, path, pool)); + SVN_ERR(print_node_search(root, path, search_str, is_dir, 0, + recurse, pool,baton,&found_count,&match_count,parent_dir_len, authz, user_name, check_auth)); + return SVN_NO_ERROR; +} + @@ -2395,0 +2579,20 @@ static svn_error_t * +subcommand_search(apr_getopt_t *os, void *baton, apr_pool_t *pool) +{ + struct svnlook_opt_state *opt_state = baton; + svnlook_ctxt_t *c; + + if (opt_state->arg2 == NULL) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Lost search string")); + + SVN_ERR(get_ctxt_baton(&c, opt_state, pool)); + SVN_ERR(do_node_search(c, opt_state->arg1, opt_state->arg2 , + ! opt_state->non_recursive, pool, baton ,opt_state->found_count, opt_state->match_count, + opt_state->authz_file, opt_state->user_name )); + return SVN_NO_ERROR; +} + + + +/* This implements `svn_opt_subcommand_t'. */ +static svn_error_t * @@ -2424,0 +2628,28 @@ subcommand_uuid(apr_getopt_t *os, void *baton, apr +/* Canonicalize ACCESS_FILE into *CANONICALIZED_ACCESS_FILE based on the type + of argument. Error out on unsupported path types. If WITHIN_TXN is set, + ACCESS_FILE has to be a fspath in the repo. Use POOL for allocations. */ +static svn_error_t * +canonicalize_access_file(const char **canonicalized_access_file, + const char *access_file, + svn_boolean_t within_txn, + apr_pool_t *pool) +{ + if (svn_path_is_repos_relative_url(access_file)) + { + /* Can't accept repos relative urls since we don't have the path to + * the repository. */ + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + ("'%s' is a repository relative URL when it " + "should be a local path or file:// URL"), + access_file); + } + else if (svn_path_is_url(access_file)) + { + if (within_txn) + { + /* Don't allow urls with transaction argument. */ + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + ("'%s' is a URL when it should be a " + "repository-relative path"), + access_file); + } @@ -2425,0 +2657,21 @@ subcommand_uuid(apr_getopt_t *os, void *baton, apr + *canonicalized_access_file = svn_uri_canonicalize(access_file, pool); + } + else if (within_txn) + { + /* Transaction flag means this has to be a fspath to the access file + * in the repo. */ + *canonicalized_access_file = + svn_fspath__canonicalize(access_file, pool); + } + else + { + /* If it isn't a URL and there's no transaction flag then it's a + * dirent to the access file on local disk. */ + *canonicalized_access_file = + svn_dirent_internal_style(access_file, pool); + } + + return SVN_NO_ERROR; +} + + @@ -2519,0 +2772,41 @@ sub_main(int *exit_code, int argc, const char *arg + case svnlook__found_count: + { + char *digits_end = NULL; + opt_state.found_count= strtol(opt_arg, &digits_end, 10); + if (opt_state.found_count == -1) + opt_state.found_count = 9999999999; + if(opt_state.found_count < 0 + || (! digits_end) + || *digits_end) + SVN_INT_ERR(svn_error_create + (SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Invalid match_count number supplied"))); + } + break; + + case svnlook__match_count: + { + char *digits_end = NULL; + opt_state.match_count= strtol(opt_arg, &digits_end, 10); + if (opt_state.match_count == -1) + opt_state.match_count = 9999999999; + if(opt_state.match_count < 0 + || (! digits_end) + || *digits_end) + SVN_INT_ERR(svn_error_create + (SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Invalid match_count number supplied"))); + } + break; + + case svnlook__user_name: + SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.user_name, opt_arg, pool)); + break; + + case svnlook__authz_path: + SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.authz_file, opt_arg, pool)); + SVN_ERR(canonicalize_access_file(&opt_state.authz_file, + opt_state.authz_file, + FALSE, pool)); + break; + @@ -2630,0 +2924,3 @@ sub_main(int *exit_code, int argc, const char *arg + + if(opt_state.found_count == 0 ) + opt_state.found_count = 50000; @@ -2631,0 +2928,3 @@ sub_main(int *exit_code, int argc, const char *arg + if(opt_state.match_count == 0 ) + opt_state.match_count = 100; +