mirror of
https://github.com/haiwen/seafile-server.git
synced 2025-05-13 18:45:13 +00:00
Add download file API (#696)
* Add download file API * Go add download file API * Set http header and return http error --------- Co-authored-by: 杨赫然 <heran.yang@seafile.com>
This commit is contained in:
parent
f0c95b4e77
commit
b2bde11d89
@ -31,6 +31,7 @@ import (
|
||||
"syscall"
|
||||
|
||||
jwt "github.com/golang-jwt/jwt/v5"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/haiwen/seafile-server/fileserver/blockmgr"
|
||||
"github.com/haiwen/seafile-server/fileserver/commitmgr"
|
||||
"github.com/haiwen/seafile-server/fileserver/diff"
|
||||
@ -232,6 +233,146 @@ func parseCryptKey(rsp http.ResponseWriter, repoID string, user string, version
|
||||
return seafileKey, nil
|
||||
}
|
||||
|
||||
func accessV2CB(rsp http.ResponseWriter, r *http.Request) *appError {
|
||||
vars := mux.Vars(r)
|
||||
repoID := vars["repoid"]
|
||||
|
||||
filePath := r.URL.Query().Get("p")
|
||||
op := r.URL.Query().Get("op")
|
||||
if filePath == "" {
|
||||
msg := "No file path\n"
|
||||
return &appError{nil, msg, http.StatusBadRequest}
|
||||
}
|
||||
|
||||
decPath, err := url.PathUnescape(filePath)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("File path %s can't be decoded\n", filePath)
|
||||
return &appError{nil, msg, http.StatusBadRequest}
|
||||
}
|
||||
rpath := getCanonPath(decPath)
|
||||
fileName := filepath.Base(rpath)
|
||||
|
||||
if op != "view" && op != "download" {
|
||||
msg := "Operation is neither view or download\n"
|
||||
return &appError{nil, msg, http.StatusBadRequest}
|
||||
}
|
||||
|
||||
token := utils.GetAuthorizationToken(r.Header)
|
||||
cookie := r.Header.Get("Cookie")
|
||||
|
||||
if token == "" && cookie == "" {
|
||||
msg := "Both token and cookie are not set\n"
|
||||
return &appError{nil, msg, http.StatusBadRequest}
|
||||
}
|
||||
|
||||
user, appErr := checkFileAccess(repoID, token, cookie, filePath, "download")
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
repo := repomgr.Get(repoID)
|
||||
if repo == nil {
|
||||
msg := "Bad repo id"
|
||||
return &appError{nil, msg, http.StatusBadRequest}
|
||||
}
|
||||
|
||||
fileID, _, err := fsmgr.GetObjIDByPath(repo.StoreID, repo.RootID, rpath)
|
||||
if err != nil {
|
||||
msg := "Invalid file_path\n"
|
||||
return &appError{nil, msg, http.StatusBadRequest}
|
||||
}
|
||||
|
||||
etag := r.Header.Get("If-None-Match")
|
||||
if etag == fileID {
|
||||
return &appError{nil, "", http.StatusNotModified}
|
||||
}
|
||||
|
||||
rsp.Header().Set("ETag", fileID)
|
||||
rsp.Header().Set("Cache-Control", "private, no-cache")
|
||||
|
||||
ranges := r.Header["Range"]
|
||||
byteRanges := strings.Join(ranges, "")
|
||||
|
||||
var cryptKey *seafileCrypt
|
||||
if repo.IsEncrypted {
|
||||
key, err := parseCryptKey(rsp, repoID, user, repo.EncVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cryptKey = key
|
||||
}
|
||||
|
||||
exists, _ := fsmgr.Exists(repo.StoreID, fileID)
|
||||
if !exists {
|
||||
msg := "Invalid file id"
|
||||
return &appError{nil, msg, http.StatusBadRequest}
|
||||
}
|
||||
|
||||
if !repo.IsEncrypted && len(byteRanges) != 0 {
|
||||
if err := doFileRange(rsp, r, repo, fileID, fileName, op, byteRanges, user); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err := doFile(rsp, r, repo, fileID, fileName, op, cryptKey, user); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type UserInfo struct {
|
||||
User string `json:"user"`
|
||||
}
|
||||
|
||||
func checkFileAccess(repoID, token, cookie, filePath, op string) (string, *appError) {
|
||||
claims := SeahubClaims{
|
||||
time.Now().Add(time.Second * 300).Unix(),
|
||||
true,
|
||||
jwt.RegisteredClaims{},
|
||||
}
|
||||
|
||||
jwtToken := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), &claims)
|
||||
tokenString, err := jwtToken.SignedString([]byte(seahubPK))
|
||||
if err != nil {
|
||||
err := fmt.Errorf("failed to sign jwt token: %v", err)
|
||||
return "", &appError{err, "", http.StatusInternalServerError}
|
||||
}
|
||||
url := fmt.Sprintf("%s/repos/%s/check-access/?path=%s", seahubURL, repoID, filePath)
|
||||
header := map[string][]string{
|
||||
"Authorization": {"Token " + tokenString},
|
||||
}
|
||||
if cookie != "" {
|
||||
header["Cookie"] = []string{cookie}
|
||||
}
|
||||
req := make(map[string]string)
|
||||
req["op"] = op
|
||||
if token != "" {
|
||||
req["token"] = token
|
||||
}
|
||||
msg, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("failed to encode access token: %v", err)
|
||||
return "", &appError{err, "", http.StatusInternalServerError}
|
||||
}
|
||||
status, body, err := utils.HttpCommon("POST", url, header, bytes.NewReader(msg))
|
||||
if err != nil {
|
||||
err := fmt.Errorf("failed to get access token info: %v", err)
|
||||
return "", &appError{err, "", http.StatusInternalServerError}
|
||||
}
|
||||
if status != http.StatusOK {
|
||||
msg := "No permission to access file\n"
|
||||
return "", &appError{nil, msg, http.StatusForbidden}
|
||||
}
|
||||
|
||||
info := new(UserInfo)
|
||||
err = json.Unmarshal(body, &info)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("failed to decode access token info: %v", err)
|
||||
return "", &appError{err, "", http.StatusInternalServerError}
|
||||
}
|
||||
|
||||
return info.User, nil
|
||||
}
|
||||
|
||||
func doFile(rsp http.ResponseWriter, r *http.Request, repo *repomgr.Repo, fileID string,
|
||||
fileName string, operation string, cryptKey *seafileCrypt, user string) *appError {
|
||||
file, err := fsmgr.GetSeafile(repo.StoreID, fileID)
|
||||
@ -3571,7 +3712,7 @@ func accessLinkCB(rsp http.ResponseWriter, r *http.Request) *appError {
|
||||
}
|
||||
|
||||
rsp.Header().Set("ETag", fileID)
|
||||
rsp.Header().Set("Cache-Control", "no-cache")
|
||||
rsp.Header().Set("Cache-Control", "public, no-cache")
|
||||
|
||||
var cryptKey *seafileCrypt
|
||||
if repo.IsEncrypted {
|
||||
|
@ -487,6 +487,8 @@ func newHTTPRouter() *mux.Router {
|
||||
r.Handle("/f/{.*}{slash:\\/?}", appHandler(accessLinkCB))
|
||||
//r.Handle("/d/{.*}", appHandler(accessDirLinkCB))
|
||||
|
||||
r.Handle("/repos/{repoid:[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}}/files{slash:\\/?}", appHandler(accessV2CB))
|
||||
|
||||
// file syncing api
|
||||
r.Handle("/repo/{repoid:[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}}/permission-check{slash:\\/?}",
|
||||
appHandler(permissionCheckCB))
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "access-file.h"
|
||||
#include "zip-download-mgr.h"
|
||||
#include "http-server.h"
|
||||
#include "seaf-utils.h"
|
||||
|
||||
#define FILE_TYPE_MAP_DEFAULT_LEN 1
|
||||
#define BUFFER_SIZE 1024 * 64
|
||||
@ -1116,11 +1117,15 @@ set_etag (evhtp_request_t *req,
|
||||
}
|
||||
|
||||
static void
|
||||
set_no_cache (evhtp_request_t *req)
|
||||
set_no_cache (evhtp_request_t *req, gboolean private_cache)
|
||||
{
|
||||
evhtp_kv_t *kv;
|
||||
|
||||
kv = evhtp_kv_new ("Cache-Control", "no-cache", 1, 1);
|
||||
if (private_cache) {
|
||||
kv = evhtp_kv_new ("Cache-Control", "private, no-cache", 1, 1);
|
||||
} else {
|
||||
kv = evhtp_kv_new ("Cache-Control", "public, no-cache", 1, 1);
|
||||
}
|
||||
evhtp_kvs_add_kv (req->headers_out, kv);
|
||||
}
|
||||
|
||||
@ -1466,6 +1471,145 @@ on_error:
|
||||
evhtp_send_reply(req, error_code);
|
||||
}
|
||||
|
||||
static void
|
||||
access_v2_cb(evhtp_request_t *req, void *arg)
|
||||
{
|
||||
SeafRepo *repo = NULL;
|
||||
char *error_str = NULL;
|
||||
char *token = NULL;
|
||||
char *user = NULL;
|
||||
char *dec_path = NULL;
|
||||
char *rpath = NULL;
|
||||
char *filename = NULL;
|
||||
char *file_id = NULL;
|
||||
const char *repo_id = NULL;
|
||||
const char *path = NULL;
|
||||
const char *operation = NULL;
|
||||
const char *byte_ranges = NULL;
|
||||
const char *auth_token = NULL;
|
||||
const char *cookie = NULL;
|
||||
int error_code = EVHTP_RES_BADREQ;
|
||||
|
||||
SeafileCryptKey *key = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
/* Skip the first '/'. */
|
||||
char **parts = g_strsplit (req->uri->path->full + 1, "/", 0);
|
||||
if (!parts || g_strv_length (parts) < 3 ||
|
||||
strcmp (parts[2], "files") != 0) {
|
||||
error_str = "Invalid URL\n";
|
||||
goto out;
|
||||
}
|
||||
|
||||
repo_id = parts[1];
|
||||
|
||||
path = evhtp_kv_find (req->uri->query, "p");
|
||||
if (!path) {
|
||||
error_str = "No file path\n";
|
||||
goto out;
|
||||
}
|
||||
dec_path = g_uri_unescape_string(path, NULL);
|
||||
rpath = format_dir_path (dec_path);
|
||||
filename = g_path_get_basename (rpath);
|
||||
|
||||
operation = evhtp_kv_find (req->uri->query, "op");
|
||||
if (!operation) {
|
||||
error_str = "No operation\n";
|
||||
goto out;
|
||||
}
|
||||
if (strcmp(operation, "view") != 0 &&
|
||||
strcmp(operation, "download") != 0) {
|
||||
error_str = "Operation is neither view or download\n";
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
auth_token = evhtp_kv_find (req->headers_in, "Authorization");
|
||||
token = seaf_parse_auth_token (auth_token);
|
||||
cookie = evhtp_kv_find (req->headers_in, "Cookie");
|
||||
if (!token && !cookie) {
|
||||
error_str = "Both token and cookie are not set\n";
|
||||
goto out;
|
||||
}
|
||||
if (http_tx_manager_check_file_access (repo_id, token, cookie, path, "download", &user) < 0) {
|
||||
error_str = "No permission to access file\n";
|
||||
error_code = EVHTP_RES_FORBIDDEN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
repo = seaf_repo_manager_get_repo(seaf->repo_mgr, repo_id);
|
||||
if (!repo) {
|
||||
error_str = "Bad repo id\n";
|
||||
goto out;
|
||||
}
|
||||
|
||||
file_id = seaf_fs_manager_get_seafile_id_by_path (seaf->fs_mgr, repo->store_id, repo->version, repo->root_id, rpath, &error);
|
||||
if (!file_id) {
|
||||
error_str = "Invalid file_path\n";
|
||||
if (error)
|
||||
g_clear_error(&error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
const char *etag = evhtp_kv_find (req->headers_in, "If-None-Match");
|
||||
if (g_strcmp0 (etag, file_id) == 0) {
|
||||
evhtp_send_reply (req, EVHTP_RES_NOTMOD);
|
||||
error_code = EVHTP_RES_OK;
|
||||
goto out;
|
||||
}
|
||||
set_etag (req, file_id);
|
||||
set_no_cache (req, TRUE);
|
||||
|
||||
byte_ranges = evhtp_kv_find (req->headers_in, "Range");
|
||||
|
||||
if (repo->encrypted) {
|
||||
key = seaf_passwd_manager_get_decrypt_key (seaf->passwd_mgr,
|
||||
repo_id, user);
|
||||
if (!key) {
|
||||
error_str = "Repo is encrypted. Please provide password to view it.";
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!seaf_fs_manager_object_exists (seaf->fs_mgr,
|
||||
repo->store_id, repo->version, file_id)) {
|
||||
error_str = "Invalid file id\n";
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!repo->encrypted && byte_ranges) {
|
||||
if (do_file_range (req, repo, file_id, filename, operation, byte_ranges, user) < 0) {
|
||||
error_str = "Internal server error\n";
|
||||
error_code = EVHTP_RES_SERVERR;
|
||||
goto out;
|
||||
}
|
||||
} else if (do_file(req, repo, file_id, filename, operation, key, user) < 0) {
|
||||
error_str = "Internal server error\n";
|
||||
error_code = EVHTP_RES_SERVERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error_code = EVHTP_RES_OK;
|
||||
|
||||
out:
|
||||
g_strfreev (parts);
|
||||
g_free (token);
|
||||
g_free (user);
|
||||
g_free (dec_path);
|
||||
g_free (rpath);
|
||||
g_free (filename);
|
||||
g_free (file_id);
|
||||
if (repo != NULL)
|
||||
seaf_repo_unref (repo);
|
||||
if (key != NULL)
|
||||
g_object_unref (key);
|
||||
|
||||
if (error_code != EVHTP_RES_OK) {
|
||||
evbuffer_add_printf(req->buffer_out, "%s\n", error_str);
|
||||
evhtp_send_reply(req, error_code);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
do_block(evhtp_request_t *req, SeafRepo *repo, const char *user, const char *file_id,
|
||||
const char *blk_id)
|
||||
@ -1726,7 +1870,7 @@ access_link_cb(evhtp_request_t *req, void *arg)
|
||||
goto out;
|
||||
}
|
||||
set_etag (req, file_id);
|
||||
set_no_cache (req);
|
||||
set_no_cache (req, FALSE);
|
||||
|
||||
byte_ranges = evhtp_kv_find (req->headers_in, "Range");
|
||||
|
||||
@ -2124,6 +2268,7 @@ access_file_init (evhtp_t *htp)
|
||||
evhtp_set_regex_cb (htp, "^/zip/.*", access_zip_cb, NULL);
|
||||
evhtp_set_regex_cb (htp, "^/f/.*", access_link_cb, NULL);
|
||||
//evhtp_set_regex_cb (htp, "^/d/.*", access_dir_link_cb, NULL);
|
||||
evhtp_set_regex_cb (htp, "^/repos/[\\da-z]{8}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{4}-[\\da-z]{12}/files/.*", access_v2_cb, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -169,13 +169,24 @@ recv_response (void *contents, size_t size, size_t nmemb, void *userp)
|
||||
* the client will time out.
|
||||
*/
|
||||
static int
|
||||
http_get_common (CURL *curl, const char *url, const char *token,
|
||||
http_get_common (CURL *curl, const char *url,
|
||||
struct curl_slist **headers,
|
||||
const char *token,
|
||||
int *rsp_status, char **rsp_content, gint64 *rsp_size,
|
||||
HttpRecvCallback callback, void *cb_data,
|
||||
gboolean timeout)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (token) {
|
||||
char *token_header = g_strdup_printf ("Authorization: Token %s", token);
|
||||
*headers = curl_slist_append (*headers, token_header);
|
||||
g_free (token_header);
|
||||
}
|
||||
*headers = curl_slist_append (*headers, "User-Agent: Seafile Server");
|
||||
*headers = curl_slist_append (*headers, "Content-Type: application/json");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, *headers);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
|
||||
|
||||
@ -259,13 +270,24 @@ send_request (void *ptr, size_t size, size_t nmemb, void *userp)
|
||||
}
|
||||
|
||||
static int
|
||||
http_post_common (CURL *curl, const char *url, const char *token,
|
||||
http_post_common (CURL *curl, const char *url,
|
||||
struct curl_slist **headers,
|
||||
const char *token,
|
||||
const char *req_content, gint64 req_size,
|
||||
int *rsp_status, char **rsp_content, gint64 *rsp_size,
|
||||
gboolean timeout, int timeout_sec)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (token) {
|
||||
char *token_header = g_strdup_printf ("Authorization: Token %s", token);
|
||||
*headers = curl_slist_append (*headers, token_header);
|
||||
g_free (token_header);
|
||||
}
|
||||
*headers = curl_slist_append (*headers, "User-Agent: Seafile Server");
|
||||
*headers = curl_slist_append (*headers, "Content-Type: application/json");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, *headers);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
|
||||
@ -342,25 +364,15 @@ http_post (Connection *conn, const char *url, const char *token,
|
||||
int *rsp_status, char **rsp_content, gint64 *rsp_size,
|
||||
gboolean timeout, int timeout_sec)
|
||||
{
|
||||
char *token_header;
|
||||
struct curl_slist *headers = NULL;
|
||||
int ret = 0;
|
||||
CURL *curl;
|
||||
|
||||
curl = conn->curl;
|
||||
|
||||
headers = curl_slist_append (headers, "User-Agent: Seafile Server");
|
||||
|
||||
if (token) {
|
||||
token_header = g_strdup_printf ("Authorization: Token %s", token);
|
||||
headers = curl_slist_append (headers, token_header);
|
||||
g_free (token_header);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (req_content != NULL, -1);
|
||||
|
||||
ret = http_post_common (curl, url, token, req_content, req_size,
|
||||
ret = http_post_common (curl, url, &headers, token, req_content, req_size,
|
||||
rsp_status, rsp_content, rsp_size, timeout, timeout_sec);
|
||||
if (ret < 0) {
|
||||
conn->release = TRUE;
|
||||
@ -451,7 +463,6 @@ char *
|
||||
http_tx_manager_get_nickname (const char *modifier)
|
||||
{
|
||||
Connection *conn = NULL;
|
||||
char *token_header;
|
||||
struct curl_slist *headers = NULL;
|
||||
int ret = 0;
|
||||
CURL *curl;
|
||||
@ -490,15 +501,9 @@ http_tx_manager_get_nickname (const char *modifier)
|
||||
json_decref (content);
|
||||
|
||||
curl = conn->curl;
|
||||
headers = curl_slist_append (headers, "User-Agent: Seafile Server");
|
||||
token_header = g_strdup_printf ("Authorization: Token %s", jwt_token);
|
||||
headers = curl_slist_append (headers, token_header);
|
||||
headers = curl_slist_append (headers, "Content-Type: application/json");
|
||||
g_free (token_header);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
url = g_strdup_printf("%s/user-list/", seaf->seahub_url);
|
||||
ret = http_post_common (curl, url, jwt_token, req_content, strlen(req_content),
|
||||
ret = http_post_common (curl, url, &headers, jwt_token, req_content, strlen(req_content),
|
||||
&rsp_status, &rsp_content, &rsp_size, TRUE, 1);
|
||||
if (ret < 0) {
|
||||
conn->release = TRUE;
|
||||
@ -506,8 +511,7 @@ http_tx_manager_get_nickname (const char *modifier)
|
||||
}
|
||||
|
||||
if (rsp_status != HTTP_OK) {
|
||||
seaf_warning ("Failed to get user list from seahub %d.\n",
|
||||
rsp_status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nickname = parse_nickname (rsp_content, rsp_size);
|
||||
@ -567,7 +571,6 @@ SeafileShareLinkInfo *
|
||||
http_tx_manager_query_share_link_info (const char *token, const char *cookie, const char *type)
|
||||
{
|
||||
Connection *conn = NULL;
|
||||
char *token_header;
|
||||
char *cookie_header;
|
||||
struct curl_slist *headers = NULL;
|
||||
int ret = 0;
|
||||
@ -592,20 +595,14 @@ http_tx_manager_query_share_link_info (const char *token, const char *cookie, co
|
||||
}
|
||||
|
||||
curl = conn->curl;
|
||||
headers = curl_slist_append (headers, "User-Agent: Seafile Server");
|
||||
token_header = g_strdup_printf ("Authorization: Token %s", jwt_token);
|
||||
headers = curl_slist_append (headers, token_header);
|
||||
g_free (token_header);
|
||||
if (cookie) {
|
||||
cookie_header = g_strdup_printf ("Cookie: %s", cookie);
|
||||
headers = curl_slist_append (headers, cookie_header);
|
||||
g_free (cookie_header);
|
||||
}
|
||||
headers = curl_slist_append (headers, "Content-Type: application/json");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
url = g_strdup_printf("%s/check-share-link-access/?token=%s&type=%s", seaf->seahub_url, token, type);
|
||||
ret = http_get_common (curl, url, jwt_token, &rsp_status,
|
||||
ret = http_get_common (curl, url, &headers, jwt_token, &rsp_status,
|
||||
&rsp_content, &rsp_size, NULL, NULL, TRUE);
|
||||
if (ret < 0) {
|
||||
conn->release = TRUE;
|
||||
@ -613,8 +610,7 @@ http_tx_manager_query_share_link_info (const char *token, const char *cookie, co
|
||||
}
|
||||
|
||||
if (rsp_status != HTTP_OK) {
|
||||
seaf_warning ("Failed to query access token from seahub: %d.\n",
|
||||
rsp_status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
info = parse_share_link_info (rsp_content, rsp_size);
|
||||
@ -628,3 +624,108 @@ out:
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
char *
|
||||
parse_file_access_info (const char *rsp_content, int rsp_size)
|
||||
{
|
||||
json_t *object;
|
||||
json_error_t jerror;
|
||||
const char *user = NULL;
|
||||
|
||||
object = json_loadb (rsp_content, rsp_size, 0, &jerror);
|
||||
if (!object) {
|
||||
seaf_warning ("Failed to parse response when check file access in Seahub: %s.\n", jerror.text);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
user = json_object_get_string_member (object, "user");
|
||||
if (!user) {
|
||||
seaf_warning ("Failed to find user in json when check file access in Seahub.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
json_decref (object);
|
||||
|
||||
return g_strdup (user);
|
||||
}
|
||||
|
||||
int
|
||||
http_tx_manager_check_file_access (const char *repo_id, const char *token, const char *cookie,
|
||||
const char *path, const char *op, char **user)
|
||||
{
|
||||
Connection *conn = NULL;
|
||||
char *cookie_header;
|
||||
struct curl_slist *headers = NULL;
|
||||
int ret = -1;
|
||||
CURL *curl;
|
||||
json_t *content = NULL;
|
||||
int rsp_status;
|
||||
char *req_content = NULL;
|
||||
char *jwt_token = NULL;
|
||||
char *rsp_content = NULL;
|
||||
gint64 rsp_size;
|
||||
char *url = NULL;
|
||||
|
||||
jwt_token = gen_jwt_token ();
|
||||
if (!jwt_token) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn = connection_pool_get_connection (seaf->seahub_conn_pool);
|
||||
if (!conn) {
|
||||
g_free (jwt_token);
|
||||
seaf_warning ("Failed to get connection: out of memory.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
content = json_object ();
|
||||
json_object_set_new (content, "op", json_string(op));
|
||||
if (token) {
|
||||
json_object_set_new (content, "token", json_string(token));
|
||||
}
|
||||
req_content = json_dumps (content, JSON_COMPACT);
|
||||
if (!req_content) {
|
||||
ret = -1;
|
||||
seaf_warning ("Failed to dump json request.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
curl = conn->curl;
|
||||
if (cookie) {
|
||||
cookie_header = g_strdup_printf ("Cookie: %s", cookie);
|
||||
headers = curl_slist_append (headers, cookie_header);
|
||||
g_free (cookie_header);
|
||||
}
|
||||
|
||||
url = g_strdup_printf("%s/repos/%s/check-access/?path=%s", seaf->seahub_url, repo_id, path);
|
||||
ret = http_post_common (curl, url, &headers, jwt_token, req_content, strlen(req_content),
|
||||
&rsp_status, &rsp_content, &rsp_size, TRUE, 1);
|
||||
if (ret < 0) {
|
||||
conn->release = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rsp_status != HTTP_OK) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*user = parse_file_access_info (rsp_content, rsp_size);
|
||||
if (*user == NULL) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (content)
|
||||
json_decref (content);
|
||||
g_free (url);
|
||||
g_free (jwt_token);
|
||||
g_free (req_content);
|
||||
g_free (rsp_content);
|
||||
curl_slist_free_all (headers);
|
||||
connection_pool_return_connection (seaf->seahub_conn_pool, conn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -51,4 +51,8 @@ http_tx_manager_get_nickname (const char *modifier);
|
||||
|
||||
SeafileShareLinkInfo *
|
||||
http_tx_manager_query_share_link_info (const char *token, const char *cookie, const char *type);
|
||||
|
||||
int
|
||||
http_tx_manager_check_file_access (const char *repo_id, const char *token, const char *cookie,
|
||||
const char *path, const char *op, char **user);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user