Changeset View
Changeset View
Standalone View
Standalone View
src/kio_gdrive.cpp
Show All 19 Lines | |||||
20 | #include "kio_gdrive.h" | 20 | #include "kio_gdrive.h" | ||
21 | #include "gdrivebackend.h" | 21 | #include "gdrivebackend.h" | ||
22 | #include "gdrivedebug.h" | 22 | #include "gdrivedebug.h" | ||
23 | #include "gdrivehelper.h" | 23 | #include "gdrivehelper.h" | ||
24 | #include "gdriveurl.h" | 24 | #include "gdriveurl.h" | ||
25 | #include "gdriveversion.h" | 25 | #include "gdriveversion.h" | ||
26 | 26 | | |||
27 | #include <QApplication> | 27 | #include <QApplication> | ||
28 | #include <QUrlQuery> | 28 | #include <QMimeDatabase> | ||
29 | #include <QNetworkReply> | ||||
30 | #include <QNetworkRequest> | ||||
29 | #include <QTemporaryFile> | 31 | #include <QTemporaryFile> | ||
32 | #include <QUrlQuery> | ||||
33 | #include <QUuid> | ||||
30 | 34 | | |||
31 | #include <KGAPI/Account> | 35 | #include <KGAPI/Account> | ||
32 | #include <KGAPI/AuthJob> | 36 | #include <KGAPI/AuthJob> | ||
33 | #include <KGAPI/Drive/About> | 37 | #include <KGAPI/Drive/About> | ||
34 | #include <KGAPI/Drive/AboutFetchJob> | 38 | #include <KGAPI/Drive/AboutFetchJob> | ||
35 | #include <KGAPI/Drive/ChildReference> | 39 | #include <KGAPI/Drive/ChildReference> | ||
36 | #include <KGAPI/Drive/ChildReferenceFetchJob> | | |||
37 | #include <KGAPI/Drive/ChildReferenceCreateJob> | 40 | #include <KGAPI/Drive/ChildReferenceCreateJob> | ||
41 | #include <KGAPI/Drive/ChildReferenceFetchJob> | ||||
42 | #include <KGAPI/Drive/Drives> | ||||
43 | #include <KGAPI/Drive/DrivesCreateJob> | ||||
44 | #include <KGAPI/Drive/DrivesDeleteJob> | ||||
45 | #include <KGAPI/Drive/DrivesFetchJob> | ||||
46 | #include <KGAPI/Drive/DrivesModifyJob> | ||||
38 | #include <KGAPI/Drive/File> | 47 | #include <KGAPI/Drive/File> | ||
39 | #include <KGAPI/Drive/FileCopyJob> | 48 | #include <KGAPI/Drive/FileCopyJob> | ||
40 | #include <KGAPI/Drive/FileCreateJob> | 49 | #include <KGAPI/Drive/FileCreateJob> | ||
41 | #include <KGAPI/Drive/FileModifyJob> | | |||
42 | #include <KGAPI/Drive/FileTrashJob> | | |||
43 | #include <KGAPI/Drive/FileFetchJob> | | |||
44 | #include <KGAPI/Drive/FileFetchContentJob> | 50 | #include <KGAPI/Drive/FileFetchContentJob> | ||
51 | #include <KGAPI/Drive/FileFetchJob> | ||||
52 | #include <KGAPI/Drive/FileModifyJob> | ||||
45 | #include <KGAPI/Drive/FileSearchQuery> | 53 | #include <KGAPI/Drive/FileSearchQuery> | ||
54 | #include <KGAPI/Drive/FileTrashJob> | ||||
46 | #include <KGAPI/Drive/ParentReference> | 55 | #include <KGAPI/Drive/ParentReference> | ||
47 | #include <KGAPI/Drive/Permission> | 56 | #include <KGAPI/Drive/Permission> | ||
48 | #include <KIO/AccessManager> | 57 | #include <KIO/AccessManager> | ||
elvisangelaccio: Please keep the list of includes sorted. | |||||
49 | #include <KIO/Job> | 58 | #include <KIO/Job> | ||
50 | #include <KLocalizedString> | 59 | #include <KLocalizedString> | ||
51 | 60 | | |||
52 | #include <QNetworkRequest> | | |||
53 | #include <QNetworkReply> | | |||
54 | #include <QMimeDatabase> | | |||
55 | | ||||
56 | using namespace KGAPI2; | 61 | using namespace KGAPI2; | ||
57 | using namespace Drive; | 62 | using namespace Drive; | ||
58 | 63 | | |||
59 | class KIOPluginForMetaData : public QObject | 64 | class KIOPluginForMetaData : public QObject | ||
60 | { | 65 | { | ||
61 | Q_OBJECT | 66 | Q_OBJECT | ||
62 | Q_PLUGIN_METADATA(IID "org.kde.kio.slave.gdrive" FILE "gdrive.json") | 67 | Q_PLUGIN_METADATA(IID "org.kde.kio.slave.gdrive" FILE "gdrive.json") | ||
63 | }; | 68 | }; | ||
▲ Show 20 Lines • Show All 199 Lines • ▼ Show 20 Line(s) | 263 | { | |||
263 | entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); | 268 | entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); | ||
264 | entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 0); | 269 | entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 0); | ||
265 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); | 270 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); | ||
266 | entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("folder-gdrive")); | 271 | entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("folder-gdrive")); | ||
267 | 272 | | |||
268 | return entry; | 273 | return entry; | ||
269 | } | 274 | } | ||
270 | 275 | | |||
276 | KIO::UDSEntry KIOGDrive::sharedDriveToUDSEntry(const DrivesPtr &sharedDrive) | ||||
elvisangelaccio: Missing pass-by-reference | |||||
277 | { | ||||
278 | KIO::UDSEntry entry; | ||||
279 | | ||||
280 | qlonglong udsAccess = S_IRUSR | S_IXUSR | S_IRGRP; | ||||
281 | if (sharedDrive->capabilities()->canRenameDrive() || sharedDrive->capabilities()->canDeleteDrive()) { | ||||
282 | udsAccess |= S_IWUSR; | ||||
283 | } | ||||
284 | | ||||
285 | entry.fastInsert(KIO::UDSEntry::UDS_NAME, sharedDrive->id()); | ||||
286 | entry.fastInsert(KIO::UDSEntry::UDS_DISPLAY_NAME, sharedDrive->name()); | ||||
287 | entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); | ||||
288 | entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 0); | ||||
289 | entry.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, sharedDrive->createdDate().toSecsSinceEpoch()); | ||||
290 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, udsAccess); | ||||
291 | entry.fastInsert(KIO::UDSEntry::UDS_HIDDEN, sharedDrive->hidden()); | ||||
292 | entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("folder-gdrive")); | ||||
293 | | ||||
294 | return entry; | ||||
295 | } | ||||
296 | | ||||
271 | void KIOGDrive::createAccount() | 297 | void KIOGDrive::createAccount() | ||
272 | { | 298 | { | ||
273 | const KGAPI2::AccountPtr account = m_accountManager->createAccount(); | 299 | const KGAPI2::AccountPtr account = m_accountManager->createAccount(); | ||
274 | if (!account->accountName().isEmpty()) { | 300 | if (!account->accountName().isEmpty()) { | ||
275 | // Redirect to the account we just created. | 301 | // Redirect to the account we just created. | ||
276 | redirection(QUrl(QStringLiteral("gdrive:/%1").arg(account->accountName()))); | 302 | redirection(QUrl(QStringLiteral("gdrive:/%1").arg(account->accountName()))); | ||
277 | finished(); | 303 | finished(); | ||
278 | return; | 304 | return; | ||
Show All 35 Lines | 318 | { | |||
314 | entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 0); | 340 | entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 0); | ||
315 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); | 341 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); | ||
316 | listEntry(entry); | 342 | listEntry(entry); | ||
317 | 343 | | |||
318 | finished(); | 344 | finished(); | ||
319 | return; | 345 | return; | ||
320 | } | 346 | } | ||
321 | 347 | | |||
348 | void KIOGDrive::listSharedDrivesRoot(const QUrl &url) | ||||
349 | { | ||||
350 | const auto gdriveUrl = GDriveUrl(url); | ||||
351 | const QString accountId = gdriveUrl.account(); | ||||
352 | DrivesFetchJob sharedDrivesFetchJob(getAccount(accountId)); | ||||
353 | sharedDrivesFetchJob.setFields({ | ||||
354 | Drives::Fields::Kind, | ||||
355 | Drives::Fields::Id, | ||||
356 | Drives::Fields::Name, | ||||
357 | Drives::Fields::Hidden, | ||||
358 | Drives::Fields::CreatedDate, | ||||
359 | Drives::Fields::Capabilities | ||||
360 | }); | ||||
361 | | ||||
362 | if (runJob(sharedDrivesFetchJob, url, accountId)) { | ||||
363 | const auto objects = sharedDrivesFetchJob.items(); | ||||
elvisangelaccio: `const` | |||||
364 | for (const auto &object : objects) { | ||||
elvisangelaccio: Q_FOREACH is deprecated, please avoid it in new code. | |||||
365 | const DrivesPtr sharedDrive = object.dynamicCast<Drives>(); | ||||
366 | const KIO::UDSEntry entry = sharedDriveToUDSEntry(sharedDrive); | ||||
367 | listEntry(entry); | ||||
368 | } | ||||
369 | | ||||
370 | auto entry = fetchSharedDrivesRootEntry(accountId, FetchEntryFlags::CurrentDir); | ||||
371 | listEntry(entry); | ||||
372 | | ||||
373 | finished(); | ||||
374 | } | ||||
375 | } | ||||
376 | | ||||
377 | bool KIOGDrive::createSharedDrive(const QUrl &url) | ||||
elvisangelaccio: Nitpick: opening brace goes to the next line | |||||
378 | { | ||||
379 | const auto gdriveUrl = GDriveUrl(url); | ||||
380 | const QString accountId = gdriveUrl.account(); | ||||
381 | | ||||
382 | DrivesPtr sharedDrive = DrivesPtr::create(); | ||||
383 | sharedDrive->setName(gdriveUrl.filename()); | ||||
384 | | ||||
elvisangelaccio: `const` | |||||
385 | const QString requestId = QUuid::createUuid().toString(); | ||||
386 | DrivesCreateJob createJob(requestId, sharedDrive, getAccount(accountId)); | ||||
387 | return runJob(createJob, url, accountId); | ||||
388 | } | ||||
389 | | ||||
Missing pass-by-reference Nitpick: opening brace goes to the next line elvisangelaccio: Missing pass-by-reference
Nitpick: opening brace goes to the next line | |||||
390 | bool KIOGDrive::deleteSharedDrive(const QUrl &url) | ||||
391 | { | ||||
392 | const auto gdriveUrl = GDriveUrl(url); | ||||
393 | const QString accountId = gdriveUrl.account(); | ||||
394 | DrivesDeleteJob sharedDriveDeleteJob(gdriveUrl.filename(), getAccount(accountId)); | ||||
395 | return runJob(sharedDriveDeleteJob, url, accountId); | ||||
396 | } | ||||
Missing pass-by-reference Nitpick: opening brace goes to the next line elvisangelaccio: Missing pass-by-reference
Nitpick: opening brace goes to the next line | |||||
397 | | ||||
398 | void KIOGDrive::statSharedDrive(const QUrl &url) | ||||
399 | { | ||||
400 | const auto gdriveUrl = GDriveUrl(url); | ||||
401 | const QString accountId = gdriveUrl.account(); | ||||
402 | DrivesFetchJob sharedDriveFetchJob(gdriveUrl.filename(), getAccount(accountId)); | ||||
403 | sharedDriveFetchJob.setFields({ | ||||
404 | Drives::Fields::Kind, | ||||
405 | Drives::Fields::Id, | ||||
406 | Drives::Fields::Name, | ||||
407 | Drives::Fields::Hidden, | ||||
408 | Drives::Fields::CreatedDate, | ||||
409 | Drives::Fields::Capabilities | ||||
elvisangelaccio: Redundant comment, info is already in the apidox of `runJob`. | |||||
410 | }); | ||||
411 | if (!runJob(sharedDriveFetchJob, url, accountId)) { | ||||
412 | return; | ||||
413 | } | ||||
elvisangelaccio: Prefer `at(0)` | |||||
414 | | ||||
415 | ObjectPtr object = sharedDriveFetchJob.items().at(0); | ||||
416 | const DrivesPtr sharedDrive = object.dynamicCast<Drives>(); | ||||
417 | const auto entry = sharedDriveToUDSEntry(sharedDrive); | ||||
418 | statEntry(entry); | ||||
419 | finished(); | ||||
420 | } | ||||
421 | | ||||
422 | KIO::UDSEntry KIOGDrive::fetchSharedDrivesRootEntry(const QString &accountId, FetchEntryFlags flags) | ||||
423 | { | ||||
424 | // Not every user is allowed to create shared Drives, | ||||
425 | // check with About resource. | ||||
426 | bool canCreateDrives = false; | ||||
427 | AboutFetchJob aboutFetch(getAccount(accountId)); | ||||
428 | aboutFetch.setFields({ | ||||
429 | About::Fields::Kind, | ||||
430 | About::Fields::CanCreateDrives | ||||
431 | }); | ||||
432 | QEventLoop eventLoop; | ||||
433 | QObject::connect(&aboutFetch, &KGAPI2::Job::finished, | ||||
434 | &eventLoop, &QEventLoop::quit); | ||||
elvisangelaccio: Can't we use `runJob()` here? | |||||
The desired behavior is silently failing if the user isn't allowed to create shared drives and being that runJob() will always call error(), it isn't used. barchiesi: The desired behavior is silently failing if the user isn't allowed to create shared drives and… | |||||
435 | eventLoop.exec(); | ||||
436 | if (aboutFetch.error() == KGAPI2::OK || aboutFetch.error() == KGAPI2::NoError) { | ||||
437 | const AboutPtr about = aboutFetch.aboutData(); | ||||
438 | if (about) { | ||||
439 | canCreateDrives = about->canCreateDrives(); | ||||
440 | } | ||||
441 | } | ||||
442 | qCDebug(GDRIVE) << "Account" << accountId << (canCreateDrives ? "can" : "can't") << "create Drives"; | ||||
443 | | ||||
444 | KIO::UDSEntry entry; | ||||
445 | | ||||
446 | if (flags == FetchEntryFlags::CurrentDir) { | ||||
447 | entry.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral(".")); | ||||
448 | } else { | ||||
449 | entry.fastInsert(KIO::UDSEntry::UDS_NAME, GDriveUrl::SharedDrivesDir); | ||||
elvisangelaccio: Nitpick: else after closing brace on previous line | |||||
450 | entry.fastInsert(KIO::UDSEntry::UDS_DISPLAY_NAME, i18n("Shared Drives")); | ||||
451 | } | ||||
452 | entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); | ||||
453 | entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 0); | ||||
454 | entry.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("folder-gdrive")); | ||||
455 | | ||||
elvisangelaccio: This comment should be just before the `if()` | |||||
456 | qlonglong udsAccess = S_IRUSR | S_IXUSR; | ||||
457 | // If user is allowed to create shared Drives, add write bit on directory | ||||
458 | if (canCreateDrives) { | ||||
459 | udsAccess |= S_IWUSR; | ||||
460 | } | ||||
461 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, udsAccess); | ||||
462 | | ||||
463 | return entry; | ||||
464 | } | ||||
465 | | ||||
322 | class RecursionDepthCounter | 466 | class RecursionDepthCounter | ||
323 | { | 467 | { | ||
324 | public: | 468 | public: | ||
325 | RecursionDepthCounter() | 469 | RecursionDepthCounter() | ||
326 | { | 470 | { | ||
327 | ++sDepth; | 471 | ++sDepth; | ||
328 | } | 472 | } | ||
329 | ~RecursionDepthCounter() | 473 | ~RecursionDepthCounter() | ||
Show All 36 Lines | 494 | { | |||
366 | const auto gdriveUrl = GDriveUrl(url); | 510 | const auto gdriveUrl = GDriveUrl(url); | ||
367 | Q_ASSERT(!gdriveUrl.isRoot()); | 511 | Q_ASSERT(!gdriveUrl.isRoot()); | ||
368 | 512 | | |||
369 | if (gdriveUrl.isAccountRoot() || gdriveUrl.isTrashDir()) { | 513 | if (gdriveUrl.isAccountRoot() || gdriveUrl.isTrashDir()) { | ||
370 | qCDebug(GDRIVE) << "Resolved" << path << "to \"root\""; | 514 | qCDebug(GDRIVE) << "Resolved" << path << "to \"root\""; | ||
371 | return rootFolderId(gdriveUrl.account()); | 515 | return rootFolderId(gdriveUrl.account()); | ||
372 | } | 516 | } | ||
373 | 517 | | |||
518 | if (gdriveUrl.isSharedDrive()) { | ||||
519 | qCDebug(GDRIVE) << "Resolved" << path << "to Shared Drive" << gdriveUrl.filename(); | ||||
520 | return gdriveUrl.filename(); | ||||
521 | } | ||||
522 | | ||||
elvisangelaccio: Nitpick: `else` not needed after `return` | |||||
523 | if (gdriveUrl.isSharedDrivesRoot()) { | ||||
524 | qCDebug(GDRIVE) << "Resolved" << path << "to Shared Drives root"; | ||||
525 | return QString(); | ||||
526 | } | ||||
527 | | ||||
374 | // Try to recursively resolve ID of parent path - either from cache, or by | 528 | // Try to recursively resolve ID of parent path - either from cache, or by | ||
375 | // querying Google | 529 | // querying Google | ||
376 | const QString parentId = resolveFileIdFromPath(gdriveUrl.parentPath(), KIOGDrive::PathIsFolder); | 530 | const QString parentId = resolveFileIdFromPath(gdriveUrl.parentPath(), KIOGDrive::PathIsFolder); | ||
377 | if (parentId.isEmpty()) { | 531 | if (parentId.isEmpty()) { | ||
378 | // We failed to resolve parent -> error | 532 | // We failed to resolve parent -> error | ||
379 | return QString(); | 533 | return QString(); | ||
380 | } | 534 | } | ||
381 | 535 | | |||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Line(s) | 599 | if (accountId == QLatin1String("new-account")) { | |||
447 | return; | 601 | return; | ||
448 | } | 602 | } | ||
449 | 603 | | |||
450 | QString folderId; | 604 | QString folderId; | ||
451 | if (gdriveUrl.isRoot()) { | 605 | if (gdriveUrl.isRoot()) { | ||
452 | listAccounts(); | 606 | listAccounts(); | ||
453 | return; | 607 | return; | ||
454 | } else if (gdriveUrl.isAccountRoot()) { | 608 | } else if (gdriveUrl.isAccountRoot()) { | ||
609 | auto entry = fetchSharedDrivesRootEntry(accountId); | ||||
610 | listEntry(entry); | ||||
455 | folderId = rootFolderId(accountId); | 611 | folderId = rootFolderId(accountId); | ||
612 | } else if (gdriveUrl.isSharedDrivesRoot()) { | ||||
613 | listSharedDrivesRoot(url); | ||||
614 | return; | ||||
456 | } else { | 615 | } else { | ||
457 | folderId = m_cache.idForPath(url.path()); | 616 | folderId = m_cache.idForPath(url.path()); | ||
458 | if (folderId.isEmpty()) { | 617 | if (folderId.isEmpty()) { | ||
459 | folderId = resolveFileIdFromPath(url.adjusted(QUrl::StripTrailingSlash).path(), | 618 | folderId = resolveFileIdFromPath(url.adjusted(QUrl::StripTrailingSlash).path(), | ||
460 | KIOGDrive::PathIsFolder); | 619 | KIOGDrive::PathIsFolder); | ||
461 | } | 620 | } | ||
462 | if (folderId.isEmpty()) { | 621 | if (folderId.isEmpty()) { | ||
463 | error(KIO::ERR_DOES_NOT_EXIST, url.path()); | 622 | error(KIO::ERR_DOES_NOT_EXIST, url.path()); | ||
Show All 33 Lines | |||||
497 | entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); | 656 | entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); | ||
498 | entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 0); | 657 | entry.fastInsert(KIO::UDSEntry::UDS_SIZE, 0); | ||
499 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH); | 658 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH); | ||
500 | listEntry(entry); | 659 | listEntry(entry); | ||
501 | 660 | | |||
502 | finished(); | 661 | finished(); | ||
503 | } | 662 | } | ||
504 | 663 | | |||
505 | | ||||
506 | void KIOGDrive::mkdir(const QUrl &url, int permissions) | 664 | void KIOGDrive::mkdir(const QUrl &url, int permissions) | ||
507 | { | 665 | { | ||
508 | // NOTE: We deliberately ignore the permissions field here, because GDrive | 666 | // NOTE: We deliberately ignore the permissions field here, because GDrive | ||
509 | // does not recognize any privileges that could be mapped to standard UNIX | 667 | // does not recognize any privileges that could be mapped to standard UNIX | ||
510 | // file permissions. | 668 | // file permissions. | ||
511 | Q_UNUSED(permissions); | 669 | Q_UNUSED(permissions); | ||
512 | 670 | | |||
513 | qCDebug(GDRIVE) << "Creating directory" << url; | 671 | qCDebug(GDRIVE) << "Creating directory" << url; | ||
514 | 672 | | |||
515 | const auto gdriveUrl = GDriveUrl(url); | 673 | const auto gdriveUrl = GDriveUrl(url); | ||
516 | const QString accountId = gdriveUrl.account(); | 674 | const QString accountId = gdriveUrl.account(); | ||
517 | // At least account and new folder name | 675 | // At least account and new folder name | ||
518 | if (gdriveUrl.isRoot() || gdriveUrl.isAccountRoot()) { | 676 | if (gdriveUrl.isRoot() || gdriveUrl.isAccountRoot()) { | ||
519 | error(KIO::ERR_DOES_NOT_EXIST, url.path()); | 677 | error(KIO::ERR_DOES_NOT_EXIST, url.path()); | ||
520 | return; | 678 | return; | ||
521 | } | 679 | } | ||
680 | | ||||
681 | if (gdriveUrl.isSharedDrive()) { | ||||
682 | qCDebug(GDRIVE) << "Directory is shared drive, creating that instead" << url; | ||||
683 | if (createSharedDrive(url)) { | ||||
684 | // runJob will have shown an error otherwise | ||||
elvisangelaccio: Typo: runJob | |||||
685 | finished(); | ||||
686 | } | ||||
687 | return; | ||||
688 | } | ||||
689 | | ||||
522 | QString parentId; | 690 | QString parentId; | ||
523 | if (gdriveUrl.isTopLevel()) { | 691 | if (gdriveUrl.isTopLevel()) { | ||
524 | parentId = rootFolderId(accountId); | 692 | parentId = rootFolderId(accountId); | ||
525 | } else { | 693 | } else { | ||
526 | parentId = resolveFileIdFromPath(gdriveUrl.parentPath(), KIOGDrive::PathIsFolder); | 694 | parentId = resolveFileIdFromPath(gdriveUrl.parentPath(), KIOGDrive::PathIsFolder); | ||
527 | } | 695 | } | ||
528 | 696 | | |||
529 | if (parentId.isEmpty()) { | 697 | if (parentId.isEmpty()) { | ||
Show All 26 Lines | 721 | if (gdriveUrl.isRoot()) { | |||
556 | return; | 724 | return; | ||
557 | } | 725 | } | ||
558 | if (gdriveUrl.isAccountRoot()) { | 726 | if (gdriveUrl.isAccountRoot()) { | ||
559 | const KIO::UDSEntry entry = accountToUDSEntry(accountId); | 727 | const KIO::UDSEntry entry = accountToUDSEntry(accountId); | ||
560 | statEntry(entry); | 728 | statEntry(entry); | ||
561 | finished(); | 729 | finished(); | ||
562 | return; | 730 | return; | ||
563 | } | 731 | } | ||
732 | if (gdriveUrl.isSharedDrivesRoot()) { | ||||
733 | qCDebug(GDRIVE) << "stat()ing Shared Drives root"; | ||||
734 | const auto entry = fetchSharedDrivesRootEntry(accountId); | ||||
735 | statEntry(entry); | ||||
736 | finished(); | ||||
737 | return; | ||||
738 | } | ||||
739 | if (gdriveUrl.isSharedDrive()) { | ||||
740 | qCDebug(GDRIVE) << "stat()ing Shared Drive" << url; | ||||
741 | statSharedDrive(url); | ||||
742 | return; | ||||
743 | } | ||||
564 | 744 | | |||
565 | const QUrlQuery urlQuery(url); | 745 | const QUrlQuery urlQuery(url); | ||
566 | const QString fileId | 746 | const QString fileId | ||
567 | = urlQuery.hasQueryItem(QStringLiteral("id")) | 747 | = urlQuery.hasQueryItem(QStringLiteral("id")) | ||
568 | ? urlQuery.queryItemValue(QStringLiteral("id")) | 748 | ? urlQuery.queryItemValue(QStringLiteral("id")) | ||
569 | : resolveFileIdFromPath(url.adjusted(QUrl::StripTrailingSlash).path(), | 749 | : resolveFileIdFromPath(url.adjusted(QUrl::StripTrailingSlash).path(), | ||
570 | KIOGDrive::None); | 750 | KIOGDrive::None); | ||
571 | if (fileId.isEmpty()) { | 751 | if (fileId.isEmpty()) { | ||
572 | error(KIO::ERR_DOES_NOT_EXIST, url.path()); | 752 | error(KIO::ERR_DOES_NOT_EXIST, url.path()); | ||
573 | return; | 753 | return; | ||
574 | } | 754 | } | ||
575 | 755 | | |||
576 | FileFetchJob fileFetchJob(fileId, getAccount(accountId)); | 756 | FileFetchJob fileFetchJob(fileId, getAccount(accountId)); | ||
577 | if (!runJob(fileFetchJob, url, accountId)) { | 757 | if (!runJob(fileFetchJob, url, accountId)) { | ||
758 | qCDebug(GDRIVE) << "Failed stat()ing file" << fileFetchJob.errorString(); | ||||
578 | return; | 759 | return; | ||
579 | } | 760 | } | ||
580 | 761 | | |||
581 | const ObjectsList objects = fileFetchJob.items(); | 762 | const ObjectsList objects = fileFetchJob.items(); | ||
582 | if (objects.count() != 1) { | 763 | if (objects.count() != 1) { | ||
583 | error(KIO::ERR_DOES_NOT_EXIST, url.path()); | 764 | error(KIO::ERR_DOES_NOT_EXIST, url.path()); | ||
584 | return; | 765 | return; | ||
585 | } | 766 | } | ||
▲ Show 20 Lines • Show All 235 Lines • ▼ Show 20 Line(s) | 1001 | { | |||
821 | // NOTE: We deliberately ignore the permissions field here, because GDrive | 1002 | // NOTE: We deliberately ignore the permissions field here, because GDrive | ||
822 | // does not recognize any privileges that could be mapped to standard UNIX | 1003 | // does not recognize any privileges that could be mapped to standard UNIX | ||
823 | // file permissions. | 1004 | // file permissions. | ||
824 | Q_UNUSED(permissions) | 1005 | Q_UNUSED(permissions) | ||
825 | Q_UNUSED(flags) | 1006 | Q_UNUSED(flags) | ||
826 | 1007 | | |||
827 | qCDebug(GDRIVE) << Q_FUNC_INFO << url; | 1008 | qCDebug(GDRIVE) << Q_FUNC_INFO << url; | ||
828 | 1009 | | |||
1010 | const auto gdriveUrl = GDriveUrl(url); | ||||
1011 | | ||||
1012 | if (gdriveUrl.isSharedDrive()) { | ||||
1013 | qCDebug(GDRIVE) << "Can't create files in Shared Drives root" << url; | ||||
1014 | error(KIO::ERR_CANNOT_WRITE, url.path()); | ||||
1015 | return; | ||||
1016 | } | ||||
1017 | | ||||
829 | if (QUrlQuery(url).hasQueryItem(QStringLiteral("id"))) { | 1018 | if (QUrlQuery(url).hasQueryItem(QStringLiteral("id"))) { | ||
830 | if (!putUpdate(url)) { | 1019 | if (!putUpdate(url)) { | ||
831 | return; | 1020 | return; | ||
832 | } | 1021 | } | ||
833 | } else { | 1022 | } else { | ||
834 | if (!putCreate(url)) { | 1023 | if (!putCreate(url)) { | ||
835 | return; | 1024 | return; | ||
836 | } | 1025 | } | ||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Line(s) | 1122 | { | |||
938 | 1127 | | |||
939 | // FIXME: Because of the above, we are not really deleting the file, but only | 1128 | // FIXME: Because of the above, we are not really deleting the file, but only | ||
940 | // moving it to trash - so if users really really really wants to delete the | 1129 | // moving it to trash - so if users really really really wants to delete the | ||
941 | // file, they have to go to GDrive web interface and delete it there. I think | 1130 | // file, they have to go to GDrive web interface and delete it there. I think | ||
942 | // that we should do the DELETE operation here, because for trash people have | 1131 | // that we should do the DELETE operation here, because for trash people have | ||
943 | // their local trashes. This however requires fixing the first FIXME first, | 1132 | // their local trashes. This however requires fixing the first FIXME first, | ||
944 | // otherwise we are risking severe data loss. | 1133 | // otherwise we are risking severe data loss. | ||
945 | 1134 | | |||
1135 | const auto gdriveUrl = GDriveUrl(url); | ||||
1136 | | ||||
1137 | // Trying to delete the Team Drive root is pointless | ||||
1138 | if (gdriveUrl.isSharedDrivesRoot()) { | ||||
1139 | qCDebug(GDRIVE) << "Tried deleting Shared Drives root."; | ||||
1140 | error(KIO::ERR_SLAVE_DEFINED, i18n("Can't delete Shared Drives root.")); | ||||
1141 | return; | ||||
1142 | } | ||||
1143 | | ||||
946 | qCDebug(GDRIVE) << "Deleting URL" << url << "- is it a file?" << isfile; | 1144 | qCDebug(GDRIVE) << "Deleting URL" << url << "- is it a file?" << isfile; | ||
947 | 1145 | | |||
948 | const QUrlQuery urlQuery(url); | 1146 | const QUrlQuery urlQuery(url); | ||
949 | const QString fileId | 1147 | const QString fileId | ||
950 | = isfile && urlQuery.hasQueryItem(QStringLiteral("id")) | 1148 | = isfile && urlQuery.hasQueryItem(QStringLiteral("id")) | ||
951 | ? urlQuery.queryItemValue(QStringLiteral("id")) | 1149 | ? urlQuery.queryItemValue(QStringLiteral("id")) | ||
952 | : resolveFileIdFromPath(url.adjusted(QUrl::StripTrailingSlash).path(), | 1150 | : resolveFileIdFromPath(url.adjusted(QUrl::StripTrailingSlash).path(), | ||
953 | isfile ? KIOGDrive::PathIsFile : KIOGDrive::PathIsFolder); | 1151 | isfile ? KIOGDrive::PathIsFile : KIOGDrive::PathIsFolder); | ||
954 | if (fileId.isEmpty()) { | 1152 | if (fileId.isEmpty()) { | ||
955 | error(KIO::ERR_DOES_NOT_EXIST, url.path()); | 1153 | error(KIO::ERR_DOES_NOT_EXIST, url.path()); | ||
956 | return; | 1154 | return; | ||
957 | } | 1155 | } | ||
958 | const auto gdriveUrl = GDriveUrl(url); | | |||
959 | const QString accountId = gdriveUrl.account(); | 1156 | const QString accountId = gdriveUrl.account(); | ||
960 | 1157 | | |||
961 | // If user tries to delete the account folder, remove the account from the keychain | 1158 | // If user tries to delete the account folder, remove the account from the keychain | ||
962 | if (gdriveUrl.isAccountRoot()) { | 1159 | if (gdriveUrl.isAccountRoot()) { | ||
963 | const KGAPI2::AccountPtr account = getAccount(accountId); | 1160 | const KGAPI2::AccountPtr account = getAccount(accountId); | ||
964 | if (account->accountName().isEmpty()) { | 1161 | if (account->accountName().isEmpty()) { | ||
965 | error(KIO::ERR_DOES_NOT_EXIST, accountId); | 1162 | error(KIO::ERR_DOES_NOT_EXIST, accountId); | ||
966 | return; | 1163 | return; | ||
967 | } | 1164 | } | ||
968 | m_accountManager->removeAccount(accountId); | 1165 | m_accountManager->removeAccount(accountId); | ||
969 | finished(); | 1166 | finished(); | ||
970 | return; | 1167 | return; | ||
971 | } | 1168 | } | ||
972 | 1169 | | |||
1170 | if (gdriveUrl.isSharedDrive()) { | ||||
1171 | qCDebug(GDRIVE) << "Deleting Shared Drive" << url; | ||||
1172 | if (deleteSharedDrive(url)) { | ||||
1173 | // error( will have been called in case of error | ||||
elvisangelaccio: "error() will have been called in case of error" | |||||
1174 | finished(); | ||||
1175 | } | ||||
1176 | return; | ||||
1177 | } | ||||
1178 | | ||||
973 | // GDrive allows us to delete entire directory even when it's not empty, | 1179 | // GDrive allows us to delete entire directory even when it's not empty, | ||
974 | // so we need to emulate the normal behavior ourselves by checking number of | 1180 | // so we need to emulate the normal behavior ourselves by checking number of | ||
975 | // child references | 1181 | // child references | ||
976 | if (!isfile) { | 1182 | if (!isfile) { | ||
977 | ChildReferenceFetchJob referencesFetch(fileId, getAccount(accountId)); | 1183 | ChildReferenceFetchJob referencesFetch(fileId, getAccount(accountId)); | ||
978 | if (!runJob(referencesFetch, url, accountId)) { | 1184 | if (!runJob(referencesFetch, url, accountId)) { | ||
979 | return; | 1185 | return; | ||
980 | } | 1186 | } | ||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Line(s) | 1229 | = urlQuery.hasQueryItem(QStringLiteral("id")) | |||
1024 | ? urlQuery.queryItemValue(QStringLiteral("id")) | 1230 | ? urlQuery.queryItemValue(QStringLiteral("id")) | ||
1025 | : resolveFileIdFromPath(src.adjusted(QUrl::StripTrailingSlash).path(), | 1231 | : resolveFileIdFromPath(src.adjusted(QUrl::StripTrailingSlash).path(), | ||
1026 | KIOGDrive::PathIsFile); | 1232 | KIOGDrive::PathIsFile); | ||
1027 | if (sourceFileId.isEmpty()) { | 1233 | if (sourceFileId.isEmpty()) { | ||
1028 | error(KIO::ERR_DOES_NOT_EXIST, src.path()); | 1234 | error(KIO::ERR_DOES_NOT_EXIST, src.path()); | ||
1029 | return; | 1235 | return; | ||
1030 | } | 1236 | } | ||
1031 | 1237 | | |||
1238 | if (srcGDriveUrl.isSharedDrive()) { | ||||
1239 | qCDebug(GDRIVE) << "Renaming Shared Drive" << srcGDriveUrl.filename() << "to" << destGDriveUrl.filename(); | ||||
1240 | DrivesPtr drives = DrivesPtr::create(); | ||||
1241 | drives->setId(sourceFileId); | ||||
1242 | drives->setName(destGDriveUrl.filename()); | ||||
1243 | | ||||
1244 | DrivesModifyJob modifyJob(drives, getAccount(sourceAccountId)); | ||||
1245 | if (!runJob(modifyJob, src, sourceAccountId)) { | ||||
1246 | return; | ||||
elvisangelaccio: `runJob` already called `error()` here, no? | |||||
1247 | } | ||||
1248 | | ||||
1249 | finished(); | ||||
1250 | return; | ||||
1251 | } | ||||
1252 | | ||||
1032 | // We need to fetch ALL, so that we can do update later | 1253 | // We need to fetch ALL, so that we can do update later | ||
1033 | FileFetchJob sourceFileFetchJob(sourceFileId, getAccount(sourceAccountId)); | 1254 | FileFetchJob sourceFileFetchJob(sourceFileId, getAccount(sourceAccountId)); | ||
1034 | if (!runJob(sourceFileFetchJob, src, sourceAccountId)) { | 1255 | if (!runJob(sourceFileFetchJob, src, sourceAccountId)) { | ||
1035 | return; | 1256 | return; | ||
1036 | } | 1257 | } | ||
1037 | 1258 | | |||
1038 | const ObjectsList objects = sourceFileFetchJob.items(); | 1259 | const ObjectsList objects = sourceFileFetchJob.items(); | ||
1039 | if (objects.count() != 1) { | 1260 | if (objects.count() != 1) { | ||
▲ Show 20 Lines • Show All 86 Lines • Show Last 20 Lines |
Please keep the list of includes sorted.