diff --git a/kdirshare/filepropertiesplugin/kdirshareplugin.cpp b/kdirshare/filepropertiesplugin/kdirshareplugin.cpp index 6f1139cf..4be8e451 100644 --- a/kdirshare/filepropertiesplugin/kdirshareplugin.cpp +++ b/kdirshare/filepropertiesplugin/kdirshareplugin.cpp @@ -60,9 +60,11 @@ KDirSharePlugin::KDirSharePlugin(QObject *parent, const QList &args) kWarning() << "Invalid kdirshare module reply for isShared()"; m_ui.sharebox->setChecked(false); m_ui.portgroup->setEnabled(false); + m_ui.authgroup->setEnabled(false); } else { m_ui.sharebox->setChecked(kdirsharereply.value()); m_ui.portgroup->setEnabled(kdirsharereply.value()); + m_ui.authgroup->setEnabled(kdirsharereply.value()); } QDBusReply kdirsharereply2 = m_kdirshareiface.call("getPortMin", m_url); @@ -82,16 +84,40 @@ KDirSharePlugin::KDirSharePlugin(QObject *parent, const QList &args) const bool randomport = (m_ui.portmininput->value() != m_ui.portmaxinput->value()); m_ui.randombox->setChecked(randomport); m_ui.portmininput->setVisible(randomport); + + QDBusReply kdirsharereply3 = m_kdirshareiface.call("getUser", m_url); + if (!kdirsharereply3.isValid()) { + kWarning() << "Invalid kdirshare module reply for getUser()"; + m_ui.useredit->setText(QString()); + } else { + m_ui.useredit->setText(kdirsharereply3.value()); + } + kdirsharereply3 = m_kdirshareiface.call("getPassword", m_url); + if (!kdirsharereply3.isValid()) { + kWarning() << "Invalid kdirshare module reply for getPassword()"; + m_ui.passwordedit->setText(QString()); + } else { + m_ui.passwordedit->setText(kdirsharereply3.value()); + } + if (!m_ui.useredit->text().isEmpty() || !m_ui.passwordedit->text().isEmpty()) { + m_ui.authbox->setChecked(true); + } + m_ui.useredit->setEnabled(m_ui.authbox->isChecked()); + m_ui.passwordedit->setEnabled(m_ui.authbox->isChecked()); } else { kWarning() << "kdirshare module interface is not valid"; m_ui.sharebox->setEnabled(false); m_ui.portgroup->setEnabled(false); + m_ui.authgroup->setEnabled(false); } connect(m_ui.sharebox, SIGNAL(toggled(bool)), this, SLOT(slotShare(bool))); connect(m_ui.randombox, SIGNAL(toggled(bool)), this, SLOT(slotRandomPort(bool))); connect(m_ui.portmininput, SIGNAL(valueChanged(int)), this, SLOT(slotPortMin(int))); connect(m_ui.portmaxinput, SIGNAL(valueChanged(int)), this, SLOT(slotPortMax(int))); + connect(m_ui.authbox, SIGNAL(toggled(bool)), this, SLOT(slotAuthorization(bool))); + connect(m_ui.useredit, SIGNAL(textEdited(QString)), this, SLOT(slotUserEdited(QString))); + connect(m_ui.passwordedit, SIGNAL(textEdited(QString)), this, SLOT(slotPasswordEdited(QString))); } KDirSharePlugin::~KDirSharePlugin() @@ -106,7 +132,8 @@ void KDirSharePlugin::applyChanges() if (m_ui.sharebox->isChecked()) { kdirsharereply = m_kdirshareiface.call("share", m_url, - uint(m_ui.portmininput->value()), uint(m_ui.portmaxinput->value()) + uint(m_ui.portmininput->value()), uint(m_ui.portmaxinput->value()), + m_ui.useredit->text(), m_ui.passwordedit->text() ); } else { kdirsharereply = m_kdirshareiface.call("unshare", m_url); @@ -126,6 +153,7 @@ void KDirSharePlugin::slotShare(const bool value) { // qDebug() << Q_FUNC_INFO << value; m_ui.portgroup->setEnabled(value); + m_ui.authgroup->setEnabled(value); emit changed(); } @@ -157,4 +185,28 @@ void KDirSharePlugin::slotPortMax(const int value) emit changed(); } +void KDirSharePlugin::slotAuthorization(const bool value) +{ + // qDebug() << Q_FUNC_INFO << value; + m_ui.useredit->setEnabled(value); + m_ui.passwordedit->setEnabled(value); + if (!value) { + m_ui.useredit->clear(); + m_ui.passwordedit->clear(); + } + emit changed(); +} + +void KDirSharePlugin::slotUserEdited(const QString &value) +{ + // qDebug() << Q_FUNC_INFO << value; + emit changed(); +} + +void KDirSharePlugin::slotPasswordEdited(const QString &value) +{ + // qDebug() << Q_FUNC_INFO << value; + emit changed(); +} + #include "moc_kdirshareplugin.cpp" diff --git a/kdirshare/filepropertiesplugin/kdirshareplugin.h b/kdirshare/filepropertiesplugin/kdirshareplugin.h index 56906f91..a57a925f 100644 --- a/kdirshare/filepropertiesplugin/kdirshareplugin.h +++ b/kdirshare/filepropertiesplugin/kdirshareplugin.h @@ -38,6 +38,9 @@ private Q_SLOTS: void slotRandomPort(const bool value); void slotPortMin(const int value); void slotPortMax(const int value); + void slotAuthorization(const bool value); + void slotUserEdited(const QString &value); + void slotPasswordEdited(const QString &value); private: Ui_KDirShareUI m_ui; diff --git a/kdirshare/filepropertiesplugin/kdirshareplugin.ui b/kdirshare/filepropertiesplugin/kdirshareplugin.ui index 682451a6..8f28b3c2 100644 --- a/kdirshare/filepropertiesplugin/kdirshareplugin.ui +++ b/kdirshare/filepropertiesplugin/kdirshareplugin.ui @@ -71,6 +71,46 @@ + + + + Authentication + + + + + + Password: + + + + + + + User: + + + + + + + + + + QLineEdit::Password + + + + + + + Require authentication + + + + + + diff --git a/kdirshare/kded/CMakeLists.txt b/kdirshare/kded/CMakeLists.txt index a103e083..cac8be5e 100644 --- a/kdirshare/kded/CMakeLists.txt +++ b/kdirshare/kded/CMakeLists.txt @@ -14,6 +14,7 @@ target_link_libraries(kded_kdirshare PRIVATE ${KDE4_KDEUI_LIBS} ${KDE4_KHTTP_LIBS} ${KDE4_KDNSSD_LIBS} + ${KDE4_KPASSWDSTORE_LIBS} ) if(OPENSSL_FOUND) diff --git a/kdirshare/kded/kded_kdirshare.cpp b/kdirshare/kded/kded_kdirshare.cpp index f6b4ca6f..d86a71f1 100644 --- a/kdirshare/kded/kded_kdirshare.cpp +++ b/kdirshare/kded/kded_kdirshare.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -52,10 +53,14 @@ public: KDirShareThread(QObject *parent = nullptr); ~KDirShareThread(); - QString serve(const QString &dirpath, const quint16 portmin, const quint16 portmax); + QString serve(const QString &dirpath, + const quint16 portmin, const quint16 portmax, + const QString &username, const QString &password); QString directory() const; quint16 portMin() const; quint16 portMax() const; + QString user() const; + QString password() const; Q_SIGNALS: void unblock(); @@ -75,6 +80,8 @@ private: quint16 m_port; quint16 m_portmin; quint16 m_portmax; + QString m_user; + QString m_password; QString m_error; }; @@ -119,6 +126,16 @@ quint16 KDirShareThread::portMax() const return m_portmax; } +QString KDirShareThread::user() const +{ + return m_user; +} + +QString KDirShareThread::password() const +{ + return m_password; +} + void KDirShareThread::run() { if (!m_kdirshareimpl->setDirectory(m_directory)) { @@ -126,6 +143,13 @@ void KDirShareThread::run() emit unblock(); return; } + if (!m_user.isEmpty() && !m_password.isEmpty()) { + if (!m_kdirshareimpl->setAuthenticate(m_user.toUtf8(), m_password.toUtf8(), i18n("Not authorized"))) { + emit serveError(i18n("Could not set authentication: %1", m_kdirshareimpl->errorString())); + emit unblock(); + return; + } + } if (!m_kdirshareimpl->serve(QHostAddress(QHostAddress::Any), m_port)) { emit serveError(i18n("Could not serve: %1", m_kdirshareimpl->errorString())); emit unblock(); @@ -140,13 +164,17 @@ void KDirShareThread::run() emit unblock(); } -QString KDirShareThread::serve(const QString &dirpath, const quint16 portmin, const quint16 portmax) +QString KDirShareThread::serve(const QString &dirpath, + const quint16 portmin, const quint16 portmax, + const QString &username, const QString &password) { // qDebug() << Q_FUNC_INFO << dirpath << port; m_directory = dirpath; m_port = getPort(portmin, portmax); m_portmin = portmin; m_portmax = portmax; + m_user = username; + m_password = password; m_starting = true; m_error.clear(); start(); @@ -174,35 +202,9 @@ K_EXPORT_PLUGIN(KDirShareModuleFactory("kdirshare")) KDirShareModule::KDirShareModule(QObject *parent, const QList&) : KDEDModule(parent) { - bool shareerror = false; - KConfig kdirshareconfig("kdirsharerc", KConfig::SimpleConfig); - foreach (const QString &kdirsharekey, kdirshareconfig.groupList()) { - // qDebug() << Q_FUNC_INFO << kdirsharekey; - KConfigGroup kdirsharegroup = kdirshareconfig.group(kdirsharekey); - const QString kdirsharedirpath = kdirsharegroup.readEntry("dirpath", QString()); - if (kdirsharedirpath.isEmpty()) { - continue; - } - const uint kdirshareportmin = kdirsharegroup.readEntry("portmin", uint(s_kdirshareportmin)); - const uint kdirshareportmax = kdirsharegroup.readEntry("portmax", uint(s_kdirshareportmax)); - // qDebug() << Q_FUNC_INFO << kdirsharekey << kdirsharedirpath << kdirshareportmin << kdirshareportmax; - const QString kdirshareerror = share( - kdirsharedirpath, - quint16(kdirshareportmin), quint16(kdirshareportmax) - ); - if (!kdirshareerror.isEmpty()) { - kWarning() << kdirshareerror; - shareerror = true; - } - } - - if (shareerror) { - KNotification *knotification = new KNotification("ShareError"); - knotification->setComponentData(KComponentData("kdirshare")); - knotification->setTitle(i18n("Directory share")); - knotification->setText(i18n("Unable to share one or more directories")); - knotification->sendEvent(); - } + m_passwdstore.setStoreID("KDirShare"); + // HACK: kpasswdstore uses on-demand service so doing delayed restore + QTimer::singleShot(2000, this, SLOT(slotDelayedRestore())); } KDirShareModule::~KDirShareModule() @@ -215,12 +217,15 @@ KDirShareModule::~KDirShareModule() kdirsharegroup.writeEntry("dirpath", kdirsharethread->directory()); kdirsharegroup.writeEntry("portmin", uint(kdirsharethread->portMin())); kdirsharegroup.writeEntry("portmax", uint(kdirsharethread->portMax())); + kdirsharegroup.writeEntry("user", kdirsharethread->user()); } qDeleteAll(m_dirshares); m_dirshares.clear(); } -QString KDirShareModule::share(const QString &dirpath, const uint portmin, const uint portmax) +QString KDirShareModule::share(const QString &dirpath, + const uint portmin, const uint portmax, + const QString &username, const QString &password) { if (isShared(dirpath)) { const QString unshareerror = unshare(dirpath); @@ -231,7 +236,14 @@ QString KDirShareModule::share(const QString &dirpath, const uint portmin, const KDirShareThread *kdirsharethread = new KDirShareThread(this); // qDebug() << Q_FUNC_INFO << dirpath << portmin << portmax; - const QString serveerror = kdirsharethread->serve(dirpath, portmin, portmax); + const QString serveerror = kdirsharethread->serve( + dirpath, + portmin, portmax, + username, password + ); + if (!username.isEmpty() && !password.isEmpty()) { + m_passwdstore.storePasswd(KPasswdStore::makeKey(dirpath), password); + } if (!serveerror.isEmpty()) { delete kdirsharethread; return serveerror; @@ -287,4 +299,84 @@ quint16 KDirShareModule::getPortMax(const QString &dirpath) const return s_kdirshareportmax; } +QString KDirShareModule::getUser(const QString &dirpath) const +{ + foreach (const KDirShareThread *kdirsharethread, m_dirshares) { + if (kdirsharethread->directory() == dirpath) { + return kdirsharethread->user(); + } + } + return QString(); +} + +QString KDirShareModule::getPassword(const QString &dirpath) const +{ + foreach (const KDirShareThread *kdirsharethread, m_dirshares) { + if (kdirsharethread->directory() == dirpath) { + return kdirsharethread->password(); + } + } + return QString(); +} + +void KDirShareModule::slotDelayedRestore() +{ + bool requiresauth = false; + KConfig kdirshareconfig("kdirsharerc", KConfig::SimpleConfig); + foreach (const QString &kdirsharekey, kdirshareconfig.groupList()) { + // qDebug() << Q_FUNC_INFO << kdirsharekey; + KConfigGroup kdirsharegroup = kdirshareconfig.group(kdirsharekey); + const QString kdirsharedirpath = kdirsharegroup.readEntry("dirpath", QString()); + if (kdirsharedirpath.isEmpty()) { + continue; + } + const QString kdirshareuser = kdirsharegroup.readEntry("user", QString()); + if (!kdirshareuser.isEmpty()) { + requiresauth = true; + break; + } + } + if (requiresauth) { + if (!m_passwdstore.openStore()) { + KNotification *knotification = new KNotification("AuthError"); + knotification->setComponentData(KComponentData("kdirshare")); + knotification->setTitle(i18n("Directory share")); + knotification->setText(i18n("Authorization is required but could not open password store")); + knotification->sendEvent(); + return; + } + } + + bool shareerror = false; + foreach (const QString &kdirsharekey, kdirshareconfig.groupList()) { + // qDebug() << Q_FUNC_INFO << kdirsharekey; + KConfigGroup kdirsharegroup = kdirshareconfig.group(kdirsharekey); + const QString kdirsharedirpath = kdirsharegroup.readEntry("dirpath", QString()); + if (kdirsharedirpath.isEmpty()) { + continue; + } + const uint kdirshareportmin = kdirsharegroup.readEntry("portmin", uint(s_kdirshareportmin)); + const uint kdirshareportmax = kdirsharegroup.readEntry("portmax", uint(s_kdirshareportmax)); + const QString kdirshareuser = kdirsharegroup.readEntry("user", QString()); + const QString kdirsharepassword = m_passwdstore.getPasswd(KPasswdStore::makeKey(kdirsharedirpath)); + // qDebug() << Q_FUNC_INFO << kdirsharekey << kdirsharedirpath << kdirshareportmin << kdirshareportmax; + const QString kdirshareerror = share( + kdirsharedirpath, + quint16(kdirshareportmin), quint16(kdirshareportmax), + kdirshareuser, kdirsharepassword + ); + if (!kdirshareerror.isEmpty()) { + kWarning() << kdirshareerror; + shareerror = true; + } + } + if (shareerror) { + KNotification *knotification = new KNotification("ShareError"); + knotification->setComponentData(KComponentData("kdirshare")); + knotification->setTitle(i18n("Directory share")); + knotification->setText(i18n("Unable to share one or more directories")); + knotification->sendEvent(); + } +} + #include "kded_kdirshare.moc" diff --git a/kdirshare/kded/kded_kdirshare.h b/kdirshare/kded/kded_kdirshare.h index 10692b05..7e52a947 100644 --- a/kdirshare/kded/kded_kdirshare.h +++ b/kdirshare/kded/kded_kdirshare.h @@ -23,6 +23,7 @@ #include #include +#include class KDirShareThread; @@ -36,16 +37,24 @@ public: ~KDirShareModule(); public Q_SLOTS: - Q_SCRIPTABLE QString share(const QString &dirpath, const uint portmin, const uint portmax); + Q_SCRIPTABLE QString share(const QString &dirpath, + const uint portmin, const uint portmax, + const QString &username, const QString &password); Q_SCRIPTABLE QString unshare(const QString &dirpath); Q_SCRIPTABLE bool isShared(const QString &dirpath) const; Q_SCRIPTABLE quint16 getPortMin(const QString &dirpath) const; Q_SCRIPTABLE quint16 getPortMax(const QString &dirpath) const; + Q_SCRIPTABLE QString getUser(const QString &dirpath) const; + Q_SCRIPTABLE QString getPassword(const QString &dirpath) const; + +private Q_SLOTS: + void slotDelayedRestore(); private: QList m_dirshares; + KPasswdStore m_passwdstore; }; #endif // KDIRSHARE_KDED_H diff --git a/kdirshare/kded/kdirshareimpl.cpp b/kdirshare/kded/kdirshareimpl.cpp index d32301d1..db0a0b35 100644 --- a/kdirshare/kded/kdirshareimpl.cpp +++ b/kdirshare/kded/kdirshareimpl.cpp @@ -148,11 +148,6 @@ KDirShareImpl::~KDirShareImpl() stop(); } -QString KDirShareImpl::directory() const -{ - return m_directory; -} - bool KDirShareImpl::setDirectory(const QString &dirpath) { if (!QDir(dirpath).exists()) { diff --git a/kdirshare/kded/kdirshareimpl.h b/kdirshare/kded/kdirshareimpl.h index c5b10d95..6f2dc6b9 100644 --- a/kdirshare/kded/kdirshareimpl.h +++ b/kdirshare/kded/kdirshareimpl.h @@ -29,7 +29,6 @@ public: KDirShareImpl(QObject *parent = nullptr); ~KDirShareImpl(); - QString directory() const; bool setDirectory(const QString &dirpath); bool serve(const QHostAddress &address, const quint16 port); bool publish(); diff --git a/kdirshare/kdirshare.notifyrc b/kdirshare/kdirshare.notifyrc index c901f795..7d527bd9 100644 --- a/kdirshare/kdirshare.notifyrc +++ b/kdirshare/kdirshare.notifyrc @@ -3,6 +3,12 @@ Name=kdirshare Comment=Directory share IconName=network-server +[Event/AuthError] +Name=Authorization is required but could not open password store +Action=Sound|Popup +Sound=KDE-Sys-App-Error-Serious.ogg +IconName=dialog-error + [Event/ShareError] Name=Unable to share one or more directories Action=Sound|Popup