1 #include "file-browser-requests.h"
2 
3 #include <jansson.h>
4 #include <QtNetwork>
5 #include <QScopedPointer>
6 #include <QMapIterator>
7 
8 #include "account.h"
9 #include "api/api-error.h"
10 #include "seaf-dirent.h"
11 #include "utils/utils.h"
12 #include "utils/file-utils.h"
13 #include "src/open-local-helper.h"
14 #include "utils/json-utils.h"
15 #include "seafile-applet.h"
16 
17 namespace {
18 
19 const char kGetDirentsUrl[] = "api2/repos/%1/dir/";
20 const char kGetFilesUrl[] = "api2/repos/%1/file/";
21 const char kGetFileSharedLinkUrl[] = "api2/repos/%1/file/shared-link/";
22 const char kGetFileUploadUrl[] = "api2/repos/%1/upload-link/";
23 const char kGetFileUpdateUrl[] = "api2/repos/%1/update-link/";
24 const char kGetStarredFilesUrl[] = "api2/starredfiles/";
25 const char kQueryAsyncOperationProgressUrl[] = "api/v2.1/query-copy-move-progress/";
26 const char kCopyMoveSingleItemUrl[] = "api/v2.1/copy-move-task/";
27 const char kFileOperationCopy[] = "api2/repos/%1/fileops/copy/";
28 const char kAsyncCopyMultipleItems[] = "api/v2.1/repos/async-batch-copy-item/";
29 const char kAsyncMoveMultipleItems[] = "api/v2.1/repos/async-batch-move-item/";
30 const char kFileOperationMove[] = "api2/repos/%1/fileops/move/";
31 const char kRemoveDirentsURL[] = "api2/repos/%1/fileops/delete/";
32 const char kGetFileUploadedBytesUrl[] = "api/v2.1/repos/%1/file-uploaded-bytes/";
33 const char kGetSmartLink[] = "api/v2.1/smart-link/";
34 const char kGetUploadLinkUrl[] = "api/v2.1/upload-links/";
35 
36 //const char kGetFileFromRevisionUrl[] = "api2/repos/%1/file/revision/";
37 //const char kGetFileDetailUrl[] = "api2/repos/%1/file/detail/";
38 //const char kGetFileHistoryUrl[] = "api2/repos/%1/file/history/";
39 
assembleJsonReq(const QString & repo_id,const QString & src_dir_path,const QStringList & src_file_names,const QString & dst_repo_id,const QString & dst_dir_path)40 QByteArray assembleJsonReq(const QString&  repo_id, const QString& src_dir_path,
41                            const QStringList& src_file_names, const QString& dst_repo_id,
42                            const QString& dst_dir_path)
43 {
44     QJsonObject json_obj;
45     QJsonArray dirents_array;
46     json_obj.insert("src_repo_id", repo_id);
47     json_obj.insert("src_parent_dir", src_dir_path);
48     Q_FOREACH(const QString & src_file_name, src_file_names) {
49             dirents_array.append(src_file_name);
50     }
51     json_obj.insert("src_dirents", dirents_array);
52     json_obj.insert("dst_repo_id", dst_repo_id);
53     json_obj.insert("dst_parent_dir", dst_dir_path);
54 
55     QJsonDocument json_document(json_obj);
56     return json_document.toJson(QJsonDocument::Compact);
57 }
58 
59 } // namespace
60 
61 
GetDirentsRequest(const Account & account,const QString & repo_id,const QString & path)62 GetDirentsRequest::GetDirentsRequest(const Account& account,
63                                      const QString& repo_id,
64                                      const QString& path)
65     : SeafileApiRequest (account.getAbsoluteUrl(QString(kGetDirentsUrl).arg(repo_id)),
66                          SeafileApiRequest::METHOD_GET, account.token),
67       repo_id_(repo_id), path_(path), readonly_(false)
68 {
69     setUrlParam("p", path);
70 }
71 
requestSuccess(QNetworkReply & reply)72 void GetDirentsRequest::requestSuccess(QNetworkReply& reply)
73 {
74     json_error_t error;
75     QString dir_id = reply.rawHeader("oid");
76     if (dir_id.length() != 40) {
77         emit failed(ApiError::fromHttpError(500), repo_id_);
78         return;
79     }
80     // this extra header column only supported from v4.2 seahub
81     readonly_ = reply.rawHeader("dir_perm") == "r";
82 
83     json_t *root = parseJSON(reply, &error);
84     if (!root) {
85         qDebug("GetDirentsRequest: failed to parse json:%s\n", error.text);
86         emit failed(ApiError::fromJsonError(), repo_id_);
87         return;
88     }
89 
90     QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
91 
92     QList<SeafDirent> dirents;
93     dirents = SeafDirent::listFromJSON(json.data(), &error);
94     emit success(readonly_, dirents, repo_id_);
95 }
96 
GetFileDownloadLinkRequest(const Account & account,const QString & repo_id,const QString & path)97 GetFileDownloadLinkRequest::GetFileDownloadLinkRequest(const Account &account,
98                                                        const QString &repo_id,
99                                                        const QString &path)
100     : SeafileApiRequest(
101           account.getAbsoluteUrl(QString(kGetFilesUrl).arg(repo_id)),
102           SeafileApiRequest::METHOD_GET, account.token)
103 {
104     setUrlParam("p", path);
105 }
106 
requestSuccess(QNetworkReply & reply)107 void GetFileDownloadLinkRequest::requestSuccess(QNetworkReply& reply)
108 {
109     QString reply_content(reply.readAll());
110     QString oid;
111 
112     if (reply.hasRawHeader("oid"))
113         oid = reply.rawHeader("oid");
114 
115     do {
116         if (reply_content.size() <= 2)
117             break;
118         reply_content.remove(0, 1);
119         reply_content.chop(1);
120         QUrl new_url(reply_content);
121 
122         if (!new_url.isValid())
123             break;
124 
125         file_id_ = oid;
126         emit success(reply_content);
127         return;
128     } while (0);
129     emit failed(ApiError::fromHttpError(500));
130 }
131 
GetSharedLinkRequest(const Account & account,const QString & repo_id,const QString & path,bool is_file)132 GetSharedLinkRequest::GetSharedLinkRequest(const Account &account,
133                                            const QString &repo_id,
134                                            const QString &path,
135                                            bool is_file)
136     : SeafileApiRequest(
137           account.getAbsoluteUrl(QString(kGetFileSharedLinkUrl).arg(repo_id)),
138           SeafileApiRequest::METHOD_PUT, account.token), repo_id_(repo_id)
139 {
140     setFormParam("type", is_file ? "f" : "d");
141     setFormParam("p", path);
142 }
143 
requestSuccess(QNetworkReply & reply)144 void GetSharedLinkRequest::requestSuccess(QNetworkReply& reply)
145 {
146     QString reply_content(reply.rawHeader("Location"));
147 
148     emit success(reply_content, repo_id_);
149 }
150 
CreateDirectoryRequest(const Account & account,const QString & repo_id,const QString & path,bool create_parents)151 CreateDirectoryRequest::CreateDirectoryRequest(const Account &account,
152                                                const QString &repo_id,
153                                                const QString &path,
154                                                bool create_parents)
155     : SeafileApiRequest(
156           account.getAbsoluteUrl(QString(kGetDirentsUrl).arg(repo_id)),
157           SeafileApiRequest::METHOD_POST, account.token),
158       repo_id_(repo_id), path_(path), create_parents_(create_parents)
159 {
160     setUrlParam("p", path);
161 
162     setFormParam("operation", "mkdir");
163     setFormParam("create_parents", create_parents ? "true" : "false");
164 }
165 
requestSuccess(QNetworkReply & reply)166 void CreateDirectoryRequest::requestSuccess(QNetworkReply& reply)
167 {
168     emit success(repo_id_);
169 }
170 
GetFileUploadLinkRequest(const Account & account,const QString & repo_id,const QString & path,bool use_upload)171 GetFileUploadLinkRequest::GetFileUploadLinkRequest(const Account &account,
172                                                    const QString &repo_id,
173                                                    const QString &path,
174                                                    bool use_upload)
175     : SeafileApiRequest(
176           account.getAbsoluteUrl(QString(
177               use_upload ? kGetFileUploadUrl : kGetFileUpdateUrl).arg(repo_id)),
178           SeafileApiRequest::METHOD_GET, account.token)
179 {
180     setUrlParam("p", path);
181 }
182 
requestSuccess(QNetworkReply & reply)183 void GetFileUploadLinkRequest::requestSuccess(QNetworkReply& reply)
184 {
185     QString reply_content(reply.readAll());
186 
187     do {
188         if (reply_content.size() <= 2)
189             break;
190         reply_content.remove(0, 1);
191         reply_content.chop(1);
192         QUrl new_url(reply_content);
193 
194         if (!new_url.isValid())
195             break;
196 
197         emit success(reply_content);
198         return;
199     } while (0);
200     emit failed(ApiError::fromHttpError(500));
201 }
202 
203 
RenameDirentRequest(const Account & account,const QString & repo_id,const QString & path,const QString & new_name,bool is_file)204 RenameDirentRequest::RenameDirentRequest(const Account &account,
205                                          const QString &repo_id,
206                                          const QString &path,
207                                          const QString &new_name,
208                                          bool is_file)
209     : SeafileApiRequest(
210         account.getAbsoluteUrl(
211             QString(is_file ? kGetFilesUrl: kGetDirentsUrl).arg(repo_id)),
212         SeafileApiRequest::METHOD_POST, account.token),
213     is_file_(is_file), repo_id_(repo_id), path_(path), new_name_(new_name)
214 {
215     setUrlParam("p", path);
216 
217     setFormParam("operation", "rename");
218     setFormParam("newname", new_name);
219 }
220 
requestSuccess(QNetworkReply & reply)221 void RenameDirentRequest::requestSuccess(QNetworkReply& reply)
222 {
223     emit success(repo_id_);
224 }
225 
RemoveDirentRequest(const Account & account,const QString & repo_id,const QString & path,bool is_file)226 RemoveDirentRequest::RemoveDirentRequest(const Account &account,
227                                          const QString &repo_id,
228                                          const QString &path,
229                                          bool is_file)
230     : SeafileApiRequest(
231         account.getAbsoluteUrl(
232             QString(is_file ? kGetFilesUrl : kGetDirentsUrl).arg(repo_id)),
233         SeafileApiRequest::METHOD_DELETE, account.token),
234     is_file_(is_file), repo_id_(repo_id), path_(path)
235 {
236     setUrlParam("p", path);
237 }
238 
requestSuccess(QNetworkReply & reply)239 void RemoveDirentRequest::requestSuccess(QNetworkReply& reply)
240 {
241     emit success(repo_id_);
242 }
243 
RemoveDirentsRequest(const Account & account,const QString & repo_id,const QString & parent_path,const QStringList & filenames)244 RemoveDirentsRequest::RemoveDirentsRequest(const Account &account,
245                                            const QString &repo_id,
246                                            const QString &parent_path,
247                                            const QStringList& filenames)
248     : SeafileApiRequest(
249         account.getAbsoluteUrl(
250             QString(kRemoveDirentsURL).arg(repo_id)),
251         SeafileApiRequest::METHOD_POST, account.token),
252       repo_id_(repo_id), parent_path_(parent_path), filenames_(filenames)
253 {
254     setUrlParam("p", parent_path_);
255     setFormParam("file_names", filenames_.join(":"));
256 }
257 
requestSuccess(QNetworkReply & reply)258 void RemoveDirentsRequest::requestSuccess(QNetworkReply& reply)
259 {
260     emit success(repo_id_);
261 }
262 
263 
MoveFileRequest(const Account & account,const QString & repo_id,const QString & path,const QString & dst_repo_id,const QString & dst_dir_path)264 MoveFileRequest::MoveFileRequest(const Account &account,
265                                  const QString &repo_id,
266                                  const QString &path,
267                                  const QString &dst_repo_id,
268                                  const QString &dst_dir_path)
269     : SeafileApiRequest(
270           account.getAbsoluteUrl(QString(kGetFilesUrl).arg(repo_id)),
271           SeafileApiRequest::METHOD_POST, account.token)
272 {
273     setUrlParam("p", path);
274 
275     setFormParam("operation", "move");
276     setFormParam("dst_repo", dst_repo_id);
277     setFormParam("dst_dir", dst_dir_path);
278 }
279 
requestSuccess(QNetworkReply & reply)280 void MoveFileRequest::requestSuccess(QNetworkReply& reply)
281 {
282     emit success();
283 }
284 
285 
QueryAsyncOperationProgress(const Account & account,const QString & task_id)286 QueryAsyncOperationProgress::QueryAsyncOperationProgress(const Account &account,
287                                                          const QString& task_id)
288         : SeafileApiRequest(
289         account.getAbsoluteUrl(kQueryAsyncOperationProgressUrl),
290         SeafileApiRequest::METHOD_GET, account.token)
291 {
292     setUrlParam("task_id", task_id);
293 }
294 
requestSuccess(QNetworkReply & reply)295 void QueryAsyncOperationProgress::requestSuccess(QNetworkReply& reply)
296 {
297     json_error_t error;
298     json_t* root = parseJSON(reply, &error);
299     if (!root) {
300         qWarning("failed to parse json:%s\n", error.text);
301         return;
302     }
303 
304     Json json(root);
305     bool is_success = json.getBool("successful");
306     bool is_failed = json.getBool("failed");
307     if (is_success) {
308         emit success();
309     } else if (is_failed) {
310         qWarning("operation failed");
311         emit failed(ApiError::fromHttpError(500));
312     }
313 }
314 
315 
AsyncCopyAndMoveOneItemRequest(const Account & account,const QString & src_repo_id,const QString & src_parent_dir,const QString & src_dirent_name,const QString & dst_repo_id,const QString & dst_parent_dir,const QString & operation,const QString & dirent_type)316 AsyncCopyAndMoveOneItemRequest::AsyncCopyAndMoveOneItemRequest(const Account &account,
317                                                                const QString &src_repo_id,
318                                                                const QString &src_parent_dir,
319                                                                const QString &src_dirent_name,
320                                                                const QString &dst_repo_id,
321                                                                const QString &dst_parent_dir,
322                                                                const QString &operation,
323                                                                const QString &dirent_type)
324     : SeafileApiRequest(
325           account.getAbsoluteUrl(QString(kCopyMoveSingleItemUrl)),
326           SeafileApiRequest::METHOD_POST, account.token),
327     account_(account),
328     repo_id_(src_repo_id),
329     src_dir_path_(src_parent_dir),
330     src_dirent_name_(src_dirent_name),
331     dst_repo_id_(dst_repo_id),
332     dst_repo_path_(dst_parent_dir),
333     operation_(operation),
334     dirent_type_(dirent_type)
335 {
336     setFormParam("src_repo_id", src_repo_id);
337     setFormParam("src_parent_dir", src_parent_dir);
338     setFormParam("src_dirent_name", src_dirent_name);
339     setFormParam("dst_repo_id", dst_repo_id);
340     setFormParam("dst_parent_dir", dst_parent_dir);
341     setFormParam("operation", operation);
342     setFormParam("dirent_type", dirent_type);
343 }
344 
requestSuccess(QNetworkReply & reply)345 void AsyncCopyAndMoveOneItemRequest::requestSuccess(QNetworkReply& reply)
346 {
347     json_error_t error;
348     json_t* root = parseJSON(reply, &error);
349     if (!root) {
350         qWarning("failed to parse json:%s\n", error.text);
351         return;
352     }
353 
354     Json json(root);
355     QString task_id= json.getString("task_id");
356     emit success(task_id);
357 }
358 
359 
360 // Asynchronous copy multiple items
AsyncCopyMultipleItemsRequest(const Account & account,const QString & repo_id,const QString & src_dir_path,const QMap<QString,int> & src_dirents,const QString & dst_repo_id,const QString & dst_dir_path)361 AsyncCopyMultipleItemsRequest::AsyncCopyMultipleItemsRequest(const Account &account,
362                                                              const QString &repo_id,
363                                                              const QString &src_dir_path,
364                                                              const QMap<QString, int>&src_dirents,
365                                                              const QString &dst_repo_id,
366                                                              const QString &dst_dir_path)
367      : SeafileApiRequest(
368              account.getAbsoluteUrl(QString(kAsyncCopyMultipleItems)),
369              SeafileApiRequest::METHOD_POST, account.token),
370        account_(account),
371        repo_id_(repo_id),
372        src_dir_path_(src_dir_path),
373        src_dirents_(src_dirents),
374        dst_repo_id_(dst_repo_id),
375        dst_repo_path_(dst_dir_path)
376 
377 {
378 
379     setHeader("Content-Type","application/json");
380     setHeader("Accept", "application/json");
381 
382     QStringList file_names;
383     for ( const QString & file_name : src_dirents.keys()) {
384         file_names.push_back(file_name);
385     }
386     QByteArray byte_array = assembleJsonReq(repo_id, src_dir_path, file_names,
387                                             dst_repo_id, dst_dir_path);
388     setRequestBody(byte_array);
389 }
390 
requestSuccess(QNetworkReply & reply)391 void AsyncCopyMultipleItemsRequest::requestSuccess(QNetworkReply& reply)
392 {
393     json_error_t error;
394     json_t* root = parseJSON(reply, &error);
395     if (!root) {
396         qWarning("failed to parse json:%s\n", error.text);
397         return;
398     }
399 
400     Json json(root);
401     QString task_id = json.getString("task_id");
402     emit success(task_id);
403 }
404 
405 
406 // Asynchronous api for move multiple items
AsyncMoveMultipleItemsRequest(const Account & account,const QString & repo_id,const QString & src_dir_path,const QMap<QString,int> & src_dirents,const QString & dst_repo_id,const QString & dst_dir_path)407 AsyncMoveMultipleItemsRequest::AsyncMoveMultipleItemsRequest(const Account &account,
408                                                              const QString &repo_id,
409                                                              const QString &src_dir_path,
410                                                              const QMap<QString, int> &src_dirents,
411                                                              const QString &dst_repo_id,
412                                                              const QString &dst_dir_path)
413         : SeafileApiRequest(
414             account.getAbsoluteUrl(QString(kAsyncMoveMultipleItems)),
415             SeafileApiRequest::METHOD_POST, account.token),
416           account_(account),
417           repo_id_(repo_id),
418           src_dir_path_(src_dir_path),
419           src_dirents_(src_dirents),
420           dst_repo_id_(dst_repo_id),
421           dst_repo_path_(dst_dir_path)
422 {
423     setHeader("Content-Type","application/json");
424     setHeader("Accept", "application/json");
425 
426     QStringList file_names;
427     for ( const QString & file_name : src_dirents.keys()) {
428         file_names.push_back(file_name);
429     }
430 
431     QByteArray byte_array = assembleJsonReq(repo_id, src_dir_path, file_names,
432                                             dst_repo_id, dst_dir_path);
433     setRequestBody(byte_array);
434 }
435 
requestSuccess(QNetworkReply & reply)436 void AsyncMoveMultipleItemsRequest::requestSuccess(QNetworkReply& reply)
437 {
438     json_error_t error;
439     json_t* root = parseJSON(reply, &error);
440     if (!root) {
441         qWarning("failed to parse json:%s\n", error.text);
442         return;
443     }
444 
445     Json json(root);
446     QString task_id = json.getString("task_id");
447     emit success(task_id);
448 }
449 
450 
CopyMultipleFilesRequest(const Account & account,const QString & repo_id,const QString & src_dir_path,const QStringList & src_file_names,const QString & dst_repo_id,const QString & dst_dir_path)451 CopyMultipleFilesRequest::CopyMultipleFilesRequest(const Account &account,
452                                                    const QString &repo_id,
453                                                    const QString &src_dir_path,
454                                                    const QStringList &src_file_names,
455                                                    const QString &dst_repo_id,
456                                                    const QString &dst_dir_path)
457     : SeafileApiRequest(
458         account.getAbsoluteUrl(QString(kFileOperationCopy).arg(repo_id)),
459     SeafileApiRequest::METHOD_POST, account.token),
460     repo_id_(repo_id),
461     src_dir_path_(src_dir_path),
462     src_file_names_(src_file_names),
463     dst_repo_id_(dst_repo_id)
464 {
465     setUrlParam("p", src_dir_path);
466 
467     setFormParam("file_names", src_file_names.join(":"));
468     setFormParam("dst_repo", dst_repo_id);
469     setFormParam("dst_dir", dst_dir_path);
470 }
471 
requestSuccess(QNetworkReply & reply)472 void CopyMultipleFilesRequest::requestSuccess(QNetworkReply& reply)
473 {
474     emit success(dst_repo_id_);
475 }
476 
MoveMultipleFilesRequest(const Account & account,const QString & repo_id,const QString & src_dir_path,const QStringList & src_file_names,const QString & dst_repo_id,const QString & dst_dir_path)477 MoveMultipleFilesRequest::MoveMultipleFilesRequest(const Account &account,
478                                                    const QString &repo_id,
479                                                    const QString &src_dir_path,
480                                                    const QStringList &src_file_names,
481                                                    const QString &dst_repo_id,
482                                                    const QString &dst_dir_path)
483     : SeafileApiRequest(
484         account.getAbsoluteUrl(QString(kFileOperationMove).arg(repo_id)),
485     SeafileApiRequest::METHOD_POST, account.token),
486     repo_id_(repo_id),
487     src_dir_path_(src_dir_path),
488     src_file_names_(src_file_names),
489     dst_repo_id_(dst_repo_id)
490 {
491     setUrlParam("p", src_dir_path);
492 
493     setFormParam("file_names", src_file_names.join(":"));
494     setFormParam("dst_repo", dst_repo_id);
495     setFormParam("dst_dir", dst_dir_path);
496 }
497 
requestSuccess(QNetworkReply & reply)498 void MoveMultipleFilesRequest::requestSuccess(QNetworkReply& reply)
499 {
500     emit success(dst_repo_id_);
501 }
502 
StarFileRequest(const Account & account,const QString & repo_id,const QString & path)503 StarFileRequest::StarFileRequest(const Account &account,
504                                  const QString &repo_id,
505                                  const QString &path)
506     : SeafileApiRequest(
507           account.getAbsoluteUrl(kGetStarredFilesUrl),
508           SeafileApiRequest::METHOD_POST, account.token)
509 {
510     setFormParam("repo_id", repo_id);
511     setFormParam("p", path);
512 }
513 
requestSuccess(QNetworkReply & reply)514 void StarFileRequest::requestSuccess(QNetworkReply& reply)
515 {
516     emit success();
517 }
518 
UnstarFileRequest(const Account & account,const QString & repo_id,const QString & path)519 UnstarFileRequest::UnstarFileRequest(const Account &account,
520                                      const QString &repo_id,
521                                      const QString &path)
522     : SeafileApiRequest(
523           account.getAbsoluteUrl(kGetStarredFilesUrl),
524           SeafileApiRequest::METHOD_DELETE, account.token)
525 {
526     setUrlParam("repo_id", repo_id);
527     setUrlParam("p", path);
528 }
529 
requestSuccess(QNetworkReply & reply)530 void UnstarFileRequest::requestSuccess(QNetworkReply& reply)
531 {
532     emit success();
533 }
534 
LockFileRequest(const Account & account,const QString & repo_id,const QString & path,bool lock)535 LockFileRequest::LockFileRequest(const Account &account, const QString &repo_id,
536                                  const QString &path, bool lock)
537     : SeafileApiRequest(
538           account.getAbsoluteUrl(QString(kGetFilesUrl).arg(repo_id)),
539           SeafileApiRequest::METHOD_PUT, account.token),
540       lock_(lock), repo_id_(repo_id), path_(path)
541 {
542     setFormParam("p", path.startsWith("/") ? path : "/" + path);
543 
544     setFormParam("operation", lock ? "lock" : "unlock");
545 }
546 
requestSuccess(QNetworkReply & reply)547 void LockFileRequest::requestSuccess(QNetworkReply& reply)
548 {
549     emit success(repo_id_);
550 }
551 
GetFileUploadedBytesRequest(const Account & account,const QString & repo_id,const QString & parent_dir,const QString & file_name)552 GetFileUploadedBytesRequest::GetFileUploadedBytesRequest(
553     const Account &account,
554     const QString &repo_id,
555     const QString &parent_dir,
556     const QString &file_name)
557     : SeafileApiRequest(
558           account.getAbsoluteUrl(QString(kGetFileUploadedBytesUrl).arg(repo_id)),
559           SeafileApiRequest::METHOD_GET,
560           account.token),
561       repo_id_(repo_id),
562       parent_dir_(parent_dir),
563       file_name_(file_name)
564 {
565     setUrlParam("parent_dir",
566                 parent_dir.startsWith("/") ? parent_dir : "/" + parent_dir);
567     setUrlParam("file_name", file_name);
568 }
569 
requestSuccess(QNetworkReply & reply)570 void GetFileUploadedBytesRequest::requestSuccess(QNetworkReply &reply)
571 {
572     QString accept_ranges_header = reply.rawHeader("Accept-Ranges");
573     // printf ("accept_ranges_header = %s\n", toCStr(accept_ranges_header));
574     if (accept_ranges_header != "bytes") {
575         // Chunked uploading is not supported on the server
576         emit success(false, 0);
577         return;
578     }
579 
580     json_error_t error;
581     json_t* root = parseJSON(reply, &error);
582     if (!root) {
583         qWarning("GetFileUploadedBytesRequest: failed to parse json:%s\n",
584                  error.text);
585         emit failed(ApiError::fromJsonError());
586         return;
587     }
588 
589     QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
590 
591     QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
592     quint64 uploaded_bytes = dict["uploadedBytes"].toLongLong();
593     // printf ("uploadedBytes = %lld\n", uploaded_bytes);
594     emit success(true, uploaded_bytes);
595 }
596 
GetIndexProgressRequest(const QUrl & url,const QString & task_id)597 GetIndexProgressRequest::GetIndexProgressRequest(const QUrl &url, const QString &task_id)
598     : SeafileApiRequest(url, SeafileApiRequest::METHOD_GET)
599 {
600     setUrlParam("task_id", task_id);
601 }
602 
requestSuccess(QNetworkReply & reply)603 void GetIndexProgressRequest::requestSuccess(QNetworkReply& reply)
604 {
605     json_error_t error;
606     json_t *root = parseJSON(reply, &error);
607     if (!root) {
608         qWarning("GetIndexProgressRequest: failed to parse json:%s\n", error.text);
609         emit failed(ApiError::fromJsonError());
610         return;
611     }
612 
613     QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
614 
615     QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
616     ServerIndexProgress result;
617 
618     result.total = dict.value("total").toInt();
619     result.indexed = dict.value("indexed").toInt();
620     result.status = dict.value("status").toInt();
621     emit success(result);
622 }
623 
GetSmartLinkRequest(const Account & account,const QString & repo_id,const QString & path,bool is_dir)624 GetSmartLinkRequest::GetSmartLinkRequest(const Account& account,
625                                          const QString &repo_id,
626                                          const QString &path,
627                                          bool is_dir)
628     : SeafileApiRequest(
629           account.getAbsoluteUrl(QString(kGetSmartLink)),
630           SeafileApiRequest::METHOD_GET, account.token),
631       repo_id_(repo_id),
632       path_(path),
633       is_dir_(is_dir),
634       protocol_link_(OpenLocalHelper::instance()->generateLocalFileSeafileUrl(repo_id, account, path).toEncoded())
635 {
636     setUrlParam("repo_id", repo_id);
637     setUrlParam("path", path);
638     setUrlParam("is_dir", is_dir ? "true" : "false");
639 }
640 
requestSuccess(QNetworkReply & reply)641 void GetSmartLinkRequest::requestSuccess(QNetworkReply& reply)
642 {
643     json_error_t error;
644     json_t* root = parseJSON(reply, &error);
645     if (!root) {
646         qWarning("failed to parse json:%s\n", error.text);
647         emit failed(ApiError::fromJsonError());
648         return;
649     }
650 
651     QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
652     const char* smart_link =
653         json_string_value(json_object_get(json.data(), "smart_link"));
654 
655     emit success(smart_link, protocol_link_);
656 }
657 
GetFileLockInfoRequest(const Account & account,const QString & repo_id,const QString & path)658 GetFileLockInfoRequest::GetFileLockInfoRequest(const Account& account,
659                                                const QString &repo_id,
660                                                const QString &path)
661     : SeafileApiRequest(
662           account.getAbsoluteUrl(QString(kGetDirentsUrl)),
663           SeafileApiRequest::METHOD_GET, account.token),
664       path_(path)
665 {
666     // Seahub doesn't provide a standalone api for getting file lock
667     // info. We have to get that from dirents api.
668     dirents_req_.reset(
669         new GetDirentsRequest(account, repo_id, ::getParentPath(path_)));
670     connect(dirents_req_.data(),
671             SIGNAL(success(bool, const QList<SeafDirent> &, const QString &)),
672             this,
673             SLOT(onGetDirentsSuccess(bool, const QList<SeafDirent> &)));
674     connect(dirents_req_.data(),
675             SIGNAL(failed(const ApiError &)),
676             this,
677             SIGNAL(failed(const ApiError &)));
678 }
679 
send()680 void GetFileLockInfoRequest::send()
681 {
682     dirents_req_->send();
683 }
684 
requestSuccess(QNetworkReply & reply)685 void GetFileLockInfoRequest::requestSuccess(QNetworkReply& reply)
686 {
687     // Just a place holder. A `GetFileLockInfoRequest` is a wrapper around a
688     // `GetDirentsRequest`, which really sends the api
689     // requests.
690 }
691 
onGetDirentsSuccess(bool current_readonly,const QList<SeafDirent> & dirents)692 void GetFileLockInfoRequest::onGetDirentsSuccess(bool current_readonly, const QList<SeafDirent> &dirents)
693 {
694     const QString name = ::getBaseName(path_);
695     foreach(const SeafDirent& dirent, dirents) {
696         if (dirent.name == name) {
697             const QString lock_owner = dirent.getLockOwnerDisplayString();
698             if (!lock_owner.isEmpty()) {
699                 emit success(true, lock_owner);
700             } else {
701                 emit success(false, "");
702             }
703             return;
704         }
705     }
706     emit success(false, "");
707 }
708 
GetUploadLinkRequest(const Account & account,const QString & repo_id,const QString & path)709 GetUploadLinkRequest::GetUploadLinkRequest(const Account& account,
710                                            const QString& repo_id,
711                                            const QString& path)
712         : SeafileApiRequest(
713         account.getAbsoluteUrl(QString(kGetUploadLinkUrl)),
714         SeafileApiRequest::METHOD_POST, account.token),
715         path_(path)
716 {
717     setFormParam("repo_id", repo_id);
718     setFormParam("path", path);
719 }
720 
requestSuccess(QNetworkReply & reply)721 void GetUploadLinkRequest::requestSuccess(QNetworkReply& reply)
722 {
723     json_error_t error;
724     json_t* root = parseJSON(reply, &error);
725     if (!root) {
726         qWarning("failed to parse json:%s\n", error.text);
727         emit failed(ApiError::fromJsonError());
728         return;
729     }
730     QScopedPointer<json_t, JsonPointerCustomDeleter> json(root);
731     QMap<QString, QVariant> dict = mapFromJSON(json.data(), &error);
732     QString upload_link = dict["link"].toString();
733     emit success(upload_link);
734 }
735