static int getattr_user(SeafileSession *seaf, const char *user, struct stat *stbuf) { SearpcClient *client; CcnetEmailUser *emailuser; client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "ccnet-threaded-rpcserver"); if (!client) { seaf_warning ("Failed to alloc rpc client.\n"); return -ENOMEM; } emailuser = get_user_from_ccnet (client, user); if (!emailuser) { ccnet_rpc_client_free (client); return -ENOENT; } g_object_unref (emailuser); ccnet_rpc_client_free (client); stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 2; stbuf->st_size = 4096; return 0; }
static int readdir_user(SeafileSession *seaf, const char *user, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *info) { SearpcClient *client; CcnetEmailUser *emailuser; GList *list = NULL, *p; GString *name; client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "ccnet-threaded-rpcserver"); if (!client) { seaf_warning ("Failed to alloc rpc client.\n"); return -ENOMEM; } emailuser = get_user_from_ccnet (client, user); if (!emailuser) { ccnet_rpc_client_free (client); return -ENOENT; } g_object_unref (emailuser); ccnet_rpc_client_free (client); list = seaf_repo_manager_get_repos_by_owner (seaf->repo_mgr, user); if (!list) return 0; for (p = list; p; p = p->next) { SeafRepo *repo = (SeafRepo *)p->data; /* Don't list virtual repos. */ if (seaf_repo_manager_is_virtual_repo(seaf->repo_mgr, repo->id)) { seaf_repo_unref (repo); continue; } //skip the encrypted repo if(repo -> encrypted) continue; char *clean_repo_name = replace_slash (repo->name); name = g_string_new (""); g_string_printf (name, "%s_%s", repo->id, clean_repo_name); filler(buf, name->str, NULL, 0); g_string_free (name, TRUE); g_free (clean_repo_name); seaf_repo_unref (repo); } g_list_free (list); return 0; }
static int handle_auth_req_content_cb (char *content, int clen, void *cbarg) { BlockTxServer *server = cbarg; char *session_token = content; SearpcClient *client = NULL; char repo_id[37]; SeafRepo *repo; if (session_token[clen - 1] != '\0') { seaf_warning ("Invalid session token format.\n"); send_auth_response (server, STATUS_BAD_REQUEST); return -1; } client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "ccnet-rpcserver"); if (!client) { seaf_warning ("Failed to create rpc client.\n"); send_auth_response (server, STATUS_INTERNAL_SERVER_ERROR); return -1; } if (seaf_token_manager_verify_token (seaf->token_mgr, client, NULL, session_token, repo_id) < 0) { seaf_warning ("Session token check failed.\n"); send_auth_response (server, STATUS_ACCESS_DENIED); ccnet_rpc_client_free (client); return -1; } ccnet_rpc_client_free (client); repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id); if (!repo) { seaf_warning ("Failed to get repo %.8s.\n", repo_id); return -1; } memcpy (server->store_id, repo->store_id, 36); server->repo_version = repo->version; seaf_repo_unref (repo); if (send_auth_response (server, STATUS_OK) < 0) return -1; seaf_debug ("recv_state set to HEADER.\n"); server->parser.content_cb = handle_block_header_content_cb; server->recv_state = RECV_STATE_HEADER; return 0; }
static int readdir_root(SeafileSession *seaf, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *info) { SearpcClient *client = NULL; GList *users, *p; CcnetEmailUser *user; const char *email; GHashTable *user_hash; int dummy; client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "ccnet-threaded-rpcserver"); if (!client) { seaf_warning ("Failed to alloc rpc client.\n"); return -ENOMEM; } user_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); users = get_users_from_ccnet (client, "DB"); for (p = users; p; p = p->next) { user = p->data; email = ccnet_email_user_get_email (user); g_hash_table_insert (user_hash, g_strdup(email), &dummy); g_object_unref (user); } g_list_free (users); users = get_users_from_ccnet (client, "LDAP"); for (p = users; p; p = p->next) { user = p->data; email = ccnet_email_user_get_email (user); g_hash_table_insert (user_hash, g_strdup(email), &dummy); g_object_unref (user); } g_list_free (users); users = g_hash_table_get_keys (user_hash); for (p = users; p; p = p->next) { email = p->data; filler (buf, email, NULL, 0); } g_list_free (users); g_hash_table_destroy (user_hash); ccnet_rpc_client_free (client); return 0; }
SeafileRpcClient::~SeafileRpcClient() { if (ccnet_rpc_client_) { ccnet_rpc_client_free(ccnet_rpc_client_); ccnet_rpc_client_ = 0; } if (seafile_rpc_client_) { ccnet_rpc_client_free(seafile_rpc_client_); seafile_rpc_client_ = 0; } if (seafile_threaded_rpc_client_) { ccnet_rpc_client_free(seafile_threaded_rpc_client_); seafile_threaded_rpc_client_ = 0; } if (sync_client_) { g_object_unref(sync_client_); sync_client_ = 0; } if (sync_client_for_threaded_rpc_) { g_object_unref(sync_client_for_threaded_rpc_); sync_client_for_threaded_rpc_ = 0; } }
static int process_session_key (BlockTxServer *server, unsigned char *enc_session_key) { char *enc_key_b64 = NULL, *key_b64 = NULL; unsigned char *session_key = NULL; gsize len; SearpcClient *client = NULL; int ret = 0; client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "ccnet-rpcserver"); if (!client) { seaf_warning ("Failed to create rpc client.\n"); send_handshake_response (server, STATUS_INTERNAL_SERVER_ERROR); ret = -1; goto out; } enc_key_b64 = g_base64_encode (enc_session_key, server->session_key_len); key_b64 = ccnet_privkey_decrypt (client, enc_key_b64); if (!key_b64) { seaf_warning ("Failed to decrypt session key.\n"); send_handshake_response (server, STATUS_INTERNAL_SERVER_ERROR); ret = -1; goto out; } session_key = g_base64_decode (key_b64, &len); if (server->version == 1) blocktx_generate_encrypt_key (session_key, len, server->key, server->iv); else if (server->version == 2) blocktx_generate_encrypt_key (session_key, len, server->key_v2, server->iv_v2); init_frame_parser (server); out: g_free (enc_key_b64); g_free (key_b64); g_free (session_key); ccnet_rpc_client_free (client); return ret; }
static gint64 repo_share_usage (const char *user, const char *repo_id) { GHashTable *user_hash; int dummy; GList *personal = NULL, *groups = NULL, *members = NULL, *p; SearpcClient *client = NULL; gint64 usage = -1; /* seaf_debug ("Computing share usage for repo %s.\n", repo_id); */ /* If a repo is shared to both a user and a group, and that user is also * a member of the group, we don't want to count that user twice. * This also applies to two groups with overlapped members. * So we have to use a hash table to filter out duplicated users. */ user_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); /* First count personal share */ personal = seaf_share_manager_list_shared_to (seaf->share_mgr, user, repo_id); for (p = personal; p; p = p->next) { char *email = p->data; g_hash_table_insert (user_hash, g_strdup(email), &dummy); /* seaf_debug ("Shared to %s.\n", email); */ } /* Then groups... */ client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "ccnet-threaded-rpcserver"); if (!client) { seaf_warning ("Failed to alloc rpc client.\n"); goto out; } groups = seaf_repo_manager_get_groups_by_repo (seaf->repo_mgr, repo_id, NULL); for (p = groups; p; p = p->next) { members = ccnet_get_group_members (client, (int)p->data); if (!members) { seaf_warning ("Cannot get member list for groupd %d.\n", (int)p->data); goto out; } count_group_members (user_hash, members); } /* Remove myself if i'm in a group. */ g_hash_table_remove (user_hash, user); guint n_shared_to = g_hash_table_size(user_hash); /* seaf_debug ("n_shared_to = %u.\n", n_shared_to); */ if (n_shared_to == 0) { usage = 0; goto out; } gint64 size = seaf_repo_manager_get_repo_size (seaf->repo_mgr, repo_id); if (size < 0) { seaf_warning ("Cannot get size of repo %s.\n", repo_id); goto out; } /* share_usage = repo_size * n_shared_to / 2 */ usage = size * n_shared_to / 2; out: g_hash_table_destroy (user_hash); string_list_free (personal); g_list_free (groups); ccnet_rpc_client_free (client); return usage; }
/* * Permission priority: owner --> personal share --> group share --> public. * Permission with higher priority overwrites those with lower priority. */ static char * check_repo_share_permission (SeafRepoManager *mgr, const char *repo_id, const char *user_name) { SearpcClient *rpc_client; GList *groups, *p1; GList *group_perms, *p2; CcnetGroup *group; GroupPerm *perm; int group_id; char *permission; permission = seaf_share_manager_check_permission (seaf->share_mgr, repo_id, user_name); if (permission != NULL) return permission; g_free (permission); rpc_client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "ccnet-threaded-rpcserver"); if (!rpc_client) return NULL; /* Get the groups this user belongs to. */ groups = ccnet_get_groups_by_user (rpc_client, user_name); ccnet_rpc_client_free (rpc_client); /* Get the groups this repo shared to. */ group_perms = seaf_repo_manager_get_group_perm_by_repo (mgr, repo_id, NULL); permission = NULL; /* Check if any one group overlaps. */ for (p1 = groups; p1 != NULL; p1 = p1->next) { group = p1->data; g_object_get (group, "id", &group_id, NULL); for (p2 = group_perms; p2 != NULL; p2 = p2->next) { perm = p2->data; if (group_id == perm->group_id) { /* If the repo is shared to more than 1 groups, * and user is in more than 1 of these groups, * "rw" permission will overwrite "ro" permission. */ if (g_strcmp0(perm->permission, "rw") == 0) { permission = perm->permission; goto group_out; } else if (g_strcmp0(perm->permission, "r") == 0 && !permission) { permission = perm->permission; } } } } group_out: if (permission != NULL) permission = g_strdup(permission); for (p1 = groups; p1 != NULL; p1 = p1->next) g_object_unref ((GObject *)p1->data); g_list_free (groups); for (p2 = group_perms; p2 != NULL; p2 = p2->next) g_free (p2->data); g_list_free (group_perms); if (permission != NULL) return permission; if (!mgr->seaf->cloud_mode) return seaf_repo_manager_get_inner_pub_repo_perm (mgr, repo_id); return NULL; }
static evhtp_res upload_headers_cb (evhtp_request_t *req, evhtp_headers_t *hdr, void *arg) { SearpcClient *rpc_client = NULL; char *token, *repo_id = NULL, *user = NULL; char *boundary = NULL; gint64 content_len; char *progress_id = NULL; char *err_msg = NULL; RecvFSM *fsm = NULL; Progress *progress = NULL; /* URL format: http://host:port/[upload|update]/<token>?X-Progress-ID=<uuid> */ token = req->uri->path->file; if (!token) { seaf_warning ("[upload] No token in url.\n"); err_msg = "Invalid URL"; goto err; } rpc_client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "seafserv-rpcserver"); if (check_access_token (rpc_client, token, &repo_id, &user) < 0) { seaf_warning ("[upload] Invalid token.\n"); err_msg = "Access denied"; goto err; } boundary = get_boundary (hdr); if (!boundary) { goto err; } if (get_progress_info (req, hdr, &content_len, &progress_id) < 0) goto err; progress = g_new0 (Progress, 1); progress->size = content_len; fsm = g_new0 (RecvFSM, 1); fsm->boundary = boundary; fsm->repo_id = repo_id; fsm->user = user; fsm->line = evbuffer_new (); fsm->form_kvs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); fsm->progress_id = progress_id; fsm->progress = progress; pthread_mutex_lock (&pg_lock); g_hash_table_insert (upload_progress, g_strdup(progress_id), progress); pthread_mutex_unlock (&pg_lock); /* Set up per-request hooks, so that we can read file data piece by piece. */ evhtp_set_hook (&req->hooks, evhtp_hook_on_read, upload_read_cb, fsm); evhtp_set_hook (&req->hooks, evhtp_hook_on_request_fini, upload_finish_cb, fsm); /* Set arg for upload_cb or update_cb. */ req->cbarg = fsm; ccnet_rpc_client_free (rpc_client); return EVHTP_RES_OK; err: /* Don't receive any data before the connection is closed. */ evhtp_request_pause (req); /* Set keepalive to 0. This will cause evhtp to close the * connection after sending the reply. */ req->keepalive = 0; if (err_msg) evbuffer_add_printf (req->buffer_out, "%s\n", err_msg); evhtp_send_reply (req, EVHTP_RES_BADREQ); if (rpc_client) ccnet_rpc_client_free (rpc_client); g_free (repo_id); g_free (user); g_free (boundary); return EVHTP_RES_OK; }
static void update_cb(evhtp_request_t *req, void *arg) { RecvFSM *fsm = arg; SearpcClient *rpc_client = NULL; char *target_file, *parent_dir = NULL, *filename = NULL; const char *head_id = NULL; GError *error = NULL; int error_code = ERROR_INTERNAL; if (!fsm || fsm->state == RECV_ERROR) return; if (!fsm->tmp_files) { seaf_warning ("[update] No file uploaded.\n"); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } target_file = g_hash_table_lookup (fsm->form_kvs, "target_file"); if (!target_file) { seaf_warning ("[Update] No target file given.\n"); evbuffer_add_printf(req->buffer_out, "Invalid URL.\n"); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } parent_dir = g_path_get_dirname (target_file); filename = g_path_get_basename (target_file); if (!check_tmp_file_list (fsm->tmp_files, &error_code)) goto error; head_id = evhtp_kv_find (req->uri->query, "head"); rpc_client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "seafserv-threaded-rpcserver"); if (seafile_check_quota (rpc_client, fsm->repo_id, NULL) < 0) { seaf_warning ("[update] Out of quota.\n"); error_code = ERROR_QUOTA; goto error; } seafile_put_file (rpc_client, fsm->repo_id, (char *)(fsm->tmp_files->data), parent_dir, filename, fsm->user, head_id, &error); if (error) { if (g_strcmp0 (error->message, "file does not exist") == 0) { error_code = ERROR_NOT_EXIST; } if (error->message) printf ("%s\n", error->message); g_clear_error (&error); goto error; } ccnet_rpc_client_free (rpc_client); /* Redirect to repo dir page after upload finishes. */ redirect_to_success_page (req, fsm->repo_id, parent_dir); g_free (parent_dir); g_free (filename); return; error: if (rpc_client) ccnet_rpc_client_free (rpc_client); redirect_to_update_error (req, fsm->repo_id, target_file, error_code); g_free (parent_dir); g_free (filename); }
static void upload_cb(evhtp_request_t *req, void *arg) { RecvFSM *fsm = arg; SearpcClient *rpc_client = NULL; char *parent_dir; GError *error = NULL; int error_code = ERROR_INTERNAL; char *err_file = NULL; char *filenames_json, *tmp_files_json; /* After upload_headers_cb() returns an error, libevhtp may still * receive data from the web browser and call into this cb. * In this case fsm will be NULL. */ if (!fsm || fsm->state == RECV_ERROR) return; if (!fsm->tmp_files) { seaf_warning ("[upload] No file uploaded.\n"); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } parent_dir = g_hash_table_lookup (fsm->form_kvs, "parent_dir"); if (!parent_dir) { seaf_warning ("[upload] No parent dir given.\n"); evbuffer_add_printf(req->buffer_out, "Invalid URL.\n"); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } if (!check_tmp_file_list (fsm->tmp_files, &error_code)) goto error; rpc_client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "seafserv-threaded-rpcserver"); if (seafile_check_quota (rpc_client, fsm->repo_id, NULL) < 0) { seaf_warning ("[upload] Out of quota.\n"); error_code = ERROR_QUOTA; goto error; } filenames_json = file_list_to_json (fsm->uploaded_files); tmp_files_json = file_list_to_json (fsm->tmp_files); seafile_post_multi_files (rpc_client, fsm->repo_id, parent_dir, filenames_json, tmp_files_json, fsm->user, &error); g_free (filenames_json); g_free (tmp_files_json); if (error) { if (error->code == POST_FILE_ERR_FILENAME) { error_code = ERROR_FILENAME; err_file = g_strdup(error->message); } g_clear_error (&error); goto error; } ccnet_rpc_client_free (rpc_client); /* Redirect to repo dir page after upload finishes. */ redirect_to_success_page (req, fsm->repo_id, parent_dir); return; error: if (rpc_client) ccnet_rpc_client_free (rpc_client); redirect_to_upload_error (req, fsm->repo_id, parent_dir, err_file, error_code); g_free (err_file); }
static void update_api_cb(evhtp_request_t *req, void *arg) { RecvFSM *fsm = arg; SearpcClient *rpc_client = NULL; char *target_file, *parent_dir = NULL, *filename = NULL; const char *head_id = NULL; GError *error = NULL; int error_code = ERROR_INTERNAL; char *new_file_id = NULL; if (!fsm || fsm->state == RECV_ERROR) return; if (!fsm->files) { seaf_warning ("[update] No file uploaded.\n"); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } target_file = g_hash_table_lookup (fsm->form_kvs, "target_file"); if (!target_file) { seaf_warning ("[Update] No target file given.\n"); evbuffer_add_printf(req->buffer_out, "Invalid URL.\n"); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } parent_dir = g_path_get_dirname (target_file); filename = g_path_get_basename (target_file); if (!check_tmp_file_list (fsm->files, &error_code)) goto error; head_id = evhtp_kv_find (req->uri->query, "head"); rpc_client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "seafserv-threaded-rpcserver"); if (seafile_check_quota (rpc_client, fsm->repo_id, NULL) < 0) { seaf_warning ("[update] Out of quota.\n"); error_code = ERROR_QUOTA; goto error; } new_file_id = seafile_put_file (rpc_client, fsm->repo_id, (char *)(fsm->files->data), parent_dir, filename, fsm->user, head_id, &error); g_free (parent_dir); g_free (filename); if (error) { if (g_strcmp0 (error->message, "file does not exist") == 0) { error_code = ERROR_NOT_EXIST; } if (error->message) seaf_warning ("%s\n", error->message); g_clear_error (&error); goto error; } ccnet_rpc_client_free (rpc_client); /* Send back the new file id, so that the mobile client can update local cache */ evbuffer_add(req->buffer_out, new_file_id, strlen(new_file_id)); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_OK); g_free (new_file_id); return; error: if (rpc_client) ccnet_rpc_client_free (rpc_client); switch (error_code) { case ERROR_FILENAME: evbuffer_add_printf(req->buffer_out, "Invalid filename.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_BADFILENAME); break; case ERROR_EXISTS: evbuffer_add_printf(req->buffer_out, "File already exists.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_EXISTS); break; case ERROR_SIZE: evbuffer_add_printf(req->buffer_out, "File size is too large.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_TOOLARGE); break; case ERROR_QUOTA: evbuffer_add_printf(req->buffer_out, "Out of quota.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_NOQUOTA); break; case ERROR_NOT_EXIST: evbuffer_add_printf(req->buffer_out, "File does not exist.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_NOT_EXISTS); break; case ERROR_RECV: case ERROR_INTERNAL: default: set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_SERVERR); break; } }
/* Handle AJAX file upload. @return an array of json data, e.g. [{"name": "foo.txt"}] */ static void upload_ajax_cb(evhtp_request_t *req, void *arg) { RecvFSM *fsm = arg; SearpcClient *rpc_client = NULL; char *parent_dir; GError *error = NULL; int error_code = ERROR_INTERNAL; char *filenames_json, *tmp_files_json; evhtp_headers_add_header (req->headers_out, evhtp_header_new("Access-Control-Allow-Headers", "x-requested-with, content-type, accept, origin, authorization", 1, 1)); evhtp_headers_add_header (req->headers_out, evhtp_header_new("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS", 1, 1)); evhtp_headers_add_header (req->headers_out, evhtp_header_new("Access-Control-Allow-Origin", "*", 1, 1)); evhtp_headers_add_header (req->headers_out, evhtp_header_new("Access-Control-Max-Age", "86400", 1, 1)); if (evhtp_request_get_method(req) == htp_method_OPTIONS) { /* If CORS preflight header, then create an empty body response (200 OK) * and return it. */ evhtp_headers_add_header (req->headers_out, evhtp_header_new("Content-Type", "text/html; charset=utf-8", 1, 1)); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_OK); return; } /* After upload_headers_cb() returns an error, libevhtp may still * receive data from the web browser and call into this cb. * In this case fsm will be NULL. */ if (!fsm || fsm->state == RECV_ERROR) return; if (!fsm->files) { seaf_warning ("[upload] No file uploaded.\n"); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } parent_dir = g_hash_table_lookup (fsm->form_kvs, "parent_dir"); if (!parent_dir) { seaf_warning ("[upload] No parent dir given.\n"); evbuffer_add_printf(req->buffer_out, "Invalid URL.\n"); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } if (!check_tmp_file_list (fsm->files, &error_code)) goto error; rpc_client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "seafserv-threaded-rpcserver"); if (seafile_check_quota (rpc_client, fsm->repo_id, NULL) < 0) { seaf_warning ("[upload] Out of quota.\n"); error_code = ERROR_QUOTA; goto error; } filenames_json = file_list_to_json (fsm->filenames); tmp_files_json = file_list_to_json (fsm->files); seafile_post_multi_files (rpc_client, fsm->repo_id, parent_dir, filenames_json, tmp_files_json, fsm->user, &error); g_free (filenames_json); g_free (tmp_files_json); if (error) { if (error->code == POST_FILE_ERR_FILENAME) { error_code = ERROR_FILENAME; seaf_warning ("[upload] Bad filename.\n"); } g_clear_error (&error); goto error; } ccnet_rpc_client_free (rpc_client); GString *res_buf = g_string_new (NULL); GList *ptr; g_string_append (res_buf, "["); for (ptr = fsm->filenames; ptr; ptr = ptr->next) { char *filename = ptr->data; if (ptr->next) g_string_append_printf (res_buf, "{\"name\": \"%s\"}, ", filename); else g_string_append_printf (res_buf, "{\"name\": \"%s\"}", filename); } g_string_append (res_buf, "]"); evbuffer_add (req->buffer_out, res_buf->str, res_buf->len); g_string_free (res_buf, TRUE); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_OK); return; error: if (rpc_client) ccnet_rpc_client_free (rpc_client); switch (error_code) { case ERROR_FILENAME: evbuffer_add_printf(req->buffer_out, "Invalid filename.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_BADFILENAME); break; case ERROR_EXISTS: evbuffer_add_printf(req->buffer_out, "File already exists.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_EXISTS); break; case ERROR_SIZE: evbuffer_add_printf(req->buffer_out, "File size is too large.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_TOOLARGE); break; case ERROR_QUOTA: evbuffer_add_printf(req->buffer_out, "Out of quota.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_NOQUOTA); break; case ERROR_RECV: case ERROR_INTERNAL: set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_SERVERR); break; } }
static void upload_api_cb(evhtp_request_t *req, void *arg) { RecvFSM *fsm = arg; SearpcClient *rpc_client = NULL; char *parent_dir; GError *error = NULL; int error_code = ERROR_INTERNAL; char *filenames_json, *tmp_files_json; /* After upload_headers_cb() returns an error, libevhtp may still * receive data from the web browser and call into this cb. * In this case fsm will be NULL. */ if (!fsm || fsm->state == RECV_ERROR) return; if (!fsm->files) { seaf_warning ("[upload] No file uploaded.\n"); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } parent_dir = g_hash_table_lookup (fsm->form_kvs, "parent_dir"); if (!parent_dir) { seaf_warning ("[upload] No parent dir given.\n"); evbuffer_add_printf(req->buffer_out, "Invalid URL.\n"); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } if (!check_tmp_file_list (fsm->files, &error_code)) goto error; rpc_client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "seafserv-threaded-rpcserver"); if (seafile_check_quota (rpc_client, fsm->repo_id, NULL) < 0) { seaf_warning ("[upload] Out of quota.\n"); error_code = ERROR_QUOTA; goto error; } filenames_json = file_list_to_json (fsm->filenames); tmp_files_json = file_list_to_json (fsm->files); char *new_file_ids = seafile_post_multi_files (rpc_client, fsm->repo_id, parent_dir, filenames_json, tmp_files_json, fsm->user, &error); g_free (filenames_json); g_free (tmp_files_json); if (error) { if (error->code == POST_FILE_ERR_FILENAME) { error_code = ERROR_FILENAME; seaf_warning ("[upload] Bad filename.\n"); } g_clear_error (&error); goto error; } ccnet_rpc_client_free (rpc_client); evbuffer_add (req->buffer_out, new_file_ids, strlen(new_file_ids)); g_free (new_file_ids); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_OK); return; error: if (rpc_client) ccnet_rpc_client_free (rpc_client); switch (error_code) { case ERROR_FILENAME: evbuffer_add_printf(req->buffer_out, "Invalid filename.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_BADFILENAME); break; case ERROR_EXISTS: evbuffer_add_printf(req->buffer_out, "File already exists.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_EXISTS); break; case ERROR_SIZE: evbuffer_add_printf(req->buffer_out, "File size is too large.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_TOOLARGE); break; case ERROR_QUOTA: evbuffer_add_printf(req->buffer_out, "Out of quota.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_NOQUOTA); break; case ERROR_RECV: case ERROR_INTERNAL: set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_SERVERR); break; } }