1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 #include "common.h"
4 #include <glib/gstdio.h>
5 #include <ctype.h>
6 
7 #include <sys/stat.h>
8 #include <dirent.h>
9 #include "utils.h"
10 
11 #include "seafile-session.h"
12 #include "fs-mgr.h"
13 #include "repo-mgr.h"
14 #include "seafile-error.h"
15 #include "seafile-rpc.h"
16 #include "mq-mgr.h"
17 
18 #ifdef SEAFILE_SERVER
19 #include "web-accesstoken-mgr.h"
20 #endif
21 
22 #ifndef SEAFILE_SERVER
23 #include "seafile-config.h"
24 #endif
25 
26 #define DEBUG_FLAG SEAFILE_DEBUG_OTHER
27 #include "log.h"
28 
29 #define CCNET_ERR_INTERNAL 500
30 
31 #ifndef SEAFILE_SERVER
32 #include "../daemon/vc-utils.h"
33 
34 #endif  /* SEAFILE_SERVER */
35 
36 
37 /* -------- Utilities -------- */
38 static GObject*
convert_repo(SeafRepo * r)39 convert_repo (SeafRepo *r)
40 {
41     SeafileRepo *repo = NULL;
42 
43 #ifndef SEAFILE_SERVER
44     if (r->head == NULL)
45         return NULL;
46 
47     if (r->worktree_invalid && !seafile_session_config_get_allow_invalid_worktree(seaf))
48         return NULL;
49 #endif
50 
51     repo = seafile_repo_new ();
52     if (!repo)
53         return NULL;
54 
55     g_object_set (repo, "id", r->id, "name", r->name,
56                   "desc", r->desc, "encrypted", r->encrypted,
57                   "magic", r->magic, "enc_version", r->enc_version,
58                   "head_cmmt_id", r->head ? r->head->commit_id : NULL,
59                   "root", r->root_id,
60                   "version", r->version, "last_modify", r->last_modify,
61                   "last_modifier", r->last_modifier,
62                   NULL);
63     g_object_set (repo,
64                   "repo_id", r->id, "repo_name", r->name,
65                   "repo_desc", r->desc, "last_modified", r->last_modify,
66                   "status", r->status,
67                   NULL);
68 
69 #ifdef SEAFILE_SERVER
70     if (r->virtual_info) {
71         g_object_set (repo,
72                       "is_virtual", TRUE,
73                       "origin_repo_id", r->virtual_info->origin_repo_id,
74                       "origin_path", r->virtual_info->path,
75                       NULL);
76     }
77 
78     if (r->encrypted) {
79         if (r->enc_version >= 2)
80             g_object_set (repo, "random_key", r->random_key, NULL);
81         if (r->enc_version >= 3)
82             g_object_set (repo, "salt", r->salt, NULL);
83     }
84 
85     g_object_set (repo, "store_id", r->store_id,
86                   "repaired", r->repaired,
87                   "size", r->size, "file_count", r->file_count, NULL);
88     g_object_set (repo, "is_corrupted", r->is_corrupted, NULL);
89 #endif
90 
91 #ifndef SEAFILE_SERVER
92     g_object_set (repo, "worktree", r->worktree,
93                   "relay-id", r->relay_id,
94                   "worktree-invalid", r->worktree_invalid,
95                   "last-sync-time", r->last_sync_time,
96                   "auto-sync", r->auto_sync,
97                   NULL);
98 
99 #endif  /* SEAFILE_SERVER */
100 
101     return (GObject *)repo;
102 }
103 
104 static void
free_repo_obj(gpointer repo)105 free_repo_obj (gpointer repo)
106 {
107     if (!repo)
108         return;
109     g_object_unref ((GObject *)repo);
110 }
111 
112 static GList *
convert_repo_list(GList * inner_repos)113 convert_repo_list (GList *inner_repos)
114 {
115     GList *ret = NULL, *ptr;
116     GObject *repo = NULL;
117 
118     for (ptr = inner_repos; ptr; ptr=ptr->next) {
119         SeafRepo *r = ptr->data;
120         repo = convert_repo (r);
121         if (!repo) {
122             g_list_free_full (ret, free_repo_obj);
123             return NULL;
124         }
125 
126         ret = g_list_prepend (ret, repo);
127     }
128 
129     return g_list_reverse (ret);
130 }
131 
132 /*
133  * RPC functions available for both clients and server.
134  */
135 
136 GList *
seafile_branch_gets(const char * repo_id,GError ** error)137 seafile_branch_gets (const char *repo_id, GError **error)
138 {
139     if (!is_uuid_valid (repo_id)) {
140         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
141         return NULL;
142     }
143 
144     GList *blist = seaf_branch_manager_get_branch_list(seaf->branch_mgr,
145                                                        repo_id);
146     GList *ptr;
147     GList *ret = NULL;
148 
149     for (ptr = blist; ptr; ptr=ptr->next) {
150         SeafBranch *b = ptr->data;
151         SeafileBranch *branch = seafile_branch_new ();
152         g_object_set (branch, "repo_id", b->repo_id, "name", b->name,
153                       "commit_id", b->commit_id, NULL);
154         ret = g_list_prepend (ret, branch);
155         seaf_branch_unref (b);
156     }
157     ret = g_list_reverse (ret);
158     g_list_free (blist);
159     return ret;
160 }
161 
162 #ifdef SEAFILE_SERVER
163 GList*
seafile_get_trash_repo_list(int start,int limit,GError ** error)164 seafile_get_trash_repo_list (int start, int limit, GError **error)
165 {
166     return seaf_repo_manager_get_trash_repo_list (seaf->repo_mgr,
167                                                   start, limit,
168                                                   error);
169 }
170 
171 GList *
seafile_get_trash_repos_by_owner(const char * owner,GError ** error)172 seafile_get_trash_repos_by_owner (const char *owner, GError **error)
173 {
174     if (!owner) {
175         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
176         return NULL;
177     }
178 
179     return seaf_repo_manager_get_trash_repos_by_owner (seaf->repo_mgr,
180                                                        owner,
181                                                        error);
182 }
183 
184 int
seafile_del_repo_from_trash(const char * repo_id,GError ** error)185 seafile_del_repo_from_trash (const char *repo_id, GError **error)
186 {
187     int ret = 0;
188 
189     if (!repo_id) {
190         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
191         return -1;
192     }
193     if (!is_uuid_valid (repo_id)) {
194         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
195         return -1;
196     }
197 
198     ret = seaf_repo_manager_del_repo_from_trash (seaf->repo_mgr, repo_id, error);
199 
200     return ret;
201 }
202 
203 int
seafile_empty_repo_trash(GError ** error)204 seafile_empty_repo_trash (GError **error)
205 {
206     return seaf_repo_manager_empty_repo_trash (seaf->repo_mgr, error);
207 }
208 
209 int
seafile_empty_repo_trash_by_owner(const char * owner,GError ** error)210 seafile_empty_repo_trash_by_owner (const char *owner, GError **error)
211 {
212     if (!owner) {
213         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
214         return -1;
215     }
216 
217     return seaf_repo_manager_empty_repo_trash_by_owner (seaf->repo_mgr, owner, error);
218 }
219 
220 int
seafile_restore_repo_from_trash(const char * repo_id,GError ** error)221 seafile_restore_repo_from_trash (const char *repo_id, GError **error)
222 {
223     int ret = 0;
224 
225     if (!repo_id) {
226         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
227         return -1;
228     }
229     if (!is_uuid_valid (repo_id)) {
230         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
231         return -1;
232     }
233 
234     ret = seaf_repo_manager_restore_repo_from_trash (seaf->repo_mgr, repo_id, error);
235 
236     return ret;
237 }
238 
239 int
seafile_publish_event(const char * channel,const char * content,GError ** error)240 seafile_publish_event(const char *channel, const char *content, GError **error)
241 {
242     int ret = 0;
243 
244     if (!channel || !content) {
245         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
246         return -1;
247     }
248 
249     ret = seaf_mq_manager_publish_event (seaf->mq_mgr, channel, content);
250 
251     return ret;
252 }
253 
254 json_t *
seafile_pop_event(const char * channel,GError ** error)255 seafile_pop_event(const char *channel, GError **error)
256 {
257     if (!channel) {
258         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
259         return NULL;
260     }
261     return seaf_mq_manager_pop_event (seaf->mq_mgr, channel);
262 }
263 #endif
264 
265 GList*
seafile_get_repo_list(int start,int limit,const char * order_by,GError ** error)266 seafile_get_repo_list (int start, int limit, const char *order_by, GError **error)
267 {
268     GList *repos = seaf_repo_manager_get_repo_list(seaf->repo_mgr, start, limit, order_by);
269     GList *ret = NULL;
270 
271     ret = convert_repo_list (repos);
272 
273 #ifdef SEAFILE_SERVER
274     GList *ptr;
275     for (ptr = repos; ptr != NULL; ptr = ptr->next)
276         seaf_repo_unref ((SeafRepo *)ptr->data);
277 #endif
278     g_list_free (repos);
279 
280     return ret;
281 }
282 
283 #ifdef SEAFILE_SERVER
284 gint64
seafile_count_repos(GError ** error)285 seafile_count_repos (GError **error)
286 {
287     return seaf_repo_manager_count_repos (seaf->repo_mgr, error);
288 }
289 #endif
290 
291 GObject*
seafile_get_repo(const char * repo_id,GError ** error)292 seafile_get_repo (const char *repo_id, GError **error)
293 {
294     SeafRepo *r;
295 
296     if (!repo_id) {
297         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
298         return NULL;
299     }
300     if (!is_uuid_valid (repo_id)) {
301         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
302         return NULL;
303     }
304 
305     r = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
306     /* Don't return repo that's not checked out. */
307     if (r == NULL)
308         return NULL;
309 
310     GObject *repo = convert_repo (r);
311 
312 #ifdef SEAFILE_SERVER
313     seaf_repo_unref (r);
314 #endif
315 
316     return repo;
317 }
318 
319 SeafileCommit *
convert_to_seafile_commit(SeafCommit * c)320 convert_to_seafile_commit (SeafCommit *c)
321 {
322     SeafileCommit *commit = seafile_commit_new ();
323     g_object_set (commit,
324                   "id", c->commit_id,
325                   "creator_name", c->creator_name,
326                   "creator", c->creator_id,
327                   "desc", c->desc,
328                   "ctime", c->ctime,
329                   "repo_id", c->repo_id,
330                   "root_id", c->root_id,
331                   "parent_id", c->parent_id,
332                   "second_parent_id", c->second_parent_id,
333                   "version", c->version,
334                   "new_merge", c->new_merge,
335                   "conflict", c->conflict,
336                   "device_name", c->device_name,
337                   "client_version", c->client_version,
338                   NULL);
339     return commit;
340 }
341 
342 GObject*
seafile_get_commit(const char * repo_id,int version,const gchar * id,GError ** error)343 seafile_get_commit (const char *repo_id, int version,
344                     const gchar *id, GError **error)
345 {
346     SeafileCommit *commit;
347     SeafCommit *c;
348 
349     if (!repo_id || !is_uuid_valid(repo_id)) {
350         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
351         return NULL;
352     }
353 
354     if (!id || !is_object_id_valid(id)) {
355         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid commit id");
356         return NULL;
357     }
358 
359     c = seaf_commit_manager_get_commit (seaf->commit_mgr, repo_id, version, id);
360     if (!c)
361         return NULL;
362 
363     commit = convert_to_seafile_commit (c);
364     seaf_commit_unref (c);
365     return (GObject *)commit;
366 }
367 
368 struct CollectParam {
369     int offset;
370     int limit;
371     int count;
372     GList *commits;
373 #ifdef SEAFILE_SERVER
374     gint64 truncate_time;
375     gboolean traversed_head;
376 #endif
377 };
378 
379 static gboolean
get_commit(SeafCommit * c,void * data,gboolean * stop)380 get_commit (SeafCommit *c, void *data, gboolean *stop)
381 {
382     struct CollectParam *cp = data;
383 
384 #ifdef SEAFILE_SERVER
385     if (cp->truncate_time == 0)
386     {
387         *stop = TRUE;
388         /* Stop after traversing the head commit. */
389     }
390     /* We use <= here. This is for handling clean trash and history.
391      * If the user cleans all history, truncate time will be equal to
392      * the commit's ctime. In such case, we don't actually want to display
393      * this commit.
394      */
395     else if (cp->truncate_time > 0 &&
396              (gint64)(c->ctime) <= cp->truncate_time &&
397              cp->traversed_head)
398     {
399         *stop = TRUE;
400         return TRUE;
401     }
402 
403     /* Always traverse the head commit. */
404     if (!cp->traversed_head)
405         cp->traversed_head = TRUE;
406 #endif
407 
408     /* if offset = 1, limit = 1, we should stop when the count = 2 */
409     if (cp->limit > 0 && cp->count >= cp->offset + cp->limit) {
410         *stop = TRUE;
411         return TRUE;  /* TRUE to indicate no error */
412     }
413 
414     if (cp->count >= cp->offset) {
415         SeafileCommit *commit = convert_to_seafile_commit (c);
416         cp->commits = g_list_prepend (cp->commits, commit);
417     }
418 
419     ++cp->count;
420     return TRUE;                /* TRUE to indicate no error */
421 }
422 
423 
424 GList*
seafile_get_commit_list(const char * repo_id,int offset,int limit,GError ** error)425 seafile_get_commit_list (const char *repo_id,
426                          int offset,
427                          int limit,
428                          GError **error)
429 {
430     SeafRepo *repo;
431     GList *commits = NULL;
432     gboolean ret;
433     struct CollectParam cp;
434     char *commit_id;
435 
436     if (!is_uuid_valid (repo_id)) {
437         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
438         return NULL;
439     }
440 
441     /* correct parameter */
442     if (offset < 0)
443         offset = 0;
444 
445     if (!repo_id) {
446         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
447         return NULL;
448     }
449 
450     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
451     if (!repo) {
452         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_REPO, "No such repository");
453         return NULL;
454     }
455 
456     if (!repo->head) {
457         SeafBranch *branch =
458             seaf_branch_manager_get_branch (seaf->branch_mgr,
459                                             repo->id, "master");
460         if (branch != NULL) {
461             commit_id = g_strdup (branch->commit_id);
462             seaf_branch_unref (branch);
463         } else {
464             seaf_warning ("[repo-mgr] Failed to get repo %s branch master\n",
465                        repo_id);
466             g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_REPO,
467                          "No head and branch master");
468 #ifdef SEAFILE_SERVER
469             seaf_repo_unref (repo);
470 #endif
471             return NULL;
472         }
473     } else {
474         commit_id = g_strdup (repo->head->commit_id);
475     }
476 
477     /* Init CollectParam */
478     memset (&cp, 0, sizeof(cp));
479     cp.offset = offset;
480     cp.limit = limit;
481 
482 #ifdef SEAFILE_SERVER
483     cp.truncate_time = seaf_repo_manager_get_repo_truncate_time (seaf->repo_mgr,
484                                                                  repo_id);
485 #endif
486 
487     ret =
488         seaf_commit_manager_traverse_commit_tree (seaf->commit_mgr,
489                                                   repo->id, repo->version,
490                                                   commit_id, get_commit, &cp, TRUE);
491     g_free (commit_id);
492 #ifdef SEAFILE_SERVER
493     seaf_repo_unref (repo);
494 #endif
495 
496     if (!ret) {
497         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_LIST_COMMITS, "Failed to list commits");
498         return NULL;
499     }
500 
501     commits = g_list_reverse (cp.commits);
502     return commits;
503 }
504 
505 #ifndef SEAFILE_SERVER
506 static
do_unsync_repo(SeafRepo * repo)507 int do_unsync_repo(SeafRepo *repo)
508 {
509     if (!seaf->started) {
510         seaf_message ("System not started, skip removing repo.\n");
511         return -1;
512     }
513 
514     if (repo->auto_sync && (repo->sync_interval == 0))
515         seaf_wt_monitor_unwatch_repo (seaf->wt_monitor, repo->id);
516 
517     seaf_sync_manager_cancel_sync_task (seaf->sync_mgr, repo->id);
518 
519     SyncInfo *info = seaf_sync_manager_get_sync_info (seaf->sync_mgr, repo->id);
520 
521     /* If we are syncing the repo,
522      * we just mark the repo as deleted and let sync-mgr actually delete it.
523      * Otherwise we are safe to delete the repo.
524      */
525     char *worktree = g_strdup (repo->worktree);
526     if (info != NULL && info->in_sync) {
527         seaf_repo_manager_mark_repo_deleted (seaf->repo_mgr, repo);
528     } else {
529         seaf_repo_manager_del_repo (seaf->repo_mgr, repo);
530     }
531 
532     g_free (worktree);
533 
534     return 0;
535 }
536 
537 static void
cancel_clone_tasks_by_account(const char * account_server,const char * account_email)538 cancel_clone_tasks_by_account (const char *account_server, const char *account_email)
539 {
540     GList *ptr, *tasks;
541     CloneTask *task;
542 
543     tasks = seaf_clone_manager_get_tasks (seaf->clone_mgr);
544     for (ptr = tasks; ptr != NULL; ptr = ptr->next) {
545         task = ptr->data;
546 
547         if (g_strcmp0(account_server, task->peer_addr) == 0
548             && g_strcmp0(account_email, task->email) == 0) {
549             seaf_clone_manager_cancel_task (seaf->clone_mgr, task->repo_id);
550         }
551     }
552 
553     g_list_free (tasks);
554 }
555 
556 int
seafile_unsync_repos_by_account(const char * server_addr,const char * email,GError ** error)557 seafile_unsync_repos_by_account (const char *server_addr, const char *email, GError **error)
558 {
559     if (!server_addr || !email) {
560         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
561         return -1;
562     }
563 
564     GList *ptr, *repos = seaf_repo_manager_get_repo_list(seaf->repo_mgr, -1, -1);
565     if (!repos) {
566         return 0;
567     }
568 
569     for (ptr = repos; ptr; ptr = ptr->next) {
570         SeafRepo *repo = (SeafRepo*)ptr->data;
571         char *addr = NULL;
572         seaf_repo_manager_get_repo_relay_info(seaf->repo_mgr,
573                                               repo->id,
574                                               &addr, /* addr */
575                                               NULL); /* port */
576 
577         if (g_strcmp0(addr, server_addr) == 0 && g_strcmp0(repo->email, email) == 0) {
578             if (do_unsync_repo(repo) < 0) {
579                 return -1;
580             }
581         }
582 
583         g_free (addr);
584     }
585 
586     g_list_free (repos);
587 
588     cancel_clone_tasks_by_account (server_addr, email);
589 
590     return 0;
591 }
592 
593 int
seafile_remove_repo_tokens_by_account(const char * server_addr,const char * email,GError ** error)594 seafile_remove_repo_tokens_by_account (const char *server_addr, const char *email, GError **error)
595 {
596     if (!server_addr || !email) {
597         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
598         return -1;
599     }
600 
601     GList *ptr, *repos = seaf_repo_manager_get_repo_list(seaf->repo_mgr, -1, -1);
602     if (!repos) {
603         return 0;
604     }
605 
606     for (ptr = repos; ptr; ptr = ptr->next) {
607         SeafRepo *repo = (SeafRepo*)ptr->data;
608         char *addr = NULL;
609         seaf_repo_manager_get_repo_relay_info(seaf->repo_mgr,
610                                               repo->id,
611                                               &addr, /* addr */
612                                               NULL); /* port */
613 
614         if (g_strcmp0(addr, server_addr) == 0 && g_strcmp0(repo->email, email) == 0) {
615             if (seaf_repo_manager_remove_repo_token(seaf->repo_mgr, repo) < 0) {
616                 return -1;
617             }
618         }
619 
620         g_free (addr);
621     }
622 
623     g_list_free (repos);
624 
625     cancel_clone_tasks_by_account (server_addr, email);
626 
627     return 0;
628 }
629 
630 int
seafile_set_repo_token(const char * repo_id,const char * token,GError ** error)631 seafile_set_repo_token (const char *repo_id,
632                         const char *token,
633                         GError **error)
634 {
635     int ret;
636 
637     if (repo_id == NULL || token == NULL) {
638         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments should not be empty");
639         return -1;
640     }
641 
642     SeafRepo *repo;
643     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
644     if (!repo) {
645         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_REPO, "Can't find Repo %s", repo_id);
646         return -1;
647     }
648 
649     ret = seaf_repo_manager_set_repo_token (seaf->repo_mgr,
650                                             repo, token);
651     if (ret < 0) {
652         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL,
653                      "Failed to set token for repo %s", repo_id);
654         return -1;
655     }
656 
657     return 0;
658 }
659 
660 #endif
661 
662 int
seafile_destroy_repo(const char * repo_id,GError ** error)663 seafile_destroy_repo (const char *repo_id, GError **error)
664 {
665     if (!repo_id) {
666         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
667         return -1;
668     }
669     if (!is_uuid_valid (repo_id)) {
670         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
671         return -1;
672     }
673 
674 #ifndef SEAFILE_SERVER
675     SeafRepo *repo;
676 
677     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
678     if (!repo) {
679         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "No such repository");
680         return -1;
681     }
682 
683     return do_unsync_repo(repo);
684 #else
685 
686     return seaf_repo_manager_del_repo (seaf->repo_mgr, repo_id, error);
687 #endif
688 }
689 
690 
691 GObject *
seafile_generate_magic_and_random_key(int enc_version,const char * repo_id,const char * passwd,GError ** error)692 seafile_generate_magic_and_random_key(int enc_version,
693                                       const char* repo_id,
694                                       const char *passwd,
695                                       GError **error)
696 {
697     if (!repo_id || !passwd) {
698         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
699         return NULL;
700     }
701 
702     gchar salt[65] = {0};
703     gchar magic[65] = {0};
704     gchar random_key[97] = {0};
705 
706     if (enc_version >= 3 && seafile_generate_repo_salt (salt) < 0) {
707         return NULL;
708     }
709 
710     seafile_generate_magic (enc_version, repo_id, passwd, salt, magic);
711     if (seafile_generate_random_key (passwd, enc_version, salt, random_key) < 0) {
712         return NULL;
713     }
714 
715     SeafileEncryptionInfo *sinfo;
716     sinfo = g_object_new (SEAFILE_TYPE_ENCRYPTION_INFO,
717                           "repo_id", repo_id,
718                           "passwd", passwd,
719                           "enc_version", enc_version,
720                           "magic", magic,
721                           "random_key", random_key,
722                           NULL);
723     if (enc_version >= 3)
724         g_object_set (sinfo, "salt", salt, NULL);
725 
726     return (GObject *)sinfo;
727 
728 }
729 
730 #include "diff-simple.h"
731 
732 inline static const char*
get_diff_status_str(char status)733 get_diff_status_str(char status)
734 {
735     if (status == DIFF_STATUS_ADDED)
736         return "add";
737     if (status == DIFF_STATUS_DELETED)
738         return "del";
739     if (status == DIFF_STATUS_MODIFIED)
740         return "mod";
741     if (status == DIFF_STATUS_RENAMED)
742         return "mov";
743     if (status == DIFF_STATUS_DIR_ADDED)
744         return "newdir";
745     if (status == DIFF_STATUS_DIR_DELETED)
746         return "deldir";
747     return NULL;
748 }
749 
750 GList *
seafile_diff(const char * repo_id,const char * arg1,const char * arg2,int fold_dir_results,GError ** error)751 seafile_diff (const char *repo_id, const char *arg1, const char *arg2, int fold_dir_results, GError **error)
752 {
753     SeafRepo *repo;
754     char *err_msgs = NULL;
755     GList *diff_entries, *p;
756     GList *ret = NULL;
757 
758     if (!repo_id || !arg1 || !arg2) {
759         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
760         return NULL;
761     }
762 
763     if (!is_uuid_valid (repo_id)) {
764         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
765         return NULL;
766     }
767 
768     if ((arg1[0] != 0 && !is_object_id_valid (arg1)) || !is_object_id_valid(arg2)) {
769         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid commit id");
770         return NULL;
771     }
772 
773     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
774     if (!repo) {
775         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "No such repository");
776         return NULL;
777     }
778 
779     diff_entries = seaf_repo_diff (repo, arg1, arg2, fold_dir_results, &err_msgs);
780     if (err_msgs) {
781         g_set_error (error, SEAFILE_DOMAIN, -1, "%s", err_msgs);
782         g_free (err_msgs);
783 #ifdef SEAFILE_SERVER
784         seaf_repo_unref (repo);
785 #endif
786         return NULL;
787     }
788 
789 #ifdef SEAFILE_SERVER
790     seaf_repo_unref (repo);
791 #endif
792 
793     for (p = diff_entries; p != NULL; p = p->next) {
794         DiffEntry *de = p->data;
795         SeafileDiffEntry *entry = g_object_new (
796             SEAFILE_TYPE_DIFF_ENTRY,
797             "status", get_diff_status_str(de->status),
798             "name", de->name,
799             "new_name", de->new_name,
800             NULL);
801         ret = g_list_prepend (ret, entry);
802     }
803 
804     for (p = diff_entries; p != NULL; p = p->next) {
805         DiffEntry *de = p->data;
806         diff_entry_free (de);
807     }
808     g_list_free (diff_entries);
809 
810     return g_list_reverse (ret);
811 }
812 
813 /*
814  * RPC functions only available for server.
815  */
816 
817 #ifdef SEAFILE_SERVER
818 
819 GList *
seafile_list_dir_by_path(const char * repo_id,const char * commit_id,const char * path,GError ** error)820 seafile_list_dir_by_path(const char *repo_id,
821                          const char *commit_id,
822                          const char *path, GError **error)
823 {
824     SeafRepo *repo = NULL;
825     SeafCommit *commit = NULL;
826     SeafDir *dir;
827     SeafDirent *dent;
828     SeafileDirent *d;
829 
830     GList *ptr;
831     GList *res = NULL;
832 
833     if (!repo_id || !commit_id || !path) {
834         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
835                      "Args can't be NULL");
836         return NULL;
837     }
838 
839     if (!is_uuid_valid (repo_id)) {
840         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
841                      "Invalid repo id");
842         return NULL;
843     }
844 
845     if (!is_object_id_valid (commit_id)) {
846         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
847                      "Invalid commit id");
848         return NULL;
849     }
850 
851     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
852     if (!repo) {
853         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad repo id");
854         return NULL;
855     }
856 
857     commit = seaf_commit_manager_get_commit (seaf->commit_mgr,
858                                              repo_id, repo->version,
859                                              commit_id);
860 
861     if (!commit) {
862         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_COMMIT, "No such commit");
863         goto out;
864     }
865 
866     char *rpath = format_dir_path (path);
867     dir = seaf_fs_manager_get_seafdir_by_path (seaf->fs_mgr,
868                                                repo->store_id,
869                                                repo->version,
870                                                commit->root_id,
871                                                rpath, error);
872     g_free (rpath);
873 
874     if (!dir) {
875         seaf_warning ("Can't find seaf dir for %s in repo %s\n", path, repo->store_id);
876         goto out;
877     }
878 
879     for (ptr = dir->entries; ptr != NULL; ptr = ptr->next) {
880         dent = ptr->data;
881 
882         if (!is_object_id_valid (dent->id))
883             continue;
884 
885         d = g_object_new (SEAFILE_TYPE_DIRENT,
886                           "obj_id", dent->id,
887                           "obj_name", dent->name,
888                           "mode", dent->mode,
889                           "version", dent->version,
890                           "mtime", dent->mtime,
891                           "size", dent->size,
892                           NULL);
893         res = g_list_prepend (res, d);
894     }
895 
896     seaf_dir_free (dir);
897     res = g_list_reverse (res);
898 
899 out:
900     seaf_repo_unref (repo);
901     seaf_commit_unref (commit);
902     return res;
903 }
904 
905 static void
filter_error(GError ** error)906 filter_error (GError **error)
907 {
908     if (*error && g_error_matches(*error,
909                                   SEAFILE_DOMAIN,
910                                   SEAF_ERR_PATH_NO_EXIST)) {
911         g_clear_error (error);
912     }
913 }
914 
915 char *
seafile_get_dir_id_by_commit_and_path(const char * repo_id,const char * commit_id,const char * path,GError ** error)916 seafile_get_dir_id_by_commit_and_path(const char *repo_id,
917                                       const char *commit_id,
918                                       const char *path,
919                                       GError **error)
920 {
921     SeafRepo *repo = NULL;
922     char *res = NULL;
923     SeafCommit *commit = NULL;
924     SeafDir *dir;
925 
926     if (!repo_id || !commit_id || !path) {
927         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
928                      "Args can't be NULL");
929         return NULL;
930     }
931 
932     if (!is_uuid_valid (repo_id)) {
933         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
934                      "Invalid repo id");
935         return NULL;
936     }
937 
938     if (!is_object_id_valid (commit_id)) {
939         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
940                      "Invalid commit id");
941         return NULL;
942     }
943 
944     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
945     if (!repo) {
946         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad repo id");
947         return NULL;
948     }
949 
950     commit = seaf_commit_manager_get_commit (seaf->commit_mgr,
951                                              repo_id, repo->version,
952                                              commit_id);
953 
954     if (!commit) {
955         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_COMMIT, "No such commit");
956         goto out;
957     }
958 
959     char *rpath = format_dir_path (path);
960 
961     dir = seaf_fs_manager_get_seafdir_by_path (seaf->fs_mgr,
962                                                repo->store_id,
963                                                repo->version,
964                                                commit->root_id,
965                                                rpath, error);
966     g_free (rpath);
967 
968     if (!dir) {
969         seaf_warning ("Can't find seaf dir for %s in repo %s\n", path, repo->store_id);
970         filter_error (error);
971         goto out;
972     }
973 
974     res = g_strdup (dir->dir_id);
975     seaf_dir_free (dir);
976 
977  out:
978     seaf_repo_unref (repo);
979     seaf_commit_unref (commit);
980     return res;
981 }
982 
983 int
seafile_edit_repo(const char * repo_id,const char * name,const char * description,const char * user,GError ** error)984 seafile_edit_repo (const char *repo_id,
985                    const char *name,
986                    const char *description,
987                    const char *user,
988                    GError **error)
989 {
990     return seaf_repo_manager_edit_repo (repo_id, name, description, user, error);
991 }
992 
993 int
seafile_change_repo_passwd(const char * repo_id,const char * old_passwd,const char * new_passwd,const char * user,GError ** error)994 seafile_change_repo_passwd (const char *repo_id,
995                             const char *old_passwd,
996                             const char *new_passwd,
997                             const char *user,
998                             GError **error)
999 {
1000     SeafRepo *repo = NULL;
1001     SeafCommit *commit = NULL, *parent = NULL;
1002     int ret = 0;
1003 
1004     if (!user) {
1005         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1006                      "No user given");
1007         return -1;
1008     }
1009 
1010     if (!old_passwd || old_passwd[0] == 0 || !new_passwd || new_passwd[0] == 0) {
1011         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1012                      "Empty passwd");
1013         return -1;
1014     }
1015 
1016     if (!is_uuid_valid (repo_id)) {
1017         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1018         return -1;
1019     }
1020 
1021 retry:
1022     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
1023     if (!repo) {
1024         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "No such library");
1025         return -1;
1026     }
1027 
1028     if (!repo->encrypted) {
1029         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Repo not encrypted");
1030         return -1;
1031     }
1032 
1033     if (repo->enc_version < 2) {
1034         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1035                      "Unsupported enc version");
1036         return -1;
1037     }
1038 
1039     if (seafile_verify_repo_passwd (repo_id, old_passwd, repo->magic,
1040                                     repo->enc_version, repo->salt) < 0) {
1041         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Incorrect password");
1042         return -1;
1043     }
1044 
1045     parent = seaf_commit_manager_get_commit (seaf->commit_mgr,
1046                                              repo->id, repo->version,
1047                                              repo->head->commit_id);
1048     if (!parent) {
1049         seaf_warning ("Failed to get commit %s:%s.\n",
1050                       repo->id, repo->head->commit_id);
1051         ret = -1;
1052         goto out;
1053     }
1054 
1055     char new_magic[65], new_random_key[97];
1056 
1057     seafile_generate_magic (repo->enc_version, repo_id, new_passwd, repo->salt, new_magic);
1058     if (seafile_update_random_key (old_passwd, repo->random_key,
1059                                    new_passwd, new_random_key,
1060                                    repo->enc_version, repo->salt) < 0) {
1061         ret = -1;
1062         goto out;
1063     }
1064 
1065     memcpy (repo->magic, new_magic, 64);
1066     memcpy (repo->random_key, new_random_key, 96);
1067 
1068     commit = seaf_commit_new (NULL,
1069                               repo->id,
1070                               parent->root_id,
1071                               user,
1072                               EMPTY_SHA1,
1073                               "Changed library password",
1074                               0);
1075     commit->parent_id = g_strdup(parent->commit_id);
1076     seaf_repo_to_commit (repo, commit);
1077 
1078     if (seaf_commit_manager_add_commit (seaf->commit_mgr, commit) < 0) {
1079         ret = -1;
1080         goto out;
1081     }
1082 
1083     seaf_branch_set_commit (repo->head, commit->commit_id);
1084     if (seaf_branch_manager_test_and_update_branch (seaf->branch_mgr,
1085                                                     repo->head,
1086                                                     parent->commit_id) < 0) {
1087         seaf_repo_unref (repo);
1088         seaf_commit_unref (commit);
1089         seaf_commit_unref (parent);
1090         repo = NULL;
1091         commit = NULL;
1092         parent = NULL;
1093         goto retry;
1094     }
1095 
1096     if (seaf_passwd_manager_is_passwd_set (seaf->passwd_mgr, repo_id, user))
1097         seaf_passwd_manager_set_passwd (seaf->passwd_mgr, repo_id,
1098                                         user, new_passwd, error);
1099 
1100 out:
1101     seaf_commit_unref (commit);
1102     seaf_commit_unref (parent);
1103     seaf_repo_unref (repo);
1104 
1105     return ret;
1106 }
1107 
1108 int
seafile_is_repo_owner(const char * email,const char * repo_id,GError ** error)1109 seafile_is_repo_owner (const char *email,
1110                        const char *repo_id,
1111                        GError **error)
1112 {
1113     if (!is_uuid_valid (repo_id)) {
1114         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1115         return 0;
1116     }
1117 
1118     char *owner = seaf_repo_manager_get_repo_owner (seaf->repo_mgr, repo_id);
1119     if (!owner) {
1120         /* seaf_warning ("Failed to get owner info for repo %s.\n", repo_id); */
1121         return 0;
1122     }
1123 
1124     if (strcmp(owner, email) != 0) {
1125         g_free (owner);
1126         return 0;
1127     }
1128 
1129     g_free (owner);
1130     return 1;
1131 }
1132 
1133 int
seafile_set_repo_owner(const char * repo_id,const char * email,GError ** error)1134 seafile_set_repo_owner(const char *repo_id, const char *email,
1135                        GError **error)
1136 {
1137     if (!repo_id || !email) {
1138         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
1139         return -1;
1140     }
1141     if (!is_uuid_valid (repo_id)) {
1142         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1143         return -1;
1144     }
1145 
1146     return seaf_repo_manager_set_repo_owner(seaf->repo_mgr, repo_id, email);
1147 }
1148 
1149 char *
seafile_get_repo_owner(const char * repo_id,GError ** error)1150 seafile_get_repo_owner (const char *repo_id, GError **error)
1151 {
1152     if (!repo_id) {
1153         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
1154         return NULL;
1155     }
1156     if (!is_uuid_valid (repo_id)) {
1157         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1158         return NULL;
1159     }
1160 
1161     char *owner = seaf_repo_manager_get_repo_owner (seaf->repo_mgr, repo_id);
1162     /* if (!owner){ */
1163     /*     seaf_warning ("Failed to get repo owner for repo %s.\n", repo_id); */
1164     /* } */
1165 
1166     return owner;
1167 }
1168 
1169 GList *
seafile_get_orphan_repo_list(GError ** error)1170 seafile_get_orphan_repo_list(GError **error)
1171 {
1172     GList *ret = NULL;
1173     GList *repos, *ptr;
1174 
1175     repos = seaf_repo_manager_get_orphan_repo_list(seaf->repo_mgr);
1176     ret = convert_repo_list (repos);
1177 
1178     for (ptr = repos; ptr; ptr = ptr->next) {
1179         seaf_repo_unref ((SeafRepo *)ptr->data);
1180     }
1181     g_list_free (repos);
1182 
1183     return ret;
1184 }
1185 
1186 GList *
seafile_list_owned_repos(const char * email,int ret_corrupted,int start,int limit,GError ** error)1187 seafile_list_owned_repos (const char *email, int ret_corrupted,
1188                           int start, int limit, GError **error)
1189 {
1190     GList *ret = NULL;
1191     GList *repos, *ptr;
1192 
1193     repos = seaf_repo_manager_get_repos_by_owner (seaf->repo_mgr, email, ret_corrupted,
1194                                                   start, limit, NULL);
1195     ret = convert_repo_list (repos);
1196 
1197     /* for (ptr = ret; ptr; ptr = ptr->next) { */
1198     /*     g_object_get (ptr->data, "repo_id", &repo_id, NULL); */
1199     /*     is_shared = seaf_share_manager_is_repo_shared (seaf->share_mgr, repo_id); */
1200     /*     if (is_shared < 0) { */
1201     /*         g_free (repo_id); */
1202     /*         break; */
1203     /*     } else { */
1204     /*         g_object_set (ptr->data, "is_shared", is_shared, NULL); */
1205     /*         g_free (repo_id); */
1206     /*     } */
1207     /* } */
1208 
1209     /* while (ptr) { */
1210     /*     g_object_set (ptr->data, "is_shared", FALSE, NULL); */
1211     /*     ptr = ptr->prev; */
1212     /* } */
1213 
1214     for(ptr = repos; ptr; ptr = ptr->next) {
1215         seaf_repo_unref ((SeafRepo *)ptr->data);
1216     }
1217     g_list_free (repos);
1218 
1219     return ret;
1220 }
1221 
1222 GList *
seafile_search_repos_by_name(const char * name,GError ** error)1223 seafile_search_repos_by_name (const char *name, GError **error)
1224 {
1225     GList *ret = NULL;
1226     GList *repos, *ptr;
1227 
1228     repos = seaf_repo_manager_search_repos_by_name (seaf->repo_mgr, name);
1229     ret = convert_repo_list (repos);
1230 
1231     for (ptr = repos; ptr; ptr = ptr->next) {
1232         seaf_repo_unref ((SeafRepo *)ptr->data);
1233     }
1234     g_list_free (repos);
1235 
1236     return g_list_reverse(ret);
1237 }
1238 
1239 gint64
seafile_get_user_quota_usage(const char * email,GError ** error)1240 seafile_get_user_quota_usage (const char *email, GError **error)
1241 {
1242     gint64 ret;
1243 
1244     if (!email) {
1245         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad user id");
1246         return -1;
1247     }
1248 
1249     ret = seaf_quota_manager_get_user_usage (seaf->quota_mgr, email);
1250     if (ret < 0) {
1251         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Internal server error");
1252         return -1;
1253     }
1254 
1255     return ret;
1256 }
1257 
1258 gint64
seafile_get_user_share_usage(const char * email,GError ** error)1259 seafile_get_user_share_usage (const char *email, GError **error)
1260 {
1261     gint64 ret;
1262 
1263     if (!email) {
1264         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad user id");
1265         return -1;
1266     }
1267 
1268     ret = seaf_quota_manager_get_user_share_usage (seaf->quota_mgr, email);
1269     if (ret < 0) {
1270         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Internal server error");
1271         return -1;
1272     }
1273 
1274     return ret;
1275 }
1276 
1277 gint64
seafile_server_repo_size(const char * repo_id,GError ** error)1278 seafile_server_repo_size(const char *repo_id, GError **error)
1279 {
1280     gint64 ret;
1281 
1282     if (!repo_id || strlen(repo_id) != 36) {
1283         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad repo id");
1284         return -1;
1285     }
1286 
1287     if (!is_uuid_valid (repo_id)) {
1288         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1289         return -1;
1290     }
1291 
1292     ret = seaf_repo_manager_get_repo_size (seaf->repo_mgr, repo_id);
1293     if (ret < 0) {
1294         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Internal server error");
1295         return -1;
1296     }
1297 
1298     return ret;
1299 }
1300 
1301 int
seafile_set_repo_history_limit(const char * repo_id,int days,GError ** error)1302 seafile_set_repo_history_limit (const char *repo_id,
1303                                 int days,
1304                                 GError **error)
1305 {
1306     if (!repo_id || !is_uuid_valid (repo_id)) {
1307         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1308         return -1;
1309     }
1310 
1311     if (!is_uuid_valid (repo_id)) {
1312         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1313         return -1;
1314     }
1315 
1316     if (seaf_repo_manager_set_repo_history_limit (seaf->repo_mgr,
1317                                                   repo_id,
1318                                                   days) < 0) {
1319         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL, "DB Error");
1320         return -1;
1321     }
1322 
1323     return 0;
1324 }
1325 
1326 int
seafile_get_repo_history_limit(const char * repo_id,GError ** error)1327 seafile_get_repo_history_limit (const char *repo_id,
1328                                 GError **error)
1329 {
1330     if (!repo_id || !is_uuid_valid (repo_id)) {
1331         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1332         return -1;
1333     }
1334 
1335     if (!is_uuid_valid (repo_id)) {
1336         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1337         return -1;
1338     }
1339 
1340     return  seaf_repo_manager_get_repo_history_limit (seaf->repo_mgr, repo_id);
1341 }
1342 
1343 int
seafile_repo_set_access_property(const char * repo_id,const char * ap,GError ** error)1344 seafile_repo_set_access_property (const char *repo_id, const char *ap, GError **error)
1345 {
1346     int ret;
1347 
1348     if (!repo_id) {
1349         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
1350         return -1;
1351     }
1352 
1353     if (strlen(repo_id) != 36) {
1354         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Wrong repo id");
1355         return -1;
1356     }
1357 
1358     if (g_strcmp0(ap, "public") != 0 && g_strcmp0(ap, "own") != 0 && g_strcmp0(ap, "private") != 0) {
1359         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Wrong access property");
1360         return -1;
1361     }
1362 
1363     ret = seaf_repo_manager_set_access_property (seaf->repo_mgr, repo_id, ap);
1364     if (ret < 0) {
1365         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Internal server error");
1366         return -1;
1367     }
1368 
1369     return ret;
1370 }
1371 
1372 char *
seafile_repo_query_access_property(const char * repo_id,GError ** error)1373 seafile_repo_query_access_property (const char *repo_id, GError **error)
1374 {
1375     char *ret;
1376 
1377     if (!repo_id) {
1378         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
1379         return NULL;
1380     }
1381 
1382     if (strlen(repo_id) != 36) {
1383         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Wrong repo id");
1384         return NULL;
1385     }
1386 
1387     ret = seaf_repo_manager_query_access_property (seaf->repo_mgr, repo_id);
1388 
1389     return ret;
1390 }
1391 
1392 char *
seafile_web_get_access_token(const char * repo_id,const char * obj_id,const char * op,const char * username,int use_onetime,GError ** error)1393 seafile_web_get_access_token (const char *repo_id,
1394                               const char *obj_id,
1395                               const char *op,
1396                               const char *username,
1397                               int use_onetime,
1398                               GError **error)
1399 {
1400     char *token;
1401 
1402     if (!repo_id || !obj_id || !op || !username) {
1403         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Missing args");
1404         return NULL;
1405     }
1406 
1407     token = seaf_web_at_manager_get_access_token (seaf->web_at_mgr,
1408                                                   repo_id, obj_id, op,
1409                                                   username, use_onetime, error);
1410     return token;
1411 }
1412 
1413 GObject *
seafile_web_query_access_token(const char * token,GError ** error)1414 seafile_web_query_access_token (const char *token, GError **error)
1415 {
1416     SeafileWebAccess *webaccess = NULL;
1417 
1418     if (!token) {
1419         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1420                      "Token should not be null");
1421         return NULL;
1422     }
1423 
1424     webaccess = seaf_web_at_manager_query_access_token (seaf->web_at_mgr,
1425                                                         token);
1426     if (webaccess)
1427         return (GObject *)webaccess;
1428 
1429     return NULL;
1430 }
1431 
1432 char *
seafile_query_zip_progress(const char * token,GError ** error)1433 seafile_query_zip_progress (const char *token, GError **error)
1434 {
1435     return zip_download_mgr_query_zip_progress (seaf->zip_download_mgr,
1436                                                 token, error);
1437 }
1438 
1439 int
seafile_cancel_zip_task(const char * token,GError ** error)1440 seafile_cancel_zip_task (const char *token, GError **error)
1441 {
1442     return zip_download_mgr_cancel_zip_task (seaf->zip_download_mgr,
1443                                              token);
1444 }
1445 
1446 int
seafile_add_share(const char * repo_id,const char * from_email,const char * to_email,const char * permission,GError ** error)1447 seafile_add_share (const char *repo_id, const char *from_email,
1448                    const char *to_email, const char *permission, GError **error)
1449 {
1450     int ret;
1451 
1452     if (!repo_id || !from_email || !to_email || !permission) {
1453         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Missing args");
1454         return -1;
1455     }
1456 
1457     if (!is_uuid_valid (repo_id)) {
1458         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1459                      "Invalid repo_id parameter");
1460         return -1;
1461     }
1462 
1463     if (g_strcmp0 (from_email, to_email) == 0) {
1464         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1465                      "Can not share repo to myself");
1466         return -1;
1467     }
1468 
1469     if (!is_permission_valid (permission)) {
1470         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1471                      "Invalid permission parameter");
1472         return -1;
1473     }
1474 
1475     ret = seaf_share_manager_add_share (seaf->share_mgr, repo_id, from_email,
1476                                         to_email, permission);
1477 
1478     return ret;
1479 }
1480 
1481 GList *
seafile_list_share_repos(const char * email,const char * type,int start,int limit,GError ** error)1482 seafile_list_share_repos (const char *email, const char *type,
1483                           int start, int limit, GError **error)
1484 {
1485     if (g_strcmp0 (type, "from_email") != 0 &&
1486         g_strcmp0 (type, "to_email") != 0 ) {
1487         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1488                      "Wrong type argument");
1489         return NULL;
1490     }
1491 
1492     return seaf_share_manager_list_share_repos (seaf->share_mgr,
1493                                                 email, type,
1494                                                 start, limit,
1495                                                 NULL);
1496 }
1497 
1498 GList *
seafile_list_repo_shared_to(const char * from_user,const char * repo_id,GError ** error)1499 seafile_list_repo_shared_to (const char *from_user, const char *repo_id,
1500                              GError **error)
1501 {
1502 
1503     if (!from_user || !repo_id) {
1504         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Missing args");
1505         return NULL;
1506     }
1507 
1508     if (!is_uuid_valid (repo_id)) {
1509         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1510         return NULL;
1511     }
1512 
1513     return seaf_share_manager_list_repo_shared_to (seaf->share_mgr,
1514                                                    from_user, repo_id,
1515                                                    error);
1516 }
1517 
1518 char *
seafile_share_subdir_to_user(const char * repo_id,const char * path,const char * owner,const char * share_user,const char * permission,const char * passwd,GError ** error)1519 seafile_share_subdir_to_user (const char *repo_id,
1520                               const char *path,
1521                               const char *owner,
1522                               const char *share_user,
1523                               const char *permission,
1524                               const char *passwd,
1525                               GError **error)
1526 {
1527     if (is_empty_string (repo_id) || !is_uuid_valid (repo_id)) {
1528         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1529                      "Invalid repo_id parameter");
1530         return NULL;
1531     }
1532 
1533     if (is_empty_string (path) || strcmp (path, "/") == 0) {
1534         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1535                      "Invalid path parameter");
1536         return NULL;
1537     }
1538 
1539     if (is_empty_string (owner)) {
1540         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1541                      "Invalid owner parameter");
1542         return NULL;
1543     }
1544 
1545     if (is_empty_string (share_user)) {
1546         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1547                      "Invalid share_user parameter");
1548         return NULL;
1549     }
1550 
1551     if (strcmp (owner, share_user) == 0) {
1552         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1553                      "Can't share subdir to myself");
1554         return NULL;
1555     }
1556 
1557     if (!is_permission_valid (permission)) {
1558         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1559                      "Invalid permission parameter");
1560         return NULL;
1561     }
1562 
1563     char *real_path;
1564     char *vrepo_name;
1565     char *vrepo_id;
1566     char *ret = NULL;
1567 
1568     real_path = format_dir_path (path);
1569     // Use subdir name as virtual repo name and description
1570     vrepo_name = g_path_get_basename (real_path);
1571     vrepo_id = seaf_repo_manager_create_virtual_repo (seaf->repo_mgr,
1572                                                       repo_id, real_path,
1573                                                       vrepo_name, vrepo_name,
1574                                                       owner, passwd, error);
1575     if (!vrepo_id)
1576         goto out;
1577 
1578     int result = seaf_share_manager_add_share (seaf->share_mgr, vrepo_id, owner,
1579                                         share_user, permission);
1580     if (result < 0) {
1581         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
1582                      "Failed to share subdir to user");
1583         g_free (vrepo_id);
1584     }
1585     else
1586         ret = vrepo_id;
1587 
1588 out:
1589     g_free (vrepo_name);
1590     g_free (real_path);
1591     return ret;
1592 }
1593 
1594 int
seafile_unshare_subdir_for_user(const char * repo_id,const char * path,const char * owner,const char * share_user,GError ** error)1595 seafile_unshare_subdir_for_user (const char *repo_id,
1596                                  const char *path,
1597                                  const char *owner,
1598                                  const char *share_user,
1599                                  GError **error)
1600 {
1601     if (is_empty_string (repo_id) || !is_uuid_valid (repo_id)) {
1602         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1603                      "Invalid repo_id parameter");
1604         return -1;
1605     }
1606 
1607     if (is_empty_string (path) || strcmp (path, "/") == 0) {
1608         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1609                      "Invalid path parameter");
1610         return -1;
1611     }
1612 
1613     if (is_empty_string (owner)) {
1614         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1615                      "Invalid owner parameter");
1616         return -1;
1617     }
1618 
1619     if (is_empty_string (share_user) ||
1620         strcmp (owner, share_user) == 0) {
1621         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1622                      "Invalid share_user parameter");
1623         return -1;
1624     }
1625 
1626     char *real_path;
1627     int ret = 0;
1628 
1629     real_path = format_dir_path (path);
1630 
1631     ret = seaf_share_manager_unshare_subdir (seaf->share_mgr,
1632                                              repo_id, real_path, owner, share_user);
1633     if (ret < 0) {
1634         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
1635                      "Failed to unshare subdir for user");
1636     }
1637 
1638     g_free (real_path);
1639     return ret;
1640 }
1641 
1642 int
seafile_update_share_subdir_perm_for_user(const char * repo_id,const char * path,const char * owner,const char * share_user,const char * permission,GError ** error)1643 seafile_update_share_subdir_perm_for_user (const char *repo_id,
1644                                            const char *path,
1645                                            const char *owner,
1646                                            const char *share_user,
1647                                            const char *permission,
1648                                            GError **error)
1649 {
1650     if (is_empty_string (repo_id) || !is_uuid_valid (repo_id)) {
1651         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1652                      "Invalid repo_id parameter");
1653         return -1;
1654     }
1655 
1656     if (is_empty_string (path) || strcmp (path, "/") == 0) {
1657         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1658                      "Invalid path parameter");
1659         return -1;
1660     }
1661 
1662     if (is_empty_string (owner)) {
1663         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1664                      "Invalid owner parameter");
1665         return -1;
1666     }
1667 
1668     if (is_empty_string (share_user) ||
1669         strcmp (owner, share_user) == 0) {
1670         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1671                      "Invalid share_user parameter");
1672         return -1;
1673     }
1674 
1675     if (!is_permission_valid (permission)) {
1676         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1677                      "Invalid permission parameter");
1678         return -1;
1679     }
1680 
1681     char *real_path;
1682     int ret = 0;
1683 
1684     real_path = format_dir_path (path);
1685 
1686     ret = seaf_share_manager_set_subdir_perm_by_path (seaf->share_mgr,
1687                                                       repo_id, owner, share_user,
1688                                                       permission, real_path);
1689 
1690     if (ret < 0) {
1691         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
1692                      "Failed to update share subdir permission for user");
1693     }
1694 
1695     g_free (real_path);
1696     return ret;
1697 }
1698 
1699 GList *
seafile_list_repo_shared_group(const char * from_user,const char * repo_id,GError ** error)1700 seafile_list_repo_shared_group (const char *from_user, const char *repo_id,
1701                                 GError **error)
1702 {
1703 
1704     if (!from_user || !repo_id) {
1705         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Missing args");
1706         return NULL;
1707     }
1708 
1709     if (!is_uuid_valid (repo_id)) {
1710         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1711         return NULL;
1712     }
1713 
1714     return seaf_share_manager_list_repo_shared_group (seaf->share_mgr,
1715                                                       from_user, repo_id,
1716                                                       error);
1717 }
1718 
1719 int
seafile_remove_share(const char * repo_id,const char * from_email,const char * to_email,GError ** error)1720 seafile_remove_share (const char *repo_id, const char *from_email,
1721                       const char *to_email, GError **error)
1722 {
1723     int ret;
1724 
1725     if (!repo_id || !from_email ||!to_email) {
1726         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Missing args");
1727         return -1;
1728     }
1729 
1730     ret = seaf_share_manager_remove_share (seaf->share_mgr, repo_id, from_email,
1731                                            to_email);
1732 
1733     return ret;
1734 }
1735 
1736 /* Group repo RPC. */
1737 
1738 int
seafile_group_share_repo(const char * repo_id,int group_id,const char * user_name,const char * permission,GError ** error)1739 seafile_group_share_repo (const char *repo_id, int group_id,
1740                           const char *user_name, const char *permission,
1741                           GError **error)
1742 {
1743     SeafRepoManager *mgr = seaf->repo_mgr;
1744     int ret;
1745 
1746     if (group_id <= 0 || !user_name || !repo_id || !permission) {
1747         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1748                      "Bad input argument");
1749         return -1;
1750     }
1751 
1752     if (!is_uuid_valid (repo_id)) {
1753         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1754         return -1;
1755     }
1756 
1757     if (!is_permission_valid (permission)) {
1758         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1759                      "Invalid permission parameter");
1760         return -1;
1761     }
1762 
1763     ret = seaf_repo_manager_add_group_repo (mgr, repo_id, group_id, user_name,
1764                                             permission, error);
1765 
1766     return ret;
1767 }
1768 
1769 int
seafile_group_unshare_repo(const char * repo_id,int group_id,const char * user_name,GError ** error)1770 seafile_group_unshare_repo (const char *repo_id, int group_id,
1771                             const char *user_name, GError **error)
1772 {
1773     SeafRepoManager *mgr = seaf->repo_mgr;
1774     int ret;
1775 
1776     if (!user_name || !repo_id) {
1777         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1778                      "User name and repo id can not be NULL");
1779         return -1;
1780     }
1781 
1782     if (!is_uuid_valid (repo_id)) {
1783         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1784         return -1;
1785     }
1786 
1787     ret = seaf_repo_manager_del_group_repo (mgr, repo_id, group_id, error);
1788 
1789     return ret;
1790 
1791 }
1792 
1793 char *
seafile_share_subdir_to_group(const char * repo_id,const char * path,const char * owner,int share_group,const char * permission,const char * passwd,GError ** error)1794 seafile_share_subdir_to_group (const char *repo_id,
1795                                const char *path,
1796                                const char *owner,
1797                                int share_group,
1798                                const char *permission,
1799                                const char *passwd,
1800                                GError **error)
1801 {
1802     if (is_empty_string (repo_id) || !is_uuid_valid (repo_id)) {
1803         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1804                      "Invalid repo_id parameter");
1805         return NULL;
1806     }
1807 
1808     if (is_empty_string (path) || strcmp (path, "/") == 0) {
1809         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1810                      "Invalid path parameter");
1811         return NULL;
1812     }
1813 
1814     if (is_empty_string (owner)) {
1815         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1816                      "Invalid owner parameter");
1817         return NULL;
1818     }
1819 
1820     if (share_group < 0) {
1821         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1822                      "Invalid share_group parameter");
1823         return NULL;
1824     }
1825 
1826     if (!is_permission_valid (permission)) {
1827         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1828                      "Invalid permission parameter");
1829         return NULL;
1830     }
1831 
1832     char *real_path;
1833     char *vrepo_name;
1834     char *vrepo_id;
1835     char* ret = NULL;
1836 
1837     real_path = format_dir_path (path);
1838     // Use subdir name as virtual repo name and description
1839     vrepo_name = g_path_get_basename (real_path);
1840     vrepo_id = seaf_repo_manager_create_virtual_repo (seaf->repo_mgr,
1841                                                       repo_id, real_path,
1842                                                       vrepo_name, vrepo_name,
1843                                                       owner, passwd, error);
1844     if (!vrepo_id)
1845         goto out;
1846 
1847     int result = seaf_repo_manager_add_group_repo (seaf->repo_mgr, vrepo_id, share_group,
1848                                             owner, permission, error);
1849     if (result < 0) {
1850         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
1851                      "Failed to share subdir to group");
1852         g_free (vrepo_id);
1853     }
1854     else
1855         ret = vrepo_id;
1856 
1857 out:
1858     g_free (vrepo_name);
1859     g_free (real_path);
1860     return ret;
1861 }
1862 
1863 int
seafile_unshare_subdir_for_group(const char * repo_id,const char * path,const char * owner,int share_group,GError ** error)1864 seafile_unshare_subdir_for_group (const char *repo_id,
1865                                   const char *path,
1866                                   const char *owner,
1867                                   int share_group,
1868                                   GError **error)
1869 {
1870     if (is_empty_string (repo_id) || !is_uuid_valid (repo_id)) {
1871         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1872                      "Invalid repo_id parameter");
1873         return -1;
1874     }
1875 
1876     if (is_empty_string (path) || strcmp (path, "/") == 0) {
1877         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1878                      "Invalid path parameter");
1879         return -1;
1880     }
1881 
1882     if (is_empty_string (owner)) {
1883         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1884                      "Invalid owner parameter");
1885         return -1;
1886     }
1887 
1888     if (share_group < 0) {
1889         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1890                      "Invalid share_group parameter");
1891         return -1;
1892     }
1893 
1894     char *real_path;
1895     int ret = 0;
1896 
1897     real_path = format_dir_path (path);
1898 
1899     ret = seaf_share_manager_unshare_group_subdir (seaf->share_mgr, repo_id,
1900                                                    real_path, owner, share_group);
1901     if (ret < 0) {
1902         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
1903                      "Failed to unshare subdir for group");
1904     }
1905 
1906     g_free (real_path);
1907     return ret;
1908 }
1909 
1910 int
seafile_update_share_subdir_perm_for_group(const char * repo_id,const char * path,const char * owner,int share_group,const char * permission,GError ** error)1911 seafile_update_share_subdir_perm_for_group (const char *repo_id,
1912                                             const char *path,
1913                                             const char *owner,
1914                                             int share_group,
1915                                             const char *permission,
1916                                             GError **error)
1917 {
1918     if (is_empty_string (repo_id) || !is_uuid_valid (repo_id)) {
1919         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1920                      "Invalid repo_id parameter");
1921         return -1;
1922     }
1923 
1924     if (is_empty_string (path) || strcmp (path, "/") == 0) {
1925         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1926                      "Invalid path parameter");
1927         return -1;
1928     }
1929 
1930     if (is_empty_string (owner)) {
1931         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1932                      "Invalid owner parameter");
1933         return -1;
1934     }
1935 
1936     if (share_group < 0) {
1937         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1938                      "Invalid share_group parameter");
1939         return -1;
1940     }
1941 
1942     if (!is_permission_valid (permission)) {
1943         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1944                      "Invalid permission parameter");
1945         return -1;
1946     }
1947 
1948     char *real_path;
1949     int ret = 0;
1950 
1951     real_path = format_dir_path (path);
1952     ret = seaf_repo_manager_set_subdir_group_perm_by_path (seaf->repo_mgr,
1953                                                            repo_id, owner, share_group,
1954                                                            permission, real_path);
1955     if (ret < 0) {
1956         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
1957                      "Failed to update share subdir permission for group");
1958     }
1959 
1960     g_free (real_path);
1961     return ret;
1962 }
1963 
1964 char *
seafile_get_shared_groups_by_repo(const char * repo_id,GError ** error)1965 seafile_get_shared_groups_by_repo(const char *repo_id, GError **error)
1966 {
1967     SeafRepoManager *mgr = seaf->repo_mgr;
1968     GList *group_ids = NULL, *ptr;
1969     GString *result;
1970 
1971     if (!repo_id) {
1972         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
1973                      "Bad arguments");
1974         return NULL;
1975     }
1976 
1977     if (!is_uuid_valid (repo_id)) {
1978         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
1979         return NULL;
1980     }
1981 
1982     group_ids = seaf_repo_manager_get_groups_by_repo (mgr, repo_id, error);
1983     if (!group_ids) {
1984         return NULL;
1985     }
1986 
1987     result = g_string_new("");
1988     ptr = group_ids;
1989     while (ptr) {
1990         g_string_append_printf (result, "%d\n", (int)(long)ptr->data);
1991         ptr = ptr->next;
1992     }
1993     g_list_free (group_ids);
1994 
1995     return g_string_free (result, FALSE);
1996 }
1997 
1998 char *
seafile_get_group_repoids(int group_id,GError ** error)1999 seafile_get_group_repoids (int group_id, GError **error)
2000 {
2001     SeafRepoManager *mgr = seaf->repo_mgr;
2002     GList *repo_ids = NULL, *ptr;
2003     GString *result;
2004 
2005     repo_ids = seaf_repo_manager_get_group_repoids (mgr, group_id, error);
2006     if (!repo_ids) {
2007         return NULL;
2008     }
2009 
2010     result = g_string_new("");
2011     ptr = repo_ids;
2012     while (ptr) {
2013         g_string_append_printf (result, "%s\n", (char *)ptr->data);
2014         g_free (ptr->data);
2015         ptr = ptr->next;
2016     }
2017     g_list_free (repo_ids);
2018 
2019     return g_string_free (result, FALSE);
2020 }
2021 
2022 GList *
seafile_get_repos_by_group(int group_id,GError ** error)2023 seafile_get_repos_by_group (int group_id, GError **error)
2024 {
2025     SeafRepoManager *mgr = seaf->repo_mgr;
2026     GList *ret = NULL;
2027 
2028     if (group_id < 0) {
2029         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2030                      "Invalid group id.");
2031         return NULL;
2032     }
2033 
2034     ret = seaf_repo_manager_get_repos_by_group (mgr, group_id, error);
2035 
2036     return ret;
2037 }
2038 
2039 GList *
seafile_get_group_repos_by_owner(char * user,GError ** error)2040 seafile_get_group_repos_by_owner (char *user, GError **error)
2041 {
2042     SeafRepoManager *mgr = seaf->repo_mgr;
2043     GList *ret = NULL;
2044 
2045     if (!user) {
2046         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2047                      "user name can not be NULL");
2048         return NULL;
2049     }
2050 
2051     ret = seaf_repo_manager_get_group_repos_by_owner (mgr, user, error);
2052     if (!ret) {
2053         return NULL;
2054     }
2055 
2056     return g_list_reverse (ret);
2057 }
2058 
2059 char *
seafile_get_group_repo_owner(const char * repo_id,GError ** error)2060 seafile_get_group_repo_owner (const char *repo_id, GError **error)
2061 {
2062     SeafRepoManager *mgr = seaf->repo_mgr;
2063     GString *result = g_string_new ("");
2064 
2065     if (!is_uuid_valid (repo_id)) {
2066         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2067         return NULL;
2068     }
2069 
2070     char *share_from = seaf_repo_manager_get_group_repo_owner (mgr, repo_id,
2071                                                                error);
2072     if (share_from) {
2073         g_string_append_printf (result, "%s", share_from);
2074         g_free (share_from);
2075     }
2076 
2077     return g_string_free (result, FALSE);
2078 }
2079 
2080 int
seafile_remove_repo_group(int group_id,const char * username,GError ** error)2081 seafile_remove_repo_group(int group_id, const char *username, GError **error)
2082 {
2083     if (group_id <= 0) {
2084         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2085                      "Wrong group id argument");
2086         return -1;
2087     }
2088 
2089     return seaf_repo_manager_remove_group_repos (seaf->repo_mgr,
2090                                                  group_id, username,
2091                                                  error);
2092 }
2093 
2094 /* Inner public repo RPC */
2095 
2096 int
seafile_set_inner_pub_repo(const char * repo_id,const char * permission,GError ** error)2097 seafile_set_inner_pub_repo (const char *repo_id,
2098                             const char *permission,
2099                             GError **error)
2100 {
2101     if (!repo_id) {
2102         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad args");
2103         return -1;
2104     }
2105 
2106     if (!is_uuid_valid (repo_id)) {
2107         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2108         return -1;
2109     }
2110 
2111     if (seaf_repo_manager_set_inner_pub_repo (seaf->repo_mgr,
2112                                               repo_id, permission) < 0) {
2113         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Internal error");
2114         return -1;
2115     }
2116 
2117     return 0;
2118 }
2119 
2120 int
seafile_unset_inner_pub_repo(const char * repo_id,GError ** error)2121 seafile_unset_inner_pub_repo (const char *repo_id, GError **error)
2122 {
2123     if (!repo_id) {
2124         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad args");
2125         return -1;
2126     }
2127 
2128     if (!is_uuid_valid (repo_id)) {
2129         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2130         return -1;
2131     }
2132 
2133     if (seaf_repo_manager_unset_inner_pub_repo (seaf->repo_mgr, repo_id) < 0) {
2134         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Internal error");
2135         return -1;
2136     }
2137 
2138     return 0;
2139 }
2140 
2141 GList *
seafile_list_inner_pub_repos(GError ** error)2142 seafile_list_inner_pub_repos (GError **error)
2143 {
2144     return seaf_repo_manager_list_inner_pub_repos (seaf->repo_mgr, NULL);
2145 }
2146 
2147 gint64
seafile_count_inner_pub_repos(GError ** error)2148 seafile_count_inner_pub_repos (GError **error)
2149 {
2150     return seaf_repo_manager_count_inner_pub_repos (seaf->repo_mgr);
2151 }
2152 
2153 GList *
seafile_list_inner_pub_repos_by_owner(const char * user,GError ** error)2154 seafile_list_inner_pub_repos_by_owner (const char *user, GError **error)
2155 {
2156     if (!user) {
2157         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Bad arguments");
2158         return NULL;
2159     }
2160 
2161     return seaf_repo_manager_list_inner_pub_repos_by_owner (seaf->repo_mgr, user);
2162 }
2163 
2164 int
seafile_is_inner_pub_repo(const char * repo_id,GError ** error)2165 seafile_is_inner_pub_repo (const char *repo_id, GError **error)
2166 {
2167     if (!repo_id) {
2168         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Bad arguments");
2169         return -1;
2170     }
2171 
2172     if (!is_uuid_valid (repo_id)) {
2173         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2174         return -1;
2175     }
2176 
2177     return seaf_repo_manager_is_inner_pub_repo (seaf->repo_mgr, repo_id);
2178 }
2179 
2180 gint64
seafile_get_file_size(const char * store_id,int version,const char * file_id,GError ** error)2181 seafile_get_file_size (const char *store_id, int version,
2182                        const char *file_id, GError **error)
2183 {
2184     gint64 file_size;
2185 
2186     if (!store_id || !is_uuid_valid(store_id)) {
2187         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2188                      "Invalid store id");
2189         return -1;
2190     }
2191 
2192     if (!file_id || !is_object_id_valid (file_id)) {
2193         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2194                      "Invalid file id");
2195         return -1;
2196     }
2197 
2198     file_size = seaf_fs_manager_get_file_size (seaf->fs_mgr, store_id, version, file_id);
2199     if (file_size < 0) {
2200         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL,
2201                      "failed to read file size");
2202         return -1;
2203     }
2204 
2205     return file_size;
2206 }
2207 
2208 gint64
seafile_get_dir_size(const char * store_id,int version,const char * dir_id,GError ** error)2209 seafile_get_dir_size (const char *store_id, int version,
2210                       const char *dir_id, GError **error)
2211 {
2212     gint64 dir_size;
2213 
2214     if (!store_id || !is_uuid_valid (store_id)) {
2215         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2216                      "Invalid store id");
2217         return -1;
2218     }
2219 
2220     if (!dir_id || !is_object_id_valid (dir_id)) {
2221         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2222                      "Invalid dir id");
2223         return -1;
2224     }
2225 
2226     dir_size = seaf_fs_manager_get_fs_size (seaf->fs_mgr, store_id, version, dir_id);
2227     if (dir_size < 0) {
2228         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2229                      "Failed to caculate dir size");
2230         return -1;
2231     }
2232 
2233     return dir_size;
2234 }
2235 
2236 int
seafile_check_passwd(const char * repo_id,const char * magic,GError ** error)2237 seafile_check_passwd (const char *repo_id,
2238                       const char *magic,
2239                       GError **error)
2240 {
2241     if (!repo_id || strlen(repo_id) != 36 || !magic) {
2242         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2243                      "Bad arguments");
2244         return -1;
2245     }
2246 
2247     if (seaf_passwd_manager_check_passwd (seaf->passwd_mgr,
2248                                           repo_id, magic,
2249                                           error) < 0) {
2250         return -1;
2251     }
2252 
2253     return 0;
2254 }
2255 
2256 int
seafile_set_passwd(const char * repo_id,const char * user,const char * passwd,GError ** error)2257 seafile_set_passwd (const char *repo_id,
2258                     const char *user,
2259                     const char *passwd,
2260                     GError **error)
2261 {
2262     if (!repo_id || strlen(repo_id) != 36 || !user || !passwd) {
2263         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2264                      "Bad arguments");
2265         return -1;
2266     }
2267 
2268     if (seaf_passwd_manager_set_passwd (seaf->passwd_mgr,
2269                                         repo_id, user, passwd,
2270                                         error) < 0) {
2271         return -1;
2272     }
2273 
2274     return 0;
2275 }
2276 
2277 int
seafile_unset_passwd(const char * repo_id,const char * user,GError ** error)2278 seafile_unset_passwd (const char *repo_id,
2279                       const char *user,
2280                       GError **error)
2281 {
2282     if (!repo_id || strlen(repo_id) != 36 || !user) {
2283         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2284                      "Bad arguments");
2285         return -1;
2286     }
2287 
2288     if (seaf_passwd_manager_unset_passwd (seaf->passwd_mgr,
2289                                           repo_id, user,
2290                                           error) < 0) {
2291         return -1;
2292     }
2293 
2294     return 0;
2295 }
2296 
2297 int
seafile_is_passwd_set(const char * repo_id,const char * user,GError ** error)2298 seafile_is_passwd_set (const char *repo_id, const char *user, GError **error)
2299 {
2300     if (!repo_id || strlen(repo_id) != 36 || !user) {
2301         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2302                      "Bad arguments");
2303         return -1;
2304     }
2305 
2306     return seaf_passwd_manager_is_passwd_set (seaf->passwd_mgr,
2307                                               repo_id, user);
2308 }
2309 
2310 GObject *
seafile_get_decrypt_key(const char * repo_id,const char * user,GError ** error)2311 seafile_get_decrypt_key (const char *repo_id, const char *user, GError **error)
2312 {
2313     SeafileCryptKey *ret;
2314 
2315     if (!repo_id || strlen(repo_id) != 36 || !user) {
2316         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2317                      "Bad arguments");
2318         return NULL;
2319     }
2320 
2321     ret = seaf_passwd_manager_get_decrypt_key (seaf->passwd_mgr,
2322                                                repo_id, user);
2323     if (!ret) {
2324         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
2325                      "Password was not set");
2326         return NULL;
2327     }
2328 
2329     return (GObject *)ret;
2330 }
2331 
2332 int
seafile_revert_on_server(const char * repo_id,const char * commit_id,const char * user_name,GError ** error)2333 seafile_revert_on_server (const char *repo_id,
2334                           const char *commit_id,
2335                           const char *user_name,
2336                           GError **error)
2337 {
2338     if (!repo_id || strlen(repo_id) != 36 ||
2339         !commit_id || strlen(commit_id) != 40 ||
2340         !user_name) {
2341         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2342                      "Bad arguments");
2343         return -1;
2344     }
2345 
2346     if (!is_uuid_valid (repo_id)) {
2347         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2348         return -1;
2349     }
2350 
2351     if (!is_object_id_valid (commit_id)) {
2352         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid commit id");
2353         return -1;
2354     }
2355 
2356     return seaf_repo_manager_revert_on_server (seaf->repo_mgr,
2357                                                repo_id,
2358                                                commit_id,
2359                                                user_name,
2360                                                error);
2361 }
2362 
2363 int
seafile_post_file(const char * repo_id,const char * temp_file_path,const char * parent_dir,const char * file_name,const char * user,GError ** error)2364 seafile_post_file (const char *repo_id, const char *temp_file_path,
2365                    const char *parent_dir, const char *file_name,
2366                    const char *user,
2367                    GError **error)
2368 {
2369     char *norm_parent_dir = NULL, *norm_file_name = NULL, *rpath = NULL;
2370     int ret = 0;
2371 
2372     if (!repo_id || !temp_file_path || !parent_dir || !file_name || !user) {
2373         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2374                      "Argument should not be null");
2375         return -1;
2376     }
2377 
2378     if (!is_uuid_valid (repo_id)) {
2379         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2380         return -1;
2381     }
2382 
2383     norm_parent_dir = normalize_utf8_path (parent_dir);
2384     if (!norm_parent_dir) {
2385         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2386                      "Path is in valid UTF8 encoding");
2387         ret = -1;
2388         goto out;
2389     }
2390 
2391     norm_file_name = normalize_utf8_path (file_name);
2392     if (!norm_file_name) {
2393         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2394                      "Path is in valid UTF8 encoding");
2395         ret = -1;
2396         goto out;
2397     }
2398 
2399     rpath = format_dir_path (norm_parent_dir);
2400 
2401     if (seaf_repo_manager_post_file (seaf->repo_mgr, repo_id,
2402                                      temp_file_path, rpath,
2403                                      norm_file_name, user,
2404                                      error) < 0) {
2405         ret = -1;
2406     }
2407 
2408 out:
2409     g_free (norm_parent_dir);
2410     g_free (norm_file_name);
2411     g_free (rpath);
2412 
2413     return ret;
2414 }
2415 
2416 /* char * */
2417 /* seafile_post_file_blocks (const char *repo_id, */
2418 /*                           const char *parent_dir, */
2419 /*                           const char *file_name, */
2420 /*                           const char *blockids_json, */
2421 /*                           const char *paths_json, */
2422 /*                           const char *user, */
2423 /*                           gint64 file_size, */
2424 /*                           int replace_existed, */
2425 /*                           GError **error) */
2426 /* { */
2427 /*     char *norm_parent_dir = NULL, *norm_file_name = NULL, *rpath = NULL; */
2428 /*     char *new_id = NULL; */
2429 
2430 /*     if (!repo_id || !parent_dir || !file_name */
2431 /*         || !blockids_json || ! paths_json || !user || file_size < 0) { */
2432 /*         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, */
2433 /*                      "Argument should not be null"); */
2434 /*         return NULL; */
2435 /*     } */
2436 
2437 /*     if (!is_uuid_valid (repo_id)) { */
2438 /*         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id"); */
2439 /*         return NULL; */
2440 /*     } */
2441 
2442 /*     norm_parent_dir = normalize_utf8_path (parent_dir); */
2443 /*     if (!norm_parent_dir) { */
2444 /*         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, */
2445 /*                      "Path is in valid UTF8 encoding"); */
2446 /*         goto out; */
2447 /*     } */
2448 
2449 /*     norm_file_name = normalize_utf8_path (file_name); */
2450 /*     if (!norm_file_name) { */
2451 /*         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, */
2452 /*                      "Path is in valid UTF8 encoding"); */
2453 /*         goto out; */
2454 /*     } */
2455 
2456 /*     rpath = format_dir_path (norm_parent_dir); */
2457 
2458 /*     seaf_repo_manager_post_file_blocks (seaf->repo_mgr, */
2459 /*                                         repo_id, */
2460 /*                                         rpath, */
2461 /*                                         norm_file_name, */
2462 /*                                         blockids_json, */
2463 /*                                         paths_json, */
2464 /*                                         user, */
2465 /*                                         file_size, */
2466 /*                                         replace_existed, */
2467 /*                                         &new_id, */
2468 /*                                         error); */
2469 
2470 /* out: */
2471 /*     g_free (norm_parent_dir); */
2472 /*     g_free (norm_file_name); */
2473 /*     g_free (rpath); */
2474 
2475 /*     return new_id; */
2476 /* } */
2477 
2478 char *
seafile_post_multi_files(const char * repo_id,const char * parent_dir,const char * filenames_json,const char * paths_json,const char * user,int replace_existed,GError ** error)2479 seafile_post_multi_files (const char *repo_id,
2480                           const char *parent_dir,
2481                           const char *filenames_json,
2482                           const char *paths_json,
2483                           const char *user,
2484                           int replace_existed,
2485                           GError **error)
2486 {
2487     char *norm_parent_dir = NULL, *rpath = NULL;
2488     char *ret_json = NULL;
2489 
2490     if (!repo_id || !filenames_json || !parent_dir || !paths_json || !user) {
2491         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2492                      "Argument should not be null");
2493         return NULL;
2494     }
2495 
2496     if (!is_uuid_valid (repo_id)) {
2497         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2498         return NULL;
2499     }
2500 
2501     norm_parent_dir = normalize_utf8_path (parent_dir);
2502     if (!norm_parent_dir) {
2503         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2504                      "Path is in valid UTF8 encoding");
2505         goto out;
2506     }
2507 
2508     rpath = format_dir_path (norm_parent_dir);
2509 
2510     seaf_repo_manager_post_multi_files (seaf->repo_mgr,
2511                                         repo_id,
2512                                         rpath,
2513                                         filenames_json,
2514                                         paths_json,
2515                                         user,
2516                                         replace_existed,
2517                                         &ret_json,
2518                                         NULL,
2519                                         error);
2520 
2521 out:
2522     g_free (norm_parent_dir);
2523     g_free (rpath);
2524 
2525     return ret_json;
2526 }
2527 
2528 char *
seafile_put_file(const char * repo_id,const char * temp_file_path,const char * parent_dir,const char * file_name,const char * user,const char * head_id,GError ** error)2529 seafile_put_file (const char *repo_id, const char *temp_file_path,
2530                   const char *parent_dir, const char *file_name,
2531                   const char *user, const char *head_id,
2532                   GError **error)
2533 {
2534     char *norm_parent_dir = NULL, *norm_file_name = NULL, *rpath = NULL;
2535     char *new_file_id = NULL;
2536 
2537     if (!repo_id || !temp_file_path || !parent_dir || !file_name || !user) {
2538         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2539                      "Argument should not be null");
2540         return NULL;
2541     }
2542 
2543     if (!is_uuid_valid (repo_id)) {
2544         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2545         return NULL;
2546     }
2547 
2548     norm_parent_dir = normalize_utf8_path (parent_dir);
2549     if (!norm_parent_dir) {
2550         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2551                      "Path is in valid UTF8 encoding");
2552         goto out;
2553     }
2554 
2555     norm_file_name = normalize_utf8_path (file_name);
2556     if (!norm_file_name) {
2557         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2558                      "Path is in valid UTF8 encoding");
2559         goto out;
2560     }
2561 
2562     rpath = format_dir_path (norm_parent_dir);
2563 
2564     seaf_repo_manager_put_file (seaf->repo_mgr, repo_id,
2565                                 temp_file_path, rpath,
2566                                 norm_file_name, user, head_id,
2567                                 &new_file_id, error);
2568 
2569 out:
2570     g_free (norm_parent_dir);
2571     g_free (norm_file_name);
2572     g_free (rpath);
2573 
2574     return new_file_id;
2575 }
2576 
2577 /* char * */
2578 /* seafile_put_file_blocks (const char *repo_id, const char *parent_dir, */
2579 /*                          const char *file_name, const char *blockids_json, */
2580 /*                          const char *paths_json, const char *user, */
2581 /*                          const char *head_id, gint64 file_size, GError **error) */
2582 /* { */
2583 /*     char *norm_parent_dir = NULL, *norm_file_name = NULL, *rpath = NULL; */
2584 /*     char *new_file_id = NULL; */
2585 
2586 /*     if (!repo_id || !parent_dir || !file_name */
2587 /*         || !blockids_json || ! paths_json || !user) { */
2588 /*         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, */
2589 /*                      "Argument should not be null"); */
2590 /*         return NULL; */
2591 /*     } */
2592 
2593 /*     if (!is_uuid_valid (repo_id)) { */
2594 /*         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id"); */
2595 /*         return NULL; */
2596 /*     } */
2597 
2598 /*     norm_parent_dir = normalize_utf8_path (parent_dir); */
2599 /*     if (!norm_parent_dir) { */
2600 /*         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, */
2601 /*                      "Path is in valid UTF8 encoding"); */
2602 /*         goto out; */
2603 /*     } */
2604 
2605 /*     norm_file_name = normalize_utf8_path (file_name); */
2606 /*     if (!norm_file_name) { */
2607 /*         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, */
2608 /*                      "Path is in valid UTF8 encoding"); */
2609 /*         goto out; */
2610 /*     } */
2611 
2612 /*     rpath = format_dir_path (norm_parent_dir); */
2613 
2614 /*     seaf_repo_manager_put_file_blocks (seaf->repo_mgr, repo_id, */
2615 /*                                        rpath, norm_file_name, */
2616 /*                                        blockids_json, paths_json, */
2617 /*                                        user, head_id, file_size, */
2618 /*                                        &new_file_id, error); */
2619 
2620 /* out: */
2621 /*     g_free (norm_parent_dir); */
2622 /*     g_free (norm_file_name); */
2623 /*     g_free (rpath); */
2624 
2625 /*     return new_file_id; */
2626 /* } */
2627 
2628 int
seafile_post_dir(const char * repo_id,const char * parent_dir,const char * new_dir_name,const char * user,GError ** error)2629 seafile_post_dir (const char *repo_id, const char *parent_dir,
2630                   const char *new_dir_name, const char *user,
2631                   GError **error)
2632 {
2633     char *norm_parent_dir = NULL, *norm_dir_name = NULL, *rpath = NULL;
2634     int ret = 0;
2635 
2636     if (!repo_id || !parent_dir || !new_dir_name || !user) {
2637         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
2638         return -1;
2639     }
2640 
2641     if (!is_uuid_valid (repo_id)) {
2642         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2643         return -1;
2644     }
2645 
2646     norm_parent_dir = normalize_utf8_path (parent_dir);
2647     if (!norm_parent_dir) {
2648         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2649                      "Path is in valid UTF8 encoding");
2650         ret = -1;
2651         goto out;
2652     }
2653 
2654     norm_dir_name = normalize_utf8_path (new_dir_name);
2655     if (!norm_dir_name) {
2656         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2657                      "Path is in valid UTF8 encoding");
2658         ret = -1;
2659         goto out;
2660     }
2661 
2662     rpath = format_dir_path (norm_parent_dir);
2663 
2664     if (seaf_repo_manager_post_dir (seaf->repo_mgr, repo_id,
2665                                     rpath, norm_dir_name,
2666                                     user, error) < 0) {
2667         ret = -1;
2668     }
2669 
2670 out:
2671     g_free (norm_parent_dir);
2672     g_free (norm_dir_name);
2673     g_free (rpath);
2674 
2675     return ret;
2676 }
2677 
2678 int
seafile_post_empty_file(const char * repo_id,const char * parent_dir,const char * new_file_name,const char * user,GError ** error)2679 seafile_post_empty_file (const char *repo_id, const char *parent_dir,
2680                          const char *new_file_name, const char *user,
2681                          GError **error)
2682 {
2683     char *norm_parent_dir = NULL, *norm_file_name = NULL, *rpath = NULL;
2684     int ret = 0;
2685 
2686     if (!repo_id || !parent_dir || !new_file_name || !user) {
2687         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
2688         return -1;
2689     }
2690 
2691     if (!is_uuid_valid (repo_id)) {
2692         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2693         return -1;
2694     }
2695 
2696     norm_parent_dir = normalize_utf8_path (parent_dir);
2697     if (!norm_parent_dir) {
2698         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2699                      "Path is in valid UTF8 encoding");
2700         ret = -1;
2701         goto out;
2702     }
2703 
2704     norm_file_name = normalize_utf8_path (new_file_name);
2705     if (!norm_file_name) {
2706         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2707                      "Path is in valid UTF8 encoding");
2708         ret = -1;
2709         goto out;
2710     }
2711 
2712     rpath = format_dir_path (norm_parent_dir);
2713 
2714     if (seaf_repo_manager_post_empty_file (seaf->repo_mgr, repo_id,
2715                                            rpath, norm_file_name,
2716                                            user, error) < 0) {
2717         ret = -1;
2718     }
2719 
2720 out:
2721     g_free (norm_parent_dir);
2722     g_free (norm_file_name);
2723     g_free (rpath);
2724 
2725     return ret;
2726 }
2727 
2728 int
seafile_del_file(const char * repo_id,const char * parent_dir,const char * file_name,const char * user,GError ** error)2729 seafile_del_file (const char *repo_id, const char *parent_dir,
2730                   const char *file_name, const char *user,
2731                   GError **error)
2732 {
2733     char *norm_parent_dir = NULL, *norm_file_name = NULL, *rpath = NULL;
2734     int ret = 0;
2735 
2736     if (!repo_id || !parent_dir || !file_name || !user) {
2737         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
2738         return -1;
2739     }
2740 
2741     if (!is_uuid_valid (repo_id)) {
2742         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2743         return -1;
2744     }
2745 
2746     norm_parent_dir = normalize_utf8_path (parent_dir);
2747     if (!norm_parent_dir) {
2748         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2749                      "Path is in valid UTF8 encoding");
2750         ret = -1;
2751         goto out;
2752     }
2753 
2754     norm_file_name = normalize_utf8_path (file_name);
2755     if (!norm_file_name) {
2756         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2757                      "Path is in valid UTF8 encoding");
2758         ret = -1;
2759         goto out;
2760     }
2761 
2762     rpath = format_dir_path (norm_parent_dir);
2763 
2764     if (seaf_repo_manager_del_file (seaf->repo_mgr, repo_id,
2765                                     rpath, norm_file_name,
2766                                     user, error) < 0) {
2767         ret = -1;
2768     }
2769 
2770 out:
2771     g_free (norm_parent_dir);
2772     g_free (norm_file_name);
2773     g_free (rpath);
2774 
2775     return ret;
2776 }
2777 
2778 GObject *
seafile_copy_file(const char * src_repo_id,const char * src_dir,const char * src_filename,const char * dst_repo_id,const char * dst_dir,const char * dst_filename,const char * user,int need_progress,int synchronous,GError ** error)2779 seafile_copy_file (const char *src_repo_id,
2780                    const char *src_dir,
2781                    const char *src_filename,
2782                    const char *dst_repo_id,
2783                    const char *dst_dir,
2784                    const char *dst_filename,
2785                    const char *user,
2786                    int need_progress,
2787                    int synchronous,
2788                    GError **error)
2789 {
2790     char *norm_src_dir = NULL, *norm_src_filename = NULL;
2791     char *norm_dst_dir = NULL, *norm_dst_filename = NULL;
2792     char *rsrc_dir = NULL, *rdst_dir = NULL;
2793     GObject *ret = NULL;
2794 
2795     if (!src_repo_id || !src_dir || !src_filename ||
2796         !dst_repo_id || !dst_dir || !dst_filename || !user) {
2797         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
2798         return NULL;
2799     }
2800 
2801     if (!is_uuid_valid (src_repo_id) || !is_uuid_valid(dst_repo_id)) {
2802         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2803         return NULL;
2804     }
2805 
2806     norm_src_dir = normalize_utf8_path (src_dir);
2807     if (!norm_src_dir) {
2808         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2809                      "Path is in valid UTF8 encoding");
2810         goto out;
2811     }
2812 
2813     norm_src_filename = normalize_utf8_path (src_filename);
2814     if (!norm_src_filename) {
2815         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2816                      "Path is in valid UTF8 encoding");
2817         goto out;
2818     }
2819 
2820     norm_dst_dir = normalize_utf8_path (dst_dir);
2821     if (!norm_dst_dir) {
2822         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2823                      "Path is in valid UTF8 encoding");
2824         goto out;
2825     }
2826 
2827     norm_dst_filename = normalize_utf8_path (dst_filename);
2828     if (!norm_dst_filename) {
2829         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2830                      "Path is in valid UTF8 encoding");
2831         goto out;
2832     }
2833 
2834     rsrc_dir = format_dir_path (norm_src_dir);
2835     rdst_dir = format_dir_path (norm_dst_dir);
2836 
2837     if (strchr(norm_src_filename, '\t') && strchr(norm_dst_filename, '\t'))
2838         ret = (GObject *)seaf_repo_manager_copy_multiple_files (seaf->repo_mgr,
2839                                                                 src_repo_id, rsrc_dir, norm_src_filename,
2840                                                                 dst_repo_id, rdst_dir, norm_dst_filename,
2841                                                                 user, need_progress, synchronous,
2842                                                                 error);
2843 
2844     else
2845         ret = (GObject *)seaf_repo_manager_copy_file (seaf->repo_mgr,
2846                                                       src_repo_id, rsrc_dir, norm_src_filename,
2847                                                       dst_repo_id, rdst_dir, norm_dst_filename,
2848                                                       user, need_progress, synchronous,
2849                                                       error);
2850 
2851 out:
2852     g_free (norm_src_dir);
2853     g_free (norm_src_filename);
2854     g_free (norm_dst_dir);
2855     g_free (norm_dst_filename);
2856     g_free (rsrc_dir);
2857     g_free (rdst_dir);
2858 
2859     return ret;
2860 }
2861 
2862 GObject *
seafile_move_file(const char * src_repo_id,const char * src_dir,const char * src_filename,const char * dst_repo_id,const char * dst_dir,const char * dst_filename,int replace,const char * user,int need_progress,int synchronous,GError ** error)2863 seafile_move_file (const char *src_repo_id,
2864                    const char *src_dir,
2865                    const char *src_filename,
2866                    const char *dst_repo_id,
2867                    const char *dst_dir,
2868                    const char *dst_filename,
2869                    int replace,
2870                    const char *user,
2871                    int need_progress,
2872                    int synchronous,
2873                    GError **error)
2874 {
2875     char *norm_src_dir = NULL, *norm_src_filename = NULL;
2876     char *norm_dst_dir = NULL, *norm_dst_filename = NULL;
2877     char *rsrc_dir = NULL, *rdst_dir = NULL;
2878     GObject *ret = NULL;
2879 
2880     if (!src_repo_id || !src_dir || !src_filename ||
2881         !dst_repo_id || !dst_dir || !dst_filename || !user) {
2882         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
2883         return NULL;
2884     }
2885 
2886     if (!is_uuid_valid (src_repo_id) || !is_uuid_valid(dst_repo_id)) {
2887         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2888         return NULL;
2889     }
2890 
2891     norm_src_dir = normalize_utf8_path (src_dir);
2892     if (!norm_src_dir) {
2893         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2894                      "Path is in valid UTF8 encoding");
2895         goto out;
2896     }
2897 
2898     norm_src_filename = normalize_utf8_path (src_filename);
2899     if (!norm_src_filename) {
2900         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2901                      "Path is in valid UTF8 encoding");
2902         goto out;
2903     }
2904 
2905     norm_dst_dir = normalize_utf8_path (dst_dir);
2906     if (!norm_dst_dir) {
2907         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2908                      "Path is in valid UTF8 encoding");
2909         goto out;
2910     }
2911 
2912     norm_dst_filename = normalize_utf8_path (dst_filename);
2913     if (!norm_dst_filename) {
2914         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2915                      "Path is in valid UTF8 encoding");
2916         goto out;
2917     }
2918 
2919     rsrc_dir = format_dir_path (norm_src_dir);
2920     rdst_dir = format_dir_path (norm_dst_dir);
2921 
2922     if (strchr(norm_src_filename, '\t') && strchr(norm_dst_filename, '\t'))
2923         ret = (GObject *)seaf_repo_manager_move_multiple_files (seaf->repo_mgr,
2924                                                                 src_repo_id, rsrc_dir, norm_src_filename,
2925                                                                 dst_repo_id, rdst_dir, norm_dst_filename,
2926                                                                 replace, user, need_progress, synchronous,
2927                                                                 error);
2928     else
2929         ret = (GObject *)seaf_repo_manager_move_file (seaf->repo_mgr,
2930                                                       src_repo_id, rsrc_dir, norm_src_filename,
2931                                                       dst_repo_id, rdst_dir, norm_dst_filename,
2932                                                       replace, user, need_progress, synchronous,
2933                                                       error);
2934 
2935 out:
2936     g_free (norm_src_dir);
2937     g_free (norm_src_filename);
2938     g_free (norm_dst_dir);
2939     g_free (norm_dst_filename);
2940     g_free (rsrc_dir);
2941     g_free (rdst_dir);
2942 
2943     return ret;
2944 }
2945 
2946 GObject *
seafile_get_copy_task(const char * task_id,GError ** error)2947 seafile_get_copy_task (const char *task_id, GError **error)
2948 {
2949     return (GObject *)seaf_copy_manager_get_task (seaf->copy_mgr, task_id);
2950 }
2951 
2952 int
seafile_cancel_copy_task(const char * task_id,GError ** error)2953 seafile_cancel_copy_task (const char *task_id, GError **error)
2954 {
2955     return seaf_copy_manager_cancel_task (seaf->copy_mgr, task_id);
2956 }
2957 
2958 int
seafile_rename_file(const char * repo_id,const char * parent_dir,const char * oldname,const char * newname,const char * user,GError ** error)2959 seafile_rename_file (const char *repo_id,
2960                      const char *parent_dir,
2961                      const char *oldname,
2962                      const char *newname,
2963                      const char *user,
2964                      GError **error)
2965 {
2966     char *norm_parent_dir = NULL, *norm_oldname = NULL, *norm_newname = NULL;
2967     char *rpath = NULL;
2968     int ret = 0;
2969 
2970     if (!repo_id || !parent_dir || !oldname || !newname || !user) {
2971         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
2972         return -1;
2973     }
2974 
2975     if (!is_uuid_valid (repo_id)) {
2976         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
2977         return -1;
2978     }
2979 
2980     norm_parent_dir = normalize_utf8_path (parent_dir);
2981     if (!norm_parent_dir) {
2982         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2983                      "Path is in valid UTF8 encoding");
2984         ret = -1;
2985         goto out;
2986     }
2987 
2988     norm_oldname = normalize_utf8_path (oldname);
2989     if (!norm_oldname) {
2990         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2991                      "Path is in valid UTF8 encoding");
2992         ret = -1;
2993         goto out;
2994     }
2995 
2996     norm_newname = normalize_utf8_path (newname);
2997     if (!norm_newname) {
2998         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
2999                      "Path is in valid UTF8 encoding");
3000         ret = -1;
3001         goto out;
3002     }
3003 
3004     rpath = format_dir_path (norm_parent_dir);
3005 
3006     if (seaf_repo_manager_rename_file (seaf->repo_mgr, repo_id,
3007                                        rpath, norm_oldname, norm_newname,
3008                                        user, error) < 0) {
3009         ret = -1;
3010     }
3011 
3012 out:
3013     g_free (norm_parent_dir);
3014     g_free (norm_oldname);
3015     g_free (norm_newname);
3016     g_free (rpath);
3017     return ret;
3018 }
3019 
3020 int
seafile_is_valid_filename(const char * repo_id,const char * filename,GError ** error)3021 seafile_is_valid_filename (const char *repo_id,
3022                            const char *filename,
3023                            GError **error)
3024 {
3025     if (!repo_id || !filename) {
3026         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
3027         return -1;
3028     }
3029 
3030     int ret = seaf_repo_manager_is_valid_filename (seaf->repo_mgr,
3031                                                    repo_id,
3032                                                    filename,
3033                                                    error);
3034     return ret;
3035 }
3036 
3037 char *
seafile_create_repo(const char * repo_name,const char * repo_desc,const char * owner_email,const char * passwd,int enc_version,GError ** error)3038 seafile_create_repo (const char *repo_name,
3039                      const char *repo_desc,
3040                      const char *owner_email,
3041                      const char *passwd,
3042                      int enc_version,
3043                      GError **error)
3044 {
3045     if (!repo_name || !repo_desc || !owner_email) {
3046         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
3047         return NULL;
3048     }
3049 
3050     char *repo_id;
3051 
3052     repo_id = seaf_repo_manager_create_new_repo (seaf->repo_mgr,
3053                                                  repo_name, repo_desc,
3054                                                  owner_email,
3055                                                  passwd,
3056                                                  enc_version,
3057                                                  error);
3058     return repo_id;
3059 }
3060 
3061 char *
seafile_create_enc_repo(const char * repo_id,const char * repo_name,const char * repo_desc,const char * owner_email,const char * magic,const char * random_key,const char * salt,int enc_version,GError ** error)3062 seafile_create_enc_repo (const char *repo_id,
3063                          const char *repo_name,
3064                          const char *repo_desc,
3065                          const char *owner_email,
3066                          const char *magic,
3067                          const char *random_key,
3068                          const char *salt,
3069                          int enc_version,
3070                          GError **error)
3071 {
3072     if (!repo_id || !repo_name || !repo_desc || !owner_email) {
3073         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
3074         return NULL;
3075     }
3076 
3077     char *ret;
3078 
3079     ret = seaf_repo_manager_create_enc_repo (seaf->repo_mgr,
3080                                              repo_id, repo_name, repo_desc,
3081                                              owner_email,
3082                                              magic, random_key, salt, enc_version,
3083                                              error);
3084     return ret;
3085 }
3086 
3087 int
seafile_set_user_quota(const char * user,gint64 quota,GError ** error)3088 seafile_set_user_quota (const char *user, gint64 quota, GError **error)
3089 {
3090     if (!user) {
3091         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3092                      "Bad arguments");
3093         return -1;
3094     }
3095 
3096     return seaf_quota_manager_set_user_quota (seaf->quota_mgr, user, quota);
3097 }
3098 
3099 gint64
seafile_get_user_quota(const char * user,GError ** error)3100 seafile_get_user_quota (const char *user, GError **error)
3101 {
3102     if (!user) {
3103         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3104                      "Bad arguments");
3105         return -1;
3106     }
3107 
3108     return seaf_quota_manager_get_user_quota (seaf->quota_mgr, user);
3109 }
3110 
3111 int
seafile_check_quota(const char * repo_id,gint64 delta,GError ** error)3112 seafile_check_quota (const char *repo_id, gint64 delta, GError **error)
3113 {
3114     int rc;
3115 
3116     if (!repo_id) {
3117         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad arguments");
3118         return -1;
3119     }
3120 
3121     rc = seaf_quota_manager_check_quota_with_delta (seaf->quota_mgr, repo_id, delta);
3122     if (rc == 1)
3123         return -1;
3124     return rc;
3125 }
3126 
3127 GList *
seafile_list_user_quota_usage(GError ** error)3128 seafile_list_user_quota_usage (GError **error)
3129 {
3130     return seaf_repo_quota_manager_list_user_quota_usage (seaf->quota_mgr);
3131 }
3132 
3133 static char *
get_obj_id_by_path(const char * repo_id,const char * path,gboolean want_dir,GError ** error)3134 get_obj_id_by_path (const char *repo_id,
3135                     const char *path,
3136                     gboolean want_dir,
3137                     GError **error)
3138 {
3139     SeafRepo *repo = NULL;
3140     SeafCommit *commit = NULL;
3141     char *obj_id = NULL;
3142 
3143     if (!repo_id || !path) {
3144         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3145                      "Bad arguments");
3146         return NULL;
3147     }
3148 
3149     if (!is_uuid_valid (repo_id)) {
3150         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3151         return NULL;
3152     }
3153 
3154     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
3155     if (!repo) {
3156         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL,
3157                      "Get repo error");
3158         goto out;
3159     }
3160 
3161     commit = seaf_commit_manager_get_commit (seaf->commit_mgr,
3162                                              repo->id, repo->version,
3163                                              repo->head->commit_id);
3164     if (!commit) {
3165         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL,
3166                      "Get commit error");
3167         goto out;
3168     }
3169 
3170     guint32 mode = 0;
3171     obj_id = seaf_fs_manager_path_to_obj_id (seaf->fs_mgr,
3172                                              repo->store_id, repo->version,
3173                                              commit->root_id,
3174                                              path, &mode, error);
3175 
3176 out:
3177     if (repo)
3178         seaf_repo_unref (repo);
3179     if (commit)
3180         seaf_commit_unref (commit);
3181     if (obj_id) {
3182         /* check if the mode matches */
3183         if ((want_dir && !S_ISDIR(mode)) || ((!want_dir) && S_ISDIR(mode))) {
3184             g_free (obj_id);
3185             return NULL;
3186         }
3187     }
3188 
3189     return obj_id;
3190 }
3191 
seafile_get_file_id_by_path(const char * repo_id,const char * path,GError ** error)3192 char *seafile_get_file_id_by_path (const char *repo_id,
3193                                    const char *path,
3194                                    GError **error)
3195 {
3196     char *rpath = format_dir_path (path);
3197     char *ret = get_obj_id_by_path (repo_id, rpath, FALSE, error);
3198 
3199     g_free (rpath);
3200 
3201     filter_error (error);
3202 
3203     return ret;
3204 }
3205 
seafile_get_dir_id_by_path(const char * repo_id,const char * path,GError ** error)3206 char *seafile_get_dir_id_by_path (const char *repo_id,
3207                                   const char *path,
3208                                   GError **error)
3209 {
3210     char *rpath = format_dir_path (path);
3211     char *ret = get_obj_id_by_path (repo_id, rpath, TRUE, error);
3212 
3213     g_free (rpath);
3214 
3215     filter_error (error);
3216 
3217     return ret;
3218 }
3219 
3220 GObject *
seafile_get_dirent_by_path(const char * repo_id,const char * path,GError ** error)3221 seafile_get_dirent_by_path (const char *repo_id, const char *path,
3222                             GError **error)
3223 {
3224     if (!repo_id || !path) {
3225         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3226                      "Bad arguments");
3227         return NULL;
3228     }
3229 
3230     if (!is_uuid_valid (repo_id)) {
3231         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3232                      "invalid repo id");
3233         return NULL;
3234     }
3235 
3236     char *rpath = format_dir_path (path);
3237     if (strcmp (rpath, "/") == 0) {
3238         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3239                      "invalid path");
3240         g_free (rpath);
3241         return NULL;
3242     }
3243 
3244     SeafRepo *repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
3245     if (!repo) {
3246         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL,
3247                      "Get repo error");
3248         return NULL;
3249     }
3250 
3251     SeafCommit *commit = seaf_commit_manager_get_commit (seaf->commit_mgr,
3252                                                          repo->id, repo->version,
3253                                                          repo->head->commit_id);
3254     if (!commit) {
3255         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL,
3256                      "Get commit error");
3257         seaf_repo_unref (repo);
3258         return NULL;
3259     }
3260 
3261     SeafDirent *dirent = seaf_fs_manager_get_dirent_by_path (seaf->fs_mgr,
3262                                                              repo->store_id, repo->version,
3263                                                              commit->root_id, rpath,
3264                                                              error);
3265     g_free (rpath);
3266 
3267     if (!dirent) {
3268         filter_error (error);
3269         seaf_repo_unref (repo);
3270         seaf_commit_unref (commit);
3271         return NULL;
3272     }
3273 
3274     GObject *obj = g_object_new (SEAFILE_TYPE_DIRENT,
3275                                  "obj_id", dirent->id,
3276                                  "obj_name", dirent->name,
3277                                  "mode", dirent->mode,
3278                                  "version", dirent->version,
3279                                  "mtime", dirent->mtime,
3280                                  "size", dirent->size,
3281                                  "modifier", dirent->modifier,
3282                                  NULL);
3283 
3284     seaf_repo_unref (repo);
3285     seaf_commit_unref (commit);
3286     seaf_dirent_free (dirent);
3287 
3288     return obj;
3289 }
3290 
3291 char *
seafile_list_file_blocks(const char * repo_id,const char * file_id,int offset,int limit,GError ** error)3292 seafile_list_file_blocks (const char *repo_id,
3293                           const char *file_id,
3294                           int offset, int limit,
3295                           GError **error)
3296 {
3297     SeafRepo *repo;
3298     Seafile *file;
3299     GString *buf = g_string_new ("");
3300     int index = 0;
3301 
3302     if (!repo_id || !is_uuid_valid(repo_id)) {
3303         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad repo id");
3304         return NULL;
3305     }
3306 
3307     if (!file_id || !is_object_id_valid(file_id)) {
3308         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad file id");
3309         return NULL;
3310     }
3311 
3312     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
3313     if (!repo) {
3314         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad repo id");
3315         return NULL;
3316     }
3317 
3318     file = seaf_fs_manager_get_seafile (seaf->fs_mgr,
3319                                         repo->store_id,
3320                                         repo->version, file_id);
3321     if (!file) {
3322         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad file id");
3323         seaf_repo_unref (repo);
3324         return NULL;
3325     }
3326 
3327     if (offset < 0)
3328         offset = 0;
3329 
3330     for (index = 0; index < file->n_blocks; index++) {
3331         if (index < offset) {
3332             continue;
3333         }
3334 
3335         if (limit > 0) {
3336             if (index >= offset + limit)
3337                 break;
3338         }
3339         g_string_append_printf (buf, "%s\n", file->blk_sha1s[index]);
3340     }
3341 
3342     seafile_unref (file);
3343     seaf_repo_unref (repo);
3344     return g_string_free (buf, FALSE);
3345 }
3346 
3347 /*
3348  * Directories are always before files. Otherwise compare the names.
3349  */
3350 static gint
comp_dirent_func(gconstpointer a,gconstpointer b)3351 comp_dirent_func (gconstpointer a, gconstpointer b)
3352 {
3353     const SeafDirent *dent_a = a, *dent_b = b;
3354 
3355     if (S_ISDIR(dent_a->mode) && S_ISREG(dent_b->mode))
3356         return -1;
3357 
3358     if (S_ISREG(dent_a->mode) && S_ISDIR(dent_b->mode))
3359         return 1;
3360 
3361     return strcasecmp (dent_a->name, dent_b->name);
3362 }
3363 
3364 GList *
seafile_list_dir(const char * repo_id,const char * dir_id,int offset,int limit,GError ** error)3365 seafile_list_dir (const char *repo_id,
3366                   const char *dir_id, int offset, int limit, GError **error)
3367 {
3368     SeafRepo *repo;
3369     SeafDir *dir;
3370     SeafDirent *dent;
3371     SeafileDirent *d;
3372     GList *res = NULL;
3373     GList *p;
3374 
3375     if (!repo_id || !is_uuid_valid(repo_id)) {
3376         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad repo id");
3377         return NULL;
3378     }
3379 
3380     if (!dir_id || !is_object_id_valid (dir_id)) {
3381         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad dir id");
3382         return NULL;
3383     }
3384 
3385     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
3386     if (!repo) {
3387         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad repo id");
3388         return NULL;
3389     }
3390 
3391     dir = seaf_fs_manager_get_seafdir (seaf->fs_mgr,
3392                                        repo->store_id, repo->version, dir_id);
3393     if (!dir) {
3394         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_DIR_ID, "Bad dir id");
3395         seaf_repo_unref (repo);
3396         return NULL;
3397     }
3398 
3399     dir->entries = g_list_sort (dir->entries, comp_dirent_func);
3400 
3401     if (offset < 0) {
3402         offset = 0;
3403     }
3404 
3405     int index = 0;
3406     for (p = dir->entries; p != NULL; p = p->next, index++) {
3407         if (index < offset) {
3408             continue;
3409         }
3410 
3411         if (limit > 0) {
3412             if (index >= offset + limit)
3413                 break;
3414         }
3415 
3416         dent = p->data;
3417 
3418         if (!is_object_id_valid (dent->id))
3419             continue;
3420 
3421         d = g_object_new (SEAFILE_TYPE_DIRENT,
3422                           "obj_id", dent->id,
3423                           "obj_name", dent->name,
3424                           "mode", dent->mode,
3425                           "version", dent->version,
3426                           "mtime", dent->mtime,
3427                           "size", dent->size,
3428                           "permission", "",
3429                           NULL);
3430         res = g_list_prepend (res, d);
3431     }
3432 
3433     seaf_dir_free (dir);
3434     seaf_repo_unref (repo);
3435     res = g_list_reverse (res);
3436     return res;
3437 }
3438 
3439 GList *
seafile_list_file_revisions(const char * repo_id,const char * commit_id,const char * path,int limit,GError ** error)3440 seafile_list_file_revisions (const char *repo_id,
3441                              const char *commit_id,
3442                              const char *path,
3443                              int limit,
3444                              GError **error)
3445 {
3446     if (!repo_id || !path) {
3447         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3448                      "Bad arguments");
3449         return NULL;
3450     }
3451 
3452     if (!is_uuid_valid (repo_id)) {
3453         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3454         return NULL;
3455     }
3456 
3457     char *rpath = format_dir_path (path);
3458 
3459     GList *commit_list;
3460     commit_list = seaf_repo_manager_list_file_revisions (seaf->repo_mgr,
3461                                                          repo_id, commit_id, rpath,
3462                                                          limit, FALSE, FALSE, error);
3463     g_free (rpath);
3464 
3465     return commit_list;
3466 }
3467 
3468 GList *
seafile_calc_files_last_modified(const char * repo_id,const char * parent_dir,int limit,GError ** error)3469 seafile_calc_files_last_modified (const char *repo_id,
3470                                   const char *parent_dir,
3471                                   int limit,
3472                                   GError **error)
3473 {
3474     if (!repo_id || !parent_dir) {
3475         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3476                      "Bad arguments");
3477         return NULL;
3478     }
3479 
3480     if (!is_uuid_valid (repo_id)) {
3481         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3482         return NULL;
3483     }
3484 
3485     char *rpath = format_dir_path (parent_dir);
3486 
3487     GList *ret = seaf_repo_manager_calc_files_last_modified (seaf->repo_mgr,
3488                                                              repo_id, rpath,
3489                                                              limit, error);
3490     g_free (rpath);
3491 
3492     return ret;
3493 }
3494 
3495 int
seafile_revert_file(const char * repo_id,const char * commit_id,const char * path,const char * user,GError ** error)3496 seafile_revert_file (const char *repo_id,
3497                      const char *commit_id,
3498                      const char *path,
3499                      const char *user,
3500                      GError **error)
3501 {
3502     if (!repo_id || !commit_id || !path || !user) {
3503         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3504                      "Bad arguments");
3505         return -1;
3506     }
3507 
3508     if (!is_uuid_valid (repo_id)) {
3509         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3510         return -1;
3511     }
3512 
3513     if (!is_object_id_valid (commit_id)) {
3514         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid commit id");
3515         return -1;
3516     }
3517 
3518     char *rpath = format_dir_path (path);
3519 
3520     int ret = seaf_repo_manager_revert_file (seaf->repo_mgr,
3521                                              repo_id, commit_id,
3522                                              rpath, user, error);
3523     g_free (rpath);
3524 
3525     return ret;
3526 }
3527 
3528 int
seafile_revert_dir(const char * repo_id,const char * commit_id,const char * path,const char * user,GError ** error)3529 seafile_revert_dir (const char *repo_id,
3530                     const char *commit_id,
3531                     const char *path,
3532                     const char *user,
3533                     GError **error)
3534 {
3535     if (!repo_id || !commit_id || !path || !user) {
3536         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3537                      "Bad arguments");
3538         return -1;
3539     }
3540 
3541     if (!is_uuid_valid (repo_id)) {
3542         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3543         return -1;
3544     }
3545 
3546     if (!is_object_id_valid (commit_id)) {
3547         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid commit id");
3548         return -1;
3549     }
3550 
3551     char *rpath = format_dir_path (path);
3552 
3553     int ret = seaf_repo_manager_revert_dir (seaf->repo_mgr,
3554                                             repo_id, commit_id,
3555                                             rpath, user, error);
3556     g_free (rpath);
3557 
3558     return ret;
3559 }
3560 
3561 
3562 char *
seafile_check_repo_blocks_missing(const char * repo_id,const char * blockids_json,GError ** error)3563 seafile_check_repo_blocks_missing (const char *repo_id,
3564                                    const char *blockids_json,
3565                                    GError **error)
3566 {
3567     json_t *array, *value, *ret_json;
3568     json_error_t err;
3569     size_t index;
3570     char *json_data, *ret;
3571     SeafRepo *repo = NULL;
3572 
3573     array = json_loadb (blockids_json, strlen(blockids_json), 0, &err);
3574     if (!array) {
3575         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3576                      "Bad arguments");
3577         return NULL;
3578     }
3579 
3580     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
3581     if (!repo) {
3582         seaf_warning ("Failed to get repo %.8s.\n", repo_id);
3583         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3584                      "Repo not found");
3585         json_decref (array);
3586         return NULL;
3587     }
3588 
3589     ret_json = json_array();
3590     size_t n = json_array_size (array);
3591     for (index = 0; index < n; index++) {
3592         value = json_array_get (array, index);
3593         const char *blockid = json_string_value (value);
3594         if (!blockid)
3595             continue;
3596         if (!seaf_block_manager_block_exists(seaf->block_mgr, repo_id,
3597                                              repo->version, blockid)) {
3598             json_array_append_new (ret_json, json_string(blockid));
3599         }
3600     }
3601 
3602     json_data = json_dumps (ret_json, 0);
3603     ret = g_strdup (json_data);
3604 
3605     free (json_data);
3606     json_decref (ret_json);
3607     json_decref (array);
3608     return ret;
3609 }
3610 
3611 
3612 GList *
seafile_get_deleted(const char * repo_id,int show_days,const char * path,const char * scan_stat,int limit,GError ** error)3613 seafile_get_deleted (const char *repo_id, int show_days,
3614                      const char *path, const char *scan_stat,
3615                      int limit, GError **error)
3616 {
3617     if (!repo_id) {
3618         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3619                      "Bad arguments");
3620         return NULL;
3621     }
3622 
3623     if (!is_uuid_valid (repo_id)) {
3624         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3625         return NULL;
3626     }
3627 
3628     char *rpath = NULL;
3629     if (path)
3630         rpath = format_dir_path (path);
3631 
3632     GList *ret = seaf_repo_manager_get_deleted_entries (seaf->repo_mgr,
3633                                                         repo_id, show_days,
3634                                                         rpath, scan_stat,
3635                                                         limit, error);
3636     g_free (rpath);
3637 
3638     return ret;
3639 }
3640 
3641 char *
seafile_generate_repo_token(const char * repo_id,const char * email,GError ** error)3642 seafile_generate_repo_token (const char *repo_id,
3643                              const char *email,
3644                              GError **error)
3645 {
3646     char *token;
3647 
3648     if (!repo_id || !email) {
3649         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments should not be empty");
3650         return NULL;
3651     }
3652 
3653     if (!is_uuid_valid (repo_id)) {
3654         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3655         return NULL;
3656     }
3657 
3658     token = seaf_repo_manager_generate_repo_token (seaf->repo_mgr, repo_id, email, error);
3659 
3660     return token;
3661 }
3662 
3663 int
seafile_delete_repo_token(const char * repo_id,const char * token,const char * user,GError ** error)3664 seafile_delete_repo_token (const char *repo_id,
3665                            const char *token,
3666                            const char *user,
3667                            GError **error)
3668 {
3669     if (!repo_id || !token || !user) {
3670         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments should not be empty");
3671         return -1;
3672     }
3673 
3674     if (!is_uuid_valid (repo_id)) {
3675         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3676         return -1;
3677     }
3678 
3679     return seaf_repo_manager_delete_token (seaf->repo_mgr,
3680                                            repo_id, token, user, error);
3681 }
3682 
3683 GList *
seafile_list_repo_tokens(const char * repo_id,GError ** error)3684 seafile_list_repo_tokens (const char *repo_id,
3685                           GError **error)
3686 {
3687     GList *ret_list;
3688 
3689     if (!repo_id) {
3690         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments should not be empty");
3691         return NULL;
3692     }
3693 
3694     if (!is_uuid_valid (repo_id)) {
3695         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3696         return NULL;
3697     }
3698 
3699     ret_list = seaf_repo_manager_list_repo_tokens (seaf->repo_mgr, repo_id, error);
3700 
3701     return ret_list;
3702 }
3703 
3704 GList *
seafile_list_repo_tokens_by_email(const char * email,GError ** error)3705 seafile_list_repo_tokens_by_email (const char *email,
3706                                    GError **error)
3707 {
3708     GList *ret_list;
3709 
3710     if (!email) {
3711         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments should not be empty");
3712         return NULL;
3713     }
3714 
3715     ret_list = seaf_repo_manager_list_repo_tokens_by_email (seaf->repo_mgr, email, error);
3716 
3717     return ret_list;
3718 }
3719 
3720 int
seafile_delete_repo_tokens_by_peer_id(const char * email,const char * peer_id,GError ** error)3721 seafile_delete_repo_tokens_by_peer_id(const char *email,
3722                                       const char *peer_id,
3723                                       GError **error)
3724 {
3725     if (!email || !peer_id) {
3726         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments should not be empty");
3727         return -1;
3728     }
3729 
3730     /* check the peer id */
3731     if (strlen(peer_id) != 40) {
3732         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "invalid peer id");
3733         return -1;
3734     }
3735     const char *c = peer_id;
3736     while (*c) {
3737         char v = *c;
3738         if ((v >= '0' && v <= '9') || (v >= 'a' && v <= 'z')) {
3739             c++;
3740             continue;
3741         } else {
3742             g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "invalid peer id");
3743             return -1;
3744         }
3745     }
3746 
3747     GList *tokens = NULL;
3748     if (seaf_repo_manager_delete_repo_tokens_by_peer_id (seaf->repo_mgr, email, peer_id, &tokens, error) < 0) {
3749         g_list_free_full (tokens, (GDestroyNotify)g_free);
3750         return -1;
3751     }
3752 
3753     seaf_http_server_invalidate_tokens(seaf->http_server, tokens);
3754     g_list_free_full (tokens, (GDestroyNotify)g_free);
3755     return 0;
3756 }
3757 
3758 int
seafile_delete_repo_tokens_by_email(const char * email,GError ** error)3759 seafile_delete_repo_tokens_by_email (const char *email,
3760                                      GError **error)
3761 {
3762     if (!email) {
3763         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments should not be empty");
3764         return -1;
3765     }
3766 
3767     return seaf_repo_manager_delete_repo_tokens_by_email (seaf->repo_mgr, email, error);
3768 }
3769 
3770 char *
seafile_check_permission(const char * repo_id,const char * user,GError ** error)3771 seafile_check_permission (const char *repo_id, const char *user, GError **error)
3772 {
3773     if (!repo_id || !user) {
3774         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments should not be empty");
3775         return NULL;
3776     }
3777 
3778     if (!is_uuid_valid (repo_id)) {
3779         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3780         return NULL;
3781     }
3782 
3783     if (strlen(user) == 0)
3784         return NULL;
3785 
3786     return seaf_repo_manager_check_permission (seaf->repo_mgr,
3787                                                repo_id, user, error);
3788 }
3789 
3790 char *
seafile_check_permission_by_path(const char * repo_id,const char * path,const char * user,GError ** error)3791 seafile_check_permission_by_path (const char *repo_id, const char *path,
3792                                   const char *user, GError **error)
3793 {
3794     return seafile_check_permission (repo_id, user, error);
3795 }
3796 
3797 GList *
seafile_list_dir_with_perm(const char * repo_id,const char * path,const char * dir_id,const char * user,int offset,int limit,GError ** error)3798 seafile_list_dir_with_perm (const char *repo_id,
3799                             const char *path,
3800                             const char *dir_id,
3801                             const char *user,
3802                             int offset,
3803                             int limit,
3804                             GError **error)
3805 {
3806     if (!repo_id || !is_uuid_valid (repo_id)) {
3807         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3808         return NULL;
3809     }
3810 
3811     if (!path) {
3812         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid path");
3813         return NULL;
3814     }
3815 
3816     if (!dir_id || !is_object_id_valid (dir_id)) {
3817         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid dir id");
3818         return NULL;
3819     }
3820 
3821     if (!user) {
3822         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid user");
3823         return NULL;
3824     }
3825 
3826     char *rpath = format_dir_path (path);
3827 
3828     GList *ret = seaf_repo_manager_list_dir_with_perm (seaf->repo_mgr,
3829                                                        repo_id,
3830                                                        rpath,
3831                                                        dir_id,
3832                                                        user,
3833                                                        offset,
3834                                                        limit,
3835                                                        error);
3836     g_free (rpath);
3837 
3838     return ret;
3839 }
3840 
3841 int
seafile_set_share_permission(const char * repo_id,const char * from_email,const char * to_email,const char * permission,GError ** error)3842 seafile_set_share_permission (const char *repo_id,
3843                               const char *from_email,
3844                               const char *to_email,
3845                               const char *permission,
3846                               GError **error)
3847 {
3848     if (!repo_id || !from_email || !to_email || !permission) {
3849         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments should not be empty");
3850         return -1;
3851     }
3852 
3853     if (!is_uuid_valid (repo_id)) {
3854         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3855                      "Invalid repo_id parameter");
3856         return -1;
3857     }
3858 
3859     if (!is_permission_valid (permission)) {
3860         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3861                      "Invalid permission parameter");
3862         return -1;
3863     }
3864 
3865     return seaf_share_manager_set_permission (seaf->share_mgr,
3866                                               repo_id,
3867                                               from_email,
3868                                               to_email,
3869                                               permission);
3870 }
3871 
3872 int
seafile_set_group_repo_permission(int group_id,const char * repo_id,const char * permission,GError ** error)3873 seafile_set_group_repo_permission (int group_id,
3874                                    const char *repo_id,
3875                                    const char *permission,
3876                                    GError **error)
3877 {
3878     if (!repo_id || !permission) {
3879         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments should not be empty");
3880         return -1;
3881     }
3882 
3883     if (!is_uuid_valid (repo_id)) {
3884         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3885         return -1;
3886     }
3887 
3888     if (!is_permission_valid (permission)) {
3889         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3890                      "Invalid permission parameter");
3891         return -1;
3892 
3893     }
3894 
3895     return seaf_repo_manager_set_group_repo_perm (seaf->repo_mgr,
3896                                                   repo_id,
3897                                                   group_id,
3898                                                   permission,
3899                                                   error);
3900 }
3901 
3902 char *
seafile_get_file_id_by_commit_and_path(const char * repo_id,const char * commit_id,const char * path,GError ** error)3903 seafile_get_file_id_by_commit_and_path(const char *repo_id,
3904                                        const char *commit_id,
3905                                        const char *path,
3906                                        GError **error)
3907 {
3908     SeafRepo *repo;
3909     SeafCommit *commit;
3910     char *file_id;
3911     guint32 mode;
3912 
3913     if (!repo_id || !is_uuid_valid(repo_id) || !commit_id || !path) {
3914         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3915                      "Arguments should not be empty");
3916         return NULL;
3917     }
3918 
3919     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
3920     if (!repo) {
3921         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad repo id");
3922         return NULL;
3923     }
3924 
3925     commit = seaf_commit_manager_get_commit(seaf->commit_mgr,
3926                                             repo_id,
3927                                             repo->version,
3928                                             commit_id);
3929     if (!commit) {
3930         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
3931                      "bad commit id");
3932         seaf_repo_unref (repo);
3933         return NULL;
3934     }
3935 
3936     char *rpath = format_dir_path (path);
3937 
3938     file_id = seaf_fs_manager_path_to_obj_id (seaf->fs_mgr,
3939                                               repo->store_id, repo->version,
3940                                               commit->root_id, rpath, &mode, error);
3941     if (file_id && S_ISDIR(mode)) {
3942         g_free (file_id);
3943         file_id = NULL;
3944     }
3945     g_free (rpath);
3946 
3947     filter_error (error);
3948 
3949     seaf_commit_unref(commit);
3950     seaf_repo_unref (repo);
3951 
3952     return file_id;
3953 }
3954 
3955 /* Virtual repo related */
3956 
3957 char *
seafile_create_virtual_repo(const char * origin_repo_id,const char * path,const char * repo_name,const char * repo_desc,const char * owner,const char * passwd,GError ** error)3958 seafile_create_virtual_repo (const char *origin_repo_id,
3959                              const char *path,
3960                              const char *repo_name,
3961                              const char *repo_desc,
3962                              const char *owner,
3963                              const char *passwd,
3964                              GError **error)
3965 {
3966     if (!origin_repo_id || !path ||!repo_name || !repo_desc || !owner) {
3967         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
3968         return NULL;
3969     }
3970 
3971     if (!is_uuid_valid (origin_repo_id)) {
3972         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
3973         return NULL;
3974     }
3975 
3976     char *repo_id;
3977     char *rpath = format_dir_path (path);
3978 
3979     repo_id = seaf_repo_manager_create_virtual_repo (seaf->repo_mgr,
3980                                                      origin_repo_id, rpath,
3981                                                      repo_name, repo_desc,
3982                                                      owner, passwd, error);
3983     g_free (rpath);
3984 
3985     return repo_id;
3986 }
3987 
3988 GList *
seafile_get_virtual_repos_by_owner(const char * owner,GError ** error)3989 seafile_get_virtual_repos_by_owner (const char *owner, GError **error)
3990 {
3991     GList *repos, *ret = NULL, *ptr;
3992     SeafRepo *r, *o;
3993     SeafileRepo *repo;
3994     char *orig_repo_id;
3995     gboolean is_original_owner;
3996 
3997     if (!owner) {
3998         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
3999         return NULL;
4000     }
4001 
4002     repos = seaf_repo_manager_get_virtual_repos_by_owner (seaf->repo_mgr,
4003                                                           owner,
4004                                                           error);
4005     for (ptr = repos; ptr != NULL; ptr = ptr->next) {
4006         r = ptr->data;
4007 
4008         orig_repo_id = r->virtual_info->origin_repo_id;
4009         o = seaf_repo_manager_get_repo (seaf->repo_mgr, orig_repo_id);
4010         if (!o) {
4011             seaf_warning ("Failed to get origin repo %.10s.\n", orig_repo_id);
4012             seaf_repo_unref (r);
4013             continue;
4014         }
4015 
4016         char *orig_owner = seaf_repo_manager_get_repo_owner (seaf->repo_mgr,
4017                                                              orig_repo_id);
4018         if (g_strcmp0 (orig_owner, owner) == 0)
4019             is_original_owner = TRUE;
4020         else
4021             is_original_owner = FALSE;
4022         g_free (orig_owner);
4023 
4024         char *perm = seaf_repo_manager_check_permission (seaf->repo_mgr,
4025                                                          r->id, owner, NULL);
4026 
4027         repo = (SeafileRepo *)convert_repo (r);
4028         if (repo) {
4029             g_object_set (repo, "is_original_owner", is_original_owner,
4030                           "origin_repo_name", o->name,
4031                           "virtual_perm", perm, NULL);
4032             ret = g_list_prepend (ret, repo);
4033         }
4034 
4035         seaf_repo_unref (r);
4036         seaf_repo_unref (o);
4037         g_free (perm);
4038     }
4039     g_list_free (repos);
4040 
4041     return g_list_reverse (ret);
4042 }
4043 
4044 GObject *
seafile_get_virtual_repo(const char * origin_repo,const char * path,const char * owner,GError ** error)4045 seafile_get_virtual_repo (const char *origin_repo,
4046                           const char *path,
4047                           const char *owner,
4048                           GError **error)
4049 {
4050     char *repo_id;
4051     GObject *repo_obj;
4052 
4053     char *rpath = format_dir_path (path);
4054 
4055     repo_id = seaf_repo_manager_get_virtual_repo_id (seaf->repo_mgr,
4056                                                      origin_repo,
4057                                                      rpath,
4058                                                      owner);
4059     g_free (rpath);
4060 
4061     if (!repo_id)
4062         return NULL;
4063 
4064     repo_obj = seafile_get_repo (repo_id, error);
4065 
4066     g_free (repo_id);
4067     return repo_obj;
4068 }
4069 
4070 /* System default library */
4071 
4072 char *
seafile_get_system_default_repo_id(GError ** error)4073 seafile_get_system_default_repo_id (GError **error)
4074 {
4075     return get_system_default_repo_id(seaf);
4076 }
4077 
4078 static int
update_valid_since_time(SeafRepo * repo,gint64 new_time)4079 update_valid_since_time (SeafRepo *repo, gint64 new_time)
4080 {
4081     int ret = 0;
4082     gint64 old_time = seaf_repo_manager_get_repo_valid_since (repo->manager,
4083                                                               repo->id);
4084 
4085     if (new_time > 0) {
4086         if (new_time > old_time)
4087             ret = seaf_repo_manager_set_repo_valid_since (repo->manager,
4088                                                           repo->id,
4089                                                           new_time);
4090     } else if (new_time == 0) {
4091         /* Only the head commit is valid after GC if no history is kept. */
4092         SeafCommit *head = seaf_commit_manager_get_commit (seaf->commit_mgr,
4093                                                            repo->id, repo->version,
4094                                                            repo->head->commit_id);
4095         if (head && (old_time < 0 || head->ctime > (guint64)old_time))
4096             ret = seaf_repo_manager_set_repo_valid_since (repo->manager,
4097                                                           repo->id,
4098                                                           head->ctime);
4099         seaf_commit_unref (head);
4100     }
4101 
4102     return ret;
4103 }
4104 
4105 /* Clean up a repo's history.
4106  * It just set valid-since time but not actually delete the data.
4107  */
4108 int
seafile_clean_up_repo_history(const char * repo_id,int keep_days,GError ** error)4109 seafile_clean_up_repo_history (const char *repo_id, int keep_days, GError **error)
4110 {
4111     SeafRepo *repo;
4112     int ret;
4113 
4114     if (!is_uuid_valid (repo_id)) {
4115         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid arguments");
4116         return -1;
4117     }
4118 
4119     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
4120     if (!repo) {
4121         seaf_warning ("Cannot find repo %s.\n", repo_id);
4122         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid arguments");
4123         return -1;
4124     }
4125 
4126     gint64 truncate_time, now;
4127     if (keep_days > 0) {
4128         now = (gint64)time(NULL);
4129         truncate_time = now - keep_days * 24 * 3600;
4130     } else
4131         truncate_time = 0;
4132 
4133     ret = update_valid_since_time (repo, truncate_time);
4134     if (ret < 0) {
4135         seaf_warning ("Failed to update valid since time for repo %.8s.\n", repo->id);
4136         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Database error");
4137     }
4138 
4139     seaf_repo_unref (repo);
4140     return ret;
4141 }
4142 
4143 GList *
seafile_get_shared_users_for_subdir(const char * repo_id,const char * path,const char * from_user,GError ** error)4144 seafile_get_shared_users_for_subdir (const char *repo_id,
4145                                      const char *path,
4146                                      const char *from_user,
4147                                      GError **error)
4148 {
4149     if (!repo_id || !path || !from_user) {
4150         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4151         return NULL;
4152     }
4153 
4154     if (!is_uuid_valid (repo_id)) {
4155         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo_id");
4156         return NULL;
4157     }
4158 
4159     char *rpath = format_dir_path (path);
4160 
4161     GList *ret = seaf_repo_manager_get_shared_users_for_subdir (seaf->repo_mgr,
4162                                                                 repo_id, rpath,
4163                                                                 from_user, error);
4164     g_free (rpath);
4165 
4166     return ret;
4167 }
4168 
4169 GList *
seafile_get_shared_groups_for_subdir(const char * repo_id,const char * path,const char * from_user,GError ** error)4170 seafile_get_shared_groups_for_subdir (const char *repo_id,
4171                                       const char *path,
4172                                       const char *from_user,
4173                                       GError **error)
4174 {
4175     if (!repo_id || !path || !from_user) {
4176         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4177         return NULL;
4178     }
4179 
4180     if (!is_uuid_valid (repo_id)) {
4181         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo_id");
4182         return NULL;
4183     }
4184 
4185     char *rpath = format_dir_path (path);
4186 
4187     GList *ret = seaf_repo_manager_get_shared_groups_for_subdir (seaf->repo_mgr,
4188                                                                  repo_id, rpath,
4189                                                                  from_user, error);
4190     g_free (rpath);
4191 
4192     return ret;
4193 }
4194 
4195 gint64
seafile_get_total_file_number(GError ** error)4196 seafile_get_total_file_number (GError **error)
4197 {
4198     return seaf_get_total_file_number (error);
4199 }
4200 
4201 gint64
seafile_get_total_storage(GError ** error)4202 seafile_get_total_storage (GError **error)
4203 {
4204     return seaf_get_total_storage (error);
4205 }
4206 
4207 GObject *
seafile_get_file_count_info_by_path(const char * repo_id,const char * path,GError ** error)4208 seafile_get_file_count_info_by_path (const char *repo_id,
4209                                      const char *path,
4210                                      GError **error)
4211 {
4212     if (!repo_id || !path) {
4213         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4214         return NULL;
4215     }
4216 
4217     GObject *ret = NULL;
4218     SeafRepo *repo = NULL;
4219     repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
4220     if (!repo) {
4221         seaf_warning ("Failed to get repo %.10s\n", repo_id);
4222         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
4223                      "Library not exists");
4224         return NULL;
4225     }
4226 
4227     ret = seaf_fs_manager_get_file_count_info_by_path (seaf->fs_mgr,
4228                                                        repo->store_id,
4229                                                        repo->version,
4230                                                        repo->root_id,
4231                                                        path, error);
4232     seaf_repo_unref (repo);
4233 
4234     return ret;
4235 }
4236 
4237 char *
seafile_get_trash_repo_owner(const char * repo_id,GError ** error)4238 seafile_get_trash_repo_owner (const char *repo_id, GError **error)
4239 {
4240     if (!repo_id) {
4241         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4242         return NULL;
4243     }
4244 
4245     return seaf_get_trash_repo_owner (repo_id);
4246 }
4247 
4248 int
seafile_mkdir_with_parents(const char * repo_id,const char * parent_dir,const char * new_dir_path,const char * user,GError ** error)4249 seafile_mkdir_with_parents (const char *repo_id, const char *parent_dir,
4250                             const char *new_dir_path, const char *user,
4251                             GError **error)
4252 {
4253     if (!repo_id || !parent_dir || !new_dir_path || !user) {
4254         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4255         return -1;
4256     }
4257 
4258     if (!is_uuid_valid (repo_id)) {
4259         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
4260         return -1;
4261     }
4262 
4263     if (seaf_repo_manager_mkdir_with_parents (seaf->repo_mgr, repo_id,
4264                                               parent_dir, new_dir_path,
4265                                               user, error) < 0) {
4266         return -1;
4267     }
4268 
4269     return 0;
4270 }
4271 
4272 int
seafile_set_server_config_int(const char * group,const char * key,int value,GError ** error)4273 seafile_set_server_config_int (const char *group, const char *key, int value,
4274                                GError **error)
4275 {
4276     if (!group || !key) {
4277         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4278         return -1;
4279     }
4280 
4281     return seaf_cfg_manager_set_config_int (seaf->cfg_mgr, group, key, value);
4282 }
4283 
4284 int
seafile_get_server_config_int(const char * group,const char * key,GError ** error)4285 seafile_get_server_config_int (const char *group, const char *key, GError **error)
4286 {
4287     if (!group || !key ) {
4288         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4289         return -1;
4290     }
4291 
4292     return seaf_cfg_manager_get_config_int (seaf->cfg_mgr, group, key);
4293 }
4294 
4295 int
seafile_set_server_config_int64(const char * group,const char * key,gint64 value,GError ** error)4296 seafile_set_server_config_int64 (const char *group, const char *key, gint64 value,
4297                                  GError **error)
4298 {
4299     if (!group || !key) {
4300         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4301         return -1;
4302     }
4303 
4304     return seaf_cfg_manager_set_config_int64 (seaf->cfg_mgr, group, key, value);
4305 }
4306 
4307 gint64
seafile_get_server_config_int64(const char * group,const char * key,GError ** error)4308 seafile_get_server_config_int64 (const char *group, const char *key, GError **error)
4309 {
4310     if (!group || !key ) {
4311         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4312         return -1;
4313     }
4314 
4315     return seaf_cfg_manager_get_config_int64 (seaf->cfg_mgr, group, key);
4316 }
4317 
4318 int
seafile_set_server_config_string(const char * group,const char * key,const char * value,GError ** error)4319 seafile_set_server_config_string (const char *group, const char *key, const char *value,
4320                                   GError **error)
4321 {
4322     if (!group || !key || !value) {
4323         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4324         return -1;
4325     }
4326 
4327     return seaf_cfg_manager_set_config_string (seaf->cfg_mgr, group, key, value);
4328 }
4329 
4330 char *
seafile_get_server_config_string(const char * group,const char * key,GError ** error)4331 seafile_get_server_config_string (const char *group, const char *key, GError **error)
4332 {
4333     if (!group || !key ) {
4334         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4335         return NULL;
4336     }
4337 
4338     return seaf_cfg_manager_get_config_string (seaf->cfg_mgr, group, key);
4339 }
4340 
4341 int
seafile_set_server_config_boolean(const char * group,const char * key,int value,GError ** error)4342 seafile_set_server_config_boolean (const char *group, const char *key, int value,
4343                                    GError **error)
4344 {
4345     if (!group || !key) {
4346         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4347         return -1;
4348     }
4349 
4350     return seaf_cfg_manager_set_config_boolean (seaf->cfg_mgr, group, key, value);
4351 }
4352 
4353 int
seafile_get_server_config_boolean(const char * group,const char * key,GError ** error)4354 seafile_get_server_config_boolean (const char *group, const char *key, GError **error)
4355 {
4356     if (!group || !key ) {
4357         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Argument should not be null");
4358         return -1;
4359     }
4360 
4361     return seaf_cfg_manager_get_config_boolean (seaf->cfg_mgr, group, key);
4362 }
4363 
4364 GObject *
seafile_get_group_shared_repo_by_path(const char * repo_id,const char * path,int group_id,int is_org,GError ** error)4365 seafile_get_group_shared_repo_by_path (const char *repo_id,
4366                                        const char *path,
4367                                        int group_id,
4368                                        int is_org,
4369                                        GError **error)
4370 {
4371     if (!repo_id || group_id < 0) {
4372         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Arguments error");
4373         return NULL;
4374     }
4375     SeafRepoManager *mgr = seaf->repo_mgr;
4376 
4377     return seaf_get_group_shared_repo_by_path (mgr, repo_id, path, group_id, is_org ? TRUE:FALSE, error);
4378 }
4379 
4380 GObject *
seafile_get_shared_repo_by_path(const char * repo_id,const char * path,const char * shared_to,int is_org,GError ** error)4381 seafile_get_shared_repo_by_path (const char *repo_id,
4382                                  const char *path,
4383                                  const char *shared_to,
4384                                  int is_org,
4385                                  GError **error)
4386 {
4387     if (!repo_id || !shared_to) {
4388         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Arguments error");
4389         return NULL;
4390     }
4391     SeafRepoManager *mgr = seaf->repo_mgr;
4392 
4393     return seaf_get_shared_repo_by_path (mgr, repo_id, path, shared_to, is_org ? TRUE:FALSE, error);
4394 }
4395 
4396 GList *
seafile_get_group_repos_by_user(const char * user,GError ** error)4397 seafile_get_group_repos_by_user (const char *user, GError **error)
4398 {
4399     if (!user) {
4400         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Arguments error");
4401         return NULL;
4402     }
4403     SeafRepoManager *mgr = seaf->repo_mgr;
4404 
4405     return seaf_get_group_repos_by_user (mgr, user, -1, error);
4406 }
4407 
4408 GList *
seafile_get_org_group_repos_by_user(const char * user,int org_id,GError ** error)4409 seafile_get_org_group_repos_by_user (const char *user, int org_id, GError **error)
4410 {
4411     if (!user) {
4412         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Arguments error");
4413         return NULL;
4414     }
4415     SeafRepoManager *mgr = seaf->repo_mgr;
4416 
4417     return seaf_get_group_repos_by_user (mgr, user, org_id, error);
4418 }
4419 
4420 int
seafile_repo_has_been_shared(const char * repo_id,int including_groups,GError ** error)4421 seafile_repo_has_been_shared (const char *repo_id, int including_groups, GError **error)
4422 {
4423     if (!repo_id) {
4424         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Arguments error");
4425         return FALSE;
4426     }
4427 
4428     gboolean exists = seaf_share_manager_repo_has_been_shared (seaf->share_mgr, repo_id,
4429                                                                including_groups ? TRUE : FALSE);
4430     return exists ? 1 : 0;
4431 }
4432 
4433 GList *
seafile_get_shared_users_by_repo(const char * repo_id,GError ** error)4434 seafile_get_shared_users_by_repo (const char *repo_id, GError **error)
4435 {
4436     if (!repo_id) {
4437         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Arguments error");
4438         return NULL;
4439     }
4440 
4441     return seaf_share_manager_get_shared_users_by_repo (seaf->share_mgr,
4442                                                         repo_id);
4443 }
4444 
4445 GList *
seafile_org_get_shared_users_by_repo(int org_id,const char * repo_id,GError ** error)4446 seafile_org_get_shared_users_by_repo (int org_id,
4447                                       const char *repo_id,
4448                                       GError **error)
4449 {
4450     if (!repo_id || org_id < 0) {
4451         g_set_error (error, 0, SEAF_ERR_BAD_ARGS, "Arguments error");
4452         return NULL;
4453     }
4454 
4455     return seaf_share_manager_org_get_shared_users_by_repo (seaf->share_mgr,
4456                                                             org_id, repo_id);
4457 }
4458 
4459 /* Resumable file upload. */
4460 
4461 gint64
seafile_get_upload_tmp_file_offset(const char * repo_id,const char * file_path,GError ** error)4462 seafile_get_upload_tmp_file_offset (const char *repo_id, const char *file_path,
4463                                     GError **error)
4464 {
4465     if (!repo_id || !is_uuid_valid(repo_id)) {
4466         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
4467                      "Invalid repo id");
4468         return -1;
4469     }
4470 
4471     int path_len;
4472     if (!file_path || (path_len = strlen(file_path)) == 0) {
4473         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
4474                      "Invalid file path");
4475         return -1;
4476     }
4477 
4478     char *rfile_path = format_dir_path (file_path);
4479     gint64 ret = seaf_repo_manager_get_upload_tmp_file_offset (seaf->repo_mgr, repo_id,
4480                                                                rfile_path, error);
4481     g_free (rfile_path);
4482 
4483     return ret;
4484 }
4485 
4486 char *
seafile_convert_repo_path(const char * repo_id,const char * path,const char * user,int is_org,GError ** error)4487 seafile_convert_repo_path (const char *repo_id,
4488                            const char *path,
4489                            const char *user,
4490                            int is_org,
4491                            GError **error)
4492 {
4493     if (!is_uuid_valid(repo_id) || !path || !user) {
4494         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments error");
4495         return NULL;
4496     }
4497 
4498     char *rpath = format_dir_path (path);
4499     char *ret = seaf_repo_manager_convert_repo_path(seaf->repo_mgr, repo_id, rpath, user, is_org ? TRUE : FALSE, error);
4500     g_free(rpath);
4501 
4502     return ret;
4503 }
4504 
4505 int
seafile_set_repo_status(const char * repo_id,int status,GError ** error)4506 seafile_set_repo_status(const char *repo_id, int status, GError **error)
4507 {
4508     if (!is_uuid_valid(repo_id) ||
4509         status < 0 || status >= N_REPO_STATUS) {
4510         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments error");
4511         return -1;
4512     }
4513 
4514     return seaf_repo_manager_set_repo_status(seaf->repo_mgr, repo_id, status);
4515 }
4516 
4517 int
seafile_get_repo_status(const char * repo_id,GError ** error)4518 seafile_get_repo_status(const char *repo_id, GError **error)
4519 {
4520     int status;
4521 
4522     if (!is_uuid_valid(repo_id)) {
4523         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Arguments error");
4524         return -1;
4525     }
4526 
4527     status = seaf_repo_manager_get_repo_status(seaf->repo_mgr, repo_id);
4528 
4529     return (status == -1) ? 0 : status;
4530 }
4531 
4532 GList *
seafile_search_files(const char * repo_id,const char * str,GError ** error)4533 seafile_search_files (const char *repo_id, const char *str, GError **error)
4534 {
4535     if (!is_uuid_valid (repo_id)) {
4536         g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Invalid repo id");
4537         return NULL;
4538     }
4539 
4540     GList *file_list = seaf_fs_manager_search_files (seaf->fs_mgr, repo_id, str);
4541     GList *ret = NULL, *ptr;
4542 
4543     for (ptr = file_list; ptr; ptr=ptr->next) {
4544         SearchResult *sr = ptr->data;
4545         SeafileSearchResult *search_result = seafile_search_result_new ();
4546         g_object_set (search_result, "path", sr->path, "size", sr->size,
4547                       "mtime", sr->mtime, "is_dir", sr->is_dir, NULL);
4548 
4549         ret = g_list_prepend (ret, search_result);
4550         g_free (sr->path);
4551         g_free (sr);
4552     }
4553 
4554     return g_list_reverse (ret);
4555 }
4556 
4557 /*RPC functions merged from ccnet-server*/
4558 int
ccnet_rpc_add_emailuser(const char * email,const char * passwd,int is_staff,int is_active,GError ** error)4559 ccnet_rpc_add_emailuser (const char *email, const char *passwd,
4560                          int is_staff, int is_active, GError **error)
4561 {
4562     CcnetUserManager *user_mgr = seaf->user_mgr;
4563     int ret;
4564 
4565     if (!email || !passwd) {
4566         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Email and passwd can not be NULL");
4567         return -1;
4568     }
4569 
4570     ret = ccnet_user_manager_add_emailuser (user_mgr, email, passwd,
4571                                             is_staff, is_active);
4572 
4573     return ret;
4574 }
4575 
4576 int
ccnet_rpc_remove_emailuser(const char * source,const char * email,GError ** error)4577 ccnet_rpc_remove_emailuser (const char *source, const char *email, GError **error)
4578 {
4579     CcnetUserManager *user_mgr = seaf->user_mgr;
4580     int ret;
4581 
4582     if (!email) {
4583         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Email can not be NULL");
4584         return -1;
4585     }
4586 
4587     ret = ccnet_user_manager_remove_emailuser (user_mgr, source, email);
4588 
4589     return ret;
4590 }
4591 
4592 int
ccnet_rpc_validate_emailuser(const char * email,const char * passwd,GError ** error)4593 ccnet_rpc_validate_emailuser (const char *email, const char *passwd, GError **error)
4594 {
4595    CcnetUserManager *user_mgr = seaf->user_mgr;
4596     int ret;
4597 
4598     if (!email || !passwd) {
4599         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Email and passwd can not be NULL");
4600         return -1;
4601     }
4602 
4603     if (passwd[0] == 0)
4604         return -1;
4605 
4606     ret = ccnet_user_manager_validate_emailuser (user_mgr, email, passwd);
4607 
4608     return ret;
4609 }
4610 
4611 GObject*
ccnet_rpc_get_emailuser(const char * email,GError ** error)4612 ccnet_rpc_get_emailuser (const char *email, GError **error)
4613 {
4614     if (!email) {
4615         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Email can not be NULL");
4616         return NULL;
4617     }
4618 
4619     CcnetUserManager *user_mgr = seaf->user_mgr;
4620     CcnetEmailUser *emailuser = NULL;
4621 
4622     emailuser = ccnet_user_manager_get_emailuser (user_mgr, email);
4623 
4624     return (GObject *)emailuser;
4625 }
4626 
4627 GObject*
ccnet_rpc_get_emailuser_with_import(const char * email,GError ** error)4628 ccnet_rpc_get_emailuser_with_import (const char *email, GError **error)
4629 {
4630     if (!email) {
4631         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Email can not be NULL");
4632         return NULL;
4633     }
4634 
4635     CcnetUserManager *user_mgr = seaf->user_mgr;
4636     CcnetEmailUser *emailuser = NULL;
4637 
4638     emailuser = ccnet_user_manager_get_emailuser_with_import (user_mgr, email);
4639 
4640     return (GObject *)emailuser;
4641 }
4642 
4643 GObject*
ccnet_rpc_get_emailuser_by_id(int id,GError ** error)4644 ccnet_rpc_get_emailuser_by_id (int id, GError **error)
4645 {
4646    CcnetUserManager *user_mgr = seaf->user_mgr;
4647     CcnetEmailUser *emailuser = NULL;
4648 
4649     emailuser = ccnet_user_manager_get_emailuser_by_id (user_mgr, id);
4650 
4651     return (GObject *)emailuser;
4652 }
4653 
4654 GList*
ccnet_rpc_get_emailusers(const char * source,int start,int limit,const char * status,GError ** error)4655 ccnet_rpc_get_emailusers (const char *source,
4656                           int start, int limit,
4657                           const char *status,
4658                           GError **error)
4659 {
4660    CcnetUserManager *user_mgr = seaf->user_mgr;
4661     GList *emailusers = NULL;
4662 
4663     emailusers = ccnet_user_manager_get_emailusers (user_mgr, source, start, limit, status);
4664 
4665     return emailusers;
4666 }
4667 
4668 GList*
ccnet_rpc_search_emailusers(const char * source,const char * email_patt,int start,int limit,GError ** error)4669 ccnet_rpc_search_emailusers (const char *source,
4670                              const char *email_patt,
4671                              int start, int limit,
4672                              GError **error)
4673 {
4674     CcnetUserManager *user_mgr = seaf->user_mgr;
4675     GList *emailusers = NULL;
4676 
4677     emailusers = ccnet_user_manager_search_emailusers (user_mgr,
4678                                                        source,
4679                                                        email_patt,
4680                                                        start, limit);
4681 
4682     return emailusers;
4683 }
4684 
4685 GList*
ccnet_rpc_search_groups(const char * group_patt,int start,int limit,GError ** error)4686 ccnet_rpc_search_groups (const char *group_patt,
4687                          int start, int limit,
4688                          GError **error)
4689 {
4690     CcnetGroupManager *group_mgr = seaf->group_mgr;
4691     GList *groups = NULL;
4692 
4693     groups = ccnet_group_manager_search_groups (group_mgr,
4694                                                 group_patt,
4695                                                 start, limit);
4696     return groups;
4697 }
4698 
4699 GList*
ccnet_rpc_get_top_groups(int including_org,GError ** error)4700 ccnet_rpc_get_top_groups (int including_org, GError **error)
4701 {
4702     CcnetGroupManager *group_mgr = seaf->group_mgr;
4703     GList *groups = NULL;
4704 
4705     groups = ccnet_group_manager_get_top_groups (group_mgr, including_org ? TRUE : FALSE, error);
4706 
4707     return groups;
4708 }
4709 
4710 GList*
ccnet_rpc_get_child_groups(int group_id,GError ** error)4711 ccnet_rpc_get_child_groups (int group_id, GError **error)
4712 {
4713     CcnetGroupManager *group_mgr = seaf->group_mgr;
4714     GList *groups = NULL;
4715 
4716     groups = ccnet_group_manager_get_child_groups (group_mgr, group_id, error);
4717 
4718     return groups;
4719 }
4720 
4721 GList*
ccnet_rpc_get_descendants_groups(int group_id,GError ** error)4722 ccnet_rpc_get_descendants_groups(int group_id, GError **error)
4723 {
4724     CcnetGroupManager *group_mgr = seaf->group_mgr;
4725     GList *groups = NULL;
4726 
4727     groups = ccnet_group_manager_get_descendants_groups (group_mgr, group_id, error);
4728 
4729     return groups;
4730 }
4731 
4732 GList*
ccnet_rpc_search_ldapusers(const char * keyword,int start,int limit,GError ** error)4733 ccnet_rpc_search_ldapusers (const char *keyword,
4734                             int start, int limit,
4735                             GError **error)
4736 {
4737     GList *ldapusers = NULL;
4738     CcnetUserManager *user_mgr = seaf->user_mgr;
4739 
4740     ldapusers = ccnet_user_manager_search_ldapusers (user_mgr, keyword,
4741                                                      start, limit);
4742     return ldapusers;
4743 }
4744 
4745 gint64
ccnet_rpc_count_emailusers(const char * source,GError ** error)4746 ccnet_rpc_count_emailusers (const char *source, GError **error)
4747 {
4748    CcnetUserManager *user_mgr = seaf->user_mgr;
4749 
4750    return ccnet_user_manager_count_emailusers (user_mgr, source);
4751 }
4752 
4753 gint64
ccnet_rpc_count_inactive_emailusers(const char * source,GError ** error)4754 ccnet_rpc_count_inactive_emailusers (const char *source, GError **error)
4755 {
4756    CcnetUserManager *user_mgr = seaf->user_mgr;
4757 
4758    return ccnet_user_manager_count_inactive_emailusers (user_mgr, source);
4759 }
4760 
4761 int
ccnet_rpc_update_emailuser(const char * source,int id,const char * passwd,int is_staff,int is_active,GError ** error)4762 ccnet_rpc_update_emailuser (const char *source, int id, const char* passwd,
4763                             int is_staff, int is_active,
4764                             GError **error)
4765 {
4766     CcnetUserManager *user_mgr = seaf->user_mgr;
4767 
4768     return ccnet_user_manager_update_emailuser(user_mgr, source, id, passwd,
4769                                                is_staff, is_active);
4770 }
4771 
4772 int
ccnet_rpc_update_role_emailuser(const char * email,const char * role,GError ** error)4773 ccnet_rpc_update_role_emailuser (const char* email, const char* role,
4774                             GError **error)
4775 {
4776     CcnetUserManager *user_mgr = seaf->user_mgr;
4777 
4778     return ccnet_user_manager_update_role_emailuser(user_mgr, email, role);
4779 }
4780 
4781 GList*
ccnet_rpc_get_superusers(GError ** error)4782 ccnet_rpc_get_superusers (GError **error)
4783 {
4784     CcnetUserManager *user_mgr = seaf->user_mgr;
4785 
4786     return ccnet_user_manager_get_superusers(user_mgr);
4787 }
4788 
4789 GList *
ccnet_rpc_get_emailusers_in_list(const char * source,const char * user_list,GError ** error)4790 ccnet_rpc_get_emailusers_in_list(const char *source, const char *user_list, GError **error)
4791 {
4792     if (!user_list || !source) {
4793         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
4794         return NULL;
4795     }
4796     CcnetUserManager *user_mgr = seaf->user_mgr;
4797 
4798     return ccnet_user_manager_get_emailusers_in_list (user_mgr, source, user_list, error);
4799 }
4800 
4801 int
ccnet_rpc_update_emailuser_id(const char * old_email,const char * new_email,GError ** error)4802 ccnet_rpc_update_emailuser_id (const char *old_email, const char *new_email, GError **error)
4803 {
4804     if (!old_email || !new_email) {
4805         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
4806         return -1;
4807     }
4808     CcnetUserManager *user_mgr = seaf->user_mgr;
4809 
4810     return ccnet_user_manager_update_emailuser_id (user_mgr, old_email, new_email, error);
4811 }
4812 
4813 int
ccnet_rpc_create_group(const char * group_name,const char * user_name,const char * type,int parent_group_id,GError ** error)4814 ccnet_rpc_create_group (const char *group_name, const char *user_name,
4815                         const char *type, int parent_group_id, GError **error)
4816 {
4817     CcnetGroupManager *group_mgr = seaf->group_mgr;
4818     int ret;
4819 
4820     if (!group_name || !user_name) {
4821         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL,
4822                      "Group name and user name can not be NULL");
4823         return -1;
4824     }
4825 
4826     ret = ccnet_group_manager_create_group (group_mgr, group_name, user_name, parent_group_id, error);
4827 
4828     return ret;
4829 }
4830 
4831 int
ccnet_rpc_create_org_group(int org_id,const char * group_name,const char * user_name,int parent_group_id,GError ** error)4832 ccnet_rpc_create_org_group (int org_id, const char *group_name,
4833                             const char *user_name, int parent_group_id, GError **error)
4834 {
4835     CcnetGroupManager *group_mgr = seaf->group_mgr;
4836     int ret;
4837 
4838     if (org_id < 0 || !group_name || !user_name) {
4839         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad args");
4840         return -1;
4841     }
4842 
4843     ret = ccnet_group_manager_create_org_group (group_mgr, org_id,
4844                                                 group_name, user_name, parent_group_id, error);
4845 
4846     return ret;
4847 }
4848 
4849 int
ccnet_rpc_remove_group(int group_id,GError ** error)4850 ccnet_rpc_remove_group (int group_id, GError **error)
4851 {
4852     CcnetGroupManager *group_mgr = seaf->group_mgr;
4853     int ret;
4854 
4855     if (group_id <= 0) {
4856         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL,
4857                      "Invalid group_id parameter");
4858         return -1;
4859     }
4860 
4861     ret = ccnet_group_manager_remove_group (group_mgr, group_id, FALSE, error);
4862 
4863     return ret;
4864 
4865 }
4866 
4867 int
ccnet_rpc_group_add_member(int group_id,const char * user_name,const char * member_name,GError ** error)4868 ccnet_rpc_group_add_member (int group_id, const char *user_name,
4869                             const char *member_name, GError **error)
4870 {
4871     CcnetGroupManager *group_mgr = seaf->group_mgr;
4872     int ret;
4873 
4874     if (group_id <= 0 || !user_name || !member_name) {
4875         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL,
4876                      "Group id and user name and member name can not be NULL");
4877         return -1;
4878     }
4879 
4880     ret = ccnet_group_manager_add_member (group_mgr, group_id, user_name, member_name,
4881                                           error);
4882 
4883     return ret;
4884 }
4885 
4886 int
ccnet_rpc_group_remove_member(int group_id,const char * user_name,const char * member_name,GError ** error)4887 ccnet_rpc_group_remove_member (int group_id, const char *user_name,
4888                                const char *member_name, GError **error)
4889 {
4890     CcnetGroupManager *group_mgr = seaf->group_mgr;
4891     int ret;
4892 
4893     if (!user_name || !member_name) {
4894         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL,
4895                      "User name and member name can not be NULL");
4896         return -1;
4897     }
4898 
4899     ret = ccnet_group_manager_remove_member (group_mgr, group_id, user_name,
4900                                              member_name, error);
4901 
4902     return ret;
4903 }
4904 
4905 int
ccnet_rpc_group_set_admin(int group_id,const char * member_name,GError ** error)4906 ccnet_rpc_group_set_admin (int group_id, const char *member_name,
4907                            GError **error)
4908 {
4909     CcnetGroupManager *group_mgr = seaf->group_mgr;
4910     int ret;
4911 
4912     if (group_id <= 0 || !member_name) {
4913         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL,
4914                      "Bad arguments");
4915         return -1;
4916     }
4917 
4918     ret = ccnet_group_manager_set_admin (group_mgr, group_id, member_name,
4919                                          error);
4920     return ret;
4921 }
4922 
4923 int
ccnet_rpc_group_unset_admin(int group_id,const char * member_name,GError ** error)4924 ccnet_rpc_group_unset_admin (int group_id, const char *member_name,
4925                            GError **error)
4926 {
4927     CcnetGroupManager *group_mgr = seaf->group_mgr;
4928     int ret;
4929 
4930     if (group_id <= 0 || !member_name) {
4931         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL,
4932                      "Bad arguments");
4933         return -1;
4934     }
4935 
4936     ret = ccnet_group_manager_unset_admin (group_mgr, group_id, member_name,
4937                                            error);
4938     return ret;
4939 }
4940 
4941 int
ccnet_rpc_set_group_name(int group_id,const char * group_name,GError ** error)4942 ccnet_rpc_set_group_name (int group_id, const char *group_name,
4943                           GError **error)
4944 {
4945     CcnetGroupManager *group_mgr = seaf->group_mgr;
4946     int ret;
4947 
4948     if (group_id <= 0 || !group_name) {
4949         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL,
4950                      "Bad arguments");
4951         return -1;
4952     }
4953 
4954     ret = ccnet_group_manager_set_group_name (group_mgr, group_id, group_name,
4955                                               error);
4956     return ret;
4957 }
4958 
4959 int
ccnet_rpc_quit_group(int group_id,const char * user_name,GError ** error)4960 ccnet_rpc_quit_group (int group_id, const char *user_name, GError **error)
4961 {
4962     CcnetGroupManager *group_mgr = seaf->group_mgr;
4963     int ret;
4964 
4965     if (group_id <= 0 || !user_name) {
4966         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL,
4967                      "Group id and user name can not be NULL");
4968         return -1;
4969     }
4970 
4971     ret = ccnet_group_manager_quit_group (group_mgr, group_id, user_name, error);
4972 
4973     return ret;
4974 }
4975 
4976 GList *
ccnet_rpc_get_groups(const char * username,int return_ancestors,GError ** error)4977 ccnet_rpc_get_groups (const char *username, int return_ancestors, GError **error)
4978 {
4979     CcnetGroupManager *group_mgr = seaf->group_mgr;
4980     GList *ret = NULL;
4981 
4982     if (!username) {
4983         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL,
4984                      "User name can not be NULL");
4985         return NULL;
4986     }
4987 
4988     ret = ccnet_group_manager_get_groups_by_user (group_mgr, username,
4989                                                   return_ancestors ? TRUE : FALSE, error);
4990     return ret;
4991 }
4992 
4993 GList *
ccnet_rpc_list_all_departments(GError ** error)4994 ccnet_rpc_list_all_departments (GError **error)
4995 {
4996     CcnetGroupManager *group_mgr = seaf->group_mgr;
4997     GList *ret = NULL;
4998 
4999     ret = ccnet_group_manager_list_all_departments (group_mgr, error);
5000 
5001     return ret;
5002 }
5003 
5004 GList *
ccnet_rpc_get_all_groups(int start,int limit,const char * source,GError ** error)5005 ccnet_rpc_get_all_groups (int start, int limit,
5006                           const char *source, GError **error)
5007 {
5008     CcnetGroupManager *group_mgr = seaf->group_mgr;
5009     GList *ret = NULL;
5010 
5011     ret = ccnet_group_manager_get_all_groups (group_mgr, start, limit, error);
5012 
5013     return ret;
5014 }
5015 
5016 GList *
ccnet_rpc_get_ancestor_groups(int group_id,GError ** error)5017 ccnet_rpc_get_ancestor_groups (int group_id, GError ** error)
5018 {
5019     CcnetGroupManager *group_mgr = seaf->group_mgr;
5020     GList *ret = NULL;
5021 
5022     ret = ccnet_group_manager_get_ancestor_groups (group_mgr, group_id);
5023 
5024     return ret;
5025 }
5026 
5027 GObject *
ccnet_rpc_get_group(int group_id,GError ** error)5028 ccnet_rpc_get_group (int group_id, GError **error)
5029 {
5030     CcnetGroupManager *group_mgr = seaf->group_mgr;
5031     CcnetGroup *group = NULL;
5032 
5033     group = ccnet_group_manager_get_group (group_mgr, group_id, error);
5034     if (!group) {
5035         return NULL;
5036     }
5037 
5038     /* g_object_ref (group); */
5039     return (GObject *)group;
5040 }
5041 
5042 
5043 GList *
ccnet_rpc_get_group_members(int group_id,int start,int limit,GError ** error)5044 ccnet_rpc_get_group_members (int group_id, int start, int limit, GError **error)
5045 {
5046     CcnetGroupManager *group_mgr = seaf->group_mgr;
5047     GList *ret = NULL;
5048 
5049     if (start < 0 ) {
5050         start = 0;
5051     }
5052 
5053     ret = ccnet_group_manager_get_group_members (group_mgr, group_id, start, limit, error);
5054     if (ret == NULL)
5055         return NULL;
5056 
5057     return g_list_reverse (ret);
5058 }
5059 
5060 GList *
ccnet_rpc_get_members_with_prefix(int group_id,const char * prefix,GError ** error)5061 ccnet_rpc_get_members_with_prefix(int group_id, const char *prefix, GError **error)
5062 {
5063     CcnetGroupManager *group_mgr = seaf->group_mgr;
5064     GList *ret = NULL;
5065 
5066     ret = ccnet_group_manager_get_members_with_prefix (group_mgr, group_id, prefix, error);
5067 
5068     return ret;
5069 }
5070 
5071 int
ccnet_rpc_check_group_staff(int group_id,const char * user_name,int in_structure,GError ** error)5072 ccnet_rpc_check_group_staff (int group_id, const char *user_name, int in_structure,
5073                              GError **error)
5074 {
5075     CcnetGroupManager *group_mgr = seaf->group_mgr;
5076 
5077     if (group_id <= 0 || !user_name) {
5078         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL,
5079                      "Bad arguments");
5080         return -1;
5081     }
5082 
5083     return ccnet_group_manager_check_group_staff (group_mgr,
5084                                                   group_id, user_name,
5085                                                   in_structure ? TRUE : FALSE);
5086 }
5087 
5088 int
ccnet_rpc_remove_group_user(const char * user,GError ** error)5089 ccnet_rpc_remove_group_user (const char *user, GError **error)
5090 {
5091     CcnetGroupManager *group_mgr = seaf->group_mgr;
5092     if (!user) {
5093         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5094         return -1;
5095     }
5096 
5097     return ccnet_group_manager_remove_group_user (group_mgr, user);
5098 }
5099 
5100 int
ccnet_rpc_is_group_user(int group_id,const char * user,int in_structure,GError ** error)5101 ccnet_rpc_is_group_user (int group_id, const char *user, int in_structure, GError **error)
5102 {
5103     CcnetGroupManager *group_mgr = seaf->group_mgr;
5104     if (!user || group_id < 0) {
5105         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5106         return 0;
5107     }
5108 
5109     return ccnet_group_manager_is_group_user (group_mgr, group_id, user, in_structure ? TRUE : FALSE);
5110 }
5111 
5112 int
ccnet_rpc_set_group_creator(int group_id,const char * user_name,GError ** error)5113 ccnet_rpc_set_group_creator (int group_id, const char *user_name,
5114                              GError **error)
5115 {
5116     CcnetGroupManager *group_mgr = seaf->group_mgr;
5117     if (!user_name || group_id < 0) {
5118         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5119         return -1;
5120     }
5121 
5122     return ccnet_group_manager_set_group_creator (group_mgr, group_id,
5123                                                   user_name);
5124 }
5125 
5126 GList *
ccnet_rpc_get_groups_members(const char * group_ids,GError ** error)5127 ccnet_rpc_get_groups_members (const char *group_ids, GError **error)
5128 {
5129     if (!group_ids || g_strcmp0(group_ids, "") == 0) {
5130         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5131         return NULL;
5132     }
5133     CcnetGroupManager *group_mgr = seaf->group_mgr;
5134 
5135     return ccnet_group_manager_get_groups_members (group_mgr, group_ids, error);
5136 }
5137 
5138 int
ccnet_rpc_create_org(const char * org_name,const char * url_prefix,const char * creator,GError ** error)5139 ccnet_rpc_create_org (const char *org_name, const char *url_prefix,
5140                       const char *creator, GError **error)
5141 {
5142     CcnetOrgManager *org_mgr = seaf->org_mgr;
5143 
5144     if (!org_name || !url_prefix || !creator) {
5145         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5146         return -1;
5147     }
5148 
5149     return ccnet_org_manager_create_org (org_mgr, org_name, url_prefix, creator,
5150                                          error);
5151 }
5152 
5153 int
ccnet_rpc_remove_org(int org_id,GError ** error)5154 ccnet_rpc_remove_org (int org_id, GError **error)
5155 {
5156     GList *group_ids = NULL, *email_list=NULL, *ptr;
5157     const char *url_prefix = NULL;
5158     CcnetOrgManager *org_mgr = seaf->org_mgr;
5159     CcnetUserManager *user_mgr = seaf->user_mgr;
5160     CcnetGroupManager *group_mgr = seaf->group_mgr;
5161 
5162     if (org_id < 0) {
5163         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5164         return -1;
5165     }
5166 
5167     url_prefix = ccnet_org_manager_get_url_prefix_by_org_id (org_mgr, org_id,
5168                                                              error);
5169     email_list = ccnet_org_manager_get_org_emailusers (org_mgr, url_prefix,
5170                                                        0, INT_MAX);
5171     ptr = email_list;
5172     while (ptr) {
5173         ccnet_user_manager_remove_emailuser (user_mgr, "DB", (gchar *)ptr->data);
5174         ptr = ptr->next;
5175     }
5176     string_list_free (email_list);
5177 
5178     group_ids = ccnet_org_manager_get_org_group_ids (org_mgr, org_id, 0, INT_MAX);
5179     ptr = group_ids;
5180     while (ptr) {
5181         ccnet_group_manager_remove_group (group_mgr, (int)(long)ptr->data, TRUE, error);
5182         ptr = ptr->next;
5183     }
5184     g_list_free (group_ids);
5185 
5186     return ccnet_org_manager_remove_org (org_mgr, org_id, error);
5187 }
5188 
5189 GList *
ccnet_rpc_get_all_orgs(int start,int limit,GError ** error)5190 ccnet_rpc_get_all_orgs (int start, int limit, GError **error)
5191 {
5192     CcnetOrgManager *org_mgr = seaf->org_mgr;
5193     GList *ret = NULL;
5194 
5195     ret = ccnet_org_manager_get_all_orgs (org_mgr, start, limit);
5196 
5197     return ret;
5198 }
5199 
5200 gint64
ccnet_rpc_count_orgs(GError ** error)5201 ccnet_rpc_count_orgs (GError **error)
5202 {
5203     CcnetOrgManager *org_mgr = seaf->org_mgr;
5204 
5205     return ccnet_org_manager_count_orgs(org_mgr);
5206 }
5207 
5208 
5209 GObject *
ccnet_rpc_get_org_by_url_prefix(const char * url_prefix,GError ** error)5210 ccnet_rpc_get_org_by_url_prefix (const char *url_prefix, GError **error)
5211 {
5212     CcnetOrganization *org = NULL;
5213     CcnetOrgManager *org_mgr = seaf->org_mgr;
5214 
5215     if (!url_prefix) {
5216         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5217         return NULL;
5218     }
5219 
5220     org = ccnet_org_manager_get_org_by_url_prefix (org_mgr, url_prefix, error);
5221     if (!org)
5222         return NULL;
5223 
5224     return (GObject *)org;
5225 }
5226 
5227 GObject *
ccnet_rpc_get_org_by_id(int org_id,GError ** error)5228 ccnet_rpc_get_org_by_id (int org_id, GError **error)
5229 {
5230     CcnetOrganization *org = NULL;
5231     CcnetOrgManager *org_mgr = seaf->org_mgr;
5232 
5233     if (org_id <= 0) {
5234         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5235         return NULL;
5236     }
5237 
5238     org = ccnet_org_manager_get_org_by_id (org_mgr, org_id, error);
5239     if (!org)
5240         return NULL;
5241 
5242     return (GObject *)org;
5243 }
5244 
5245 int
ccnet_rpc_add_org_user(int org_id,const char * email,int is_staff,GError ** error)5246 ccnet_rpc_add_org_user (int org_id, const char *email, int is_staff,
5247                         GError **error)
5248 {
5249     CcnetOrgManager *org_mgr = seaf->org_mgr;
5250 
5251     if (org_id < 0 || !email) {
5252         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5253         return -1;
5254     }
5255 
5256     return ccnet_org_manager_add_org_user (org_mgr, org_id, email, is_staff,
5257                                            error);
5258 }
5259 
5260 int
ccnet_rpc_remove_org_user(int org_id,const char * email,GError ** error)5261 ccnet_rpc_remove_org_user (int org_id, const char *email, GError **error)
5262 {
5263     CcnetOrgManager *org_mgr = seaf->org_mgr;
5264 
5265     if (org_id < 0 || !email) {
5266         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5267         return -1;
5268     }
5269 
5270     return ccnet_org_manager_remove_org_user (org_mgr, org_id, email, error);
5271 }
5272 
5273 GList *
ccnet_rpc_get_orgs_by_user(const char * email,GError ** error)5274 ccnet_rpc_get_orgs_by_user (const char *email, GError **error)
5275 {
5276     CcnetOrgManager *org_mgr = seaf->org_mgr;
5277     GList *org_list = NULL;
5278 
5279     org_list = ccnet_org_manager_get_orgs_by_user (org_mgr, email, error);
5280 
5281     return org_list;
5282 }
5283 
5284 GList *
ccnet_rpc_get_org_emailusers(const char * url_prefix,int start,int limit,GError ** error)5285 ccnet_rpc_get_org_emailusers (const char *url_prefix, int start , int limit,
5286                               GError **error)
5287 {
5288     CcnetUserManager *user_mgr = seaf->user_mgr;
5289     CcnetOrgManager *org_mgr = seaf->org_mgr;
5290     GList *email_list = NULL, *ptr;
5291     GList *ret = NULL;
5292 
5293     if (!url_prefix) {
5294         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5295         return NULL;
5296     }
5297 
5298     email_list = ccnet_org_manager_get_org_emailusers (org_mgr, url_prefix,
5299                                                        start, limit);
5300     if (email_list == NULL) {
5301         return NULL;
5302     }
5303 
5304     ptr = email_list;
5305     while (ptr) {
5306         char *email = ptr->data;
5307         CcnetEmailUser *emailuser = ccnet_user_manager_get_emailuser (user_mgr,
5308                                                                       email);
5309         if (emailuser != NULL) {
5310             ret = g_list_prepend (ret, emailuser);
5311         }
5312 
5313         ptr = ptr->next;
5314     }
5315 
5316     string_list_free (email_list);
5317 
5318     return g_list_reverse (ret);
5319 }
5320 
5321 int
ccnet_rpc_add_org_group(int org_id,int group_id,GError ** error)5322 ccnet_rpc_add_org_group (int org_id, int group_id, GError **error)
5323 {
5324     CcnetOrgManager *org_mgr = seaf->org_mgr;
5325 
5326     if (org_id < 0 || group_id < 0) {
5327         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5328         return -1;
5329     }
5330 
5331     return ccnet_org_manager_add_org_group (org_mgr, org_id, group_id, error);
5332 }
5333 
5334 int
ccnet_rpc_remove_org_group(int org_id,int group_id,GError ** error)5335 ccnet_rpc_remove_org_group (int org_id, int group_id, GError **error)
5336 {
5337     CcnetOrgManager *org_mgr = seaf->org_mgr;
5338 
5339     if (org_id < 0 || group_id < 0) {
5340         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5341         return -1;
5342     }
5343 
5344     return ccnet_org_manager_remove_org_group (org_mgr, org_id, group_id,
5345                                                error);
5346 }
5347 
5348 int
ccnet_rpc_is_org_group(int group_id,GError ** error)5349 ccnet_rpc_is_org_group (int group_id, GError **error)
5350 {
5351     CcnetOrgManager *org_mgr = seaf->org_mgr;
5352 
5353     if (group_id <= 0) {
5354         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5355         return -1;
5356     }
5357 
5358     return ccnet_org_manager_is_org_group (org_mgr, group_id, error);
5359 }
5360 
5361 int
ccnet_rpc_get_org_id_by_group(int group_id,GError ** error)5362 ccnet_rpc_get_org_id_by_group (int group_id, GError **error)
5363 {
5364     CcnetOrgManager *org_mgr = seaf->org_mgr;
5365 
5366     if (group_id <= 0) {
5367         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5368         return -1;
5369     }
5370 
5371     return ccnet_org_manager_get_org_id_by_group (org_mgr, group_id, error);
5372 }
5373 
5374 GList *
ccnet_rpc_get_org_groups(int org_id,int start,int limit,GError ** error)5375 ccnet_rpc_get_org_groups (int org_id, int start, int limit, GError **error)
5376 {
5377     CcnetOrgManager *org_mgr = seaf->org_mgr;
5378     GList *ret = NULL;
5379 
5380     if (org_id < 0) {
5381         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5382         return NULL;
5383     }
5384 
5385     /* correct parameter */
5386     if (start < 0 ) {
5387         start = 0;
5388     }
5389 
5390     ret = ccnet_org_manager_get_org_groups (org_mgr, org_id, start, limit);
5391 
5392     return ret;
5393 }
5394 
5395 GList *
ccnet_rpc_get_org_groups_by_user(const char * user,int org_id,GError ** error)5396 ccnet_rpc_get_org_groups_by_user (const char *user, int org_id, GError **error)
5397 {
5398     CcnetOrgManager *org_mgr = seaf->org_mgr;
5399     GList *ret = NULL;
5400 
5401     if (org_id < 0 || !user) {
5402         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5403         return NULL;
5404     }
5405     ret = ccnet_org_manager_get_org_groups_by_user (org_mgr, user, org_id);
5406 
5407     return ret;
5408 }
5409 
5410 GList *
ccnet_rpc_get_org_top_groups(int org_id,GError ** error)5411 ccnet_rpc_get_org_top_groups (int org_id, GError **error)
5412 {
5413     CcnetOrgManager *org_mgr = seaf->org_mgr;
5414     GList *ret = NULL;
5415 
5416     if (org_id < 0) {
5417         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5418         return NULL;
5419     }
5420     ret = ccnet_org_manager_get_org_top_groups (org_mgr, org_id, error);
5421 
5422     return ret;
5423 }
5424 
5425 int
ccnet_rpc_org_user_exists(int org_id,const char * email,GError ** error)5426 ccnet_rpc_org_user_exists (int org_id, const char *email, GError **error)
5427 {
5428     CcnetOrgManager *org_mgr = seaf->org_mgr;
5429 
5430     if (org_id < 0 || !email) {
5431         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5432         return -1;
5433     }
5434 
5435     return ccnet_org_manager_org_user_exists (org_mgr, org_id, email, error);
5436 }
5437 
5438 int
ccnet_rpc_is_org_staff(int org_id,const char * email,GError ** error)5439 ccnet_rpc_is_org_staff (int org_id, const char *email, GError **error)
5440 {
5441     CcnetOrgManager *org_mgr = seaf->org_mgr;
5442 
5443     if (org_id < 0 || !email) {
5444         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5445         return -1;
5446     }
5447 
5448     return ccnet_org_manager_is_org_staff (org_mgr, org_id, email, error);
5449 }
5450 
5451 int
ccnet_rpc_set_org_staff(int org_id,const char * email,GError ** error)5452 ccnet_rpc_set_org_staff (int org_id, const char *email, GError **error)
5453 {
5454     CcnetOrgManager *org_mgr = seaf->org_mgr;
5455 
5456     if (org_id < 0 || !email) {
5457         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5458         return -1;
5459     }
5460 
5461     return ccnet_org_manager_set_org_staff (org_mgr, org_id, email, error);
5462 }
5463 
5464 int
ccnet_rpc_unset_org_staff(int org_id,const char * email,GError ** error)5465 ccnet_rpc_unset_org_staff (int org_id, const char *email, GError **error)
5466 {
5467     CcnetOrgManager *org_mgr = seaf->org_mgr;
5468 
5469     if (org_id < 0 || !email) {
5470         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5471         return -1;
5472     }
5473 
5474     return ccnet_org_manager_unset_org_staff (org_mgr, org_id, email, error);
5475 }
5476 
5477 int
ccnet_rpc_set_org_name(int org_id,const char * org_name,GError ** error)5478 ccnet_rpc_set_org_name (int org_id, const char *org_name, GError **error)
5479 {
5480     CcnetOrgManager *org_mgr = seaf->org_mgr;
5481 
5482     if (org_id < 0 || !org_name) {
5483         g_set_error (error, CCNET_DOMAIN, CCNET_ERR_INTERNAL, "Bad arguments");
5484         return -1;
5485     }
5486 
5487     return ccnet_org_manager_set_org_name (org_mgr, org_id, org_name, error);
5488 }
5489 
5490 int
ccnet_rpc_set_reference_id(const char * primary_id,const char * reference_id,GError ** error)5491 ccnet_rpc_set_reference_id (const char *primary_id, const char *reference_id, GError **error)
5492 {
5493     CcnetUserManager *user_mgr = seaf->user_mgr;
5494 
5495     return ccnet_user_manager_set_reference_id (user_mgr, primary_id, reference_id, error);
5496 }
5497 
5498 char *
ccnet_rpc_get_primary_id(const char * email,GError ** error)5499 ccnet_rpc_get_primary_id (const char *email, GError **error)
5500 {
5501     CcnetUserManager *user_mgr = seaf->user_mgr;
5502 
5503     return ccnet_user_manager_get_primary_id (user_mgr, email);
5504 }
5505 
5506 #endif  /* SEAFILE_SERVER */
5507