2022-05-09 15:35:44 +03:00
|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License version 2, as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "kded_kdirshare.h"
|
2022-05-11 20:16:45 +03:00
|
|
|
#include "kdirshare.h"
|
2022-05-09 15:35:44 +03:00
|
|
|
|
2022-05-11 15:59:26 +03:00
|
|
|
#include <QThread>
|
|
|
|
#include <QCoreApplication>
|
2022-05-09 15:35:44 +03:00
|
|
|
#include <klocale.h>
|
2022-05-09 23:39:06 +03:00
|
|
|
#include <kconfiggroup.h>
|
2022-05-09 22:15:16 +03:00
|
|
|
#include <knotification.h>
|
2022-05-09 15:35:44 +03:00
|
|
|
#include <kpluginfactory.h>
|
2022-05-09 19:04:29 +03:00
|
|
|
#include <kdebug.h>
|
2022-05-09 15:35:44 +03:00
|
|
|
|
2022-05-11 20:16:45 +03:00
|
|
|
static quint16 getPort(const quint16 portmin, const quint16 portmax)
|
|
|
|
{
|
|
|
|
if (portmin == portmax) {
|
|
|
|
return portmax;
|
|
|
|
}
|
|
|
|
quint16 portnumber = 0;
|
|
|
|
while (portnumber < portmin || portnumber > portmax) {
|
|
|
|
portnumber = quint16(qrand());
|
|
|
|
}
|
|
|
|
return portnumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
static QByteArray getDirShareKey(const QString &kdirsharedirpath)
|
|
|
|
{
|
|
|
|
return kdirsharedirpath.toLocal8Bit().toHex();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2022-05-11 15:59:26 +03:00
|
|
|
class KDirShareThread : public QThread
|
2022-05-10 13:37:29 +03:00
|
|
|
{
|
2022-05-11 15:59:26 +03:00
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
KDirShareThread(QObject *parent = nullptr);
|
|
|
|
~KDirShareThread();
|
|
|
|
|
|
|
|
QString serve(const QString &dirpath, const quint16 portmin, const quint16 portmax);
|
|
|
|
QString directory() const;
|
|
|
|
quint16 portMin() const;
|
|
|
|
quint16 portMax() const;
|
|
|
|
|
|
|
|
Q_SIGNALS:
|
|
|
|
void unblock();
|
|
|
|
void serveError(const QString &error);
|
|
|
|
|
|
|
|
private Q_SLOTS:
|
|
|
|
void slotUnblock();
|
|
|
|
void slotServeError(const QString &error);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void run() final;
|
|
|
|
|
|
|
|
private:
|
|
|
|
KDirShareImpl* m_kdirshareimpl;
|
|
|
|
bool m_starting;
|
|
|
|
QString m_directory;
|
2022-05-11 20:16:45 +03:00
|
|
|
quint16 m_port;
|
2022-05-11 15:59:26 +03:00
|
|
|
quint16 m_portmin;
|
|
|
|
quint16 m_portmax;
|
|
|
|
QString m_error;
|
|
|
|
};
|
|
|
|
|
|
|
|
KDirShareThread::KDirShareThread(QObject *parent)
|
|
|
|
: QThread(parent),
|
|
|
|
m_kdirshareimpl(new KDirShareImpl(this)),
|
|
|
|
m_starting(false),
|
2022-05-11 20:16:45 +03:00
|
|
|
m_port(0),
|
|
|
|
m_portmin(s_kdirshareportmin),
|
|
|
|
m_portmax(s_kdirshareportmax)
|
2022-05-11 15:59:26 +03:00
|
|
|
{
|
|
|
|
connect(
|
|
|
|
this, SIGNAL(unblock()),
|
|
|
|
this, SLOT(slotUnblock())
|
|
|
|
);
|
|
|
|
connect(
|
|
|
|
this, SIGNAL(serveError(QString)),
|
|
|
|
this, SLOT(slotServeError(QString))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
KDirShareThread::~KDirShareThread()
|
|
|
|
{
|
|
|
|
if (m_kdirshareimpl) {
|
|
|
|
m_kdirshareimpl->stop();
|
|
|
|
m_kdirshareimpl->deleteLater();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QString KDirShareThread::directory() const
|
|
|
|
{
|
|
|
|
return m_directory;
|
|
|
|
}
|
|
|
|
|
|
|
|
quint16 KDirShareThread::portMin() const
|
|
|
|
{
|
|
|
|
return m_portmin;
|
|
|
|
}
|
|
|
|
|
|
|
|
quint16 KDirShareThread::portMax() const
|
|
|
|
{
|
|
|
|
return m_portmax;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KDirShareThread::run()
|
|
|
|
{
|
|
|
|
if (!m_kdirshareimpl->setDirectory(m_directory)) {
|
|
|
|
emit serveError(i18n("Directory does not exist: %1", m_directory));
|
|
|
|
emit unblock();
|
|
|
|
return;
|
|
|
|
}
|
2022-05-11 20:16:45 +03:00
|
|
|
if (!m_kdirshareimpl->serve(QHostAddress(QHostAddress::Any), m_port)) {
|
2022-05-11 15:59:26 +03:00
|
|
|
emit serveError(i18n("Could not serve: %1", m_kdirshareimpl->errorString()));
|
|
|
|
emit unblock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!m_kdirshareimpl->publish()) {
|
|
|
|
m_kdirshareimpl->stop();
|
|
|
|
emit serveError(i18n("Could not publish service: %1", m_kdirshareimpl->publishError()));
|
|
|
|
emit unblock();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
emit unblock();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString KDirShareThread::serve(const QString &dirpath, const quint16 portmin, const quint16 portmax)
|
|
|
|
{
|
2022-05-11 20:16:45 +03:00
|
|
|
// qDebug() << Q_FUNC_INFO << dirpath << port;
|
2022-05-11 15:59:26 +03:00
|
|
|
m_directory = dirpath;
|
2022-05-11 20:16:45 +03:00
|
|
|
m_port = getPort(portmin, portmax);
|
2022-05-11 15:59:26 +03:00
|
|
|
m_portmin = portmin;
|
|
|
|
m_portmax = portmax;
|
|
|
|
m_starting = true;
|
|
|
|
m_error.clear();
|
|
|
|
start();
|
|
|
|
while (m_starting) {
|
|
|
|
QCoreApplication::processEvents();
|
|
|
|
}
|
|
|
|
// qDebug() << Q_FUNC_INFO << m_error;
|
|
|
|
return m_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KDirShareThread::slotUnblock()
|
|
|
|
{
|
|
|
|
m_starting = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KDirShareThread::slotServeError(const QString &error)
|
|
|
|
{
|
|
|
|
m_error = error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-05-09 15:35:44 +03:00
|
|
|
K_PLUGIN_FACTORY(KDirShareModuleFactory, registerPlugin<KDirShareModule>();)
|
|
|
|
K_EXPORT_PLUGIN(KDirShareModuleFactory("kdirshare"))
|
|
|
|
|
|
|
|
KDirShareModule::KDirShareModule(QObject *parent, const QList<QVariant>&)
|
|
|
|
: KDEDModule(parent)
|
|
|
|
{
|
2022-05-09 22:15:16 +03:00
|
|
|
bool shareerror = false;
|
2022-05-09 23:39:06 +03:00
|
|
|
KConfig kdirshareconfig("kdirsharerc", KConfig::SimpleConfig);
|
2022-05-10 13:37:29 +03:00
|
|
|
foreach (const QString &kdirsharekey, kdirshareconfig.groupList()) {
|
2022-05-09 23:39:06 +03:00
|
|
|
// qDebug() << Q_FUNC_INFO << kdirsharekey;
|
|
|
|
KConfigGroup kdirsharegroup = kdirshareconfig.group(kdirsharekey);
|
|
|
|
const QString kdirsharedirpath = kdirsharegroup.readEntry("dirpath", QString());
|
2022-05-10 13:37:29 +03:00
|
|
|
if (kdirsharedirpath.isEmpty()) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-05-09 23:39:06 +03:00
|
|
|
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;
|
2022-05-09 21:50:00 +03:00
|
|
|
const QString kdirshareerror = share(
|
2022-05-09 23:39:06 +03:00
|
|
|
kdirsharedirpath,
|
|
|
|
quint16(kdirshareportmin), quint16(kdirshareportmax)
|
2022-05-09 21:50:00 +03:00
|
|
|
);
|
2022-05-09 15:35:44 +03:00
|
|
|
if (!kdirshareerror.isEmpty()) {
|
|
|
|
kWarning() << kdirshareerror;
|
2022-05-09 22:15:16 +03:00
|
|
|
shareerror = true;
|
2022-05-09 15:35:44 +03:00
|
|
|
}
|
|
|
|
}
|
2022-05-09 22:15:16 +03:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
2022-05-09 15:35:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
KDirShareModule::~KDirShareModule()
|
|
|
|
{
|
2022-05-09 23:39:06 +03:00
|
|
|
KConfig kdirshareconfig("kdirsharerc", KConfig::SimpleConfig);
|
2022-05-11 15:59:26 +03:00
|
|
|
foreach (const KDirShareThread *kdirsharethread, m_dirshares) {
|
2022-05-11 20:16:45 +03:00
|
|
|
const QByteArray kdirsharekey = getDirShareKey(kdirsharethread->directory());
|
2022-05-09 23:39:06 +03:00
|
|
|
KConfigGroup kdirsharegroup = kdirshareconfig.group(kdirsharekey);
|
2022-05-11 15:59:26 +03:00
|
|
|
// qDebug() << Q_FUNC_INFO << kdirsharekey << kdirsharethread->directory() << kdirsharethread->portMin() << kdirsharethread->portMax();
|
|
|
|
kdirsharegroup.writeEntry("dirpath", kdirsharethread->directory());
|
|
|
|
kdirsharegroup.writeEntry("portmin", uint(kdirsharethread->portMin()));
|
|
|
|
kdirsharegroup.writeEntry("portmax", uint(kdirsharethread->portMax()));
|
2022-05-09 15:35:44 +03:00
|
|
|
}
|
|
|
|
qDeleteAll(m_dirshares);
|
2022-05-09 23:39:06 +03:00
|
|
|
m_dirshares.clear();
|
2022-05-09 15:35:44 +03:00
|
|
|
}
|
|
|
|
|
2022-05-09 21:50:00 +03:00
|
|
|
QString KDirShareModule::share(const QString &dirpath, const uint portmin, const uint portmax)
|
2022-05-09 15:35:44 +03:00
|
|
|
{
|
2022-05-09 21:50:00 +03:00
|
|
|
if (isShared(dirpath)) {
|
|
|
|
const QString unshareerror = unshare(dirpath);
|
|
|
|
if (!unshareerror.isEmpty()) {
|
|
|
|
return unshareerror;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-11 15:59:26 +03:00
|
|
|
KDirShareThread *kdirsharethread = new KDirShareThread(this);
|
|
|
|
// qDebug() << Q_FUNC_INFO << dirpath << portmin << portmax;
|
|
|
|
const QString serveerror = kdirsharethread->serve(dirpath, portmin, portmax);
|
|
|
|
if (!serveerror.isEmpty()) {
|
|
|
|
delete kdirsharethread;
|
|
|
|
return serveerror;
|
2022-05-09 15:35:44 +03:00
|
|
|
}
|
2022-05-11 15:59:26 +03:00
|
|
|
m_dirshares.append(kdirsharethread);
|
2022-05-09 15:35:44 +03:00
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString KDirShareModule::unshare(const QString &dirpath)
|
|
|
|
{
|
2022-05-11 15:59:26 +03:00
|
|
|
foreach (KDirShareThread *kdirsharethread, m_dirshares) {
|
|
|
|
if (kdirsharethread->directory() == dirpath) {
|
2022-05-10 13:37:29 +03:00
|
|
|
KConfig kdirshareconfig("kdirsharerc", KConfig::SimpleConfig);
|
2022-05-11 20:16:45 +03:00
|
|
|
const QByteArray kdirsharekey = getDirShareKey(kdirsharethread->directory());
|
2022-05-10 13:37:29 +03:00
|
|
|
KConfigGroup kdirsharegroup = kdirshareconfig.group(kdirsharekey);
|
|
|
|
kdirsharegroup.writeEntry("dirpath", QString());
|
2022-05-11 15:59:26 +03:00
|
|
|
kdirsharethread->terminate();
|
|
|
|
delete kdirsharethread;
|
|
|
|
m_dirshares.removeAll(kdirsharethread);
|
2022-05-09 15:35:44 +03:00
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return i18n("Invalid directory share: %1", dirpath);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KDirShareModule::isShared(const QString &dirpath) const
|
|
|
|
{
|
2022-05-11 15:59:26 +03:00
|
|
|
foreach (const KDirShareThread *kdirsharethread, m_dirshares) {
|
|
|
|
if (kdirsharethread->directory() == dirpath) {
|
2022-05-09 15:35:44 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-05-09 21:50:00 +03:00
|
|
|
quint16 KDirShareModule::getPortMin(const QString &dirpath) const
|
|
|
|
{
|
2022-05-11 15:59:26 +03:00
|
|
|
foreach (const KDirShareThread *kdirsharethread, m_dirshares) {
|
|
|
|
if (kdirsharethread->directory() == dirpath) {
|
|
|
|
return kdirsharethread->portMin();
|
2022-05-09 21:50:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return s_kdirshareportmin;
|
|
|
|
}
|
|
|
|
|
|
|
|
quint16 KDirShareModule::getPortMax(const QString &dirpath) const
|
|
|
|
{
|
2022-05-11 15:59:26 +03:00
|
|
|
foreach (const KDirShareThread *kdirsharethread, m_dirshares) {
|
|
|
|
if (kdirsharethread->directory() == dirpath) {
|
|
|
|
return kdirsharethread->portMax();
|
2022-05-09 21:50:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return s_kdirshareportmax;
|
|
|
|
}
|
|
|
|
|
2022-05-11 15:59:26 +03:00
|
|
|
#include "kded_kdirshare.moc"
|