1 #include <jansson.h>
2
3 #include <QScopedPointer>
4 #include <QtNetwork>
5
6 #include "account.h"
7
8 #include "api-error.h"
9 #include "commit-details.h"
10 #include "event.h"
11 #include "repo-service.h"
12 #include "rpc/rpc-client.h"
13 #include "seafile-applet.h"
14 #include "server-repo.h"
15 #include "starred-file.h"
16 #include "utils/api-utils.h"
17 #include "utils/json-utils.h"
18 #include "utils/utils.h"
19 #include "account-mgr.h"
20
21 #include "requests.h"
22
23 namespace
24 {
25 const char* kApiPingUrl = "api2/ping/";
26 const char* kApiLoginUrl = "api2/auth-token/";
27 const char* kListReposUrl = "api2/repos/";
28 const char* kCreateRepoUrl = "api2/repos/";
29 const char* kGetRepoUrl = "api2/repos/%1/";
30 const char* kCreateSubrepoUrl = "api2/repos/%1/dir/sub_repo/";
31 const char* kUnseenMessagesUrl = "api2/unseen_messages/";
32 const char* kDefaultRepoUrl = "api2/default-repo/";
33 const char* kStarredFilesUrl = "api2/starredfiles/";
34 const char* kStarredItemsUrl = "api/v2.1/starred-items/";
35 const char* kGetEventsUrl = "api2/events/";
36 const char* kCommitDetailsUrl = "api2/repo_history_changes/";
37 const char* kAvatarUrl = "api2/avatars/user/";
38 const char* kSetRepoPasswordUrl = "api2/repos/";
39 const char* kServerInfoUrl = "api2/server-info/";
40 const char* kLogoutDeviceUrl = "api2/logout-device/";
41 const char* kGetRepoTokensUrl = "api2/repo-tokens/";
42 const char* kGetLoginTokenUrl = "api2/client-login/";
43 const char* kFileSearchUrl = "api2/search/";
44 const char* kAccountInfoUrl = "api2/account/info/";
45 const char* kDirSharedItemsUrl = "api2/repos/%1/dir/shared_items/";
46 const char* kRepoSharedUrl = "api2/beshared-repos/%1/";
47 const char* kFetchGroupsAndContactsUrl = "api2/groupandcontacts/";
48 const char* kFetchGroupsUrl = "api2/groups/";
49 const char* kRemoteWipeReportUrl = "api2/device-wiped/";
50 const char* kSearchUsersUrl = "api2/search-user/";
51 const char* kGetThumbnailUrl = "api2/repos/%1/thumbnail/";
52 const char* kCreateFileUploadLink = "api/v2.1/upload-links/";
53
54 const char* kGetFileActivitiesUrl = "api/v2.1/activities/";
55 } // namespace
56
57
PingServerRequest(const QUrl & serverAddr)58 PingServerRequest::PingServerRequest(const QUrl& serverAddr)
59
60 : SeafileApiRequest(::urlJoin(serverAddr, kApiPingUrl),
61 SeafileApiRequest::METHOD_GET)
62 {
63 }
64
requestSuccess(QNetworkReply & reply)65 void PingServerRequest::requestSuccess(QNetworkReply& reply)
66 {
67 emit success();
68 }
69
70 /**
71 * LoginRequest
72 */
LoginRequest(const QUrl & serverAddr,const QString & username,const QString & password,const QString & computer_name)73 LoginRequest::LoginRequest(const QUrl& serverAddr,
74 const QString& username,
75 const QString& password,
76 const QString& computer_name)
77
78 : SeafileApiRequest(::urlJoin(serverAddr, kApiLoginUrl),
79 SeafileApiRequest::METHOD_POST)
80 {
81 setFormParam("username", username);
82 setFormParam("password", password);
83
84 QHash<QString, QString> params = ::getSeafileLoginParams(computer_name);
85 foreach (const QString& key, params.keys()) {
86 setFormParam(key, params[key]);
87 }
88 }
89
requestSuccess(QNetworkReply & reply)90 void LoginRequest::requestSuccess(QNetworkReply& reply)
91 {
92 json_error_t error;
93 json_t* root = parseJSON(reply, &error);
94 if (!root) {
95 qWarning("failed to parse json:%s\n", error.text);
96 emit failed(ApiError::fromJsonError());
97 return;
98 }
99
100 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
101
102 QString s2fa_token = reply.rawHeader("X-SEAFILE-S2FA");
103 const char* token =
104 json_string_value(json_object_get(json.data(), "token"));
105 if (token == NULL) {
106 qWarning("failed to parse json:%s\n", error.text);
107 emit failed(ApiError::fromJsonError());
108 return;
109 }
110
111 emit success(token, s2fa_token);
112 }
113
114
115 /**
116 * ListReposRequest
117 */
ListReposRequest(const Account & account)118 ListReposRequest::ListReposRequest(const Account& account)
119 : SeafileApiRequest(account.getAbsoluteUrl(kListReposUrl),
120 SeafileApiRequest::METHOD_GET,
121 account.token)
122 {
123 }
124
requestSuccess(QNetworkReply & reply)125 void ListReposRequest::requestSuccess(QNetworkReply& reply)
126 {
127 json_error_t error;
128 json_t* root = parseJSON(reply, &error);
129 if (!root) {
130 qWarning("ListReposRequest:failed to parse json:%s\n", error.text);
131 emit failed(ApiError::fromJsonError());
132 return;
133 }
134
135 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
136
137 std::vector<ServerRepo> repos =
138 ServerRepo::listFromJSON(json.data(), &error);
139 emit success(repos);
140 }
141
142
143 /**
144 * DownloadRepoRequest
145 */
DownloadRepoRequest(const Account & account,const QString & repo_id,bool read_only)146 DownloadRepoRequest::DownloadRepoRequest(const Account& account,
147 const QString& repo_id,
148 bool read_only)
149 : SeafileApiRequest(
150 account.getAbsoluteUrl("api2/repos/" + repo_id + "/download-info/"),
151 SeafileApiRequest::METHOD_GET,
152 account.token),
153 read_only_(read_only)
154 {
155 }
156
fromDict(QMap<QString,QVariant> & dict,const QUrl & url_in,bool read_only)157 RepoDownloadInfo RepoDownloadInfo::fromDict(QMap<QString, QVariant>& dict,
158 const QUrl& url_in,
159 bool read_only)
160 {
161 RepoDownloadInfo info;
162 info.repo_version = dict["repo_version"].toInt();
163 info.email = dict["email"].toString();
164 info.token = dict["token"].toString();
165 info.repo_id = dict["repo_id"].toString();
166 info.repo_name = dict["repo_name"].toString();
167 info.encrypted = dict["encrypted"].toInt();
168 info.magic = dict["magic"].toString();
169 info.random_key = dict["random_key"].toString();
170 info.enc_version = dict.value("enc_version", 1).toInt();
171 info.readonly = read_only;
172
173 QUrl url = url_in;
174 url.setPath("/");
175
176 QString salt = dict.value("salt").toString();
177 QMap<QString, QVariant> map;
178 map.insert("is_readonly", read_only ? 1 : 0);
179 map.insert("server_url", url.toString());
180 map.insert("repo_salt", salt);
181
182 info.more_info = ::mapToJson(map);
183
184 return info;
185 }
186
requestSuccess(QNetworkReply & reply)187 void DownloadRepoRequest::requestSuccess(QNetworkReply& reply)
188 {
189 json_error_t error;
190 json_t* root = parseJSON(reply, &error);
191 if (!root) {
192 qWarning("failed to parse json:%s\n", error.text);
193 emit failed(ApiError::fromJsonError());
194 return;
195 }
196
197 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
198 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
199
200 RepoDownloadInfo info = RepoDownloadInfo::fromDict(dict, url(), read_only_);
201
202 emit success(info);
203 }
204
205 /**
206 * GetRepoRequest
207 */
GetRepoRequest(const Account & account,const QString & repoid)208 GetRepoRequest::GetRepoRequest(const Account& account, const QString& repoid)
209 : SeafileApiRequest(
210 account.getAbsoluteUrl(QString(kGetRepoUrl).arg(repoid)),
211 SeafileApiRequest::METHOD_GET,
212 account.token),
213 repoid_(repoid)
214 {
215 }
216
requestSuccess(QNetworkReply & reply)217 void GetRepoRequest::requestSuccess(QNetworkReply& reply)
218 {
219 json_error_t error;
220 json_t* root = parseJSON(reply, &error);
221 if (!root) {
222 qWarning("failed to parse json:%s\n", error.text);
223 emit failed(ApiError::fromJsonError());
224 return;
225 }
226
227 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
228 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
229 ServerRepo repo = ServerRepo::fromJSON(root, &error);
230
231 emit success(repo);
232 }
233
234 /**
235 * CreateRepoRequest
236 */
CreateRepoRequest(const Account & account,const QString & name,const QString & desc,const QString & passwd)237 CreateRepoRequest::CreateRepoRequest(const Account& account,
238 const QString& name,
239 const QString& desc,
240 const QString& passwd)
241 : SeafileApiRequest(account.getAbsoluteUrl(kCreateRepoUrl),
242 SeafileApiRequest::METHOD_POST,
243 account.token)
244 {
245 setFormParam(QString("name"), name);
246 setFormParam(QString("desc"), desc);
247 if (!passwd.isNull()) {
248 qWarning("Encrypted repo");
249 setFormParam(QString("passwd"), passwd);
250 }
251 }
252
CreateRepoRequest(const Account & account,const QString & name,const QString & desc,int enc_version,const QString & repo_id,const QString & magic,const QString & random_key)253 CreateRepoRequest::CreateRepoRequest(const Account& account,
254 const QString& name,
255 const QString& desc,
256 int enc_version,
257 const QString& repo_id,
258 const QString& magic,
259 const QString& random_key)
260 : SeafileApiRequest(account.getAbsoluteUrl(kCreateRepoUrl),
261 SeafileApiRequest::METHOD_POST,
262 account.token)
263 {
264 setFormParam("name", name);
265 setFormParam("desc", desc);
266 setFormParam("enc_version", QString::number(enc_version));
267 setFormParam("repo_id", repo_id);
268 setFormParam("magic", magic);
269 setFormParam("random_key", random_key);
270 }
271
CreateRepoRequest(const Account & account,const QString & name,const QString & desc,int enc_version,const QString & repo_id,const QString & magic,const QString & random_key,const QString & salt)272 CreateRepoRequest::CreateRepoRequest(const Account& account,
273 const QString& name,
274 const QString& desc,
275 int enc_version,
276 const QString& repo_id,
277 const QString& magic,
278 const QString& random_key,
279 const QString& salt)
280 : SeafileApiRequest(account.getAbsoluteUrl(kCreateRepoUrl),
281 SeafileApiRequest::METHOD_POST,
282 account.token)
283 {
284 setFormParam("name", name);
285 setFormParam("desc", desc);
286 setFormParam("enc_version", QString::number(enc_version));
287 setFormParam("repo_id", repo_id);
288 setFormParam("magic", magic);
289 setFormParam("random_key", random_key);
290 setFormParam("salt", salt);
291 }
292
requestSuccess(QNetworkReply & reply)293 void CreateRepoRequest::requestSuccess(QNetworkReply& reply)
294 {
295 json_error_t error;
296 json_t* root = parseJSON(reply, &error);
297 if (!root) {
298 qWarning("failed to parse json:%s\n", error.text);
299 emit failed(ApiError::fromJsonError());
300 return;
301 }
302
303 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
304 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
305 RepoDownloadInfo info = RepoDownloadInfo::fromDict(dict, url(), false);
306
307 emit success(info);
308 }
309
310 /**
311 * CreateSubrepoRequest
312 */
CreateSubrepoRequest(const Account & account,const QString & name,const QString & repoid,const QString & path,const QString & passwd)313 CreateSubrepoRequest::CreateSubrepoRequest(const Account& account,
314 const QString& name,
315 const QString& repoid,
316 const QString& path,
317 const QString& passwd)
318 : SeafileApiRequest(
319 account.getAbsoluteUrl(QString(kCreateSubrepoUrl).arg(repoid)),
320 SeafileApiRequest::METHOD_GET,
321 account.token)
322 {
323 setUrlParam(QString("p"), path);
324 setUrlParam(QString("name"), name);
325 if (!passwd.isNull()) {
326 setUrlParam(QString("password"), passwd);
327 }
328 }
329
requestSuccess(QNetworkReply & reply)330 void CreateSubrepoRequest::requestSuccess(QNetworkReply& reply)
331 {
332 json_error_t error;
333 json_t* root = parseJSON(reply, &error);
334 if (!root) {
335 qWarning("failed to parse json:%s\n", error.text);
336 emit failed(ApiError::fromJsonError());
337 return;
338 }
339
340 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
341 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
342
343 emit success(dict["sub_repo_id"].toString());
344 }
345
346 /**
347 * GetUnseenSeahubNotificationsRequest
348 */
GetUnseenSeahubNotificationsRequest(const Account & account)349 GetUnseenSeahubNotificationsRequest::GetUnseenSeahubNotificationsRequest(
350 const Account& account)
351 : SeafileApiRequest(account.getAbsoluteUrl(kUnseenMessagesUrl),
352 SeafileApiRequest::METHOD_GET,
353 account.token)
354 {
355 }
356
requestSuccess(QNetworkReply & reply)357 void GetUnseenSeahubNotificationsRequest::requestSuccess(QNetworkReply& reply)
358 {
359 json_error_t error;
360 json_t* root = parseJSON(reply, &error);
361 if (!root) {
362 qWarning(
363 "GetUnseenSeahubNotificationsRequest: failed to parse json:%s\n",
364 error.text);
365 emit failed(ApiError::fromJsonError());
366 return;
367 }
368
369 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
370
371 QMap<QString, QVariant> ret = mapFromJSON(root, &error);
372
373 if (!ret.contains("count")) {
374 emit failed(ApiError::fromJsonError());
375 return;
376 }
377
378 int count = ret.value("count").toInt();
379 emit success(count);
380 }
381
GetDefaultRepoRequest(const Account & account)382 GetDefaultRepoRequest::GetDefaultRepoRequest(const Account& account)
383 : SeafileApiRequest(account.getAbsoluteUrl(kDefaultRepoUrl),
384 SeafileApiRequest::METHOD_GET,
385 account.token)
386 {
387 }
388
requestSuccess(QNetworkReply & reply)389 void GetDefaultRepoRequest::requestSuccess(QNetworkReply& reply)
390 {
391 json_error_t error;
392 json_t* root = parseJSON(reply, &error);
393 if (!root) {
394 qWarning("CreateDefaultRepoRequest: failed to parse json:%s\n",
395 error.text);
396 emit failed(ApiError::fromJsonError());
397 return;
398 }
399
400 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
401
402 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
403
404 if (!dict.contains("exists")) {
405 emit failed(ApiError::fromJsonError());
406 return;
407 }
408
409 bool exists = dict.value("exists").toBool();
410 if (!exists) {
411 emit success(false, "");
412 return;
413 }
414
415 if (!dict.contains("repo_id")) {
416 emit failed(ApiError::fromJsonError());
417 return;
418 }
419
420 QString repo_id = dict.value("repo_id").toString();
421
422 emit success(true, repo_id);
423 }
424
425
CreateDefaultRepoRequest(const Account & account)426 CreateDefaultRepoRequest::CreateDefaultRepoRequest(const Account& account)
427 : SeafileApiRequest(account.getAbsoluteUrl(kDefaultRepoUrl),
428 SeafileApiRequest::METHOD_POST,
429 account.token)
430 {
431 }
432
requestSuccess(QNetworkReply & reply)433 void CreateDefaultRepoRequest::requestSuccess(QNetworkReply& reply)
434 {
435 json_error_t error;
436 json_t* root = parseJSON(reply, &error);
437 if (!root) {
438 qWarning("CreateDefaultRepoRequest: failed to parse json:%s\n",
439 error.text);
440 emit failed(ApiError::fromJsonError());
441 return;
442 }
443
444 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
445
446 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
447
448 if (!dict.contains("repo_id")) {
449 emit failed(ApiError::fromJsonError());
450 return;
451 }
452
453 emit success(dict.value("repo_id").toString());
454 }
455
GetStarredFilesRequest(const Account & account)456 GetStarredFilesRequest::GetStarredFilesRequest(const Account& account)
457 : SeafileApiRequest(account.getAbsoluteUrl(kStarredFilesUrl),
458 SeafileApiRequest::METHOD_GET,
459 account.token)
460 {
461 }
462
requestSuccess(QNetworkReply & reply)463 void GetStarredFilesRequest::requestSuccess(QNetworkReply& reply)
464 {
465 json_error_t error;
466 json_t* root = parseJSON(reply, &error);
467 if (!root) {
468 qWarning("GetStarredFilesRequest: failed to parse json:%s\n",
469 error.text);
470 emit failed(ApiError::fromJsonError());
471 return;
472 }
473
474 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
475
476 std::vector<StarredItem> files =
477 StarredItem::listFromJSON(json.data(), &error);
478 emit success(files);
479 }
480
GetStarredFilesRequestV2(const Account & account)481 GetStarredFilesRequestV2::GetStarredFilesRequestV2(const Account& account)
482 : SeafileApiRequest(account.getAbsoluteUrl(kStarredItemsUrl),
483 SeafileApiRequest::METHOD_GET,
484 account.token)
485 {
486 }
487
requestSuccess(QNetworkReply & reply)488 void GetStarredFilesRequestV2::requestSuccess(QNetworkReply& reply)
489 {
490 json_error_t error;
491 json_t* root = parseJSON(reply, &error);
492 if (!root) {
493 qWarning("GetStarredItemsRequest: failed to parse json:%s\n",
494 error.text);
495 emit failed(ApiError::fromJsonError());
496 return;
497 }
498
499 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
500 json_t* array = json_object_get(json.data(), "starred_item_list");
501 std::vector<StarredItem> files =
502 StarredItem::listFromJSON(array, &error, true);
503 emit success(files);
504 }
505
506 // Seafile get file activities api v2.1
507 // page default value is 1
508 // perpage defult value is 25
509 // avatar size defult value is 72, old api is 36
GetEventsRequestV2(const Account & account,int page,int perpage,int avatar_size)510 GetEventsRequestV2::GetEventsRequestV2(const Account& account, int page, int perpage, int avatar_size)
511 : SeafileApiRequest(account.getAbsoluteUrl(kGetFileActivitiesUrl),
512 SeafileApiRequest::METHOD_GET,
513 account.token)
514 {
515 setUrlParam("page", QString::number(page));
516 setUrlParam("avatar_size", QString::number(avatar_size));
517 }
518
requestSuccess(QNetworkReply & reply)519 void GetEventsRequestV2::requestSuccess(QNetworkReply& reply)
520 {
521 json_error_t error;
522 json_t* root = parseJSON(reply, &error);
523 if (!root) {
524 qWarning("GetEventsRequestV2: failed to parse json:%s\n", error.text);
525 emit failed(ApiError::fromJsonError());
526 return;
527 }
528
529 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
530
531 json_t* array = json_object_get(json.data(), "events");
532 std::vector<SeafEvent> events = SeafEvent::listFromJSON(array, &error, true);
533
534 emit success(events);
535 }
536
GetEventsRequest(const Account & account,int start)537 GetEventsRequest::GetEventsRequest(const Account& account, int start)
538 : SeafileApiRequest(account.getAbsoluteUrl(kGetEventsUrl),
539 SeafileApiRequest::METHOD_GET,
540 account.token)
541 {
542 if (start > 0) {
543 setUrlParam("start", QString::number(start));
544 }
545 }
546
requestSuccess(QNetworkReply & reply)547 void GetEventsRequest::requestSuccess(QNetworkReply& reply)
548 {
549 json_error_t error;
550 json_t* root = parseJSON(reply, &error);
551 if (!root) {
552 qWarning("GetEventsRequest: failed to parse json:%s\n", error.text);
553 emit failed(ApiError::fromJsonError());
554 return;
555 }
556
557 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
558
559 bool more = false;
560 int more_offset = -1;
561
562 json_t* array = json_object_get(json.data(), "events");
563 std::vector<SeafEvent> events = SeafEvent::listFromJSON(array, &error);
564
565 more = json_is_true(json_object_get(json.data(), "more"));
566 if (more) {
567 more_offset =
568 json_integer_value(json_object_get(json.data(), "more_offset"));
569 }
570
571 emit success(events, more_offset);
572 }
573
GetCommitDetailsRequest(const Account & account,const QString & repo_id,const QString & commit_id)574 GetCommitDetailsRequest::GetCommitDetailsRequest(const Account& account,
575 const QString& repo_id,
576 const QString& commit_id)
577 : SeafileApiRequest(
578 account.getAbsoluteUrl(kCommitDetailsUrl + repo_id + "/"),
579 SeafileApiRequest::METHOD_GET,
580 account.token)
581 {
582 setUrlParam("commit_id", commit_id);
583 }
584
requestSuccess(QNetworkReply & reply)585 void GetCommitDetailsRequest::requestSuccess(QNetworkReply& reply)
586 {
587 json_error_t error;
588 json_t* root = parseJSON(reply, &error);
589 if (!root) {
590 qWarning("GetCommitDetailsRequest: failed to parse json:%s\n",
591 error.text);
592 emit failed(ApiError::fromJsonError());
593 return;
594 }
595
596 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
597
598 CommitDetails details = CommitDetails::fromJSON(json.data(), &error);
599
600 emit success(details);
601 }
602
603 // /api2/user/foo@foo.com/resized/36
GetAvatarRequest(const Account & account,const QString & email,qint64 mtime,int size)604 GetAvatarRequest::GetAvatarRequest(const Account& account,
605 const QString& email,
606 qint64 mtime,
607 int size)
608 : SeafileApiRequest(
609 account.getAbsoluteUrl(kAvatarUrl + email + "/resized/" +
610 QString::number(size) + "/"),
611 SeafileApiRequest::METHOD_GET,
612 account.token),
613 fetch_img_req_(NULL),
614 mtime_(mtime)
615 {
616 account_ = account;
617 email_ = email;
618 }
619
~GetAvatarRequest()620 GetAvatarRequest::~GetAvatarRequest()
621 {
622 if (fetch_img_req_) {
623 fetch_img_req_->deleteLater();
624 fetch_img_req_ = nullptr;
625 }
626 }
627
requestSuccess(QNetworkReply & reply)628 void GetAvatarRequest::requestSuccess(QNetworkReply& reply)
629 {
630 json_error_t error;
631 json_t* root = parseJSON(reply, &error);
632 if (!root) {
633 qWarning("GetAvatarRequest: failed to parse json:%s\n", error.text);
634 emit failed(ApiError::fromJsonError());
635 return;
636 }
637
638 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
639
640 const char* avatar_url =
641 json_string_value(json_object_get(json.data(), "url"));
642
643 // we don't need to fetch all images if we have latest one
644 json_t* mtime = json_object_get(json.data(), "mtime");
645 if (!mtime) {
646 qWarning("GetAvatarRequest: no 'mtime' value in response\n");
647 }
648 else {
649 qint64 new_mtime = json_integer_value(mtime);
650 // When mtime_ < 0 it means there is no local cache yet
651 if (mtime_ >= 0 && new_mtime == mtime_) {
652 emit success(QImage());
653 return;
654 }
655 mtime_ = new_mtime;
656 }
657
658 if (!avatar_url) {
659 qWarning("GetAvatarRequest: no 'url' value in response\n");
660 emit failed(ApiError::fromJsonError());
661 return;
662 }
663
664 QString url = QUrl::fromPercentEncoding(avatar_url);
665
666 fetch_img_req_ = new FetchImageRequest(url);
667
668 connect(fetch_img_req_, SIGNAL(failed(const ApiError&)), this,
669 SIGNAL(failed(const ApiError&)));
670 connect(fetch_img_req_, SIGNAL(success(const QImage&)), this,
671 SIGNAL(success(const QImage&)));
672 fetch_img_req_->send();
673 }
674
FetchImageRequest(const QString & img_url)675 FetchImageRequest::FetchImageRequest(const QString& img_url)
676 : SeafileApiRequest(QUrl(img_url), SeafileApiRequest::METHOD_GET)
677 {
678 }
679
requestSuccess(QNetworkReply & reply)680 void FetchImageRequest::requestSuccess(QNetworkReply& reply)
681 {
682 QImage img;
683 img.loadFromData(reply.readAll());
684
685 if (img.isNull()) {
686 qWarning("FetchImageRequest: invalid image data\n");
687 emit failed(ApiError::fromHttpError(400));
688 }
689 else {
690 emit success(img);
691 }
692 }
693
SetRepoPasswordRequest(const Account & account,const QString & repo_id,const QString & password)694 SetRepoPasswordRequest::SetRepoPasswordRequest(const Account& account,
695 const QString& repo_id,
696 const QString& password)
697 : SeafileApiRequest(
698 account.getAbsoluteUrl(kSetRepoPasswordUrl + repo_id + "/"),
699 SeafileApiRequest::METHOD_POST,
700 account.token)
701 {
702 setFormParam("password", password);
703 }
704
requestSuccess(QNetworkReply & reply)705 void SetRepoPasswordRequest::requestSuccess(QNetworkReply& reply)
706 {
707 emit success();
708 }
709
ServerInfoRequest(const Account & account)710 ServerInfoRequest::ServerInfoRequest(const Account& account)
711 : SeafileApiRequest(account.getAbsoluteUrl(kServerInfoUrl),
712 SeafileApiRequest::METHOD_GET,
713 account.token),
714 account_(account)
715 {
716 }
717
requestSuccess(QNetworkReply & reply)718 void ServerInfoRequest::requestSuccess(QNetworkReply& reply)
719 {
720 json_error_t error;
721 json_t* root = parseJSON(reply, &error);
722 if (!root) {
723 qWarning("failed to parse json:%s\n", error.text);
724 emit failed(ApiError::fromJsonError());
725 return;
726 }
727 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
728
729 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
730
731 ServerInfo ret;
732
733 if (dict.contains("version")) {
734 ret.parseVersionFromString(dict["version"].toString());
735 }
736
737 if (dict.contains("encrypted_library_version")) {
738 ret.parseEncryptedLibraryVersionFromString(dict["encrypted_library_version"].toString());
739 }
740
741 if (dict.contains("features")) {
742 ret.parseFeatureFromStrings(dict["features"].toStringList());
743 }
744
745 if (dict.contains("desktop-custom-logo")) {
746 ret.customLogo = dict["desktop-custom-logo"].toString();
747 }
748
749 if (dict.contains("desktop-custom-brand")) {
750 ret.customBrand = dict["desktop-custom-brand"].toString();
751 }
752
753 emit success(account_, ret);
754 }
755
LogoutDeviceRequest(const Account & account)756 LogoutDeviceRequest::LogoutDeviceRequest(const Account& account)
757 : SeafileApiRequest(account.getAbsoluteUrl(kLogoutDeviceUrl),
758 SeafileApiRequest::METHOD_POST,
759 account.token),
760 account_(account)
761 {
762 }
763
requestSuccess(QNetworkReply & reply)764 void LogoutDeviceRequest::requestSuccess(QNetworkReply& reply)
765 {
766 emit success();
767 }
768
GetRepoTokensRequest(const Account & account,const QStringList & repo_ids,int max_retries,int batch_size)769 GetRepoTokensRequest::GetRepoTokensRequest(const Account& account,
770 const QStringList& repo_ids,
771 int max_retries,
772 int batch_size)
773 : SeafileApiRequest(account.getAbsoluteUrl(kGetRepoTokensUrl),
774 SeafileApiRequest::METHOD_GET,
775 account.token),
776 account_(account),
777 repo_ids_(repo_ids),
778 max_retries_(max_retries),
779 batch_offset_(0),
780 batch_size_(batch_size)
781 {
782 }
783
send()784 void GetRepoTokensRequest::send()
785 {
786 doNextBatch();
787 }
788
doNextBatch()789 void GetRepoTokensRequest::doNextBatch()
790 {
791 if (batch_offset_ >= repo_ids_.size()) {
792 emit success();
793 return;
794 }
795
796 int count;
797 count = qMin(batch_size_, repo_ids_.size() - batch_offset_);
798 batch_req_.reset(new SingleBatchRepoTokensRequest(
799 account_, repo_ids_.mid(batch_offset_, count)));
800
801 connect(batch_req_.data(),
802 SIGNAL(failed(const ApiError &)),
803 this,
804 SIGNAL(failed(const ApiError &)));
805 connect(batch_req_.data(), SIGNAL(success()), this, SLOT(batchSuccess()));
806 batch_req_->send();
807
808 // printf("sending request for one batch: offset = %d, count = %d\n",
809 // batch_offset_,
810 // count);
811 }
812
batchSuccess()813 void GetRepoTokensRequest::batchSuccess()
814 {
815 const QMap<QString, QString>& tokens = batch_req_->repoTokens();
816
817 // printf ("one batch finished, offset = %d, count = %d\n", batch_offset_, tokens.size());
818
819 repo_tokens_.unite(tokens);
820 batch_offset_ += batch_req_->repoIds().size();
821 doNextBatch();
822 }
823
requestSuccess(QNetworkReply & reply)824 void GetRepoTokensRequest::requestSuccess(QNetworkReply& reply)
825 {
826 // Just a place holder. A `GetRepoTokensRequest` is a wrapper around a
827 // series of `SingleBatchRepoTokensRequest`, which really sends the api
828 // requests.
829 }
830
SingleBatchRepoTokensRequest(const Account & account,const QStringList & repo_ids)831 SingleBatchRepoTokensRequest::SingleBatchRepoTokensRequest(const Account& account,
832 const QStringList& repo_ids)
833 : SeafileApiRequest(account.getAbsoluteUrl(kGetRepoTokensUrl),
834 SeafileApiRequest::METHOD_GET,
835 account.token),
836 repo_ids_(repo_ids)
837 {
838 setUrlParam("repos", repo_ids.join(","));
839 }
840
requestSuccess(QNetworkReply & reply)841 void SingleBatchRepoTokensRequest::requestSuccess(QNetworkReply& reply)
842 {
843 json_error_t error;
844 json_t* root = parseJSON(reply, &error);
845 if (!root) {
846 qWarning("SingleBatchRepoTokensRequest: failed to parse json:%s\n", error.text);
847 emit failed(ApiError::fromJsonError());
848 return;
849 }
850
851 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
852
853 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
854 foreach (const QString& repo_id, dict.keys()) {
855 repo_tokens_[repo_id] = dict[repo_id].toString();
856 }
857
858 emit success();
859 }
860
GetLoginTokenRequest(const Account & account,const QString & next_url)861 GetLoginTokenRequest::GetLoginTokenRequest(const Account& account,
862 const QString& next_url)
863 : SeafileApiRequest(account.getAbsoluteUrl(kGetLoginTokenUrl),
864 SeafileApiRequest::METHOD_POST,
865 account.token),
866 account_(account),
867 next_url_(next_url)
868 {
869 }
870
requestSuccess(QNetworkReply & reply)871 void GetLoginTokenRequest::requestSuccess(QNetworkReply& reply)
872 {
873 json_error_t error;
874 json_t* root = parseJSON(reply, &error);
875 if (!root) {
876 qWarning("GetLoginTokenRequest: failed to parse json:%s\n", error.text);
877 emit failed(ApiError::fromJsonError());
878 return;
879 }
880
881 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
882
883 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
884 if (!dict.contains("token")) {
885 emit failed(ApiError::fromJsonError());
886 return;
887 }
888 emit success(dict["token"].toString());
889 }
890
FileSearchRequest(const Account & account,const QString & keyword,int page,int per_page,const QString & repo_id)891 FileSearchRequest::FileSearchRequest(const Account& account,
892 const QString& keyword,
893 int page,
894 int per_page,
895 const QString& repo_id)
896 : SeafileApiRequest(account.getAbsoluteUrl(kFileSearchUrl),
897 SeafileApiRequest::METHOD_GET,
898 account.token),
899 keyword_(keyword),
900 page_(page)
901 {
902 setUrlParam("q", keyword_);
903 if (page > 0) {
904 setUrlParam("page", QString::number(page));
905 }
906 // per_page = 2;
907 setUrlParam("per_page", QString::number(per_page));
908 if (!repo_id.isEmpty()) {
909 setUrlParam("search_repo", repo_id);
910 }
911 }
912
requestSuccess(QNetworkReply & reply)913 void FileSearchRequest::requestSuccess(QNetworkReply& reply)
914 {
915 json_error_t error;
916 json_t* root = parseJSON(reply, &error);
917 if (!root) {
918 qWarning("FileSearchResult: failed to parse json:%s\n", error.text);
919 emit failed(ApiError::fromJsonError());
920 return;
921 }
922 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
923 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
924 if (!dict.contains("results")) {
925 emit failed(ApiError::fromJsonError());
926 return;
927 }
928 QList<QVariant> results = dict["results"].toList();
929 std::vector<FileSearchResult> retval;
930 Q_FOREACH(const QVariant& result, results)
931 {
932 FileSearchResult tmp;
933 QMap<QString, QVariant> map = result.toMap();
934 if (map.empty())
935 continue;
936 tmp.repo_id = map["repo_id"].toString();
937 tmp.repo_name = RepoService::instance()->getRepo(tmp.repo_id).name;
938 tmp.name = map["name"].toString();
939 tmp.oid = map["oid"].toString();
940 tmp.last_modified = map["last_modified"].toLongLong();
941 tmp.fullpath = map["fullpath"].toString();
942 tmp.size = map["size"].toLongLong();
943 tmp.is_dir = map["is_dir"].toBool();
944 retval.push_back(tmp);
945 }
946 bool has_more = dict["has_more"].toBool();
947 bool is_loading_more = page_ > 1;
948
949 emit success(retval, is_loading_more, has_more);
950 }
951
FetchCustomLogoRequest(const QUrl & url)952 FetchCustomLogoRequest::FetchCustomLogoRequest(const QUrl& url)
953 : SeafileApiRequest(url, SeafileApiRequest::METHOD_GET)
954 {
955 setUseCache(true);
956 }
957
requestSuccess(QNetworkReply & reply)958 void FetchCustomLogoRequest::requestSuccess(QNetworkReply& reply)
959 {
960 QPixmap logo;
961 logo.loadFromData(reply.readAll());
962
963 if (logo.isNull()) {
964 qWarning("FetchCustomLogoRequest: invalid image data\n");
965 emit failed(ApiError::fromHttpError(400));
966 }
967 else {
968 emit success(url());
969 }
970 }
971
FetchAccountInfoRequest(const Account & account)972 FetchAccountInfoRequest::FetchAccountInfoRequest(const Account& account)
973 : SeafileApiRequest(account.getAbsoluteUrl(kAccountInfoUrl),
974 SeafileApiRequest::METHOD_GET,
975 account.token)
976 {
977 account_ = account;
978 }
979
requestSuccess(QNetworkReply & reply)980 void FetchAccountInfoRequest::requestSuccess(QNetworkReply& reply)
981 {
982 json_error_t error;
983 json_t* root = parseJSON(reply, &error);
984 if (!root) {
985 qWarning("FetchAccountInfoRequest: failed to parse json:%s\n",
986 error.text);
987 emit failed(ApiError::fromJsonError());
988 return;
989 }
990
991 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
992
993 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
994
995 AccountInfo info;
996 info.email = dict["email"].toString();
997 info.name = dict["name"].toString();
998 info.totalStorage = dict["total"].toLongLong();
999 info.usedStorage = dict["usage"].toLongLong();
1000 if (info.name.isEmpty()) {
1001 info.name = dict["nickname"].toString();
1002 }
1003 emit success(info);
1004 }
1005
PrivateShareRequest(const Account & account,const QString & repo_id,const QString & path,const SeafileUser & user,int group_id,SharePermission permission,ShareType share_type,ShareOperation op)1006 PrivateShareRequest::PrivateShareRequest(const Account& account,
1007 const QString& repo_id,
1008 const QString& path,
1009 const SeafileUser& user,
1010 int group_id,
1011 SharePermission permission,
1012 ShareType share_type,
1013 ShareOperation op)
1014 : SeafileApiRequest(
1015 account.getAbsoluteUrl(QString(kDirSharedItemsUrl).arg(repo_id)),
1016 op == UPDATE_SHARE ? METHOD_POST : (op == REMOVE_SHARE ? METHOD_DELETE
1017 : METHOD_PUT),
1018 account.token),
1019 group_id_(share_type == SHARE_TO_GROUP ? group_id : -1),
1020 user_(share_type == SHARE_TO_USER ? user: SeafileUser()),
1021 permission_(permission),
1022 share_type_(share_type),
1023 share_operation_(op)
1024 {
1025 setUrlParam("p", path);
1026 setFormParam("permission", permission == READ_ONLY ? "r" : "rw");
1027 bool is_add = op == ADD_SHARE;
1028 if (is_add) {
1029 setFormParam("share_type",
1030 share_type == SHARE_TO_USER ? "user" : "group");
1031 }
1032 else {
1033 setUrlParam("share_type",
1034 share_type == SHARE_TO_USER ? "user" : "group");
1035 }
1036
1037 if (share_type == SHARE_TO_USER) {
1038 if (is_add) {
1039 setFormParam("username", user_.email);
1040 }
1041 else {
1042 setUrlParam("username", user_.email);
1043 }
1044 }
1045 else {
1046 if (is_add) {
1047 setFormParam("group_id", QString::number(group_id));
1048 }
1049 else {
1050 setUrlParam("group_id", QString::number(group_id));
1051 }
1052 }
1053 }
1054
requestSuccess(QNetworkReply & reply)1055 void PrivateShareRequest::requestSuccess(QNetworkReply& reply)
1056 {
1057 json_error_t error;
1058 json_t* root = parseJSON(reply, &error);
1059 if (!root) {
1060 qWarning("PrivateShareRequest: failed to parse json:%s\n", error.text);
1061 emit failed(ApiError::fromJsonError());
1062 return;
1063 }
1064
1065 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
1066
1067 emit success();
1068 }
1069
1070
FetchGroupsAndContactsRequest(const Account & account)1071 FetchGroupsAndContactsRequest::FetchGroupsAndContactsRequest(
1072 const Account& account)
1073 : SeafileApiRequest(account.getAbsoluteUrl(kFetchGroupsAndContactsUrl),
1074 SeafileApiRequest::METHOD_GET,
1075 account.token)
1076 {
1077 }
1078
requestSuccess(QNetworkReply & reply)1079 void FetchGroupsAndContactsRequest::requestSuccess(QNetworkReply& reply)
1080 {
1081 json_error_t error;
1082 json_t* root = parseJSON(reply, &error);
1083 if (!root) {
1084 qWarning("FetchGroupsAndContactsRequest: failed to parse json:%s\n",
1085 error.text);
1086 emit failed(ApiError::fromJsonError());
1087 return;
1088 }
1089
1090 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
1091
1092 QList<SeafileGroup> groups;
1093 QList<SeafileUser> contacts;
1094
1095 json_t* groups_array = json_object_get(json.data(), "groups");
1096 if (groups_array) {
1097 int i, n = json_array_size(groups_array);
1098 for (i = 0; i < n; i++) {
1099 json_t* group_object = json_array_get(groups_array, i);
1100 const char* name =
1101 json_string_value(json_object_get(group_object, "name"));
1102 int group_id =
1103 json_integer_value(json_object_get(group_object, "id"));
1104 if (name && group_id) {
1105 SeafileGroup group;
1106 group.id = group_id;
1107 group.name = QString::fromUtf8(name);
1108 const char* owner =
1109 json_string_value(json_object_get(group_object, "creator"));
1110 if (owner) {
1111 group.owner = QString::fromUtf8(owner);
1112 }
1113 groups.push_back(group);
1114 }
1115 }
1116 }
1117
1118 json_t* contacts_array = json_object_get(json.data(), "contacts");
1119 if (contacts_array) {
1120 int i, n = json_array_size(contacts_array);
1121
1122 for (i = 0; i < n; i++) {
1123 json_t* contact_object = json_array_get(contacts_array, i);
1124 const char* email =
1125 json_string_value(json_object_get(contact_object, "email"));
1126 if (email) {
1127 SeafileUser contact;
1128 contact.email = QString::fromUtf8(email);
1129 contact.name = QString::fromUtf8(
1130 json_string_value(json_object_get(contact_object, "name")));
1131 contacts.push_back(contact);
1132 }
1133 }
1134 }
1135
1136 emit success(groups, contacts);
1137 }
1138
GetPrivateShareItemsRequest(const Account & account,const QString & repo_id,const QString & path)1139 GetPrivateShareItemsRequest::GetPrivateShareItemsRequest(const Account& account,
1140 const QString& repo_id,
1141 const QString& path)
1142 : SeafileApiRequest(
1143 account.getAbsoluteUrl(QString(kDirSharedItemsUrl).arg(repo_id)),
1144 SeafileApiRequest::METHOD_GET,
1145 account.token)
1146 {
1147 setUrlParam("p", path);
1148 }
1149
requestSuccess(QNetworkReply & reply)1150 void GetPrivateShareItemsRequest::requestSuccess(QNetworkReply& reply)
1151 {
1152 json_error_t error;
1153 json_t* root = parseJSON(reply, &error);
1154 if (!root) {
1155 qWarning("GetPrivateShareItemsRequest: failed to parse json:%s\n",
1156 error.text);
1157 emit failed(ApiError::fromJsonError());
1158 return;
1159 }
1160
1161 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
1162
1163 QList<GroupShareInfo> group_shares;
1164 QList<UserShareInfo> user_shares;
1165
1166 int i, n = json_array_size(json.data());
1167 for (i = 0; i < n; i++) {
1168 json_t* share_info_object = json_array_get(json.data(), i);
1169 Json share_info(share_info_object);
1170 QString share_type = share_info.getString("share_type");
1171 QString permission = share_info.getString("permission");
1172 if (share_type == "group") {
1173 // group share
1174 Json group = share_info.getObject("group_info");
1175 GroupShareInfo group_share;
1176 group_share.group.id = group.getLong("id");
1177 group_share.group.name = group.getString("name");
1178 group_share.permission = ::permissionfromString(permission);
1179 group_shares.push_back(group_share);
1180 }
1181 else if (share_type == "user") {
1182 Json user = share_info.getObject("user_info");
1183 UserShareInfo user_share;
1184 user_share.user.email = user.getString("name");
1185 user_share.user.name = user.getString("nickname");
1186 user_share.permission = ::permissionfromString(permission);
1187 user_shares.push_back(user_share);
1188 }
1189 }
1190
1191 emit success(group_shares, user_shares);
1192 }
1193
RemoteWipeReportRequest(const Account & account)1194 RemoteWipeReportRequest::RemoteWipeReportRequest(const Account& account)
1195 : SeafileApiRequest(account.getAbsoluteUrl(kRemoteWipeReportUrl),
1196 SeafileApiRequest::METHOD_POST)
1197 {
1198 setFormParam(QString("token"), account.token);
1199 }
1200
requestSuccess(QNetworkReply & reply)1201 void RemoteWipeReportRequest::requestSuccess(QNetworkReply& reply)
1202 {
1203 emit success();
1204 }
1205
SearchUsersRequest(const Account & account,const QString & pattern)1206 SearchUsersRequest::SearchUsersRequest(
1207 const Account& account, const QString& pattern)
1208 : SeafileApiRequest(account.getAbsoluteUrl(kSearchUsersUrl),
1209 SeafileApiRequest::METHOD_GET,
1210 account.token),
1211 pattern_(pattern)
1212 {
1213 setUrlParam("q", pattern);
1214 }
1215
requestSuccess(QNetworkReply & reply)1216 void SearchUsersRequest::requestSuccess(QNetworkReply& reply)
1217 {
1218 json_error_t error;
1219 json_t* root = parseJSON(reply, &error);
1220 if (!root) {
1221 qWarning("SearchUsersRequest: failed to parse json:%s\n",
1222 error.text);
1223 emit failed(ApiError::fromJsonError());
1224 return;
1225 }
1226
1227 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
1228
1229 QList<SeafileUser> users;
1230
1231 json_t* users_array = json_object_get(json.data(), "users");
1232 if (users_array) {
1233 int i, n = json_array_size(users_array);
1234
1235 for (i = 0; i < n; i++) {
1236 json_t* user_object = json_array_get(users_array, i);
1237 const char* email =
1238 json_string_value(json_object_get(user_object, "email"));
1239 if (email) {
1240 SeafileUser user;
1241 user.email = QString::fromUtf8(email);
1242 user.name = QString::fromUtf8(
1243 json_string_value(json_object_get(user_object, "name")));
1244 user.contact_email = QString::fromUtf8(
1245 json_string_value(json_object_get(user_object, "contact_email")));
1246 user.avatar_url = QString::fromUtf8(
1247 json_string_value(json_object_get(user_object, "avatar_url")));
1248 users.push_back(user);
1249 }
1250 }
1251 }
1252
1253 emit success(users);
1254 }
1255
1256
FetchGroupsRequest(const Account & account)1257 FetchGroupsRequest::FetchGroupsRequest(
1258 const Account& account)
1259 : SeafileApiRequest(account.getAbsoluteUrl(kFetchGroupsUrl),
1260 SeafileApiRequest::METHOD_GET,
1261 account.token)
1262 {
1263 setUrlParam("with_msg", "false");
1264 }
1265
requestSuccess(QNetworkReply & reply)1266 void FetchGroupsRequest::requestSuccess(QNetworkReply& reply)
1267 {
1268 json_error_t error;
1269 json_t* root = parseJSON(reply, &error);
1270 if (!root) {
1271 qWarning("FetchGroupsRequest: failed to parse json:%s\n",
1272 error.text);
1273 emit failed(ApiError::fromJsonError());
1274 return;
1275 }
1276
1277 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
1278
1279 QList<SeafileGroup> groups;
1280
1281 int i, n = json_array_size(json.data());
1282 for (i = 0; i < n; i++) {
1283 json_t* group_object = json_array_get(json.data(), i);
1284 const char* name =
1285 json_string_value(json_object_get(group_object, "name"));
1286 int group_id =
1287 json_integer_value(json_object_get(group_object, "id"));
1288 if (name && group_id) {
1289 SeafileGroup group;
1290 group.id = group_id;
1291 group.name = QString::fromUtf8(name);
1292 const char* owner =
1293 json_string_value(json_object_get(group_object, "creator"));
1294 if (owner) {
1295 group.owner = QString::fromUtf8(owner);
1296 }
1297 groups.push_back(group);
1298 }
1299 }
1300
1301 emit success(groups);
1302 }
1303
GetThumbnailRequest(const Account & account,const QString & repo_id,const QString & path,const QString & dirent_id,uint size)1304 GetThumbnailRequest::GetThumbnailRequest(const Account& account,
1305 const QString& repo_id,
1306 const QString& path,
1307 const QString& dirent_id,
1308 uint size)
1309 : SeafileApiRequest(
1310 account.getAbsoluteUrl(QString(kGetThumbnailUrl).arg(repo_id)),
1311 SeafileApiRequest::METHOD_GET,
1312 account.token),
1313 account_(account),
1314 repo_id_(repo_id),
1315 path_(path),
1316 dirent_id_(dirent_id),
1317 size_(size)
1318 {
1319 setUrlParam("p", path);
1320 setUrlParam("size", QString::number(size));
1321 setUseCache(true);
1322 }
1323
requestSuccess(QNetworkReply & reply)1324 void GetThumbnailRequest::requestSuccess(QNetworkReply& reply)
1325 {
1326 QPixmap pixmap;
1327 pixmap.loadFromData(reply.readAll());
1328
1329 if (pixmap.isNull()) {
1330 qWarning("GetThumbnailRequest: invalid image data\n");
1331 emit failed(ApiError::fromHttpError(400));
1332 }
1333 else {
1334 emit success(pixmap);
1335 }
1336 }
1337
UnshareRepoRequest(const Account & account,const QString & repo_id,const QString & from_user)1338 UnshareRepoRequest::UnshareRepoRequest(const Account& account,
1339 const QString& repo_id,
1340 const QString& from_user)
1341 : SeafileApiRequest(
1342 account.getAbsoluteUrl(QString(kRepoSharedUrl).arg(repo_id)),
1343 SeafileApiRequest::METHOD_DELETE,
1344 account.token),
1345 repo_id_(repo_id)
1346 {
1347 setUrlParam("share_type", "personal");
1348 setUrlParam("from", from_user);
1349 }
1350
requestSuccess(QNetworkReply & reply)1351 void UnshareRepoRequest::requestSuccess(QNetworkReply& reply)
1352 {
1353 emit success();
1354 }
1355
CreateFileUploadLinkRequest(const Account & account,const QString & repo_id,const QString & path,const QString & password)1356 CreateFileUploadLinkRequest::CreateFileUploadLinkRequest(const Account& account,
1357 const QString &repo_id,
1358 const QString &path,
1359 const QString &password)
1360 : SeafileApiRequest(
1361 account.getAbsoluteUrl(QString(kCreateFileUploadLink)),
1362 SeafileApiRequest::METHOD_POST, account.token),
1363 repo_id_(repo_id),
1364 path_(path),
1365 password_(password)
1366 {
1367 setFormParam(QString("repo_id"), repo_id);
1368 setFormParam(QString("path"), path);
1369 if (!password.isNull()) {
1370 setFormParam(QString("password"), password);
1371 }
1372 }
1373
requestSuccess(QNetworkReply & reply)1374 void CreateFileUploadLinkRequest::requestSuccess(QNetworkReply& reply)
1375 {
1376 json_error_t error;
1377 json_t* root = parseJSON(reply, &error);
1378 if (!root) {
1379 qWarning("failed to parse json:%s\n", error.text);
1380 emit failed(ApiError::fromJsonError());
1381 return;
1382 }
1383
1384 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
1385 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
1386 UploadLinkInfo link_info;
1387 link_info.username = dict["username"].toString();
1388 link_info.repo_id = dict["repo_id"].toString();
1389 link_info.ctime = dict["ctime"].toString();
1390 link_info.token = dict["token"].toString();
1391 link_info.link = dict["link"].toString();
1392 link_info.path = dict["path"].toString();
1393
1394 emit success(link_info);
1395 }
1396
GetUploadFileLinkRequest(const QString & link)1397 GetUploadFileLinkRequest::GetUploadFileLinkRequest(const QString& link)
1398 : SeafileApiRequest(link, SeafileApiRequest::METHOD_GET)
1399 {
1400 }
1401
requestSuccess(QNetworkReply & reply)1402 void GetUploadFileLinkRequest::requestSuccess(QNetworkReply& reply)
1403 {
1404 json_error_t error;
1405 json_t* root = parseJSON(reply, &error);
1406 if (!root) {
1407 qWarning("failed to parse json:%s\n", error.text);
1408 emit failed(ApiError::fromJsonError());
1409 return;
1410 }
1411
1412 QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
1413 QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
1414 QString reply_content(dict["upload_link"].toString());
1415
1416 do {
1417 if (reply_content.size() <= 2)
1418 break;
1419 QUrl new_url(reply_content);
1420 if (!new_url.isValid())
1421 break;
1422
1423 emit success(reply_content);
1424 return;
1425 } while (0);
1426 emit failed(ApiError::fromHttpError(500));
1427 }
1428