📄 serve.c
字号:
enum access_type req = (required & svn_authz_write) ? WRITE_ACCESS : READ_ACCESS; svn_boolean_t authorized; svn_error_t *err; /* Get authz's opinion on the access. */ err = authz_check_access(&authorized, path, required, baton, pool); /* If an error made lookup fail, deny access. ### TODO: Once logging is implemented, this is a perfect place to log the problem. */ if (err) { svn_error_clear(err); return FALSE; } /* If the required access is blanket-granted AND granted by authz AND we already have a username if one is required, then the lookup has succeeded. */ if (current_access(baton) >= req && authorized && (! needs_username || baton->user)) return TRUE; return FALSE;}/* Check that the client has the REQUIRED access by consulting the * authentication and authorization states stored in BATON. If the * client does not have the required access credentials, attempt to * authenticate the client to get that access, using CONN for * communication. * * This function is supposed to be called to handle the authentication * half of a standard svn protocol reply. If an error is returned, it * probably means that the server can terminate the client connection * with an apologetic error, as it implies an authentication failure. * * PATH and NEEDS_USERNAME are passed along to lookup_access, their * behaviour is documented there. */static svn_error_t *must_have_access(svn_ra_svn_conn_t *conn, apr_pool_t *pool, server_baton_t *b, svn_repos_authz_access_t required, const char *path, svn_boolean_t needs_username){ enum access_type req = (required & svn_authz_write) ? WRITE_ACCESS : READ_ACCESS; /* See whether the user already has the required access. If so, nothing needs to be done. Create the FS access and send a trivial auth request. */ if (lookup_access(pool, b, required, path, needs_username)) { SVN_ERR(create_fs_access(b, pool)); return trivial_auth_request(conn, pool, b); } /* If the required blanket access can be obtained by authenticating, try that. Unfortunately, we can't tell until after authentication whether authz will work or not. We force requiring a username because we need one to be able to check authz configuration again with a different user credentials than the first time round. */ if (b->user == NULL && get_access(b, AUTHENTICATED) >= req && (b->tunnel_user || b->pwdb) && b->protocol_version >= 2) SVN_ERR(auth_request(conn, pool, b, req, TRUE)); /* Now that an authentication has been done get the new take of authz on the request. */ if (! lookup_access(pool, b, required, path, needs_username)) return svn_error_create(SVN_ERR_RA_SVN_CMD_ERR, svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, NULL), NULL); /* Else, access is granted, and there is much rejoicing. */ SVN_ERR(create_fs_access(b, pool)); return SVN_NO_ERROR;}/* --- REPORTER COMMAND SET --- *//* To allow for pipelining, reporter commands have no reponses. If we * get an error, we ignore all subsequent reporter commands and return * the error finish_report, to be handled by the calling command. */static svn_error_t *set_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ report_driver_baton_t *b = baton; const char *path, *lock_token; svn_revnum_t rev; svn_boolean_t start_empty; SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "crb?(?c)", &path, &rev, &start_empty, &lock_token)); path = svn_path_canonicalize(path, pool); if (!b->err) b->err = svn_repos_set_path2(b->report_baton, path, rev, start_empty, lock_token, pool); return SVN_NO_ERROR;}static svn_error_t *delete_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ report_driver_baton_t *b = baton; const char *path; SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c", &path)); path = svn_path_canonicalize(path, pool); if (!b->err) b->err = svn_repos_delete_path(b->report_baton, path, pool); return SVN_NO_ERROR;}static svn_error_t *link_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ report_driver_baton_t *b = baton; const char *path, *url, *lock_token, *fs_path; svn_revnum_t rev; svn_boolean_t start_empty; SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "ccrb?(?c)", &path, &url, &rev, &start_empty, &lock_token)); path = svn_path_canonicalize(path, pool); url = svn_path_uri_decode(svn_path_canonicalize(url, pool), pool); if (!b->err) b->err = get_fs_path(svn_path_uri_decode(b->repos_url, pool), url, &fs_path, pool); if (!b->err) b->err = svn_repos_link_path2(b->report_baton, path, fs_path, rev, start_empty, lock_token, pool); return SVN_NO_ERROR;}static svn_error_t *finish_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ report_driver_baton_t *b = baton; /* No arguments to parse. */ SVN_ERR(trivial_auth_request(conn, pool, b->sb)); if (!b->err) b->err = svn_repos_finish_report(b->report_baton, pool); return SVN_NO_ERROR;}static svn_error_t *abort_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ report_driver_baton_t *b = baton; /* No arguments to parse. */ svn_error_clear(svn_repos_abort_report(b->report_baton, pool)); return SVN_NO_ERROR;}static const svn_ra_svn_cmd_entry_t report_commands[] = { { "set-path", set_path }, { "delete-path", delete_path }, { "link-path", link_path }, { "finish-report", finish_report, TRUE }, { "abort-report", abort_report, TRUE }, { NULL }};/* Accept a report from the client, drive the network editor with the * result, and then write an empty command response. If there is a * non-protocol failure, accept_report will abort the edit and return * a command error to be reported by handle_commands(). */static svn_error_t *accept_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool, server_baton_t *b, svn_revnum_t rev, const char *target, const char *tgt_path, svn_boolean_t text_deltas, svn_boolean_t recurse, svn_boolean_t ignore_ancestry){ const svn_delta_editor_t *editor; void *edit_baton, *report_baton; report_driver_baton_t rb; svn_error_t *err; /* Make an svn_repos report baton. Tell it to drive the network editor * when the report is complete. */ svn_ra_svn_get_editor(&editor, &edit_baton, conn, pool, NULL, NULL); SVN_CMD_ERR(svn_repos_begin_report(&report_baton, rev, b->user, b->repos, b->fs_path->data, target, tgt_path, text_deltas, recurse, ignore_ancestry, editor, edit_baton, authz_check_access_cb_func(b), b, pool)); rb.sb = b; rb.repos_url = svn_path_uri_decode(b->repos_url, pool); rb.report_baton = report_baton; rb.err = NULL; err = svn_ra_svn_handle_commands(conn, pool, report_commands, &rb); if (err) { /* Network or protocol error while handling commands. */ svn_error_clear(rb.err); return err; } else if (rb.err) { /* Some failure during the reporting or editing operations. */ svn_error_clear(editor->abort_edit(edit_baton, pool)); SVN_CMD_ERR(rb.err); } SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "")); return SVN_NO_ERROR;}/* --- MAIN COMMAND SET --- *//* Write out a property list. PROPS is allowed to be NULL, in which case * an empty list will be written out; this happens if the client could * have asked for props but didn't. */static svn_error_t *write_proplist(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_hash_t *props){ apr_hash_index_t *hi; const void *namevar; void *valuevar; const char *name; svn_string_t *value; if (props) { for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi)) { apr_hash_this(hi, &namevar, NULL, &valuevar); name = namevar; value = valuevar; SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "cs", name, value)); } } return SVN_NO_ERROR;}/* Write out a list of property diffs. PROPDIFFS is an array of svn_prop_t * values. */static svn_error_t *write_prop_diffs(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *propdiffs){ int i; for (i = 0; i < propdiffs->nelts; ++i) { const svn_prop_t *prop = &APR_ARRAY_IDX(propdiffs, i, svn_prop_t); SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "c(?s)", prop->name, prop->value)); } return SVN_NO_ERROR;}/* Write out a lock to the client. */static svn_error_t *write_lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_lock_t *lock){ const char *cdate, *edate; cdate = svn_time_to_cstring(lock->creation_date, pool); edate = lock->expiration_date ? svn_time_to_cstring(lock->expiration_date, pool) : NULL; SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "ccc(?c)c(?c)", lock->path, lock->token, lock->owner, lock->comment, cdate, edate)); return SVN_NO_ERROR;}static const char *kind_word(svn_node_kind_t kind){ switch (kind) { case svn_node_none: return "none"; case svn_node_file: return "file"; case svn_node_dir: return "dir"; case svn_node_unknown: return "unknown"; default: abort(); }}/* ### This really belongs in libsvn_repos. *//* Get the properties for a path, with hardcoded committed-info values. */static svn_error_t *get_props(apr_hash_t **props, svn_fs_root_t *root, const char *path, apr_pool_t *pool){ svn_string_t *str; svn_revnum_t crev; const char *cdate, *cauthor, *uuid; /* Get the properties. */ SVN_ERR(svn_fs_node_proplist(props, root, path, pool)); /* Hardcode the values for the committed revision, date, and author. */ SVN_ERR(svn_repos_get_committed_info(&crev, &cdate, &cauthor, root, path, pool)); str = svn_string_create(apr_psprintf(pool, "%ld", crev), pool); apr_hash_set(*props, SVN_PROP_ENTRY_COMMITTED_REV, APR_HASH_KEY_STRING, str); str = (cdate) ? svn_string_create(cdate, pool) : NULL; apr_hash_set(*props, SVN_PROP_ENTRY_COMMITTED_DATE, APR_HASH_KEY_STRING, str); str = (cauthor) ? svn_string_create(cauthor, pool) : NULL; apr_hash_set(*props, SVN_PROP_ENTRY_LAST_AUTHOR, APR_HASH_KEY_STRING, str); /* Hardcode the values for the UUID. */ SVN_ERR(svn_fs_get_uuid(svn_fs_root_fs(root), &uuid, pool)); str = (uuid) ? svn_string_create(uuid, pool) : NULL; apr_hash_set(*props, SVN_PROP_ENTRY_UUID, APR_HASH_KEY_STRING, str); return SVN_NO_ERROR;}static svn_error_t *reparent(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ server_baton_t *b = baton; const char *url; const char *fs_path; SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c", &url)); url = svn_path_uri_decode(svn_path_canonicalize(url, pool), pool); SVN_ERR(trivial_auth_request(conn, pool, b)); SVN_CMD_ERR(get_fs_path(svn_path_uri_decode(b->repos_url, pool), url, &fs_path, pool)); svn_stringbuf_set(b->fs_path, fs_path); SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "")); return SVN_NO_ERROR;}static svn_error_t *get_latest_rev(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ server_baton_t *b = baton; svn_revnum_t rev; SVN_ERR(trivial_auth_request(conn, pool, b)); SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool)); SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "r", rev)); return SVN_NO_ERROR;}static svn_error_t *get_dated_rev(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ server_baton_t *b = baton;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -