File indexing completed on 2024-09-29 04:26:14
0001 /** 0002 * SPDX-FileCopyrightText: 2014 Samoilenko Yuri <kinnalru@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "sftpplugin.h" 0008 0009 #include <QDBusConnection> 0010 #include <QDebug> 0011 #include <QDir> 0012 #include <QStandardPaths> 0013 0014 #include <KIO/OpenUrlJob> 0015 #include <KLocalizedString> 0016 #include <KNotification> 0017 #include <KNotificationJobUiDelegate> 0018 #include <KPluginFactory> 0019 0020 #include "mounter.h" 0021 #include "plugin_sftp_debug.h" 0022 0023 K_PLUGIN_CLASS_WITH_JSON(SftpPlugin, "kdeconnect_sftp.json") 0024 0025 SftpPlugin::SftpPlugin(QObject *parent, const QVariantList &args) 0026 : KdeConnectPlugin(parent, args) 0027 , deviceId(device()->id()) 0028 , m_mounter(nullptr) 0029 { 0030 addToDolphin(); 0031 qCDebug(KDECONNECT_PLUGIN_SFTP) << "Created device:" << device()->name(); 0032 } 0033 0034 SftpPlugin::~SftpPlugin() 0035 { 0036 removeFromDolphin(); 0037 unmount(); 0038 } 0039 0040 void SftpPlugin::addToDolphin() 0041 { 0042 removeFromDolphin(); 0043 0044 QUrl kioUrl(QStringLiteral("kdeconnect://") + deviceId + QStringLiteral("/")); 0045 m_placesModel.addPlace(device()->name(), kioUrl, QStringLiteral("kdeconnect")); 0046 qCDebug(KDECONNECT_PLUGIN_SFTP) << "add to dolphin"; 0047 } 0048 0049 void SftpPlugin::removeFromDolphin() 0050 { 0051 QUrl kioUrl(QStringLiteral("kdeconnect://") + deviceId + QStringLiteral("/")); 0052 for (int i = 0; i < m_placesModel.rowCount(); ++i) { 0053 QModelIndex index = m_placesModel.index(i, 0); 0054 QUrl url = m_placesModel.url(index); 0055 if (url == kioUrl) { 0056 m_placesModel.removePlace(index); 0057 --i; 0058 } 0059 } 0060 } 0061 0062 void SftpPlugin::mount() 0063 { 0064 qCDebug(KDECONNECT_PLUGIN_SFTP) << "Mount device:" << device()->name(); 0065 if (m_mounter) { 0066 return; 0067 } 0068 0069 m_mounter = new Mounter(this); 0070 connect(m_mounter, &Mounter::mounted, this, &SftpPlugin::onMounted); 0071 connect(m_mounter, &Mounter::unmounted, this, &SftpPlugin::onUnmounted); 0072 connect(m_mounter, &Mounter::failed, this, &SftpPlugin::onFailed); 0073 } 0074 0075 void SftpPlugin::unmount() 0076 { 0077 if (m_mounter) { 0078 m_mounter->deleteLater(); 0079 m_mounter = nullptr; 0080 } 0081 } 0082 0083 bool SftpPlugin::mountAndWait() 0084 { 0085 mount(); 0086 return m_mounter->wait(); 0087 } 0088 0089 bool SftpPlugin::isMounted() const 0090 { 0091 return m_mounter && m_mounter->isMounted(); 0092 } 0093 0094 QString SftpPlugin::getMountError() 0095 { 0096 if (!mountError.isEmpty()) { 0097 return mountError; 0098 } 0099 return QString(); 0100 } 0101 0102 bool SftpPlugin::startBrowsing() 0103 { 0104 if (mountAndWait()) { 0105 auto *job = new KIO::OpenUrlJob(QUrl(QStringLiteral("kdeconnect://") + deviceId)); 0106 job->setUiDelegate(new KNotificationJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled)); 0107 job->start(); 0108 return true; 0109 } 0110 return false; 0111 } 0112 0113 void SftpPlugin::receivePacket(const NetworkPacket &np) 0114 { 0115 static const QSet<QString> fields_c{QStringLiteral("user"), QStringLiteral("port"), QStringLiteral("path")}; 0116 const QStringList keysList = np.body().keys(); 0117 const auto keys = QSet(keysList.begin(), keysList.end()); 0118 if (!(fields_c - keys).isEmpty() && !np.has(QStringLiteral("errorMessage"))) { 0119 qCWarning(KDECONNECT_PLUGIN_SFTP) << "Invalid sftp packet received"; 0120 return; 0121 } 0122 0123 m_mounter->onPacketReceived(np); 0124 0125 remoteDirectories.clear(); 0126 if (np.has(QStringLiteral("multiPaths"))) { 0127 QStringList paths = np.get<QStringList>(QStringLiteral("multiPaths"), QStringList()); 0128 QStringList names = np.get<QStringList>(QStringLiteral("pathNames"), QStringList()); 0129 int size = qMin<int>(names.size(), paths.size()); 0130 for (int i = 0; i < size; i++) { 0131 remoteDirectories.insert(mountPoint() + paths.at(i), names.at(i)); 0132 } 0133 } else { 0134 remoteDirectories.insert(mountPoint(), i18n("All files")); 0135 remoteDirectories.insert(mountPoint() + QStringLiteral("/DCIM/Camera"), i18n("Camera pictures")); 0136 } 0137 } 0138 0139 QString SftpPlugin::mountPoint() 0140 { 0141 QString runtimePath = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); 0142 if (runtimePath.isEmpty()) { 0143 runtimePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation); 0144 } 0145 return QDir(runtimePath).absoluteFilePath(deviceId); 0146 } 0147 0148 void SftpPlugin::onMounted() 0149 { 0150 qCDebug(KDECONNECT_PLUGIN_SFTP) << device()->name() << QStringLiteral("Remote filesystem mounted at %1").arg(mountPoint()); 0151 0152 Q_EMIT mounted(); 0153 } 0154 0155 void SftpPlugin::onUnmounted() 0156 { 0157 qCDebug(KDECONNECT_PLUGIN_SFTP) << device()->name() << "Remote filesystem unmounted"; 0158 0159 unmount(); 0160 0161 Q_EMIT unmounted(); 0162 } 0163 0164 void SftpPlugin::onFailed(const QString &message) 0165 { 0166 mountError = message; 0167 KNotification::event(KNotification::Error, device()->name(), message); 0168 0169 unmount(); 0170 0171 Q_EMIT unmounted(); 0172 } 0173 0174 QVariantMap SftpPlugin::getDirectories() 0175 { 0176 return remoteDirectories; 0177 } 0178 0179 #include "moc_sftpplugin.cpp" 0180 #include "sftpplugin.moc"