mirror of
https://github.com/haiwen/seafile-server.git
synced 2025-08-01 23:33:42 +00:00
Allow to upload folder
This commit is contained in:
parent
4dfa99882b
commit
1dc5798f4a
@ -365,6 +365,14 @@ seaf_repo_manager_post_dir (SeafRepoManager *mgr,
|
||||
const char *user,
|
||||
GError **error);
|
||||
|
||||
int
|
||||
seaf_repo_manager_mkdir_with_parents (SeafRepoManager *mgr,
|
||||
const char *repo_id,
|
||||
const char *parent_dir,
|
||||
const char *new_dir_path,
|
||||
const char *user,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* Update an existing file in a repo
|
||||
* @params: same as seaf_repo_manager_post_file
|
||||
|
161
server/repo-op.c
161
server/repo-op.c
@ -5464,3 +5464,164 @@ seaf_repo_diff (SeafRepo *repo, const char *old, const char *new, int fold_dir_r
|
||||
|
||||
return diff_entries;
|
||||
}
|
||||
|
||||
int
|
||||
seaf_repo_manager_mkdir_with_parents (SeafRepoManager *mgr,
|
||||
const char *repo_id,
|
||||
const char *parent_dir,
|
||||
const char *new_dir_path,
|
||||
const char *user,
|
||||
GError **error)
|
||||
{
|
||||
SeafRepo *repo = NULL;
|
||||
SeafCommit *head_commit = NULL;
|
||||
char **sub_folders = NULL;
|
||||
int nfolder;
|
||||
char buf[SEAF_PATH_MAX];
|
||||
char *root_id = NULL;
|
||||
SeafDirent *new_dent = NULL;
|
||||
char *parent_dir_can = NULL;
|
||||
char *relative_dir_can = NULL;
|
||||
char *abs_path = NULL;
|
||||
int total_path_len;
|
||||
int sub_folder_len;
|
||||
GList *uncre_dir_list = NULL;
|
||||
GList *iter_list = NULL;
|
||||
char *uncre_dir;
|
||||
int ret = 0;
|
||||
|
||||
if (new_dir_path[0] == '/' || new_dir_path[0] == '\\') {
|
||||
seaf_warning ("[mkdir with parent] Invalid relative path %s.\n", new_dir_path);
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
|
||||
"Invalid relative path");
|
||||
return -1;
|
||||
}
|
||||
|
||||
GET_REPO_OR_FAIL(repo, repo_id);
|
||||
GET_COMMIT_OR_FAIL(head_commit, repo->id, repo->version, repo->head->commit_id);
|
||||
|
||||
relative_dir_can = get_canonical_path (new_dir_path);
|
||||
sub_folders = g_strsplit (relative_dir_can, "/", 0);
|
||||
nfolder = g_strv_length (sub_folders);
|
||||
|
||||
int i = 0;
|
||||
for (; i < nfolder; ++i) {
|
||||
if (strcmp (sub_folders[i], "") == 0)
|
||||
continue;
|
||||
|
||||
if (should_ignore_file (sub_folders[i], NULL)) {
|
||||
seaf_warning ("[post dir] Invalid dir name %s.\n", sub_folders[i]);
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
|
||||
"Invalid dir name");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp (parent_dir, "/") == 0 ||
|
||||
strcmp (parent_dir, "\\") == 0) {
|
||||
parent_dir_can = g_strdup ("/");
|
||||
abs_path = g_strdup_printf ("%s%s", parent_dir_can, relative_dir_can);
|
||||
} else {
|
||||
parent_dir_can = get_canonical_path (parent_dir);
|
||||
abs_path = g_strdup_printf ("%s/%s", parent_dir_can, relative_dir_can);
|
||||
}
|
||||
if (!abs_path) {
|
||||
seaf_warning ("[mkdir with parent] Out of memory.\n");
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL,
|
||||
"Out of memory");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
total_path_len = strlen (abs_path);
|
||||
|
||||
// from the last, to check the folder exist
|
||||
i = nfolder - 1;
|
||||
for (; i >= 0; --i) {
|
||||
if (strcmp (sub_folders[i], "") == 0)
|
||||
continue;
|
||||
|
||||
sub_folder_len = strlen (sub_folders[i]) + 1;
|
||||
total_path_len -= sub_folder_len;
|
||||
memset (abs_path + total_path_len, '\0', sub_folder_len);
|
||||
|
||||
if (check_file_exists (repo->store_id, repo->version,
|
||||
head_commit->root_id, abs_path, sub_folders[i], NULL)) {
|
||||
// folder exist, skip loop to create unexist subfolder
|
||||
strcat (abs_path, "/");
|
||||
strcat (abs_path, sub_folders[i]);
|
||||
break;
|
||||
} else {
|
||||
// folder not exist, cache it to create later
|
||||
uncre_dir_list = g_list_prepend (uncre_dir_list, sub_folders[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (uncre_dir_list) {
|
||||
// exist parent folder has been found, based on it to create unexist subfolder
|
||||
char new_root_id[41];
|
||||
memcpy (new_root_id, head_commit->root_id, 40);
|
||||
new_root_id[40] = '\0';
|
||||
|
||||
for (iter_list = uncre_dir_list; iter_list; iter_list = iter_list->next) {
|
||||
uncre_dir = iter_list->data;
|
||||
new_dent = seaf_dirent_new (dir_version_from_repo_version(repo->version),
|
||||
EMPTY_SHA1, S_IFDIR, uncre_dir,
|
||||
(gint64)time(NULL), NULL, -1);
|
||||
|
||||
root_id = do_post_file (repo,
|
||||
new_root_id, abs_path, new_dent);
|
||||
if (!root_id) {
|
||||
seaf_warning ("[put dir] Failed to put dir.\n");
|
||||
g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
|
||||
"Failed to put dir");
|
||||
ret = -1;
|
||||
seaf_dirent_free (new_dent);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// the last folder has been created
|
||||
if (!iter_list->next) {
|
||||
seaf_dirent_free (new_dent);
|
||||
break;
|
||||
}
|
||||
|
||||
strcat (abs_path, "/");
|
||||
strcat (abs_path, uncre_dir);
|
||||
memcpy (new_root_id, root_id, 40);
|
||||
|
||||
seaf_dirent_free (new_dent);
|
||||
g_free (root_id);
|
||||
}
|
||||
|
||||
/* Commit. */
|
||||
snprintf(buf, SEAF_PATH_MAX, "Added directory \"%s\"", relative_dir_can);
|
||||
if (gen_new_commit (repo_id, head_commit, root_id,
|
||||
user, buf, NULL, error) < 0) {
|
||||
ret = -1;
|
||||
g_free (root_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
seaf_repo_manager_merge_virtual_repo (mgr, repo_id, NULL);
|
||||
g_free (root_id);
|
||||
}
|
||||
|
||||
out:
|
||||
if (repo)
|
||||
seaf_repo_unref (repo);
|
||||
if (head_commit)
|
||||
seaf_commit_unref(head_commit);
|
||||
if (sub_folders)
|
||||
g_strfreev (sub_folders);
|
||||
if (uncre_dir_list)
|
||||
g_list_free (uncre_dir_list);
|
||||
if (relative_dir_can)
|
||||
g_free (relative_dir_can);
|
||||
if (parent_dir_can)
|
||||
g_free (parent_dir_can);
|
||||
if (abs_path)
|
||||
g_free (abs_path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -909,6 +909,41 @@ error:
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
create_relative_path (RecvFSM *fsm, char *parent_dir, char **abs_path)
|
||||
{
|
||||
int rc = 0;
|
||||
GError *error = NULL;
|
||||
|
||||
char *relative_path = g_hash_table_lookup (fsm->form_kvs, "relative_path");
|
||||
if (relative_path != NULL && strcmp(relative_path, "") != 0) {
|
||||
rc = seaf_repo_manager_mkdir_with_parents (seaf->repo_mgr,
|
||||
fsm->repo_id,
|
||||
parent_dir,
|
||||
relative_path,
|
||||
fsm->user,
|
||||
&error);
|
||||
if (rc < 0) {
|
||||
if (error) {
|
||||
seaf_warning ("[upload folder] %s.", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
*abs_path = g_new0 (char, SEAF_PATH_MAX);
|
||||
if (!*abs_path) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
strcat (*abs_path, parent_dir);
|
||||
strcat (*abs_path, relative_path);
|
||||
}
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
Handle AJAX file upload.
|
||||
@return an array of json data, e.g. [{"name": "foo.txt"}]
|
||||
@ -921,6 +956,7 @@ upload_ajax_cb(evhtp_request_t *req, void *arg)
|
||||
GError *error = NULL;
|
||||
int error_code = ERROR_INTERNAL;
|
||||
char *filenames_json, *tmp_files_json;
|
||||
int rc;
|
||||
|
||||
evhtp_headers_add_header (req->headers_out,
|
||||
evhtp_header_new("Access-Control-Allow-Headers",
|
||||
@ -980,16 +1016,24 @@ upload_ajax_cb(evhtp_request_t *req, void *arg)
|
||||
filenames_json = file_list_to_json (fsm->filenames);
|
||||
tmp_files_json = file_list_to_json (fsm->files);
|
||||
|
||||
char *abs_path = NULL;
|
||||
rc = create_relative_path (fsm, parent_dir, &abs_path);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
} else if (abs_path) {
|
||||
parent_dir = abs_path;
|
||||
}
|
||||
|
||||
char *ret_json = NULL;
|
||||
int rc = seaf_repo_manager_post_multi_files (seaf->repo_mgr,
|
||||
fsm->repo_id,
|
||||
parent_dir,
|
||||
filenames_json,
|
||||
tmp_files_json,
|
||||
fsm->user,
|
||||
0,
|
||||
&ret_json,
|
||||
&error);
|
||||
rc = seaf_repo_manager_post_multi_files (seaf->repo_mgr,
|
||||
fsm->repo_id,
|
||||
parent_dir,
|
||||
filenames_json,
|
||||
tmp_files_json,
|
||||
fsm->user,
|
||||
0,
|
||||
&ret_json,
|
||||
&error);
|
||||
g_free (filenames_json);
|
||||
g_free (tmp_files_json);
|
||||
if (rc < 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user