generic: authorization reimplementation

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-09-25 17:41:18 +03:00
parent f061b1a7fd
commit e88c621aa2
78 changed files with 379 additions and 4217 deletions

View file

@ -131,9 +131,9 @@ macro(KDE4_INSTALL_ICONS _defaultpath )
set(_lang ${ARGV1})
if(_lang)
set(_l10n_SUBDIR l10n/${_lang})
else(_lang)
else()
set(_l10n_SUBDIR ".")
endif(_lang)
endif()
# first the png icons
file(GLOB _icons *.png)
@ -266,19 +266,27 @@ endmacro(KDE4_ADD_WIDGET)
# *WARNING* You have to install the helper in ${KDE4_LIBEXEC_INSTALL_DIR} to make
# sure everything will work.
function(KDE4_INSTALL_AUTH_HELPER_FILES HELPER_TARGET HELPER_ID HELPER_USER)
if (_kdeBootStrapping)
set(_stubFilesDir ${CMAKE_SOURCE_DIR}/kdecore/auth/backends/dbus/)
else (_kdeBootStrapping)
set(_stubFilesDir ${KDE4_DATA_INSTALL_DIR}/kauth/)
endif (_kdeBootStrapping)
if(_kdeBootStrapping)
set(_stubFilesDir ${CMAKE_SOURCE_DIR}/kdecore)
else()
set(_stubFilesDir ${KDE4_DATA_INSTALL_DIR}/kauth)
endif()
configure_file(${_stubFilesDir}/dbus_policy.stub
${CMAKE_CURRENT_BINARY_DIR}/${HELPER_ID}.conf)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${HELPER_ID}.conf
DESTINATION ${KDE4_SYSCONF_INSTALL_DIR}/dbus-1/system.d/)
configure_file(
${_stubFilesDir}/dbus_policy.stub
${CMAKE_CURRENT_BINARY_DIR}/${HELPER_ID}.conf
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${HELPER_ID}.conf
DESTINATION ${KDE4_SYSCONF_INSTALL_DIR}/dbus-1/system.d/
)
configure_file(${_stubFilesDir}/dbus_service.stub
${CMAKE_CURRENT_BINARY_DIR}/${HELPER_ID}.service)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${HELPER_ID}.service
DESTINATION ${KDE4_DBUS_SYSTEM_SERVICES_INSTALL_DIR})
configure_file(
${_stubFilesDir}/dbus_service.stub
${CMAKE_CURRENT_BINARY_DIR}/${HELPER_ID}.service
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${HELPER_ID}.service
DESTINATION ${KDE4_DBUS_SYSTEM_SERVICES_INSTALL_DIR}
)
endfunction(KDE4_INSTALL_AUTH_HELPER_FILES)

View file

@ -18,7 +18,7 @@ install(
KArchiveEntry
KArchiveFile
KAssistantDialog
KAuthorized
KAuthorization
KAutoMount
KAutoUnmount
KAutoSaveFile
@ -556,16 +556,6 @@ install(
COMPONENT Devel
)
install(
FILES
KAuth/Action
KAuth/ActionReply
KAuth/ActionWatcher
KAuth/HelperSupport
DESTINATION ${KDE4_INCLUDE_INSTALL_DIR}/KDE/KAuth
COMPONENT Devel
)
install(
FILES
Plasma/AbstractDialogManager

View file

@ -1 +0,0 @@
#include "../../kauthaction.h"

View file

@ -1 +0,0 @@
#include "../../kauthactionreply.h"

View file

@ -1 +0,0 @@
#include "../../kauthactionwatcher.h"

View file

@ -1 +0,0 @@
#include "../../kauthhelpersupport.h"

1
includes/KAuthorization Normal file
View file

@ -0,0 +1 @@
#include "../kauthorization.h"

View file

@ -1 +0,0 @@
#include "../kauthorized.h"

View file

@ -86,12 +86,6 @@ if(ENABLE_TESTING)
add_subdirectory(sonnet/tests)
endif()
qt4_add_dbus_adaptor(kauth_dbus_adaptor_SRCS
auth/backends/dbus/org.kde.auth.xml
auth/backends/dbus/DBusHelperProxy.h
KAuth::DBusHelperProxy
)
########### next target ###############
set(kdecore_LIB_SRCS
@ -149,7 +143,7 @@ set(kdecore_LIB_SRCS
jobs/kjob.cpp
jobs/kjobuidelegate.cpp
jobs/kjobtrackerinterface.cpp
kernel/kauthorized.cpp
kernel/kauthorization.cpp
kernel/kaboutdata.cpp
kernel/kcmdlineargs.cpp
kernel/kdbusconnectionpool.cpp
@ -157,13 +151,6 @@ set(kdecore_LIB_SRCS
kernel/kcomponentdata.cpp
kernel/kstandarddirs.cpp
kernel/ktoolinvocation.cpp
auth/kauthaction.cpp
auth/kauthactionreply.cpp
auth/kauthactionwatcher.cpp
auth/AuthBackend.cpp
auth/BackendsManager.cpp
auth/HelperProxy.cpp
auth/kauthhelpersupport.cpp
services/kfoldermimetype.cpp
services/kmimetypefactory.cpp
services/kmimemagicrule.cpp
@ -232,10 +219,6 @@ set(kdecore_LIB_SRCS
util/kmacroexpander_unix.cpp
${kdecore_OPTIONAL_SRCS}
auth/backends/dbus/DBusBackend.cpp
auth/backends/dbus/DBusBackend.h
auth/backends/dbus/DBusHelperProxy.cpp
${kauth_dbus_adaptor_SRCS}
)
if(NOT Q_WS_X11 AND NOT Q_WS_QWS)
@ -338,17 +321,13 @@ install(
jobs/kjobuidelegate.h
jobs/kjobtrackerinterface.h
kernel/kaboutdata.h
kernel/kauthorized.h
kernel/kauthorization.h
kernel/kcmdlineargs.h
kernel/kdbusconnectionpool.h
kernel/kglobal.h
kernel/kcomponentdata.h
kernel/kstandarddirs.h
kernel/ktoolinvocation.h
auth/kauthaction.h
auth/kauthactionreply.h
auth/kauthactionwatcher.h
auth/kauthhelpersupport.h
services/kmimetype.h
services/kmimetypetrader.h
services/kservice.h
@ -416,14 +395,8 @@ install(
install(
FILES
auth/backends/dbus/org.kde.auth.conf
DESTINATION ${KDE4_SYSCONF_INSTALL_DIR}/dbus-1/system.d
)
install(
FILES
auth/backends/dbus/dbus_policy.stub
auth/backends/dbus/dbus_service.stub
dbus_policy.stub
dbus_service.stub
DESTINATION ${KDE4_DATA_INSTALL_DIR}/kauth
COMPONENT Devel
)

View file

@ -56,7 +56,7 @@ kconfig_compiler/
kernel/
kaboutdata.cpp David Faure <faure@kde.org>
kauthorized.cpp
kauthorization.cpp
kautostart.cpp
kcmdlineargs.cpp
kcomponentdata.cpp

View file

@ -1,36 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2010 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#include "AuthBackend.h"
namespace KAuth
{
AuthBackend::AuthBackend()
: QObject(0)
{
}
AuthBackend::~AuthBackend()
{
}
} //namespace KAuth

View file

@ -1,52 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009-2010 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#ifndef AUTH_BACKEND_H
#define AUTH_BACKEND_H
#include <QObject>
#include "kauthaction.h"
namespace KAuth
{
class AuthBackend : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(AuthBackend)
public:
AuthBackend();
virtual ~AuthBackend();
virtual Action::AuthStatus authorizeAction(const QString &action) = 0;
virtual Action::AuthStatus actionStatus(const QString &action) = 0;
virtual bool isCallerAuthorized(const QString &action) = 0;
Q_SIGNALS:
void actionStatusChanged(const QString &action, Action::AuthStatus status);
};
} // namespace Auth
Q_DECLARE_INTERFACE(KAuth::AuthBackend, "org.kde.auth.AuthBackend/0.1")
#endif

View file

@ -1,67 +0,0 @@
/*
* Copyright (C) 2009 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#include "BackendsManager.h"
// Include dbus backends
#include "backends/dbus/DBusBackend.h"
#include "backends/dbus/DBusHelperProxy.h"
#include <kdebug.h>
namespace KAuth
{
AuthBackend *BackendsManager::auth = 0;
HelperProxy *BackendsManager::helper = 0;
BackendsManager::BackendsManager()
{
}
void BackendsManager::init()
{
if (!auth) {
auth = new DBusBackend();
}
if (!helper) {
helper = new DBusHelperProxy();
}
}
AuthBackend *BackendsManager::authBackend()
{
if (!auth) {
init();
}
return auth;
}
HelperProxy *BackendsManager::helperProxy()
{
if (!helper) {
init();
}
return helper;
}
} // namespace Auth

View file

@ -1,47 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#ifndef BACKENDS_MANAGER_H
#define BACKENDS_MANAGER_H
#include "AuthBackend.h"
#include "HelperProxy.h"
#include <kdecore_export.h>
namespace KAuth
{
class KDECORE_EXPORT BackendsManager
{
static AuthBackend *auth;
static HelperProxy *helper;
BackendsManager();
public:
static AuthBackend *authBackend();
static HelperProxy *helperProxy();
private:
static void init();
};
} // namespace Auth
#endif

View file

@ -1,28 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#include "HelperProxy.h"
namespace KAuth
{
HelperProxy::~HelperProxy() {}
} // namespace KAuth

View file

@ -1,67 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#ifndef HELPER_PROXY_H
#define HELPER_PROXY_H
#include <QObject>
#include <QMap>
#include <QString>
#include <QVariant>
#include "kauthaction.h"
#include "kauthactionreply.h"
#include "kauthactionwatcher.h"
namespace KAuth
{
class HelperProxy : public QObject
{
Q_OBJECT
public:
virtual ~HelperProxy();
// Application-side methods
virtual bool executeActions(const QList<QPair<QString, QVariantMap> > &list, const QString &helperID) = 0;
virtual ActionReply executeAction(const QString &action, const QString &helperID, const QVariantMap &arguments) = 0;
virtual Action::AuthStatus authorizeAction(const QString &action, const QString &helperID) = 0;
virtual void stopAction(const QString &action, const QString &helperID) = 0;
// Helper-side methods
virtual bool initHelper(const QString &name) = 0;
virtual void setHelperResponder(QObject *o) = 0;
virtual bool hasToStopAction() = 0;
virtual void sendDebugMessage(int level, const char *msg) = 0;
virtual void sendProgressStep(int step) = 0;
virtual void sendProgressStep(const QVariantMap &step) = 0;
signals:
void actionStarted(const QString &action);
void actionPerformed(const QString &action, ActionReply reply);
void progressStep(const QString &action, int progress);
void progressStep(const QString &action, const QVariantMap &data);
};
} // namespace KAuth
Q_DECLARE_INTERFACE(KAuth::HelperProxy, "org.kde.auth.HelperProxy/0.1")
#endif

View file

@ -1,6 +0,0 @@
Todo list for libkauth:
- Add vendor name and icon to actions.ini
- Add an option (either on build-time or at invocation time) to enable/disable the helper quit timeout.
This is useful for debugging.
- Check with others on k-c-d if it's needed to add strings with error descriptions.
- Stop requests must be action-specific instead of global

View file

@ -1,73 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#include "DBusBackend.h"
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusPendingCall>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QRegExp>
namespace KAuth
{
DBusBackend::DBusBackend()
: AuthBackend()
{
}
Action::AuthStatus DBusBackend::authorizeAction(const QString &action)
{
return actionStatus(action);
}
Action::AuthStatus DBusBackend::actionStatus(const QString &action)
{
if (isCallerAuthorized(action)) {
return Action::Authorized;
} else {
return Action::Denied;
}
}
bool DBusBackend::isCallerAuthorized(const QString &action)
{
QDBusMessage message;
QRegExp rx(QLatin1String("(\\S+\\.\\S+\\.\\S+\\.\\S+)\\."));
int pos = rx.indexIn(action);
Q_UNUSED(pos);
message = QDBusMessage::createMethodCall(rx.capturedTexts()[1],
QLatin1String("/"),
QLatin1String("org.freedesktop.DBus.Introspectable"),
QLatin1String("Introspect"));
QDBusPendingCall reply = QDBusConnection::systemBus().asyncCall(message);
reply.waitForFinished();
if (reply.reply().type() == QDBusMessage::ErrorMessage) {
return false;
}
return true;
}
} // namespace Auth

View file

@ -1,45 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#ifndef FAKE_BACKEND_H
#define FAKE_BACKEND_H
#include "AuthBackend.h"
#include <QString>
namespace KAuth
{
class DBusBackend : public AuthBackend
{
Q_OBJECT
Q_INTERFACES(KAuth::AuthBackend)
public:
DBusBackend();
Action::AuthStatus authorizeAction(const QString&) final;
Action::AuthStatus actionStatus(const QString&) final;
bool isCallerAuthorized(const QString &action) final;
};
} // namespace Auth
#endif

View file

@ -1,401 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009-2010 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#include "DBusHelperProxy.h"
#include <QObject>
#include <QMap>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QDebug>
#include <QTimer>
#include <QEventLoop>
#include <klocalizedstring.h>
#include <syslog.h>
#include "BackendsManager.h"
#include "authadaptor.h"
Q_DECLARE_METATYPE(QTimer*)
namespace KAuth
{
static void debugMessageReceived(int t, const QString &message);
void DBusHelperProxy::stopAction(const QString &action, const QString &helperID)
{
QDBusMessage message;
message = QDBusMessage::createMethodCall(helperID, QLatin1String("/"), QLatin1String("org.kde.auth"), QLatin1String("stopAction"));
QList<QVariant> args;
args << action;
message.setArguments(args);
QDBusConnection::systemBus().asyncCall(message);
}
bool DBusHelperProxy::executeActions(const QList<QPair<QString, QVariantMap> > &list, const QString &helperID)
{
QByteArray blob;
QDataStream stream(&blob, QIODevice::WriteOnly);
stream << list;
QDBusConnection::systemBus().interface()->startService(helperID);
if (!QDBusConnection::systemBus().connect(helperID, QLatin1String("/"), QLatin1String("org.kde.auth"), QLatin1String("remoteSignal"), this, SLOT(remoteSignalReceived(int,QString,QByteArray)))) {
return false;
}
QDBusMessage message;
message = QDBusMessage::createMethodCall(helperID, QLatin1String("/"), QLatin1String("org.kde.auth"), QLatin1String("performActions"));
QList<QVariant> args;
args << blob;
message.setArguments(args);
QDBusPendingCall reply = QDBusConnection::systemBus().asyncCall(message); // This is a NO_REPLY method
if (reply.reply().type() == QDBusMessage::ErrorMessage) {
return false;
}
return true;
}
ActionReply DBusHelperProxy::executeAction(const QString &action, const QString &helperID, const QVariantMap &arguments)
{
if (!m_actionsInProgress.isEmpty()) {
return ActionReply::HelperBusyReply;
}
QByteArray blob;
QDataStream stream(&blob, QIODevice::WriteOnly);
stream << arguments;
QDBusConnection::systemBus().interface()->startService(helperID);
if (!QDBusConnection::systemBus().connect(helperID, QLatin1String("/"), QLatin1String("org.kde.auth"), QLatin1String("remoteSignal"), this, SLOT(remoteSignalReceived(int,QString,QByteArray)))) {
ActionReply errorReply = ActionReply::DBusErrorReply;
errorReply.setErrorDescription(i18n("DBus Backend error: connection to helper failed. %1",
QDBusConnection::systemBus().lastError().message()));
return errorReply;
}
QDBusMessage message;
message = QDBusMessage::createMethodCall(helperID, QLatin1String("/"), QLatin1String("org.kde.auth"), QLatin1String("performAction"));
QList<QVariant> args;
args << action << blob;
message.setArguments(args);
m_actionsInProgress.push_back(action);
QEventLoop e;
QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(message);
QDBusPendingCallWatcher watcher(pendingCall, this);
connect(&watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), &e, SLOT(quit()));
e.exec();
QDBusMessage reply = pendingCall.reply();
if (reply.type() == QDBusMessage::ErrorMessage) {
ActionReply r = ActionReply::DBusErrorReply;
r.setErrorDescription(i18n("DBus Backend error: could not contact the helper. "
"Connection error: %1. Message error: %2", QDBusConnection::systemBus().lastError().message(),
reply.errorMessage()));
qDebug() << reply.errorMessage();
// The remote signal will never arrive: so let's erase the action from the list ourselves
m_actionsInProgress.removeOne(action);
return r;
}
if (reply.arguments().size() != 1) {
ActionReply errorReply = ActionReply::DBusErrorReply;
errorReply.setErrorDescription(i18n("DBus Backend error: received corrupt data from helper %1 %2",
reply.arguments().size(), QDBusConnection::systemBus().lastError().message()));
// The remote signal may never arrive: so let's erase the action from the list ourselves
m_actionsInProgress.removeOne(action);
return errorReply;
}
return ActionReply::deserialize(reply.arguments().first().toByteArray());
}
Action::AuthStatus DBusHelperProxy::authorizeAction(const QString& action, const QString& helperID)
{
if (!m_actionsInProgress.isEmpty()) {
return Action::Error;
}
QDBusConnection::systemBus().interface()->startService(helperID);
QDBusMessage message;
message = QDBusMessage::createMethodCall(helperID, QLatin1String("/"), QLatin1String("org.kde.auth"), QLatin1String("authorizeAction"));
QList<QVariant> args;
args << action;
message.setArguments(args);
m_actionsInProgress.push_back(action);
QEventLoop e;
QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(message);
QDBusPendingCallWatcher watcher(pendingCall, this);
connect(&watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), &e, SLOT(quit()));
e.exec();
m_actionsInProgress.removeOne(action);
QDBusMessage reply = pendingCall.reply();
if (reply.type() == QDBusMessage::ErrorMessage || reply.arguments().size() != 1) {
return Action::Error;
}
return static_cast<Action::AuthStatus>(reply.arguments().first().toUInt());
}
bool DBusHelperProxy::initHelper(const QString &name)
{
new AuthAdaptor(this);
if (!QDBusConnection::systemBus().registerService(name)) {
return false;
}
if (!QDBusConnection::systemBus().registerObject(QLatin1String("/"), this)) {
return false;
}
m_name = name;
return true;
}
void DBusHelperProxy::setHelperResponder(QObject *o)
{
responder = o;
}
void DBusHelperProxy::remoteSignalReceived(int t, const QString &action, QByteArray blob)
{
SignalType type = (SignalType)t;
QDataStream stream(&blob, QIODevice::ReadOnly);
if (type == ActionStarted) {
emit actionStarted(action);
} else if (type == ActionPerformed) {
ActionReply reply = ActionReply::deserialize(blob);
m_actionsInProgress.removeOne(action);
emit actionPerformed(action, reply);
} else if (type == DebugMessage) {
int level;
QString message;
stream >> level >> message;
debugMessageReceived(level, message);
} else if (type == ProgressStepIndicator) {
int step;
stream >> step;
emit progressStep(action, step);
} else if (type == ProgressStepData) {
QVariantMap data;
stream >> data;
emit progressStep(action, data);
}
}
void DBusHelperProxy::stopAction(const QString &action)
{
Q_UNUSED(action)
#warning FIXME: The stop request should be action-specific rather than global
m_stopRequest = true;
}
bool DBusHelperProxy::hasToStopAction()
{
QEventLoop loop;
loop.processEvents(QEventLoop::AllEvents);
return m_stopRequest;
}
void DBusHelperProxy::performActions(QByteArray blob)
{
QDataStream stream(&blob, QIODevice::ReadOnly);
QList< QPair< QString, QVariantMap > > actions;
stream >> actions;
QList< QPair< QString, QVariantMap > >::const_iterator i = actions.constBegin();
while (i != actions.constEnd()) {
QByteArray blob;
QDataStream stream(&blob, QIODevice::WriteOnly);
stream << i->second;
performAction(i->first, blob);
++i;
}
}
QByteArray DBusHelperProxy::performAction(const QString &action, QByteArray arguments)
{
if (!responder) {
return ActionReply::NoResponderReply.serialized();
}
if (!m_currentAction.isEmpty()) {
return ActionReply::HelperBusyReply.serialized();
}
QVariantMap args;
QDataStream s(&arguments, QIODevice::ReadOnly);
s >> args;
m_currentAction = action;
emit remoteSignal(ActionStarted, action, QByteArray());
QEventLoop e;
e.processEvents(QEventLoop::AllEvents);
ActionReply retVal;
QTimer *timer = responder->property("__KAuth_Helper_Shutdown_Timer").value<QTimer*>();
timer->stop();
if (BackendsManager::authBackend()->isCallerAuthorized(action)) {
QString slotname = action;
if (slotname.startsWith(m_name + QLatin1Char('.'))) {
slotname = slotname.right(slotname.length() - m_name.length() - 1);
}
slotname.replace(QLatin1Char('.'), QLatin1Char('_'));
bool success = QMetaObject::invokeMethod(responder, slotname.toLatin1(), Qt::DirectConnection,
Q_RETURN_ARG(ActionReply, retVal), Q_ARG(QVariantMap, args));
if (!success) {
retVal = ActionReply::NoSuchActionReply;
}
} else {
retVal = ActionReply::AuthorizationDeniedReply;
}
timer->start();
emit remoteSignal(ActionPerformed, action, retVal.serialized());
e.processEvents(QEventLoop::AllEvents);
m_currentAction.clear();
m_stopRequest = false;
return retVal.serialized();
}
uint DBusHelperProxy::authorizeAction(const QString& action)
{
if (!m_currentAction.isEmpty()) {
return static_cast<uint>(Action::Error);
}
m_currentAction = action;
uint retVal;
QTimer *timer = responder->property("__KAuth_Helper_Shutdown_Timer").value<QTimer*>();
timer->stop();
if (BackendsManager::authBackend()->isCallerAuthorized(action)) {
retVal = static_cast<uint>(Action::Authorized);
} else {
retVal = static_cast<uint>(Action::Denied);
}
timer->start();
m_currentAction.clear();
return retVal;
}
void DBusHelperProxy::sendDebugMessage(int level, const char *msg)
{
QByteArray blob;
QDataStream stream(&blob, QIODevice::WriteOnly);
stream << level << QString::fromLocal8Bit(msg);
emit remoteSignal(DebugMessage, m_currentAction, blob);
}
void DBusHelperProxy::sendProgressStep(int step)
{
QByteArray blob;
QDataStream stream(&blob, QIODevice::WriteOnly);
stream << step;
emit remoteSignal(ProgressStepIndicator, m_currentAction, blob);
}
void DBusHelperProxy::sendProgressStep(const QVariantMap &data)
{
QByteArray blob;
QDataStream stream(&blob, QIODevice::WriteOnly);
stream << data;
emit remoteSignal(ProgressStepData, m_currentAction, blob);
}
void debugMessageReceived(int t, const QString &message)
{
QtMsgType type = (QtMsgType)t;
switch (type) {
case QtDebugMsg:
qDebug("Debug message from helper: %s", message.toLatin1().data());
break;
case QtWarningMsg:
qWarning("Warning from helper: %s", message.toLatin1().data());
break;
case QtCriticalMsg:
qCritical("Critical warning from helper: %s", message.toLatin1().data());
break;
case QtFatalMsg:
qFatal("Fatal error from helper: %s", message.toLatin1().data());
break;
}
}
} // namespace Auth

View file

@ -1,79 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#ifndef DBUS_HELPER_PROXY_H
#define DBUS_HELPER_PROXY_H
#include "HelperProxy.h"
#include "kauthactionreply.h"
namespace KAuth
{
class DBusHelperProxy : public HelperProxy
{
Q_OBJECT
Q_INTERFACES(KAuth::HelperProxy)
QObject *responder;
QString m_name;
QString m_currentAction;
bool m_stopRequest;
QList<QString> m_actionsInProgress;
enum SignalType {
ActionStarted, // The blob argument is empty
ActionPerformed, // The blob argument contains the ActionReply
DebugMessage, // The blob argument contains the debug level and the message (in this order)
ProgressStepIndicator, // The blob argument contains the step indicator
ProgressStepData // The blob argument contains the QVariantMap
};
public:
DBusHelperProxy() : responder(0), m_stopRequest(false) {}
bool executeActions(const QList<QPair<QString, QVariantMap> > &list, const QString &helperID) final;
ActionReply executeAction(const QString &action, const QString &helperID, const QVariantMap &arguments) final;
Action::AuthStatus authorizeAction(const QString& action, const QString& helperID) final;
void stopAction(const QString &action, const QString &helperID) final;
bool initHelper(const QString &name) final;
void setHelperResponder(QObject *o) final;
bool hasToStopAction() final;
void sendDebugMessage(int level, const char *msg) final;
void sendProgressStep(int step) final;
void sendProgressStep(const QVariantMap &data) final;
public slots:
void stopAction(const QString &action);
void performActions(QByteArray blob);
QByteArray performAction(const QString &action, QByteArray arguments);
uint authorizeAction(const QString &action);
signals:
void remoteSignal(int type, const QString &action, const QByteArray &blob); // This signal is sent from the helper to the app
private slots:
void remoteSignalReceived(int type, const QString &action, QByteArray blob);
};
} // namespace Auth
#endif

View file

@ -1,13 +0,0 @@
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- Allow anyone to call into the service -->
<policy context="default">
<allow send_interface="org.kde.auth"/>
<allow receive_sender="org.kde.auth"/>
<allow receive_interface="org.kde.auth"/>
</policy>
</busconfig>

View file

@ -1,27 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.auth">
<method name="performAction" >
<arg name="action" type="s" direction="in" />
<arg name="arguments" type="ay" direction="in" />
<arg name="r" type="ay" direction="out" />
</method>
<method name="authorizeAction" >
<arg name="action" type="s" direction="in" />
<arg name="r" type="u" direction="out" />
</method>
<method name="performActions" >
<arg name="blob" type="ay" direction="in" />
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<method name="stopAction" >
<arg name="action" type="s" direction="in" />
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
<signal name="remoteSignal" >
<arg name="type" type="i" />
<arg name="action" type="s" />
<arg name="blob" type="ay" />
</signal>
</interface>
</node>

View file

@ -1,300 +0,0 @@
/*
* Copyright (C) 2009 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009-2010 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#include "kauthaction.h"
#include <QRegExp>
#include <QWidget>
#include "BackendsManager.h"
#include "kauthactionwatcher.h"
namespace KAuth
{
class Action::Private
{
public:
Private() : valid(false), async(false), parent(0) {}
QString name;
QString details;
QString helperId;
QVariantMap args;
bool valid;
bool async;
QWidget *parent;
};
// Constructors
Action::Action()
: d(new Private())
{
}
Action::Action(const Action &action)
: d(new Private())
{
*this = action;
}
Action::Action(const QString &name)
: d(new Private())
{
setName(name);
}
Action::Action(const QString &name, const QString &details)
: d(new Private())
{
setName(name);
setDetails(details);
}
Action::~Action()
{
delete d;
}
// Operators
Action &Action::operator=(const Action & action)
{
setName(action.d->name);
d->args = action.d->args;
return *this;
}
bool Action::operator==(const Action &action) const
{
return d->name == action.d->name;
}
bool Action::operator!=(const Action &action) const
{
return d->name != action.d->name;
}
// Accessors
QString Action::name() const
{
return d->name;
}
void Action::setName(const QString &name)
{
d->name = name;
// Check through a regexp
QRegExp exp(QLatin1String("[0-z]+(\\.[0-z]+)*"));
d->valid = exp.exactMatch(name);
}
QString Action::details() const
{
return d->details;
}
void Action::setDetails(const QString &details)
{
d->details = details;
}
bool Action::isValid() const
{
return d->valid;
}
void Action::setArguments(const QVariantMap &arguments)
{
d->args = arguments;
}
void Action::addArgument(const QString &key, const QVariant &value)
{
d->args.insert(key, value);
}
QVariantMap Action::arguments() const
{
return d->args;
}
ActionWatcher *Action::watcher()
{
return ActionWatcher::watcher(d->name);
}
QString Action::helperID() const
{
return d->helperId;
}
// TODO: Check for helper id's syntax
void Action::setHelperID(const QString &id)
{
d->helperId = id;
}
void Action::setParentWidget(QWidget* parent)
{
d->parent = parent;
}
QWidget* Action::parentWidget() const
{
return d->parent;
}
// Authorizaton methods
Action::AuthStatus Action::authorize() const
{
if (!isValid()) {
return Action::Invalid;
}
return BackendsManager::authBackend()->authorizeAction(d->name);
}
Action::AuthStatus Action::earlyAuthorize() const
{
// Check the status first
AuthStatus s = status();
if (s == AuthRequired) {
return BackendsManager::authBackend()->authorizeAction(d->name);
} else {
// It's fine, return the status
return s;
}
}
Action::AuthStatus Action::status() const
{
if (!isValid()) {
return Action::Invalid;
}
return BackendsManager::authBackend()->actionStatus(d->name);
}
// Execution methods
bool Action::executeActions(const QList<Action> &actions, QList<Action> *deniedActions, const QString &helperId)
{
return executeActions(actions, deniedActions, helperId, 0);
}
bool Action::executeActions(const QList< Action >& actions, QList< Action >* deniedActions, const QString& helperId, QWidget* parent)
{
QList<QPair<QString, QVariantMap> > list;
foreach(const Action &a, actions) {
// Save us an additional step
AuthStatus s = BackendsManager::authBackend()->authorizeAction(a.name());
if (s == Authorized) {
list.push_back(QPair<QString, QVariantMap>(a.name(), a.arguments()));
} else if ((s == Denied || s == Invalid) && deniedActions) {
*deniedActions << a;
}
}
if (list.isEmpty()) {
return false;
}
return BackendsManager::helperProxy()->executeActions(list, helperId);
}
bool Action::executesAsync() const
{
return d->async;
}
void Action::setExecutesAsync(bool async)
{
d->async = async;
}
ActionReply Action::execute() const
{
if (!isValid())
return ActionReply::InvalidActionReply;
return execute(helperID());
}
ActionReply Action::execute(const QString &helperID) const
{
// Is the action valid?
if (!isValid()) {
return ActionReply::InvalidActionReply;
}
// Authorize from here
AuthStatus s = BackendsManager::authBackend()->authorizeAction(d->name);
// Abort if authorization fails
switch (s) {
case Denied:
return ActionReply::AuthorizationDeniedReply;
case Invalid:
return ActionReply::InvalidActionReply;
case UserCancelled:
return ActionReply::UserCancelledReply;
default:
break;
}
if (d->async) {
if (!hasHelper()) {
// It makes no sense
return ActionReply::InvalidActionReply;
}
return executeActions(QList<Action>() << *this, NULL, helperID) ?
ActionReply::SuccessReply : ActionReply::AuthorizationDeniedReply;
} else {
if (hasHelper()) {
return BackendsManager::helperProxy()->executeAction(d->name, helperID, d->args);
} else {
return ActionReply::SuccessReply;
}
}
}
void Action::stop()
{
stop(helperID());
}
void Action::stop(const QString &helperID)
{
BackendsManager::helperProxy()->stopAction(d->name, helperID);
}
bool Action::hasHelper() const
{
return !d->helperId.isEmpty();
}
} // namespace Auth

View file

@ -1,504 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#ifndef ACTION_H
#define ACTION_H
#include <QtCore/qvariant.h>
#include <kdecore_export.h>
#include "kauthactionreply.h"
namespace KAuth
{
class ActionWatcher;
/**
* @brief Class to access, authorize and execute actions.
*
* This is the main class of the kauth API. It provides the interface to
* manipulate actions. Every action is identified by its name. Every instance
* of the Action class with the same name refers to the same action.
*
* Once you have an action object you can tell the helper to execute it
* (asking the user to authenticate if needed) with one of the execute*() methods.
* The simplest thing to do is to execute a single action synchronously
* blocking for the reply, using the execute() method.
*
* For asynchronous calls, use the executeAsync() method. It sends the request
* to the helper and returns immediately. You can optionally provide an object
* and a slot. This will be connected to the actionPerformed() signal of the
* action's ActionWatcher object.
* By calling the watcher() method, you obtain an object that emits some useful
* signals that you can receive while the action is in progress. Those signals
* are emitted also with the synchronous calls.
* To execute a bunch of actions with a single call, you can use the executeActions()
* static method. This is not the same as calling executeAsync() for each action,
* because the actions are execute with a single request to the helper.
* To use any of the execute*() methods you have to set the default helper's ID using
* the setHelperID() static method. Alternatively, you can specify the helperID using
* the overloaded version of the methods that takes it as a parameter.
*
* Each action object contains a QVariantMap object that is passed directly to the
* helper when the action is executed. You can access this map using the arguments()
* method. You can insert into it any kind of custom data you need to pass to the helper.
*
* @since 4.4
*/
class KDECORE_EXPORT Action
{
class Private;
Private * const d;
public:
/**
* The three values returned by authorization methods
*/
enum AuthStatus {
Denied, ///< The authorization has been denied by the authorization backend
Error, ///< An error occurred
Invalid, ///< An invalid action cannot be authorized
Authorized, ///< The authorization has been granted by the authorization backend
AuthRequired, ///< The user could obtain the authorization after authentication
UserCancelled ///< The user pressed Cancel the authentication dialog. Currently used only on the mac
};
/**
* @brief Default constructor
*
* This constructor sets the name to the empty string.
* Such an action is invalid and cannot be authorized nor executed, so
* you need to call setName() before you can use the object.
*/
Action();
/** Copy constructor */
Action(const Action &action);
/**
* This creates a new action object with this name
* @param name The name of the new action
*/
Action(const QString &name);
/**
* This creates a new action object with this name and details
* @param name The name of the new action
* @param details The details of the action
*
* @see setDetails
*/
Action(const QString &name, const QString &details);
/// Virtual destructor
~Action();
/// Assignment operator
Action &operator=(const Action &action);
/**
* @brief Comparison operator
*
* This comparison operator compares the <b>names</b> of two
* actions and returns whether they are the same. It does not
* care about the arguments stored in the actions. However,
* if two actions are invalid they'll match as equal, even
* if the invalid names are different.
*
* @returns true if the two actions are the same or both invalid
*/
bool operator==(const Action &action) const;
/**
* @brief Negated comparison operator
*
* Returns the negation of operator==
*
* @returns true if the two actions are different and not both invalid
*/
bool operator!=(const Action &action) const;
/**
* @brief Gets the action's name.
*
* This is the unique attribute that identifies
* an action object. Two action objects with the same
* name always refer to the same action.
*
* @return The action name
*/
QString name() const;
/**
* @brief Sets the action's name.
*
* It's not common to change the action name
* after its creation. Usually you set the name
* with the constructor (and you have to, because
* there's no default constructor)
*/
void setName(const QString &name);
/**
* @brief Sets the action's details
*
* You can use this function to provide the user more details
* (if the backend supports it) on the action being authorized in
* the authorization dialog
*/
void setDetails(const QString &details);
/**
* @brief Gets the action's details
*
* The details that will be shown in the authorization dialog, if the
* backend supports it.
*
* @return The action's details
*/
QString details() const;
/**
* @brief Returns if the object represents a valid action
*
* Action names have to respect a simple syntax.
* They have to be all in lowercase characters, separated
* by dots. Dots can't appear at the beginning and at the end of
* the name.
*
* In other words, the action name has to match this perl-like
* regular expression:
* @verbatim
* /^[a-z]+(\.[a-z]+)*$/
* @endverbatim
*
* This method returns false if the action name doesn't match the
* valid syntax.
*
* If the backend supports it, this method also checks if the action is
* valid and recognized by the backend itself.
*
* Invalid actions cannot be authorized nor executed.
* The empty string is not a valid action name, so the default
* constructor returns an invalid action.
*/
bool isValid() const;
/**
* @brief Gets the default helper ID used for actions execution
*
* The helper ID is the string that uniquely identifies the helper in
* the system. It is the string passed to the KDE4_AUTH_HELPER() macro
* in the helper source. Because one could have different helpers,
* you need to specify an helper ID for each execution, or set a default
* ID by calling setHelperID(). This method returns the current default
* value.
*
* @return The default helper ID.
*/
QString helperID() const;
/**
* @brief Sets the default helper ID used for actions execution
*
* This method sets the helper ID which contains the body of this action.
* If the string is non-empty, the corresponding helper will be fired and
* the action executed inside the helper. Otherwise, the action will be just
* authorized.
*
* @note To unset a previously set helper, just pass an empty string
*
* @param id The default helper ID.
*
* @see hasHelper
* @see helperID
*/
void setHelperID(const QString &id);
/**
* @brief Checks if the action has an helper
*
* This function can be used to check if an helper will be called upon the
* execution of an action. Such an helper can be set through setHelperID. If
* this function returns false, upon execution the action will be just authorized.
*
* @since 4.5
*
* @return Whether the action has an helper or not
*
* @see setHelperID
*/
bool hasHelper() const;
/**
* @brief Gets the ActionWatcher object for this action
*
* ActionWatcher objects are used to get notifications about the action
* execution status. Every action watcher is tied to an action and
* every action has a watcher. This means that if you call this method
* on two different Action objects with the same name, you'll get the
* same watcher object.
*
* @return The action watcher for this action
*/
ActionWatcher *watcher();
/**
* @brief Sets the map object used to pass arguments to the helper.
*
* This method sets the variant map that the application
* can use to pass arbitrary data to the helper when executing the action.
*
* @param arguments The new arguments map
*/
void setArguments(const QVariantMap &arguments);
/**
* @brief Returns map object used to pass arguments to the helper.
*
* This method returns the variant map that the application
* can use to pass arbitrary data to the helper when executing the action.
*
* @return The arguments map that will be passed to the helper.
*/
QVariantMap arguments() const;
/**
* @brief Convenience method to add an argument.
*
* This method adds the pair @c key/value to the QVariantMap used to
* send custom data to the helper.
*
* Use this method if you don't want to create a new QVariantMap only to
* add a new entry.
*
* @param key The new entry's key
* @param value The value of the new entry
*/
void addArgument(const QString &key, const QVariant &value);
/**
* @brief Acquires authorization for an action without excuting it.
*
* @note Please use this method if you really know what you are doing. If you are
* implementing a GUI, you probably should look into earlyAuthorize instead.
*
* @note Please remember that calling this method is not required for a successful action
* execution: it is safe and advised to call execute() only, without a previous call
* to authorize or earlyAuthorize.
*
* This method acquires the authorization rights for the action, asking
* the user to authenticate if needed. It tries very hard to resolve a possible
* challenge (AuthRequired); for this reason, it is meant only for advanced usages.
* If you are unsure, always use earlyAuthorize or execute the action directly.
*
* @return The result of the authorization process
*
* @see earlyAuthorize
*/
AuthStatus authorize() const;
/**
* @brief Tries to resolve authorization status in the best possible way without executing the action
*
* This method checks for the status of the action, and tries to acquire authorization
* (if needed) if the backend being used supports client-side authorization.
*
* This means this method is not reliable - its purpose is to provide user interfaces with
* an efficient means to acquire authorization as early as possible, without interrupting
* the user's workflow. If the backend's authentication phase happens in the helper and the
* action requires authentication, \c Authorized will be returned.
*
* The main difference with authorize is that this method does not try to acquire authorization
* if the backend's authentication phase happens in the helper: using authorize in such a case
* might lead to ask the user its password twice, as the helper might time out, or in the case
* of a one shot authorization, the scope of the authorization would end with the authorization
* check itself. For this reason, you should @b always use this method instead of authorize, which
* is meant only for very advanced usages.
*
* This method is always safe to be called and used before an execution, even if not needed.
*
* @since 4.5
*
* @return The result of the early authorization process, with the caveats described above.
*/
AuthStatus earlyAuthorize() const;
/**
* @brief Gets information about the authorization status of an action
*
* This methods query the authorization backend to know if the user can try
* to acquire the authorization for this action. If the result is Action::AuthRequired,
* the user can try to acquire the authorization by authenticating.
*
* It should not be needed to call this method directly, because the execution methods
* already take care of all the authorization stuff.
*
* @return @c Action::Denied if the user doesn't have the authorization to execute the action,
* @c Action::Authorized if the action can be executed,
* @c Action::AuthRequired if the user could acquire the authorization after authentication,
* @c Action::UserCancelled if the user cancels the authentication dialog. Not currently supported by the Polkit backend
*/
AuthStatus status() const;
/**
* @brief Synchronously executes the action
*
* This is the simpler of all the action execution methods. It sends an execution request to the
* caller, and returns the reply directly to the caller. The ActionReply object will contain the
* custom data coming from the helper.
*
* The method blocks the execution, and will
* return only when the action has been completed (or failed). Take note, however, that with the D-Bus
* helper proxy (currently the only one implemented on all the supported platforms), the request is
* sent using the QDBus::BlockWithGui flag.
*
* This means the method will enter a local eventloop to wait
* for the reply. This allows the application GUI to stay responsive, but you have to be prepared to
* receive other events in the meantime.
*
* All the signals from the ActionWatcher class are emitted also with this method (although they're more
* useful with the asynchronous calls)
*
* The method checks for authorization before to execute the action. If the user is not authorized, the
* return value will be ActionReply::AuthorizationDeniedReply.
* If the user cancels the authentication, the return value should be ActionReply::UserCancelledReply.
* Due to policykit limitations, this currently only with the Mac OS X backend.
*
* If the helper is busy executing another action (or action group) the reply will be ActionReply::HelperBusyReply
*
* If the request cannot be sent for bus errors, the method returns ActionReply::DBusErrorReply.
*
* @return The reply from the helper, or an error reply if something's wrong.
*/
ActionReply execute() const;
/**
* @brief Synchronously executes the action with a specific helperID
*
* This method does the exact same thing as execute(), but it takes a specific helperID, useful
* if you don't want to use the default one without changing it with setHelperID()
*
* @param helperID The helper ID to use for the execution of this action
* @return The reply from the helper, or an error if something's wrong.
*/
ActionReply execute(const QString &helperID) const;
void setExecutesAsync(bool async);
bool executesAsync() const;
/**
* @brief Asynchronously executes a group of actions with a single request
*
* This method executes each action in the list. It checks for authorization of each action, and put the
* denied actions, if any, in the list pointed by the deniedActions parameter, if not NULL.
*
* Please note that with the D-Bus helper proxy (currently the only one implemented), the execution of a group
* of actions is very different from executing in sequence each action using, for example, executeAsync().
* Currently, the helper can execute only one request at the time. For this reason, if you have to call
* different actions in sequence, you can't call executeAsync() like this:
* @code
* action1.executeAsync();
* action2.executeAsync();
* @endcode
* because the second call will almost certainly return ActionReply::HelperBusy. You would have to execute the second
* action in the slot connected to the first action's actionPerformed() signal. This is not so good. This method
* allows the application to send a request with a list of actions. With this method, the code above becomes:
* @code
* QList<Action> list;
* list << action1 << action2;
* Action::executeActions(list);
* @endcode
* The return value will be false if communication errors occur. It will also be false if <b>all</b> the actions
* in the list are denied.
*
* @param actions The list of actions to execute
* @param deniedActions A pointer to a list to fill with the denied actions. Pass NULL if you don't need them.
* @param helperId The helper ID to execute the actions on.
*/
static bool executeActions(const QList<Action> &actions, QList<Action> *deniedActions, const QString &helperId);
/**
* Convenience overload. This overload lets you specify, in addition, a QWidget which will be used as the
* authentication dialog's parent.
*
* @since 4.6
*
* @see executeActions
* @see setParentWidget
*/
static bool executeActions(const QList<Action> &actions, QList<Action> *deniedActions, const QString &helperId,
QWidget *parent);
/**
* @brief Ask the helper to stop executing an action
*
* This method sends a request to the helper asking to stop the execution of an action. It is only
* useful for long-running actions, because short and fast actions won't obbey to this request most of the times.
* Calling this method will make the HelperSupport::isStopped() method to return true the next time it's called.
*
* It's the helper's responsibility to regularly call it and exit if requested
* The actionPerformed() signal is emitted normally because, actually, the helper exists regularly. The return data
* in this case is application-dependent.
*/
void stop();
/**
* @brief Ask the helper to stop executing an action, using a specific helper ID
*
* This method works exactly as the stop() method, but it lets you specify an helper ID different from the
* default one.
*
* To stop an action you need to send the stop request to the helper that is executing that action. This of course means you have to
* use the same helperID used for the execution call (either passed as a parameter or set as default with setHelperID() )
*/
void stop(const QString &helperID);
/**
* @brief Sets a parent widget for the authentication dialog
*
* This function is used for explicitly setting a parent window for an eventual authentication dialog required when
* authorization is triggered. Some backends, in fact, (like polkit-1) need to have a parent explicitly set for displaying
* the dialog correctly.
*
* @note If you are using KAuth through one of KDE's GUI components (KPushButton, KCModule...) you do not need and should not
* call this function, as it is already done by the component itself.
*
* @since 4.6
*
* @param parent A QWidget which will be used as the dialog's parent
*/
void setParentWidget(QWidget *parent);
/**
* @brief Returns the parent widget for the authentication dialog for this action
*
* @since 4.6
*
* @returns A QWidget which will is being used as the dialog's parent
*/
QWidget *parentWidget() const;
};
} // namespace Auth
#endif

View file

@ -1,195 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#include "kauthactionreply.h"
#include <QDebug>
namespace KAuth
{
class ActionReply::Private
{
public:
QVariantMap data; // User-defined data for success and helper error replies, empty for kauth errors
int errorCode;
QString errorDescription;
ActionReply::Type type;
};
// Predefined replies
const ActionReply ActionReply::SuccessReply = ActionReply();
const ActionReply ActionReply::HelperErrorReply = ActionReply(ActionReply::HelperError);
const ActionReply ActionReply::NoResponderReply = ActionReply(ActionReply::NoResponder);
const ActionReply ActionReply::NoSuchActionReply = ActionReply(ActionReply::NoSuchAction);
const ActionReply ActionReply::InvalidActionReply = ActionReply(ActionReply::InvalidAction);
const ActionReply ActionReply::AuthorizationDeniedReply = ActionReply(ActionReply::AuthorizationDenied);
const ActionReply ActionReply::UserCancelledReply = ActionReply(ActionReply::UserCancelled);
const ActionReply ActionReply::HelperBusyReply = ActionReply(ActionReply::HelperBusy);
const ActionReply ActionReply::DBusErrorReply = ActionReply(ActionReply::DBusError);
// Constructors
ActionReply::ActionReply(const ActionReply &reply)
: d(new Private())
{
*this = reply;
}
ActionReply::ActionReply()
: d(new Private())
{
d->errorCode = 0;
d->type = Success;
}
ActionReply::ActionReply(ActionReply::Type type)
: d(new Private())
{
d->errorCode = 0;
d->type = type;
}
ActionReply::ActionReply(int error)
: d(new Private())
{
d->errorCode = error;
d->type = KAuthError;
}
ActionReply::~ActionReply()
{
delete d;
}
void ActionReply::setData(const QVariantMap &data)
{
d->data = data;
}
void ActionReply::addData(const QString &key, const QVariant &value)
{
d->data.insert(key, value);
}
QVariantMap ActionReply::data() const
{
return d->data;
}
ActionReply::Type ActionReply::type() const
{
return d->type;
}
void ActionReply::setType(ActionReply::Type type)
{
d->type = type;
}
bool ActionReply::succeeded() const
{
return d->type == Success;
}
bool ActionReply::failed() const
{
return d->type != Success;
}
int ActionReply::errorCode() const
{
return d->errorCode;
}
void ActionReply::setErrorCode(int errorCode)
{
d->errorCode = errorCode;
if (d->type != HelperError) {
d->type = KAuthError;
}
}
QString ActionReply::errorDescription() const
{
return d->errorDescription;
}
void ActionReply::setErrorDescription(const QString &error)
{
d->errorDescription = error;
}
QByteArray ActionReply::serialized() const
{
QByteArray data;
QDataStream s(&data, QIODevice::WriteOnly);
s << *this;
return data;
}
ActionReply ActionReply::deserialize(const QByteArray &data)
{
ActionReply reply;
QByteArray a(data);
QDataStream s(&a, QIODevice::ReadOnly);
s >> reply;
return reply;
}
// Operators
ActionReply &ActionReply::operator=(const ActionReply & reply)
{
d->data = reply.d->data;
d->errorCode = reply.d->errorCode;
d->errorDescription = reply.d->errorDescription;
d->type = reply.d->type;
return *this;
}
bool ActionReply::operator==(const ActionReply &reply) const
{
return (d->type == reply.d->type && d->errorCode == reply.d->errorCode);
}
bool ActionReply::operator!=(const ActionReply &reply) const
{
return (d->type != reply.d->type || d->errorCode != reply.d->errorCode);
}
QDataStream &operator<<(QDataStream &d, const ActionReply &reply)
{
return d << reply.d->data << reply.d->errorCode << (quint32)reply.d->type << reply.d->errorDescription;
}
QDataStream &operator>>(QDataStream &stream, ActionReply &reply)
{
quint32 i;
stream >> reply.d->data >> reply.d->errorCode >> i >> reply.d->errorDescription;
reply.d->type = (ActionReply::Type) i;
return stream;
}
} // namespace Auth

View file

@ -1,606 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#ifndef ACTION_REPLY_H
#define ACTION_REPLY_H
#include <QtCore/qvariant.h>
#include <QtCore/qdatastream.h>
#include <kdecore_export.h>
/**
@namespace KAuth
@section kauth_intro Introduction
The KDE Authorization API allows developers to write desktop applications that run high-privileged tasks in an easy, secure and cross-platform way. Previously, if an application had to do administrative tasks,
it had to be run as root, using mechanisms such as sudo or graphical equivalents, or by setting the executable's setuid bit. This approach has some drawbacks. For example, the whole application code,
including GUI handling and network communication, had to be done as root. More code that runs as root means more possible security holes.
The solution is the caller/helper pattern. With this pattern, the privileged code is isolated in a small helper tool that runs as root. This tool includes only the few lines of code that actually
need to be run with privileges, not the whole application logic. All the other parts of the application are run as a normal user, and the helper tool is called when needed, using a secure mechanism that
ensures that the user is authorized to do so. This pattern is not very easy to implement, because the developer has to deal with a lot of details about how to authorize the user, how to call the helper
with the right privileges, how to exchange data with the helper, etc.. This is where the new KDE Authorization API becomes useful. Thanks to this new library, every developer can implement the
caller/helper pattern to write application that require high privileges, with a few lines of code in an easy, secure and cross-platform way.
Not only: the library can also be used to lock down some actions in your application without using a helper but just checking for authorization and verifying if the user is allowed to perform it.
The KDE Authorization library uses different backends depending on the system where it's built. As far as the user authorization is concerned, it currently uses PolicyKit on linux and Authorization Services
on Mac OSX, and a Windows backend will eventually be written, too. At the communication layer, the library uses D-Bus on every supported platform.
@section kauth_concepts Concepts
There are a few concepts to understand when using the library. Much of those are carried from underlying APIs such as PolicyKit, so if you know something about them there shouldn't be problems.
An <i>action</i> is a single task that needs to be done by the application. You refer to an action using an action identifier, which is a string in reverse domain name syntax (to avoid duplicates). For
example, if the date/time control center module needs to change the date, it would need an action like "org.kde.datatime.change". If your application has to perform more than one privileged task, you
should configure more than one action. This allows system administrators to fine tune the policies that allow users to perform your actions.
The <i>authorization</i> is the process that is executed to decide if a user can perform an action or not. In order to execute the helper as root, the user has to be authorized. For example, on linux,
che policykit backend will look at the policykit policy database to see what requirements the user has to meet in order to execute the action you requested. The policy set for that action could allow
or deny that user, or could say the user has to authenticate in order to gain the authorization.
The <i>authentication</i> is the process that allows the system to know that the person is in front of the console is who he says to be. If an action can be allowed or not depending on the user's identity,
it has to be proved by entering a password or any other identification data the system requires.
A typical session with the authorization API is like this:
- The user want to perform some privileged task
- The application asks the system if the user is authorized.
- The system asks the user to authenticate, if needed, and reply the application.
- The application uses some system-provided mechanism to execute the helper's code as the root user. Previously, you had to set the setuid bit to do this, but we have something cool called
"dbus activation" that doesn't require the setuid bit and is much more flexible.
- The helper code, immediately after starting, checks if the caller is authorized to do what it asks. If not the helper immediately exits!
- If the caller is authorized, the helper executes the task and exits.
- The application receives data back from the helper.
All these steps are managed by the library. Following sections will focus on how to write the helper to implement your actions and how to call the helper from the application.
@section kauth_helper Writing the helper tool
The first thing you need to do before writing anything is to decide what actions you need to implement. Every action needs to be identified by a string in the reverse domain name syntax. This helps to
avoid duplicates. An example of action id is "org.kde.datetime.change" or "org.kde.ksysguard.killprocess". Action names can only contain lowercase letters and dots (not as the first or last char).
You also need an identifier for your helper. An application using the KDE auth api can implement and use more than one helper, implementing different actions. An helper is uniquely identified in the
system context with a string. It, again, is in reverse domain name syntax to avoid duplicates. A common approach is to call the helper like the common prefix of your action names.
For example, the Date/Time kcm module could use a helper called "org.kde.datetime", to perform actions like "org.kde.datetime.changedate" and "org.kde.datetime.changetime". This naming convention
simplifies the implementation of the helper.
From the code point of view, the helper is implemented as a QObject subclass. Every action is implemented by a public slot. In the example/ directory in the source code tree you find a complete example.
Let's look at that.
The helper.h file declares the class that implements the helper. It looks like:
@code
#include <kauthactionreply.h>
using namespace KAuth;
class MyHelper : public QObject
{
Q_OBJECT
public slots:
ActionReply read(const QVariantMap& args);
ActionReply write(const QVariantMap& args);
ActionReply longaction(const QVariantMap& args);
};
@endcode
The slot names are the last part of the action name, without the helper's ID if it's a prefix, with all the dots replaced by underscores. In this case, the helper ID is "org.kde.auth.example", so those
three slots implement the actions "org.kde.auth.example.read", "org.kde.auth.example.write" and "org.kde.auth.example.longaction". The helper ID doesn't have to appear at the beginning of the action
name, but it's good practice. If you want to extend MyHelper to implement also a different action like "org.kde.datetime.changetime", since the helper ID doesn't match you'll have to implement a
slot called org_kde_datetime_changetime().
The slot's signature is fixed: the return type is ActionReply, a class that allows you to return results, error codes and custom data to the application when your action has finished to run.
Please note that due to QMetaObject being picky about namespaces, you NEED to declare the return type as ActionReply and not KAuth::ActionReply. So the using declaration is compulsory
The QVariantMap object that comes as argument contains custom data coming from the application.
Let's look at the read action implementation. Its purpose is to read files:
@code
ActionReply MyHelper::read(QVariantMap args)
{
ActionReply reply;
QString filename = args["filename"].toString();
QFile file(filename);
if (!file.open(QIODevice::ReadOnly)) {
reply = ActionReply::HelperErrorReply;
reply.setErrorCode(file.error());
return reply;
}
QTextStream stream(&file);
QString contents;
stream >> contents;
reply.data()["contents"] = contents;
return reply;
}
@endcode
First, the code creates a default reply object. The default constructor creates a reply that reports success. Then it gets the filename parameter from the argument QVariantMap, that has previously been
set by the application, before calling the helper. If it fails to open the file, it creates an ActionReply object that notifies that some error has happened in the helper, then set the error code to
that returned by QFile and returns. If there is no error, it reads the file. The contents are put into the reply.data() object, which is another QVariantMap. It will be sent back to the application
with the reply.
Because this class will be compiled into a standalone executable, we need a main() function and some code to initialize everything: you don't have to write it. Instead, you use the
KDE4_AUTH_HELPER_MAIN() macro that will take care of everything. It's used like this:
@code
KDE4_AUTH_HELPER_MAIN("org.kde.auth.example", MyHelper)
@endcode
The first parameter is the string containing the helper identifier. Please note that you need to use this same string in the application's code to tell the library which helper to call, so please
stay away from typos, because we don't have any way to detect them. The second parameter is the name of the helper's class.
Your helper, if complex, can be composed of a lot of source files, but the important thing is to include this macro in one at least one of them.
To build the helper, KDE macros provide a function named kde4_install_auth_helper_files(). Use it in your cmake file like this:
@code
kde4_add_executable(<helper_target> your sources...)
target_link_libraries(<helper_target> your libraries...)
install(TARGETS <helper_target> DESTINATION ${KDE4_LIBEXEC_INSTALL_DIR})
kde4_install_auth_helper_files(<helper_target> <helper_id> <user>)
@endcode
The first argument is the cmake target name for the helper executable, which you have to build and install separately. Make sure to INSTALL THE HELPER IN ${KDE4_LIBEXEC_INSTALL_DIR},
otherwise kde4_install_auth_helper_files will not work. The second argument is the
helper id. Please be sure to don't misspell it, and to not quote it. The user parameter is the user that the helper has to be run as. It usually is root, but some actions could require less strict
permissions, so you should use the right user where possible (for example the user apache if you have to mess with apache settings). Note that the target created by this macro already links to
libkauth and QtCore
@section kauth_actions Action registration
To be able to authorize the actions, they have to be added to the policy database. To do this in a cross-platform way, we provide a cmake macro. It looks like:
@code
kde4_install_auth_actions(<helper_id> <actions definition file>)
@endcode
The action definition file describes which actions are implemented by your code and which default security options they should have. It is a common text file in ini format, with one section for
each action and some parameters. The definition for the read action is:
@verbatim
[org.kde.auth.example.read]
Name=Read action
Description=Read action description
Policy=auth_admin
Persistence=session
@endverbatim
The name parameter is a text describing the action for <i>who reads the file</i>. The description parameter is the message shown to the user in the authentication dialog. It should be a finite phrase.
The policy attribute specify the default rule that the user must satisfy to be authorized. Possible values are:
- yes: the action should be always allowed
- no: the action should be always denied
- auth_self: the user should authenticate as itself
- auth_admin: the user should authenticate as an administrator user
The persistence attribute is optional. It says how long an authorization should be retained for that action. The values could be:
- session: the authorization persists until the user logs-out
- always: the authorization will persist indefinitely
@section kauth_app Calling the helper from the application
Once the helper is ready, we need to call it from the main application. In the example's mainwindow.cpp you can see how this is done. To create a reference to an action, an object of type Action has to
be created. Every Action object refers to an action by its action id. Two objects with the same action id will act on the same action.
With an Action object, you can authorize and execute the action. To execute an action you have a couple of choices:
- A synchronous call, using the Action::execute() method, will start the helper, execute the action and return the reply.
- An asynchronous call, by setting Action::setExecutesAsync(true) and calling ::execute(), will start the helper and return immediately.
The asynchronous call is the most flexible alternative, but you need a way to obtain the reply. This is done by connecting to a signal, but the Action class is not a QObject subclass. Instead, you connect
to signals exposed by the ActionWatcher class. For every action id you use, there is one ActionWatcher object. You can retrieve it using the Action::watcher() method. If you execute an action using
Action::executeAsync(), you can connect to the actionPerformed(ActionReply) signal to be notified when the action has been completed (or failed). As a parameter, you'll get a reply object containing
all the data you need. As a convenience, you can also pass an object and a slot to the executeAsync() method to directly connect them to the signal, if you don't want to mess with watchers.
The piece of code that calls the action of the previous example is located in example/mainwindow.cpp in the on_readAction_triggered() slot. It looks like this:
@code
QVariantMap args;
args["filename"] = filename;
Action readAction = "org.kde.auth.example.read";
readAction.setHelperID("org.kde.auth.example");
readAction.setArguments(args);
ActionReply reply = readAction.execute();
if (reply.failed())
QMessageBox::information(this, "Error", QString("KAuth returned an error code: %1").arg(reply.errorCode()));
else
contents = reply.data()["contents"].toString();
@endcode
First of all, it creates the action object specifying the action id. Then it loads the filename (we want to read a forbidden file) into the arguments() QVariantMap, which will be directly passed to the
helper in the read() slot's parameter. This example code uses a synchronous call to execute the action and retrieve the reply. If the reply succeeded, the reply data is retrieved from the returned QVariantMap
object. Please note that, although the execute() method will return only when the action is completed, the GUI will remain responsive because an internal event loop is entered. This means you should be
prepared to receive other events in the meanwhile. Also, notice that you have to explicitly set the helper ID to the action: this is done for added safety, to prevent the caller from accidentally invoking
a helper, and also because KAuth actions may be used without a helper attached (the default). In this case, action.execute() will return ActionSuccess if the authentication went well. This is quite useful
if you want your user to authenticate before doing something, which however needs no privileged permissions implementation-wise.
@section kauth_async Asynchronous calls, data reporting, and action termination
For a more advanced example, we look at the action "org.kde.auth.example.longaction" in the example helper. This is an action that takes a long time to execute, so we need some features:
- The helper needs to regularly send data to the application, to inform about the execution status.
- The application needs to be able to stop the action execution if the user stops it or close the application.
The example code follows:
@code
ActionReply MyHelper::longaction(QVariantMap args)
{
for (int i = 1; i <= 100; i++) {
if (HelperSupport::isStopped())
break;
HelperSupport::progressStep(i);
usleep(250000);
}
return ActionReply::SuccessReply;
}
@endcode
In this example, the action is only waiting a "long" time using a loop, but we can see some interesting line. The progress status is sent to the application using the HelperSupport::progressStep() method.
When this method is called, the ActionWatcher associated with this action will emit the progressStep() signal, reporting back the data to the application. There are two overloads of these methods and
corresponding signals. The one used here takes an integer. Its meaning is application dependent, so you can use it as a sort of percentage. The other overload takes a QVariantMap object that is directly
passed to the app. In this way, you can report to the application all the custom data you want.
In this example code, the loop exits when the HelperSupport::isStopped() returns true. This happens when the application calls the stop() method on the correponding action object. The stop() method, this
way, asks the helper to stop the action execution. It's up to the helper to obbey to this request, and if it does so, it should return from the slot, _not_ exit.
The code that calls the action in the application connects a slot to the actionPerformed() signal and then call executeAsync(). The progressStep() signal is directly connected to a QProgressBar, and
the Stop button in the UI is connected to a slot that calls the Action::stop() method.
@code
void MainWindow::on_longAction_triggered()
{
Action longAction = "org.kde.auth.example.longaction";
connect(longAction.watcher(), SIGNAL(progressStep(int)),
progressBar, SLOT(setValue(int)));
connect(longAction.watcher(), SIGNAL(actionPerformed(ActionReply)),
this, SLOT(longActionPerformed(ActionReply)));
longAction.setExecutesAsync(true);
if (longAction.execute() != Action::Authorized)
this->statusBar()->showMessage("Could not execute the long action");
//...
}
void MainWindow::stopLongAction()
{
Action("org.kde.auth.example.longaction").stop();
}
void MainWindow::longActionPerformed(ActionReply reply)
{
//...
if (reply.succeeded())
this->statusBar()->showMessage("Action succeeded", 10000);
else
this->statusBar()->showMessage(QString("Could not execute the long action: %1").arg(reply.errorCode()), 10000);
}
@endcode
Please pay attention that when you call an action, the helper will be busy executing that action. Therefore, you can't call two execute() methods in sequence like that:
@code
action1.execute();
action2.execute();
@endcode
If you do, you'll get a HelperBusy reply from the second action.
A solution would be to launch the second action from the slot connected to the first's actionPerformed signal, but this would be very ugly. Read further to know how to solve this problem.
@section kauth_other Other features
To allow to easily execute several actions in sequence, you can execute them in a group. This means using the Action::executeActions() static method, which takes a list of actions and asks the helper
to execute them with a single request. The helper will execute the actions in the specified order. All the signals will be emitted from the watchers associated with each action.
Sometimes the application needs to know when a particular action has started to execute. For this purpose, you can connect to the actionStarted() signal. It is emitted immediately before the helper's
slot is called. This isn't very useful if you call execute(), but if you use executeActions() it lets you know when individual actions in the group are started.
It doesn't happen very frequently that you code something that doesn't require some debugging, and you'll need some tool, even a basic one, to debug your helper code as well. For this reason, the
KDE Authorization library provides a message handler for the Qt debugging system. This means that every call to qDebug() & co. will be reported to the application, and printed using the same qt debugging
system, with the same debug level.
If, in the helper code, you write something like:
@code
qDebug() << "I'm in the helper";
@endcode
You'll see something like this in the <i>application</i>'s output:
@verbatim
Debug message from the helper: I'm in the helper
@endverbatim
Remember that the debug level is preserved, so if you use qFatal() you won't only abort the helper (which isn't suggested anyway), but also the application.
*/
namespace KAuth
{
/**
* @brief Class that encapsulates a reply coming from the helper after executing an action
*
* An instance of ActionReply is returned every time you execute an action with the Action
* class. You get the reply directly from the Action::execute() method or indirectly as
* a parameter of the ActionWatcher::actionPerformed() signal.
*
* ActionReply objects can contain both data from a successful action or an error indicator.
* In case of success, the errorCode() is ActionReply::NoError (zero) and the type() is
* ActionReply::Success. The data() method returns a QVariantMap object that may contain
* custom data sent back by the helper.
*
* In case of errors coming from the library, the type() is ActionReply::KAuthError. In this
* case, errorCode() will always be one of the predefined errors from the ActionReply::Error enum.
* An error reply of KAuthError type always contains an empty data() object. For some kind of errors
* you could get a human-readable description with errorDescription().
*
* If, instead, the helper itself has to report some errors occurred during the action execution,
* the type() will be (and has to be) ActionReply::HelperError. In this case the data() object can
* contain custom data from the helper, and the errorCode() and errorDescription() values are
* application-dependent.
*
* In the helper, to create an action reply object you have two choices: using the constructor, or
* the predefined replies. For example, to create a successful reply you can use the default constructor
* but to create a helper error reply, instead of writing <i>ActionReply(ActionReply::HelperError)</i>
* you could use the more convenient <i>ActionReply::HelperErrorReply</i> constant.
*
* You should not use the predefined error replies to create and return new errors. Replies with the
* KAuthError type are intended to be returned by the library only. However, you can use them for
* comparisons.
*
* To quickly check for success or failure of an action, you can use succeeded() or failed().
*
* @since 4.4
*/
class KDECORE_EXPORT ActionReply
{
class Private;
Private * const d;
public:
/**
* Enumeration of the different kinds of replies.
*/
enum Type {
KAuthError, ///< An error reply generated by the library itself.
HelperError, ///< An error reply generated by the helper.
Success ///< The action has been completed successfully
};
static const ActionReply SuccessReply; ///< An empty successful reply. Same as using the default constructor
static const ActionReply HelperErrorReply; ///< An empty reply with type() == HelperError.
static const ActionReply NoResponderReply; ///< errorCode() == NoResponder
static const ActionReply NoSuchActionReply; ///< errorCode() == NoSuchAction
static const ActionReply InvalidActionReply; ///< errorCode() == InvalidAction
static const ActionReply AuthorizationDeniedReply; ///< errorCode() == AuthorizationDenied
static const ActionReply UserCancelledReply; ///< errorCode() == UserCancelled
static const ActionReply HelperBusyReply; ///< errorCode() == HelperBusy
static const ActionReply DBusErrorReply; ///< errorCode() == DBusError
/**
* The enumeration of the possible values of errorCode() when type() is ActionReply::KAuthError
*/
enum Error {
NoError = 0, ///< No error.
NoResponder, ///< The helper responder object hasn't been set. This shouldn't happen if you use the KDE4_AUTH_HELPER macro in the helper source
NoSuchAction, ///< The action you tried to execute doesn't exist.
InvalidAction, ///< You tried to execute an invalid action object
AuthorizationDenied, ///< You don't have the authorization to execute the action
UserCancelled, ///< Action execution has been cancelled by the user
HelperBusy, ///< The helper is busy executing another action (or group of actions). Try later
DBusError ///< An error from D-Bus occurred
};
/// Default constructor. Sets type() to Success and errorCode() to zero.
ActionReply();
/**
* @brief Constructor to directly set the type.
*
* This constructor directly sets the reply type. You shouldn't need to
* directly call this constructor, because you can use the more convenient
* predefined replies constants. You also shouldn't create a reply with
* the KAuthError type because it's reserved for errors coming from the
* library.
*
* @param type The type of the new reply
*/
ActionReply(Type type);
/**
* @brief Constructor that creates a KAuthError reply with a specified error code.
* Do not use outside the library.
*
* This constructor is for internal use only, since it creates a reply
* with KAuthError type, which is reserved for errors coming from the library.
*
* @param errorCode The error code of the new reply
*/
ActionReply(int errorCode);
/// Copy constructor
ActionReply(const ActionReply &reply);
/// Virtual destructor
virtual ~ActionReply();
/**
* @brief Sets the custom data to send back to the application
*
* In the helper's code you can use this function to set an QVariantMap
* with custom data that will be sent back to the application.
*
* @param data The new QVariantMap object.
*/
void setData(const QVariantMap &data);
/**
* @brief Returns the custom data coming from the helper.
*
* This method is used to get the object that contains the custom
* data coming from the helper. In the helper's code, you can set it
* using setData() or the convenience method addData().
*
* @return The data coming from (or that will be sent by) the helper
*/
QVariantMap data() const;
/**
* @brief Convenience method to add some data to the reply.
*
* This method adds the pair @c key/value to the QVariantMap used to
* report back custom data to the application.
*
* Use this method if you don't want to create a new QVariantMap only to
* add a new entry.
*
* @param key The new entry's key
* @param value The value of the new entry
*/
void addData(const QString &key, const QVariant &value);
/// Returns the reply's type
Type type() const;
/**
* @brief Sets the reply type
*
* Every time you create an action reply, you implicitly set a type.
* Default constructed replies or ActionReply::SuccessReply have
* type() == Success.
* ActionReply::HelperErrorReply has type() == HelperError.
* Predefined error replies have type() == KAuthError.
*
* This means you rarely need to change the type after the creation,
* but if you need to, don't set it to KAuthError, because it's reserved
* for errors coming from the library.
*
* @param type The new reply type
*/
void setType(Type type);
/// Returns true if type() == Success
bool succeeded() const;
/// Returns true if type() != Success
bool failed() const;
/**
* @brief Returns the error code of an error reply
*
* The error code returned is one of the values in the ActionReply::Error
* enumeration if type() == KAuthError, or is totally application-dependent if
* type() == HelperError. It also should be zero for successful replies.
*
* @return The reply error code
*/
int errorCode() const;
/**
* @brief Sets the error code of an error reply
*
* If you're setting the error code in the helper because
* you need to return an error to the application, please make sure
* you already have set the type to HelperError, either by calling
* setType() or by creating the reply in the right way.
*
* If the type is Success when you call this method, it will become KAuthError
*
* @param errorCode The new reply error code
*/
void setErrorCode(int errorCode);
/**
* @brief Gets a human-readble description of the error, if available
*
* Currently, replies of type KAuthError rarely report an error description.
* This situation could change in the future.
*
* By now, you can use this method for custom errors of type HelperError.
*
* @return The error human-readable description
*/
QString errorDescription() const;
/**
* @brief Sets a human-readble description of the error
*
* Call this method from the helper if you want to send back a description for
* a custom error. Note that this method doesn't affect the errorCode in any way
*
* @param error The new error description
*/
void setErrorDescription(const QString &error);
/**
* @brief Serialize the reply into a QByteArray.
*
* This is a convenience method used internally to sent the reply to a remote peer.
* To recreate the reply, use deserialize()
*
* @return A QByteArray representation of this reply
*/
QByteArray serialized() const;
/**
* @brief Deserialize a reply from a QByteArray
*
* This method returns a reply from a QByteArray obtained from
* the serialized() method.
*
* @param data A QByteArray obtained with serialized()
*/
static ActionReply deserialize(const QByteArray &data);
/// Assignment operator
ActionReply &operator=(const ActionReply &reply);
/**
* @brief Comparison operator
*
* This operator checks if the type and the error code of two replies are the same.
* It <b>doesn't</b> compare the data or the error descriptions, so be careful.
*
* The suggested use it to compare a reply agains one of the predefined error replies:
* @code
* if(reply == ActionReply::HelperBusyReply) {
* // Do something...
* }
* @endcode
*
* Note that you can do it also by compare errorCode() with the relative enumeration value.
*/
bool operator==(const ActionReply &reply) const;
/**
* @brief Negated comparison operator
*
* See the operator==() for an important notice.
*/
bool operator!=(const ActionReply &reply) const;
/// Output streaming operator for QDataStream
friend QDataStream &operator<<(QDataStream &, const ActionReply &);
/// Input streaming operator for QDataStream
friend QDataStream &operator>>(QDataStream &, ActionReply &);
};
} // namespace Auth
#endif

View file

@ -1,118 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#include "kauthactionwatcher.h"
#include "BackendsManager.h"
#include <QHash>
namespace KAuth
{
class ActionWatcher::Private
{
public:
Private(ActionWatcher *parent) : q(parent) {}
ActionWatcher *q;
QString action;
void actionStartedSlot(const QString &action);
void actionPerformedSlot(const QString &action, const ActionReply &reply);
void progressStepSlot(const QString &action, int i);
void progressStepSlot(const QString &action, const QVariantMap &data);
void statusChangedSlot(const QString &action, Action::AuthStatus status);
};
static QHash<QString, ActionWatcher *> s_watchers;
ActionWatcher::ActionWatcher(const QString &action)
: QObject(0)
, d(new Private(this))
{
d->action = action;
HelperProxy *helper = BackendsManager::helperProxy();
connect(helper, SIGNAL(actionStarted(QString)), this, SLOT(actionStartedSlot(QString)));
connect(helper, SIGNAL(actionPerformed(QString,ActionReply)), this, SLOT(actionPerformedSlot(QString,ActionReply)));
connect(helper, SIGNAL(progressStep(QString,int)), this, SLOT(progressStepSlot(QString,int)));
connect(helper, SIGNAL(progressStep(QString,QVariantMap)), this, SLOT(progressStepSlot(QString,QVariantMap)));
connect(BackendsManager::authBackend(), SIGNAL(actionStatusChanged(QString,Action::AuthStatus)),
this, SLOT(statusChangedSlot(QString,Action::AuthStatus)));
}
ActionWatcher::~ActionWatcher()
{
delete d;
}
ActionWatcher *ActionWatcher::watcher(const QString &action)
{
if (!s_watchers.contains(action)) {
s_watchers[action] = new ActionWatcher(action);
}
return s_watchers[action];
}
QString ActionWatcher::action() const
{
return d->action;
}
void ActionWatcher::Private::actionStartedSlot(const QString &taction)
{
if (taction == action) {
emit q->actionStarted();
}
}
void ActionWatcher::Private::actionPerformedSlot(const QString &taction, const ActionReply &reply)
{
if (taction == action) {
emit q->actionPerformed(reply);
}
}
void ActionWatcher::Private::progressStepSlot(const QString &taction, int i)
{
if (taction == action) {
emit q->progressStep(i);
}
}
void ActionWatcher::Private::progressStepSlot(const QString &taction, const QVariantMap &data)
{
if (taction == action) {
emit q->progressStep(data);
}
}
void ActionWatcher::Private::statusChangedSlot(const QString &taction, Action::AuthStatus status)
{
if (taction == action) {
emit q->statusChanged(status);
}
}
} // namespace Auth
#include "moc_kauthactionwatcher.cpp"

View file

@ -1,151 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#ifndef ACTION_WATCHER_H
#define ACTION_WATCHER_H
#include <kdecore_export.h>
#include "kauthactionreply.h"
#include "kauthaction.h"
namespace KAuth
{
/**
* @brief Class used to receive notifications about the status of an action execution.
*
* The ActionWatcher class provides some signals useful to track the execution of an action.
* The Action class is designed to be very ligthweight, so it's not the case to make it
* a QObject subclass. This means the action object can't expose signals. This is the reason
* why every action (not every Action object) used by the app has an associated ActionWatcher.
*
* You don't create watchers directly. Instead, you should get one from the Action::watcher() method,
* if you have an action object, or with the ActionWatcher::watcher() static method, which takes the
* action name string.
*
* See the documentation of single signals for more details about them.
*
* @since 4.4
*/
class KDECORE_EXPORT ActionWatcher : public QObject
{
Q_OBJECT
class Private;
Private * const d;
ActionWatcher();
ActionWatcher(const QString &action);
Q_PRIVATE_SLOT(d, void actionStartedSlot(const QString &action))
Q_PRIVATE_SLOT(d, void actionPerformedSlot(const QString &action, const ActionReply &reply))
Q_PRIVATE_SLOT(d, void progressStepSlot(const QString &action, int i))
Q_PRIVATE_SLOT(d, void progressStepSlot(const QString &action, const QVariantMap &data))
Q_PRIVATE_SLOT(d, void statusChangedSlot(const QString &action, Action::AuthStatus status))
public:
/**
* @brief Factory method to get watchers
*
* This method allows you to obtain (and create if needed) an
* action watcher from the action string identifier.
* It's more common to obtain a watcher using Action::watcher(),
* which actually calls this method.
*
* Every signal of this class
* is emitted whichever method you used to execute the action.
* This means you could connect to the signal actionPerformed()
* even if you're using the execute() method (which already returns the reply)
* and you'll get the same reply.
*
* @param action The action string identifier for the creation of the watcher
* @return The action watcher associated with the given action
*/
static ActionWatcher *watcher(const QString &action);
/// Virtual destructor
virtual ~ActionWatcher();
/// Returns the action name associated with this watcher
QString action() const;
Q_SIGNALS:
/**
* @brief Signal emitted when an action starts the execution
*
* This signal is emitted whe In case of
* execute() and executeAsync(), the signal is emitted about
* immediately, because the request is very fast.
*
* If you execute a group of actions using Action::executeActions(),
* this signal is emitted when the single action is actually about
* to be executed, not when the whole group starts executing.
* This means you can use this signal to start some kind of timeout
* to handle helper crashes, if you feel the need.
*/
void actionStarted();
/**
* @brief Signal emitted when an action completed the execution
*
* This signal provides the only way to obtain the reply from the helper
* in case of asynchronous calls. The reply object is the same returned
* by the helper, or an error reply from the library if something went
* wrong.
*
* @param reply The reply coming from the helper
*/
void actionPerformed(const ActionReply &reply);
/**
* @brief Signal emitted by the helper to notify the action's progress
*
* This signal is emitted every time the helper's code calls the
* HelperSupport::progressStep(int) method. This is useful to let the
* helper notify the execution status of a long action.
* The meaning of the integer passed here is totally application-dependent.
* If you need to be more expressive, you can use the other signal that
* pass a QVariantMap.
*
* @param progress The progress indicator from the helper
*/
void progressStep(int progress);
/**
* @brief Signal emitted by the helper to notify the action's progress
*
* This signal is emitted every time the helper's code calls the
* HelperSupport::progressStep(QVariantMap) method. This is useful to let the
* helper notify the execution status of a long action, also providing
* some data, for example if you want to achieve some sort of progressive loading.
* The meaning of the data passed here is totally application-dependent.
* If you only need to pass some percentage, you can use the other signal that
* pass an int.
*
* @param data The progress data from the helper
*/
void progressStep(const QVariantMap &data);
void statusChanged(int status);
};
} // namespace Auth
#endif

View file

@ -1,132 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
* Copyright (C) 2009 Dario Freddi <drf@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#include "kauthhelpersupport.h"
#include <cstdlib>
#include <syslog.h>
#ifdef Q_OS_UNIX
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#endif
#include <QCoreApplication>
#include <QTimer>
#include "BackendsManager.h"
Q_DECLARE_METATYPE(QTimer*)
namespace KAuth
{
namespace HelperSupport
{
void helperDebugHandler(QtMsgType type, const char *msg);
}
static bool remote_dbg = false;
int HelperSupport::helperMain(int argc, char **argv, const char *id, QObject *responder)
{
#ifdef Q_OS_UNIX
//try correct HOME
const char *home = "HOME";
if(getenv(home)==NULL) {
struct passwd *pw = getpwuid(getuid());
if (pw!=NULL) {
setenv(home, pw->pw_dir, 0 /* overwrite */);
}
}
#endif
openlog(id, 0, LOG_USER);
qInstallMsgHandler(&HelperSupport::helperDebugHandler);
QCoreApplication app(argc, argv);
if (!BackendsManager::helperProxy()->initHelper(QString::fromLatin1(id))) {
syslog(LOG_DEBUG, "Helper initialization failed");
return -1;
}
//closelog();
remote_dbg = true;
BackendsManager::helperProxy()->setHelperResponder(responder);
// Attach the timer
QTimer *timer = new QTimer(0);
responder->setProperty("__KAuth_Helper_Shutdown_Timer", QVariant::fromValue(timer));
timer->setInterval(10000);
timer->start();
QObject::connect(timer, SIGNAL(timeout()), &app, SLOT(quit()));
app.exec(); //krazy:exclude=crashy
return 0;
}
void HelperSupport::helperDebugHandler(QtMsgType type, const char *msg)
{
if (!remote_dbg) {
int level = LOG_DEBUG;
switch (type) {
case QtDebugMsg:
level = LOG_DEBUG;
break;
case QtWarningMsg:
level = LOG_WARNING;
break;
case QtCriticalMsg:
level = LOG_CRIT;
break;
case QtFatalMsg:
level = LOG_ERR;
break;
}
syslog(level, "%s", msg);
} else {
BackendsManager::helperProxy()->sendDebugMessage(type, msg);
}
// Anyway I should follow the rule:
if (type == QtFatalMsg) {
exit(-1);
}
}
void HelperSupport::progressStep(int step)
{
BackendsManager::helperProxy()->sendProgressStep(step);
}
void HelperSupport::progressStep(const QVariantMap &data)
{
BackendsManager::helperProxy()->sendProgressStep(data);
}
bool HelperSupport::isStopped()
{
return BackendsManager::helperProxy()->hasToStopAction();
}
} // namespace Auth

View file

@ -1,105 +0,0 @@
/*
* Copyright (C) 2008 Nicola Gigante <nicola.gigante@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .
*/
#ifndef HELPER_SUPPORT_H
#define HELPER_SUPPORT_H
#include <QtCore/qvariant.h>
#include <kdecore_export.h>
#define KDE4_AUTH_HELPER_MAIN(ID, HelperClass) \
int main(int argc, char **argv) { return KAuth::HelperSupport::helperMain(argc, argv, ID, new HelperClass()); }
namespace KAuth
{
/**
* @brief Support class with some KDECORE_EXPORT methods useful to the helper's code
*
* This class provides the API to write the helper tool that executes your actions.
* You don't create instances of HelperSupport. Instead, you use its KDECORE_EXPORT methods.
*
* This them you can notify the application of progress in your action's execution
* and you can check if the application asked you to terminate it.
*
* @since 4.4
*/
namespace HelperSupport
{
/**
* @brief Send a progressStep signal to the caller application
*
* You can use this method to notify progress information about the
* action execution. When you call this method, the ActionWatcher
* object associated with the current action will emit the progressStep(int)
* signal. The meaning of the integer passed here is totally application dependent,
* but you'll want to use it as a sort of percentage.
* If you need to be more expressive, use the other overload which takes a QVariantMap
*
* @param step The progress indicator
*/
KDECORE_EXPORT void progressStep(int step);
/**
* @brief Send a progressStep signal to the caller application
*
* You can use this method to notify progress information about the
* action execution. When you call this method, the ActionWatcher
* object associated with the current action will emit the progressStep(QVariantMap)
* signal. The meaning of the data passed here is totally application dependent.
* If you only need a simple percentage value, use the other overload which takes an int.
*
* @param data The progress data
*/
KDECORE_EXPORT void progressStep(const QVariantMap &data);
/**
* @brief Check if the caller asked the helper to stop the execution
*
* This method will return true if the helper has been asked to stop the
* execution of the current action. If this happens, your helper should
* return (NOT exit). The meaning of the data you return in this case is
* application-dependent.
* It's good practice to check it regularly if you have a long-running action
*
* @return true if the helper has been asked to stop, false otherwise
*/
KDECORE_EXPORT bool isStopped();
/**
* @brief Method that implements the main function of the helper tool. Do not call directly
*
* This method is called in the proper way by the code generated by the KDE4_AUTH_HELPER_MAIN(),
* which creates a main() function for the helper tool.
* macro. You shouldn't call this method directly.
*
* @param argc The argc parameter from the main() function.
* @param argv The argv parameter from the main() function.
* @param id The helper ID as passed to the macro
* @param responder The responder object for the helper. The macro passes a default-constructed,
* heap-allocated object of the class specified as the last macro parameter
*/
KDECORE_EXPORT int helperMain(int argc, char **argv, const char *id, QObject *responder);
} // namespace HelperSupport
} // namespace Auth
#endif

View file

@ -30,7 +30,6 @@
#include "kdebug.h"
#include "kurl.h"
#include "kconfiggroup.h"
#include "kauthorized.h"
#include "kstandarddirs.h"
#include "kconfigini_p.h"
#include "kde_file.h"
@ -243,29 +242,13 @@ bool KDesktopFile::hasDeviceType() const
bool KDesktopFile::tryExec() const
{
Q_D(const KDesktopFile);
// Test for TryExec and "X-KDE-AuthorizeAction"
// Test for TryExec
// NOT readPathEntry (see readPath())
const QString te = d->desktopGroup.readEntry("TryExec", QString());
if (!te.isEmpty() && KGlobal::dirs()->findExe(te).isEmpty()) {
return false;
}
const QStringList list = d->desktopGroup.readEntry("X-KDE-AuthorizeAction", QStringList());
foreach (const QString &it, list) {
if (!KAuthorized::authorize(it.trimmed()))
return false;
}
// See also KService::username()
bool su = d->desktopGroup.readEntry("X-KDE-SubstituteUID", false);
if (su)
{
QString user = d->desktopGroup.readEntry("X-KDE-Username", QString());
if (user.isEmpty())
user = QString::fromLatin1("root");
if (!KAuthorized::authorize(QString::fromLatin1("user/")+user))
return false;
}
return true;
}

View file

@ -83,15 +83,7 @@ public:
/**
* Checks whether the user is authorized to run this desktop file.
* By default users are authorized to run all desktop files but
* the KIOSK framework can be used to activate certain restrictions.
* See README.kiosk for more information.
*
* Note: Since KDE 4.3, there are more restrictions on authorized
* desktop files to prevent users from inadvertently running trojan
* desktop files. Your application launchers should have the executable
* bit set to prevent issues. To see if a restriction is due to
* KIOSK, see KAuthorized.
* By default users are authorized to run all desktop files.
*
* @param path the file to check
* @return true if the user is authorized to run the file

View file

@ -0,0 +1,224 @@
/* This file is part of the KDE libraries
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 "kauthorization.h"
#include <QThread>
#include <QTimer>
#include <QDBusAbstractAdaptor>
#include <QDBusInterface>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <klocale.h>
#include <kdebug.h>
#include <syslog.h>
void kAuthMessageHandler(QtMsgType type, const char *msg)
{
switch (type) {
case QtDebugMsg: {
::syslog(LOG_DEBUG, "%s", msg);
break;
}
case QtWarningMsg: {
::syslog(LOG_WARNING, "%s", msg);
break;
}
case QtCriticalMsg: {
::syslog(LOG_CRIT, "%s", msg);
break;
}
case QtFatalMsg: {
::syslog(LOG_ERR, "%s", msg);
break;
}
}
}
static bool isDBusServiceRegistered(const QString &helper)
{
QDBusReply<bool> reply = QDBusConnection::systemBus().interface()->isServiceRegistered(helper);
if (reply.value() == false) {
kDebug() << "Service not registered" << helper;
return false;
}
return true;
}
static void killDBusService(const QString &helper)
{
if (!isDBusServiceRegistered(helper)) {
return;
}
QDBusInterface kauthorizationinterface(
helper, QString::fromLatin1("/"), QString::fromLatin1("org.kde.kauthorization"),
QDBusConnection::systemBus()
);
QDBusReply<void> reply = kauthorizationinterface.call(QString::fromLatin1("stop"));
if (!reply.isValid()) {
kWarning() << reply.error().message();
}
}
class KAuthorizationAdaptor: public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.kauthorization")
public:
KAuthorizationAdaptor(QObject *parent = nullptr);
public Q_SLOTS:
Q_SCRIPTABLE bool ping();
Q_SCRIPTABLE int execute(const QString &method, const QVariantMap &arguments);
Q_SCRIPTABLE void stop();
};
KAuthorizationAdaptor::KAuthorizationAdaptor(QObject *parent)
: QDBusAbstractAdaptor(parent)
{
}
bool KAuthorizationAdaptor::ping()
{
return true;
}
int KAuthorizationAdaptor::execute(const QString &method, const QVariantMap &arguments)
{
const QByteArray bytemethod = method.toLatin1();
int result = KAuthorization::HelperError;
const bool success = QMetaObject::invokeMethod(
parent(), bytemethod.constData(), Qt::DirectConnection,
Q_RETURN_ARG(int, result), Q_ARG(QVariantMap, arguments)
);
if (!success) {
kWarning() << "Invalid method" << method;
return KAuthorization::MethodError;
}
return result;
}
void KAuthorizationAdaptor::stop()
{
qApp->quit();
}
KAuthorization::KAuthorization(QObject *parent)
: QObject(parent)
{
new KAuthorizationAdaptor(this);
}
bool KAuthorization::isAuthorized(const QString &helper)
{
QDBusInterface kauthorizationinterface(
helper, QString::fromLatin1("/"), QString::fromLatin1("org.kde.kauthorization"),
QDBusConnection::systemBus()
);
QDBusReply<bool> reply = kauthorizationinterface.call(QString::fromLatin1("ping"));
if (!reply.isValid()) {
kWarning() << reply.error().message();
killDBusService(helper);
return false;
}
const bool result = reply.value();
killDBusService(helper);
return result;
}
int KAuthorization::execute(const QString &helper, const QString &method, const QVariantMap &arguments)
{
if (!KAuthorization::isAuthorized(helper)) {
return KAuthorization::AuthorizationError;
}
while (isDBusServiceRegistered(helper)) {
kDebug() << "Waiting for service to unregister" << helper;
QCoreApplication::processEvents();
QThread::msleep(1000);
}
QDBusInterface kauthorizationinterface(
helper, QString::fromLatin1("/"), QString::fromLatin1("org.kde.kauthorization"),
QDBusConnection::systemBus()
);
QDBusReply<int> reply = kauthorizationinterface.call(QString::fromLatin1("execute"), method, arguments);
int result = KAuthorization::DBusError;
if (!reply.isValid()) {
kWarning() << reply.error().message();
} else {
result = reply.value();
}
killDBusService(helper);
kDebug() << "Result" << helper << method << result;
return result;
}
QString KAuthorization::errorString(const int status)
{
switch (status) {
case KAuthorization::NoError: {
return i18n("No error");
}
case KAuthorization::HelperError: {
return i18n("Helper error");
}
case KAuthorization::DBusError: {
return i18n("D-Bus error");
}
case KAuthorization::MethodError: {
return i18n("Method error");
}
case KAuthorization::AuthorizationError: {
return i18n("Authorization error");
}
}
if (status > KAuthorization::NoError) {
return i18n("Custom error");
}
return i18n("Unknown error");
}
void KAuthorization::helperMain(const char* const helper, KAuthorization *object)
{
::openlog(helper, 0, LOG_USER);
qInstallMsgHandler(kAuthMessageHandler);
if (!QDBusConnection::systemBus().registerService(QString::fromLatin1(helper))) {
qApp->exit(1);
return;
}
if (!QDBusConnection::systemBus().registerObject(QString::fromLatin1("/"), object)) {
qApp->exit(2);
return;
}
// in case the process executing the helper crashes
QTimer *quittimer = new QTimer();
quittimer->setInterval(30000);
quittimer->start();
QObject::connect(quittimer, SIGNAL(timeout()), qApp, SLOT(quit()));
}
#include "kauthorization.moc"
#include "moc_kauthorization.cpp"

View file

@ -0,0 +1,66 @@
/* This file is part of the KDE libraries
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.
*/
#ifndef KAUTHORIZATION_H
#define KAUTHORIZATION_H
#include <kdecore_export.h>
#include <QObject>
#include <QVariant>
#include <QCoreApplication>
/*!
Authorization class
@since 4.22
*/
class KDECORE_EXPORT KAuthorization : public QObject
{
Q_OBJECT
public:
enum KAuthorizationStatus {
NoError = 0,
HelperError = -1,
DBusError = -2,
MethodError = -3,
AuthorizationError = -4
};
KAuthorization(QObject *parent = nullptr);
static bool isAuthorized(const QString &helper);
static int execute(const QString &helper, const QString &method, const QVariantMap &arguments);
static QString errorString(const int status);
static void helperMain(const char* const helper, KAuthorization *object);
private:
Q_DISABLE_COPY(KAuthorization);
};
// application instance created before class to ensure D-Bus connection is not made before it
#define K_AUTH_MAIN(HELPER, CLASS) \
int main(int argc, char **argv) { \
QCoreApplication app(argc, argv); \
KAuthorization::helperMain(HELPER, new CLASS()); \
return app.exec(); \
}
#endif // KAUTHORIZATION_H

View file

@ -1,377 +0,0 @@
/* This file is part of the KDE libraries
Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
Copyright (C) 1998, 1999, 2000 Waldo Bastian <bastian@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
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 "kauthorized.h"
#include <QtCore/QDir>
#include <QtCore/QRegExp>
#include <QList>
#include <QCoreApplication>
#include <QMutex>
#include <kglobal.h>
#include <ksharedconfig.h>
#include <kprotocolinfo.h>
#include <kstandarddirs.h>
#include <stdlib.h> // srand(), rand()
#include <unistd.h>
#include <netdb.h>
#include <kurl.h>
#include <kconfiggroup.h>
class URLActionRule
{
public:
#define checkExactMatch(s, b) \
if (s.isEmpty()) b = true; \
else if (s[s.length()-1] == QLatin1Char('!')) \
{ b = false; s.truncate(s.length()-1); } \
else b = true;
#define checkStartWildCard(s, b) \
if (s.isEmpty()) b = true; \
else if (s[0] == QLatin1Char('*')) \
{ b = true; s = s.mid(1); } \
else b = false;
#define checkEqual(s, b) \
b = (s == QString::fromLatin1("="));
URLActionRule(const QByteArray &act,
const QString &bProt, const QString &bHost, const QString &bPath,
const QString &dProt, const QString &dHost, const QString &dPath,
bool perm)
: action(act),
baseProt(bProt), baseHost(bHost), basePath(bPath),
destProt(dProt), destHost(dHost), destPath(dPath),
permission(perm)
{
checkExactMatch(baseProt, baseProtWildCard);
checkStartWildCard(baseHost, baseHostWildCard);
checkExactMatch(basePath, basePathWildCard);
checkExactMatch(destProt, destProtWildCard);
checkStartWildCard(destHost, destHostWildCard);
checkExactMatch(destPath, destPathWildCard);
checkEqual(destProt, destProtEqual);
checkEqual(destHost, destHostEqual);
}
bool baseMatch(const KUrl &url, const QString &protClass) const
{
if (baseProtWildCard)
{
if ( !baseProt.isEmpty() && !url.protocol().startsWith(baseProt) &&
(protClass.isEmpty() || (protClass != baseProt)) )
return false;
}
else
{
if ( (url.protocol() != baseProt) &&
(protClass.isEmpty() || (protClass != baseProt)) )
return false;
}
if (baseHostWildCard)
{
if (!baseHost.isEmpty() && !url.host().endsWith(baseHost))
return false;
}
else
{
if (url.host() != baseHost)
return false;
}
if (basePathWildCard)
{
if (!basePath.isEmpty() && !url.path().startsWith(basePath))
return false;
}
else
{
if (url.path() != basePath)
return false;
}
return true;
}
bool destMatch(const KUrl &url, const QString &protClass, const KUrl &base, const QString &baseClass) const
{
if (destProtEqual)
{
if ( (url.protocol() != base.protocol()) &&
(protClass.isEmpty() || baseClass.isEmpty() || protClass != baseClass) )
return false;
}
else if (destProtWildCard)
{
if ( !destProt.isEmpty() && !url.protocol().startsWith(destProt) &&
(protClass.isEmpty() || (protClass != destProt)) )
return false;
}
else
{
if ( (url.protocol() != destProt) &&
(protClass.isEmpty() || (protClass != destProt)) )
return false;
}
if (destHostWildCard)
{
if (!destHost.isEmpty() && !url.host().endsWith(destHost))
return false;
}
else if (destHostEqual)
{
if (url.host() != base.host())
return false;
}
else
{
if (url.host() != destHost)
return false;
}
if (destPathWildCard)
{
if (!destPath.isEmpty() && !url.path().startsWith(destPath))
return false;
}
else
{
if (url.path() != destPath)
return false;
}
return true;
}
QByteArray action;
QString baseProt;
QString baseHost;
QString basePath;
QString destProt;
QString destHost;
QString destPath;
bool baseProtWildCard : 1;
bool baseHostWildCard : 1;
bool basePathWildCard : 1;
bool destProtWildCard : 1;
bool destHostWildCard : 1;
bool destPathWildCard : 1;
bool destProtEqual : 1;
bool destHostEqual : 1;
bool permission;
};
class KAuthorizedPrivate {
public:
KAuthorizedPrivate()
: actionRestrictions( false ), blockEverything(false)
{
Q_ASSERT_X(QCoreApplication::instance(),"KAuthorizedPrivate()","There has to be an existing QCoreApplication::instance() pointer");
KSharedConfig::Ptr config = KGlobal::config();
Q_ASSERT_X(config,"KAuthorizedPrivate()","There has to be an existing KGlobal::config() pointer");
if (!config) {
blockEverything=true;
return;
}
actionRestrictions = config->hasGroup("KDE Action Restrictions" );
}
~KAuthorizedPrivate()
{
}
bool actionRestrictions : 1;
bool blockEverything : 1;
QList<URLActionRule> urlActionRestrictions;
QMutex mutex;
};
Q_GLOBAL_STATIC(KAuthorizedPrivate,authPrivate)
#define MY_D KAuthorizedPrivate *d=authPrivate();
bool KAuthorized::authorize(const QString &genericAction)
{
MY_D
if (d->blockEverything) return false;
if (!d->actionRestrictions)
return true;
KConfigGroup cg(KGlobal::config(), "KDE Action Restrictions");
return cg.readEntry(genericAction, true);
}
bool KAuthorized::authorizeKAction(const QString& action)
{
MY_D
if (d->blockEverything) return false;
if (!d->actionRestrictions || action.isEmpty())
return true;
return authorize(QLatin1String("action/") + action);
}
bool KAuthorized::authorizeControlModule(const QString &menuId)
{
if (menuId.isEmpty())
return true;
KConfigGroup cg(KGlobal::config(), "KDE Control Module Restrictions");
return cg.readEntry(menuId, true);
}
QStringList KAuthorized::authorizeControlModules(const QStringList &menuIds)
{
KConfigGroup cg(KGlobal::config(), "KDE Control Module Restrictions");
QStringList result;
foreach(const QString it, menuIds)
{
if (cg.readEntry(it, true))
result.append(it);
}
return result;
}
static void initUrlActionRestrictions()
{
MY_D
const QString Any;
d->urlActionRestrictions.clear();
d->urlActionRestrictions.append(
URLActionRule("open", Any, Any, Any, Any, Any, Any, true));
d->urlActionRestrictions.append(
URLActionRule("list", Any, Any, Any, Any, Any, Any, true));
// TEST:
// d->urlActionRestrictions.append(
// URLActionRule("list", Any, Any, Any, Any, Any, Any, false));
// d->urlActionRestrictions.append(
// URLActionRule("list", Any, Any, Any, "file", Any, QDir::homePath(), true));
d->urlActionRestrictions.append(
URLActionRule("link", Any, Any, Any, QLatin1String(":internet"), Any, Any, true));
d->urlActionRestrictions.append(
URLActionRule("redirect", Any, Any, Any, QLatin1String(":internet"), Any, Any, true));
// We allow redirections to file: but not from internet protocols, redirecting to file:
// is very popular among io-slaves and we don't want to break them
d->urlActionRestrictions.append(
URLActionRule("redirect", Any, Any, Any, QLatin1String("file"), Any, Any, true));
d->urlActionRestrictions.append(
URLActionRule("redirect", QLatin1String(":internet"), Any, Any, QLatin1String("file"), Any, Any, false));
// local protocols may redirect everywhere
d->urlActionRestrictions.append(
URLActionRule("redirect", QLatin1String(":local"), Any, Any, Any, Any, Any, true));
// Anyone may redirect to about:
d->urlActionRestrictions.append(
URLActionRule("redirect", Any, Any, Any, QLatin1String("about"), Any, Any, true));
// Anyone may redirect to mailto:
d->urlActionRestrictions.append(
URLActionRule("redirect", Any, Any, Any, QLatin1String("mailto"), Any, Any, true));
// Anyone may redirect to itself, cq. within it's own group
d->urlActionRestrictions.append(
URLActionRule("redirect", Any, Any, Any, QLatin1String("="), Any, Any, true));
d->urlActionRestrictions.append(
URLActionRule("redirect", QLatin1String("about"), Any, Any, Any, Any, Any, true));
KConfigGroup cg(KGlobal::config(), "KDE URL Restrictions");
int count = cg.readEntry("rule_count", 0);
QString keyFormat = QString::fromLatin1("rule_%1");
for(int i = 1; i <= count; i++)
{
QString key = keyFormat.arg(i);
const QStringList rule = cg.readEntry(key, QStringList());
if (rule.count() != 8)
continue;
const QByteArray action = rule[0].toLatin1();
QString refProt = rule[1];
QString refHost = rule[2];
QString refPath = rule[3];
QString urlProt = rule[4];
QString urlHost = rule[5];
QString urlPath = rule[6];
bool bEnabled = (rule[7].toLower() == QLatin1String("true"));
if (refPath.startsWith(QLatin1String("$HOME")))
refPath.replace(0, 5, QDir::homePath());
else if (refPath.startsWith(QLatin1Char('~')))
refPath.replace(0, 1, QDir::homePath());
if (urlPath.startsWith(QLatin1String("$HOME")))
urlPath.replace(0, 5, QDir::homePath());
else if (urlPath.startsWith(QLatin1Char('~')))
urlPath.replace(0, 1, QDir::homePath());
if (refPath.startsWith(QLatin1String("$TMP")))
refPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp"));
if (urlPath.startsWith(QLatin1String("$TMP")))
urlPath.replace(0, 4, KGlobal::dirs()->saveLocation("tmp"));
d->urlActionRestrictions.append(
URLActionRule( action, refProt, refHost, refPath, urlProt, urlHost, urlPath, bEnabled));
}
}
void KAuthorized::allowUrlAction(const QString &action, const KUrl &_baseURL, const KUrl &_destURL)
{
MY_D
if (authorizeUrlAction(action, _baseURL, _destURL))
return;
QMutexLocker locker(&d->mutex);
d->urlActionRestrictions.append( URLActionRule
( action.toLatin1(), _baseURL.protocol(), _baseURL.host(), _baseURL.path(KUrl::RemoveTrailingSlash),
_destURL.protocol(), _destURL.host(), _destURL.path(KUrl::RemoveTrailingSlash), true));
}
bool KAuthorized::authorizeUrlAction(const QString &action, const KUrl &_baseURL, const KUrl &_destURL)
{
MY_D
QMutexLocker locker(&d->mutex);
if (d->blockEverything) return false;
if (_destURL.isEmpty())
return true;
bool result = false;
if (d->urlActionRestrictions.isEmpty())
initUrlActionRestrictions();
KUrl baseURL(_baseURL);
baseURL.setPath(QDir::cleanPath(baseURL.path()));
QString baseClass = KProtocolInfo::protocolClass(baseURL.protocol());
KUrl destURL(_destURL);
destURL.setPath(QDir::cleanPath(destURL.path()));
QString destClass = KProtocolInfo::protocolClass(destURL.protocol());
foreach(const URLActionRule &rule, d->urlActionRestrictions) {
if ((result != rule.permission) && // No need to check if it doesn't make a difference
(action == QLatin1String(rule.action)) &&
rule.baseMatch(baseURL, baseClass) &&
rule.destMatch(destURL, destClass, baseURL, baseClass))
{
result = rule.permission;
}
}
return result;
}

View file

@ -1,95 +0,0 @@
/* This file is part of the KDE libraries
Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
Copyright (c) 1998, 1999 Waldo Bastian <bastian@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
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.
*/
#ifndef KAUTHORIZED_H
#define KAUTHORIZED_H
#include <kdecore_export.h>
class KUrl;
#include <QString>
#include <QStringList>
/**
* Extracted from kapplication (3.x). Kiosk authorization framework
*/
namespace KAuthorized
{
/**
* Returns whether a certain action is authorized
* @param genericAction The name of a generic action
* @return true if the action is authorized
* @todo what are the generic actions?
*/
KDECORE_EXPORT bool authorize(const QString& genericAction);
/**
* Returns whether a certain KAction is authorized.
*
* @param action The name of a KAction action. The name is prepended
* with "action/" before being passed to authorize()
* @return true if the KAction is authorized
*/
KDECORE_EXPORT bool authorizeKAction(const QString& action);
/**
* Returns whether a certain URL related action is authorized.
*
* @param action The name of the action. Known actions are
* - list (may be listed (e.g. in file selection dialog)),
* - link (may be linked to),
* - open (may open) and
* - redirect (may be redirected to)
* @param baseUrl The url where the action originates from
* @param destUrl The object of the action
* @return true when the action is authorized, false otherwise.
*/
KDECORE_EXPORT bool authorizeUrlAction(const QString& action, const KUrl& baseUrl, const KUrl& destUrl);
/**
* Allow a certain URL action. This can be useful if your application
* needs to ensure access to an application specific directory that may
* otherwise be subject to KIOSK restrictions.
* @param action The name of the action.
* @param baseUrl The url where the action originates from
* @param _destUrl The object of the action
*/
KDECORE_EXPORT void allowUrlAction(const QString& action, const KUrl& baseUrl, const KUrl& _destUrl);
/**
* Returns whether access to a certain control module is authorized.
*
* @param menuId identifying the control module, e.g. kde-mouse.desktop
* @return true if access to the module is authorized, false otherwise.
*/
KDECORE_EXPORT bool authorizeControlModule(const QString& menuId);
/**
* Returns which control modules from a given list are authorized for access.
*
* @param menuIds list of menu-ids of control modules;
* an example of a menu-id is kde-mouse.desktop.
* @return Those control modules for which access has been authorized.
*/
KDECORE_EXPORT QStringList authorizeControlModules(const QStringList& menuIds);
}
#endif

View file

@ -34,7 +34,6 @@
#include <QtCore/QDir>
#include <QtCore/QMap>
#include <kauthorized.h>
#include <kdebug.h>
#include <kdesktopfile.h>
#include <kglobal.h>
@ -682,9 +681,6 @@ bool KService::noDisplay() const {
if (!showInKDE())
return true;
if (!KAuthorized::authorizeControlModule( storageId() ) )
return true;
return false;
}

View file

@ -29,8 +29,6 @@
#include "kglobalaccel_p.h"
#include "klocale.h"
#include "kmessagebox.h"
#include "kauthaction.h"
#include "kauthactionwatcher.h"
#include <QtGui/QApplication>
#include <QtGui/QHBoxLayout>
@ -66,46 +64,6 @@ void KActionPrivate::setActiveGlobalShortcutNoEnable(const KShortcut &cut)
void KActionPrivate::slotTriggered()
{
emit q->triggered(QApplication::mouseButtons(), QApplication::keyboardModifiers());
if (authAction) {
KAuth::Action::AuthStatus s = authAction->earlyAuthorize();
switch(s) {
case KAuth::Action::Denied:
q->setEnabled(false);
break;
case KAuth::Action::Authorized:
emit q->authorized(authAction);
break;
default:
break;
}
}
}
void KActionPrivate::authStatusChanged(int status)
{
KAuth::Action::AuthStatus s = (KAuth::Action::AuthStatus)status;
switch(s) {
case KAuth::Action::Authorized:
q->setEnabled(true);
if(!oldIcon.isNull()) {
q->setIcon(oldIcon);
oldIcon = KIcon();
}
break;
case KAuth::Action::AuthRequired:
q->setEnabled(true);
oldIcon = KIcon(q->icon());
q->setIcon(KIcon("dialog-password"));
break;
default:
q->setEnabled(false);
if(!oldIcon.isNull()) {
q->setIcon(oldIcon);
oldIcon = KIcon();
}
}
}
bool KAction::event(QEvent *event)
@ -306,51 +264,6 @@ void KAction::setHelpText(const QString& text)
setWhatsThis(text);
}
KAuth::Action *KAction::authAction() const
{
return d->authAction;
}
void KAction::setAuthAction(const QString &actionName)
{
if (actionName.isEmpty()) {
setAuthAction(0);
} else {
setAuthAction(new KAuth::Action(actionName));
// this memory leak is gone in frameworks 5
}
}
void KAction::setAuthAction(KAuth::Action *action)
{
if (d->authAction == action) {
return;
}
if (d->authAction) {
disconnect(d->authAction->watcher(), SIGNAL(statusChanged(int)),
this, SLOT(authStatusChanged(int)));
// d->authAction can not be deleted because it could
// be any kind of pointer, including a pointer to a stack object.
d->authAction = 0;
if (!d->oldIcon.isNull()) {
setIcon(d->oldIcon);
d->oldIcon = KIcon();
}
}
if (action != 0) {
d->authAction = action;
// Set the parent widget
d->authAction->setParentWidget(parentWidget());
connect(d->authAction->watcher(), SIGNAL(statusChanged(int)),
this, SLOT(authStatusChanged(int)));
d->authStatusChanged(d->authAction->status());
}
}
/* vim: et sw=2 ts=2
*/

View file

@ -33,10 +33,6 @@
class KIcon;
namespace KAuth {
class Action;
}
//TODO Reduce the word count. This is not very focused and takes too long to read.
//Keep in mind that QAction also has documentation that we don't need to repeat here.
/**
@ -438,40 +434,11 @@ public:
*/
void forgetGlobalShortcut();
/**
* Returns the action object associated with this action, or 0 if it does not have one
*
* @returns the KAuth::Action associated with this action.
*/
KAuth::Action *authAction() const;
/**
* Sets the action object associated with this action
*
* By setting a KAuth::Action, this action will become associated with it, and
* whenever it gets clicked, it will trigger the authorization and execution process
* for the action. The signal activated will also be emitted whenever the action gets
* clicked and the action gets authorized. Pass 0 to this function to disassociate the action
*
* @param action the KAuth::Action to associate with this action.
*/
void setAuthAction(KAuth::Action *action);
/**
* Sets the action object associated with this action
*
* Overloaded member to allow creating the action by name
*
* @param actionName the name of the action to associate
*/
void setAuthAction(const QString &actionName);
/**
* @reimp
*/
bool event(QEvent*);
Q_SIGNALS:
/**
@ -480,23 +447,6 @@ Q_SIGNALS:
*/
void triggered(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
/**
* Signal emitted when the action is triggered and authorized
*
* If the action needs authorization, when the user triggers the action,
* the authorization process automatically begins.
* If it succeeds, this signal is emitted. The KAuth::Action object is provided for convenience
* if you have multiple KAuthorizedAction objects, but of course it's always the same set with
* setAuthAction().
*
* WARNING: If your action needs authorization you should connect eventual slots processing
* stuff to this signal, and NOT triggered. Triggered will be emitted even if the user has not
* been authorized
*
* @param action The object set with setAuthAction()
*/
void authorized(KAuth::Action *action);
/**
* Emitted when the global shortcut is changed. A global shortcut is
* subject to be changed by the global shortcuts kcm.
@ -508,7 +458,6 @@ private:
friend class KActionCollectionPrivate; // Needs access to the component
friend class KShortcutsEditorDelegate; // Needs access to the component
Q_PRIVATE_SLOT(d, void slotTriggered())
Q_PRIVATE_SLOT(d, void authStatusChanged(int))
class KActionPrivate* const d;
friend class KActionPrivate;
friend class KGlobalShortcutTest;

View file

@ -25,20 +25,15 @@
class KAction;
namespace KAuth {
class Action;
}
class KActionPrivate
{
public:
KActionPrivate()
: componentData(KGlobal::mainComponent()), globalShortcutEnabled(false), q(0), authAction(0)
: componentData(KGlobal::mainComponent()), globalShortcutEnabled(false), q(0)
{
}
void slotTriggered();
void authStatusChanged(int status);
void init(KAction *q_ptr);
void setActiveGlobalShortcutNoEnable(const KShortcut &cut);
@ -57,7 +52,6 @@ class KActionPrivate
bool neverSetGlobalShortcut : 1;
KAction *q;
KAuth::Action *authAction;
// TODO: Remove whenever QIcon overlays will get fixed
KIcon oldIcon;
};

View file

@ -26,7 +26,6 @@
#include "kactioncollection.h"
#include "kactioncategory.h"
#include <kauthorized.h>
#include "kxmlguiclient.h"
#include "kxmlguifactory.h"
@ -267,13 +266,6 @@ QAction *KActionCollection::addAction(const QString &name, QAction *action)
return action;
}
if (!KAuthorized::authorizeKAction(indexName)) {
// Disable this action
action->setEnabled(false);
action->setVisible(false);
action->blockSignals(true);
}
// Check if we have another action under this name
if (QAction *oldAction = d->actionByName.value(indexName)) {
takeAction(oldAction);

View file

@ -35,7 +35,6 @@
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusConnectionInterface>
#include "kauthorized.h"
#include "kaboutdata.h"
#include "kcheckaccelerators.h"
#include "kcrash.h"
@ -425,8 +424,7 @@ void KApplicationPrivate::init()
QByteArray readOnly = qgetenv("KDE_HOME_READONLY");
if (readOnly.isEmpty() && q->applicationName() != QLatin1String("kdialog"))
{
if (KAuthorized::authorize(QLatin1String("warn_unwritable_config")))
config->isConfigWritable(true);
config->isConfigWritable(true);
}
if (q->type() == KAPPLICATION_GUI_TYPE)

View file

@ -34,8 +34,6 @@
#include <kglobal.h>
#include <kcomponentdata.h>
#include <klocale.h>
#include "auth/kauthaction.h"
#include "auth/kauthactionwatcher.h"
class KCModulePrivate
{
@ -45,13 +43,9 @@ public:
_about( 0 ),
_useRootOnlyMessage( false ),
_firstshow(true),
_needsAuthorization(false),
_authAction(0),
_unmanagedWidgetChangeState( false )
{ }
void authStatusChanged(int status);
KCModule::Buttons _buttons;
KComponentData _componentData;
const KAboutData *_about;
@ -62,9 +56,6 @@ public:
bool _useRootOnlyMessage : 1;
bool _firstshow : 1;
bool _needsAuthorization : 1;
KAuth::Action *_authAction;
// this member is used to record the state on non-automatically
// managed widgets, allowing for mixed KConfigXT-drive and manual
// widgets to coexist peacefully and do the correct thing with
@ -121,53 +112,6 @@ KConfigDialogManager* KCModule::addConfig( KConfigSkeleton *config, QWidget* wid
return manager;
}
void KCModule::setNeedsAuthorization(bool needsAuth)
{
d->_needsAuthorization = needsAuth;
if (needsAuth && d->_about) {
d->_authAction = new KAuth::Action(QString("org.kde.kcontrol." + d->_about->appName() + ".save"));
d->_needsAuthorization = d->_authAction->isValid();
d->_authAction->setHelperID("org.kde.kcontrol." + d->_about->appName());
d->_authAction->setParentWidget(this);
connect(d->_authAction->watcher(), SIGNAL(statusChanged(int)),
this, SLOT(authStatusChanged(int)));
authStatusChanged(d->_authAction->status());
} else {
d->_authAction = 0;
}
}
bool KCModule::needsAuthorization() const
{
return d->_needsAuthorization;
}
KAuth::Action *KCModule::authAction() const
{
return d->_authAction;
}
void KCModule::authStatusChanged(int status)
{
KAuth::Action::AuthStatus s = (KAuth::Action::AuthStatus)status;
switch(s) {
case KAuth::Action::Authorized:
setUseRootOnlyMessage(false);
break;
case KAuth::Action::AuthRequired:
setUseRootOnlyMessage(true);
setRootOnlyMessage(i18n("You will be asked to authenticate before saving"));
break;
default:
setUseRootOnlyMessage(true);
setRootOnlyMessage(i18n("You are not allowed to save the configuration"));
break;
}
qDebug() << useRootOnlyMessage();
}
KCModule::~KCModule()
{
qDeleteAll(d->managers);

View file

@ -40,10 +40,6 @@ class KConfigSkeleton;
class KCModulePrivate;
class KComponentData;
namespace KAuth {
class Action;
}
/**
* The base class for configuration modules.
*
@ -200,39 +196,6 @@ public:
*/
QList<KConfigDialogManager*> configs() const;
/**
* @brief Set if the module's save() method requires authorization to be executed.
*
* The module can set this property to @c true if it requires authorization.
* It will still have to execute the action itself using the KAuth library, so
* this method is not technically needed to perform the action, but
* using this and/or the setAuthAction() method will ensure that hosting
* applications like System Settings or kcmshell behave correctly.
*
* Called with @c true, this method will set the action to "org.kde.kcontrol.name.save" where
* "name" is aboutData()->appName() return value. This default action won't be set if
* the aboutData() object is not valid.
*
* Note that called with @c false, this method will reset the action name set with setAuthAction().
*
* @param needsAuth Tells if the module's save() method requires authorization to be executed.
*/
void setNeedsAuthorization(bool needsAuth);
/**
* Returns the value previously set with setNeedsAuthorization(). By default it's @c false.
*
* @return @c true if the module's save() method requires authorization, @c false otherwise
*/
bool needsAuthorization() const;
/**
* Returns the action previously set with setAuthAction(). By default its an invalid action.
*
* @return The action that has to be authorized to execute the save() method.
*/
KAuth::Action *authAction() const;
/**
* Returns the value set by setExportText();
*/
@ -369,11 +332,6 @@ protected Q_SLOTS:
*/
void widgetChanged();
/**
* The status of the auth action, if one, has changed
*/
void authStatusChanged(int);
protected:
/**

View file

@ -34,7 +34,6 @@
#include <kaction.h>
#include <kactioncollection.h>
#include <kapplication.h>
#include <kauthorized.h>
#include <kdialog.h>
#include <kguiitem.h>
#include <khbox.h>

View file

@ -30,7 +30,6 @@
#include <kaction.h>
#include <kapplication.h>
#include <kauthorized.h>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <kcursor.h>

View file

@ -48,7 +48,6 @@
#include <kaction.h>
#include <kapplication.h>
#include <kauthorized.h>
#include <kconfig.h>
#include <kdebug.h>
#include <kdialog.h>

View file

@ -18,9 +18,9 @@
*/
#include "kpushbutton.h"
#include <QtGui/qstyleoption.h>
#include <QStylePainter>
#include <QtGui/QDrag>
#include <QtGui/qevent.h>
#include <QtGui/QMenu>
@ -36,15 +36,12 @@
#include <kguiitem.h>
#include <kicon.h>
#include "auth/kauthaction.h"
#include "auth/kauthactionwatcher.h"
static bool s_useIcons = false;
class KPushButton::KPushButtonPrivate
{
public:
KPushButtonPrivate(KPushButton *_parent) : parent(_parent), m_dragEnabled( false ), authAction(0)
KPushButtonPrivate(KPushButton *_parent) : parent(_parent), m_dragEnabled( false )
{
}
@ -56,14 +53,12 @@ public:
QTimer * delayedMenuTimer;
bool m_dragEnabled;
QPoint startPos;
KAuth::Action *authAction;
// TODO: Remove whenever QIcon overlays will get fixed
KIcon oldIcon;
void slotSettingsChanged( int );
void slotPressedInternal();
void slotClickedInternal();
void authStatusChanged(int status);
void slotDelayedMenuTimeout();
void readSettings();
};
@ -91,20 +86,6 @@ void KPushButton::KPushButtonPrivate::slotClickedInternal()
{
if (delayedMenuTimer)
delayedMenuTimer->stop();
if (authAction) {
KAuth::Action::AuthStatus s = authAction->earlyAuthorize();
switch(s) {
case KAuth::Action::Denied:
parent->setEnabled(false);
break;
case KAuth::Action::Authorized:
emit parent->authorized(authAction);
break;
default:
break;
}
}
}
void KPushButton::KPushButtonPrivate::slotDelayedMenuTimeout() {
@ -116,32 +97,6 @@ void KPushButton::KPushButtonPrivate::slotDelayedMenuTimeout() {
}
}
void KPushButton::KPushButtonPrivate::authStatusChanged(int status)
{
KAuth::Action::AuthStatus s = (KAuth::Action::AuthStatus)status;
switch(s) {
case KAuth::Action::Authorized:
parent->setEnabled(true);
if(!oldIcon.isNull()) {
parent->setIcon(oldIcon);
oldIcon = KIcon();
}
break;
case KAuth::Action::AuthRequired:
parent->setEnabled(true);
oldIcon = KIcon(parent->icon());
parent->setIcon(KIcon("dialog-password"));
break;
default:
parent->setEnabled(false);
if(!oldIcon.isNull()) {
parent->setIcon(oldIcon);
oldIcon = KIcon();
}
}
}
void KPushButton::KPushButtonPrivate::readSettings()
{
s_useIcons = KGlobalSettings::showIconsOnPushButtons();
@ -314,49 +269,6 @@ QMenu* KPushButton::delayedMenu()
return d->delayedMenu;
}
KAuth::Action *KPushButton::authAction() const
{
return d->authAction;
}
void KPushButton::setAuthAction(const QString &actionName)
{
if (actionName.isEmpty()) {
setAuthAction(0);
} else {
setAuthAction(new KAuth::Action(actionName));
}
}
void KPushButton::setAuthAction(KAuth::Action *action)
{
if (d->authAction == action) {
return;
}
if (d->authAction) {
disconnect(d->authAction->watcher(), SIGNAL(statusChanged(int)),
this, SLOT(authStatusChanged(int)));
//delete d->authAction;
d->authAction = 0;
if (!d->oldIcon.isNull()) {
setIcon(d->oldIcon);
d->oldIcon = KIcon();
}
}
if (action != 0) {
d->authAction = action;
// Set the parent widget
d->authAction->setParentWidget(this);
connect(d->authAction->watcher(), SIGNAL(statusChanged(int)),
this, SLOT(authStatusChanged(int)));
d->authStatusChanged(d->authAction->status());
}
}
QSize KPushButton::sizeHint() const
{
const bool tempSetMenu = !menu() && d->delayedMenu;

View file

@ -21,17 +21,13 @@
#define KPUSHBUTTON_H
#include <QtGui/QPushButton>
#include <QDrag>
#include <QMenu>
#include <kstandardguiitem.h>
#include <QDrag>
#include <QMenu>
class KIcon;
namespace KAuth {
class Action;
}
/**
* @brief A QPushButton with drag-support and KGuiItem support
*
@ -135,34 +131,6 @@ public:
*/
virtual QSize sizeHint() const;
/**
* Returns the action object associated with this button, or 0 if it does not have one
*
* @returns the KAuth::Action associated with this button.
*/
KAuth::Action *authAction() const;
/**
* Sets the action object associated with this button
*
* By setting a KAuth::Action, this button will become associated with it, and
* whenever it gets clicked, it will trigger the authorization and execution process
* for the action. The signal activated will also be emitted whenever the button gets
* clicked and the action gets authorized. Pass 0 to this function to disassociate the button
*
* @param action the KAuth::Action to associate with this button.
*/
void setAuthAction(KAuth::Action *action);
/**
* Sets the action object associated with this button
*
* Overloaded member to allow creating the action by name
*
* @param actionName the name of the action to associate
*/
void setAuthAction(const QString &actionName);
protected:
/**
* Reimplement this and return the QDrag object that should be used
@ -192,24 +160,6 @@ protected:
*/
virtual void startDrag();
Q_SIGNALS:
/**
* Signal emitted when the button is triggered and authorized
*
* If the button needs authorization, whenever the user triggers it,
* the authorization process automatically begins.
* If it succeeds, this signal is emitted. The KAuth::Action object is provided for convenience
* if you have multiple Action objects, but of course it's always the same set with
* setAuthAction().
*
* WARNING: If your button needs authorization you should connect eventual slots processing
* stuff to this signal, and NOT clicked. Clicked will be emitted even if the user has not
* been authorized
*
* @param action The object set with setAuthAction()
*/
void authorized(KAuth::Action *action);
private:
/**
* Internal.
@ -225,7 +175,6 @@ private:
Q_PRIVATE_SLOT(d, void slotPressedInternal())
Q_PRIVATE_SLOT(d, void slotClickedInternal())
Q_PRIVATE_SLOT(d, void slotDelayedMenuTimeout())
Q_PRIVATE_SLOT(d, void authStatusChanged(int))
};
#endif // KPUSHBUTTON_H

View file

@ -39,7 +39,6 @@
#include <kaction.h>
#include <kactioncollection.h>
#include <kapplication.h>
#include <kauthorized.h>
#include <kconfig.h>
#include <kdebug.h>
#include <kedittoolbar.h>

View file

@ -23,7 +23,6 @@
#include <kaction.h>
#include <kactioncollection.h>
#include <kactionmenu.h>
#include <kauthorized.h>
#include <kguiitem.h>
#include <klocale.h>
#include <kxmlguiwindow.h>

View file

@ -19,9 +19,7 @@
*/
#include "kxmlguibuilder.h"
#include "kapplication.h"
#include "kauthorized.h"
#include "kxmlguiclient.h"
#include "kmenu.h"
#include "ktoolbar.h"
@ -162,9 +160,6 @@ QWidget *KXMLGUIBuilder::createContainer( QWidget *parent, int index, const QDom
QByteArray name = element.attribute( d->attrName ).toUtf8();
if (!KAuthorized::authorizeKAction(name))
return 0;
KMenu *popup = new KMenu(p);
popup->setObjectName(name);

View file

@ -21,6 +21,11 @@
#include "kxmlguiversionhandler_p.h"
#include "kxmlguifactory.h"
#include "kxmlguibuilder.h"
#include "kcomponentdata.h"
#include "kstandarddirs.h"
#include "kdebug.h"
#include "kaction.h"
#include "kactioncollection.h"
#include <QtCore/QDir>
#include <QtCore/QFile>
@ -29,14 +34,6 @@
#include <QtCore/QRegExp>
#include <QtCore/QPointer>
#include <kcomponentdata.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <kauthorized.h>
#include "kaction.h"
#include "kactioncollection.h"
#include <assert.h>
class KXMLGUIClientPrivate
@ -363,8 +360,7 @@ bool KXMLGUIClientPrivate::mergeXML( QDomElement &base, QDomElement &additive, K
// not implemented, then we remove the element
if (equalstr(tag, tagAction)) {
const QString name = e.attribute(attrName);
if (!actionCollection->action(name) ||
!KAuthorized::authorizeKAction(name))
if (!actionCollection->action(name))
{
// remove this child as we aren't using it
base.removeChild( e );

View file

@ -48,7 +48,6 @@
#include <QtDBus/QDBusConnection>
#include <kaction.h>
#include <kapplication.h>
#include <kauthorized.h>
#include <kconfig.h>
#include <kdebug.h>
#include <kedittoolbar.h>

View file

@ -26,7 +26,6 @@
#include <kactioncollection.h>
#include <kapplication.h>
#include <kauthorized.h>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <khistorycombobox.h>

View file

@ -68,7 +68,6 @@
#include <QtCore/QFSFileEngine>
#include <kshell.h>
#include <kmessagebox.h>
#include <kauthorized.h>
class KFileWidgetPrivate
{

View file

@ -20,10 +20,7 @@
#include "kbookmarkmenu.h"
#include "kbookmarkmenu_p.h"
#include "kbookmarkdialog.h"
#include <kauthorized.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <klocale.h>
@ -37,8 +34,6 @@
#include <qclipboard.h>
#include <qmimedata.h>
#include <QtCore/QStack>
#include <QtGui/QHeaderView>
#include <QtGui/QApplication>

View file

@ -32,7 +32,6 @@
#include <QtGui/QStyle>
#include <QtGui/qstyleoption.h>
#include <kauthorized.h>
#include <khistorycombobox.h>
#include <kdesktopfile.h>
#include <klineedit.h>
@ -47,12 +46,12 @@
#include <kmimetype.h>
#include <kservicegroup.h>
#include <kserviceoffer.h>
#include <kbuildsycocaprogressdialog.h>
#include <kconfiggroup.h>
#include <kdebug.h>
#include <assert.h>
#include <stdlib.h>
#include <kbuildsycocaprogressdialog.h>
#include <kconfiggroup.h>
inline void writeEntry( KConfigGroup& group, const char* key,
const KGlobalSettings::Completion& aValue,

View file

@ -78,7 +78,6 @@ extern "C" {
#include <sys/acl.h>
#endif
#include <kauthorized.h>
#include <kdialog.h>
#include <kdirnotify.h>
#include <kdiskfreespaceinfo.h>

View file

@ -866,7 +866,6 @@ void CopyJobPrivate::startListing( const KUrl & src )
state = STATE_LISTING;
m_bURLDirty = true;
ListJob * newjob = listRecursive(src, KIO::HideProgressInfo);
newjob->setUnrestricted(true);
q->connect(newjob, SIGNAL(entries(KIO::Job*,KIO::UDSEntryList)),
SLOT(slotEntries(KIO::Job*,KIO::UDSEntryList)));
q->connect(newjob, SIGNAL(subError(KIO::ListJob*,KIO::ListJob*)),

View file

@ -356,7 +356,6 @@ void DeleteJobPrivate::currentSourceStated(bool isDir, bool isLink)
//kDebug(7007) << url << "is a directory, let's list it";
ListJob *newjob = KIO::listRecursive(url, KIO::HideProgressInfo);
newjob->addMetaData("details", "0");
newjob->setUnrestricted(true); // No KIOSK restrictions
Scheduler::setJobPriority(newjob, 1);
QObject::connect(newjob, SIGNAL(entries(KIO::Job*,KIO::UDSEntryList)),
q, SLOT(slotEntries(KIO::Job*,KIO::UDSEntryList)));

View file

@ -42,7 +42,6 @@ extern "C" {
#include <QtCore/QFile>
#include <QtCore/qbuffer.h>
#include <kauthorized.h>
#include <klocale.h>
#include <kconfig.h>
#include <kdebug.h>
@ -623,13 +622,6 @@ void MkdirJobPrivate::slotRedirection( const KUrl &url)
{
Q_Q(MkdirJob);
kDebug(7007) << url;
if (!KAuthorized::authorizeUrlAction("redirect", m_url, url))
{
kWarning(7007) << "Redirection from" << m_url << "to" << url << "REJECTED!";
q->setError( ERR_ACCESS_DENIED );
q->setErrorText( url.pathOrUrl() );
return;
}
m_redirectionURL = url; // We'll remember that when the job finishes
// Tell the user that we haven't finished yet
emit q->redirection(q, m_redirectionURL);
@ -839,13 +831,6 @@ void StatJobPrivate::slotRedirection( const KUrl &url)
{
Q_Q(StatJob);
kDebug(7007) << m_url << "->" << url;
if (!KAuthorized::authorizeUrlAction("redirect", m_url, url))
{
kWarning(7007) << "Redirection from " << m_url << " to " << url << " REJECTED!";
q->setError( ERR_ACCESS_DENIED );
q->setErrorText( url.pathOrUrl() );
return;
}
m_redirectionURL = url; // We'll remember that when the job finishes
// Tell the user that we haven't finished yet
emit q->redirection(q, m_redirectionURL);
@ -946,11 +931,6 @@ void TransferJob::slotRedirection( const KUrl &url)
{
Q_D(TransferJob);
kDebug(7007) << url;
if (!KAuthorized::authorizeUrlAction("redirect", d->m_url, url))
{
kWarning(7007) << "Redirection from " << d->m_url << " to " << url << " REJECTED!";
return;
}
// Some websites keep redirecting to themselves where each redirection
// acts as the stage in a state-machine. We define "endless redirections"
@ -2280,11 +2260,6 @@ void ListJob::slotResult( KJob * job )
void ListJobPrivate::slotRedirection( const KUrl & url )
{
Q_Q(ListJob);
if (!KAuthorized::authorizeUrlAction("redirect", m_url, url))
{
kWarning(7007) << "ListJob: Redirection from " << m_url << " to " << url << " REJECTED!";
return;
}
m_redirectionURL = url; // We'll remember that when the job finishes
emit q->redirection( q, m_redirectionURL );
}
@ -2339,26 +2314,9 @@ ListJob *KIO::listRecursive( const KUrl& url, JobFlags flags, bool includeHidden
return ListJobPrivate::newJob(url, true, QString(), QString(), includeHidden, flags);
}
void ListJob::setUnrestricted(bool unrestricted)
{
Q_D(ListJob);
if (unrestricted)
d->m_extraFlags |= JobPrivate::EF_ListJobUnrestricted;
else
d->m_extraFlags &= ~JobPrivate::EF_ListJobUnrestricted;
}
void ListJobPrivate::start(Slave *slave)
{
Q_Q(ListJob);
if (!KAuthorized::authorizeUrlAction("list", m_url, m_url) &&
!(m_extraFlags & EF_ListJobUnrestricted))
{
q->setError( ERR_ACCESS_DENIED );
q->setErrorText( m_url.url() );
QTimer::singleShot(0, q, SLOT(slotFinished()) );
return;
}
q->connect( slave, SIGNAL(listEntries(KIO::UDSEntryList)),
SLOT(slotListEntries(KIO::UDSEntryList)));
q->connect( slave, SIGNAL(totalSize(KIO::filesize_t)),

View file

@ -50,8 +50,7 @@ namespace KIO {
enum { EF_TransferJobAsync = (1 << 0),
EF_TransferJobNeedData = (1 << 1),
EF_TransferJobDataSent = (1 << 2),
EF_ListJobUnrestricted = (1 << 3),
EF_KillCalled = (1 << 4) };
EF_KillCalled = (1 << 3) };
// Maybe we could use the QObject parent/child mechanism instead
// (requires a new ctor, and moving the ctor code to some init()).

View file

@ -805,11 +805,6 @@ namespace KIO {
*/
const KUrl& redirectionUrl() const;
/**
* Do not apply any KIOSK restrictions to this job.
*/
void setUnrestricted(bool unrestricted);
Q_SIGNALS:
/**
* This signal emits the entry found by the job while listing.

View file

@ -27,33 +27,17 @@
#include <kdesktopfileactions.h>
#include <kmenu.h>
#include <klocale.h>
#include <kauthorized.h>
#include <kconfiggroup.h>
#include <kdesktopfile.h>
#include <kglobal.h>
#include <kicon.h>
#include <kstandarddirs.h>
#include <kservicetypetrader.h>
#include <QFile>
#include <QtCore/qalgorithms.h>
#include <QtDBus/QtDBus>
static bool KIOSKAuthorizedAction(const KConfigGroup& cfg)
{
if (!cfg.hasKey("X-KDE-AuthorizeAction")) {
return true;
}
const QStringList list = cfg.readEntry("X-KDE-AuthorizeAction", QStringList());
for(QStringList::ConstIterator it = list.constBegin();
it != list.constEnd(); ++it) {
if (!KAuthorized::authorize((*it).trimmed())) {
return false;
}
}
return true;
}
// This helper class stores the .desktop-file actions and the servicemenus
// in order to support X-KDE-Priority and X-KDE-Submenu.
namespace KIO {
@ -169,9 +153,7 @@ int KFileItemActionsPrivate::insertServices(const ServiceList& list,
void KFileItemActionsPrivate::slotExecuteService(QAction* act)
{
KServiceAction serviceAction = act->data().value<KServiceAction>();
if (KAuthorized::authorizeKAction(serviceAction.name())) {
KDesktopFileActions::executeService(m_props.urlList(), serviceAction);
}
KDesktopFileActions::executeService(m_props.urlList(), serviceAction);
}
////
@ -242,12 +224,10 @@ int KFileItemActions::addServiceActionsTo(QMenu* mainMenu)
const KDesktopFile desktopFile(dotDirectoryFile);
const KConfigGroup cfg = desktopFile.desktopGroup();
if (KIOSKAuthorizedAction(cfg)) {
const QString priority = cfg.readEntry("X-KDE-Priority");
const QString submenuName = cfg.readEntry("X-KDE-Submenu");
ServiceList& list = s.selectList(priority, submenuName);
list += KDesktopFileActions::userDefinedServices(dotDirectoryFile, desktopFile, true);
}
const QString priority = cfg.readEntry("X-KDE-Priority");
const QString submenuName = cfg.readEntry("X-KDE-Submenu");
ServiceList& list = s.selectList(priority, submenuName);
list += KDesktopFileActions::userDefinedServices(dotDirectoryFile, desktopFile, true);
}
}
@ -264,10 +244,6 @@ int KFileItemActions::addServiceActionsTo(QMenu* mainMenu)
KDesktopFile desktopFile(file);
const KConfigGroup cfg = desktopFile.desktopGroup();
if (!KIOSKAuthorizedAction(cfg)) {
continue;
}
if (cfg.hasKey("X-KDE-ShowIfRunning")) {
const QString app = cfg.readEntry("X-KDE-ShowIfRunning");
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(app)) {

View file

@ -52,8 +52,6 @@
#include "kfile/kopenwithdialog.h"
#include "kfile/krecentdocument.h"
#include "kdesktopfileactions.h"
#include <kauthorized.h>
#include <kmessageboxwrapper.h>
#include <kurl.h>
#include <kglobal.h>

View file

@ -27,10 +27,6 @@
#include <config.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <QtCore/QCoreApplication>
#include <QtCore/qstringlist.h>
#include <QtCore/QRegExp>
@ -42,7 +38,6 @@
#include <QtCore/QThread>
#include <QtGui/qevent.h>
#include <kauthorized.h>
#include <kdebug.h>
#include <kurl.h>
#include <kio/job.h>
@ -51,7 +46,11 @@
#include <kglobal.h>
#include <kglobalsettings.h>
#include <kde_file.h>
#include <kconfiggroup.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
@ -59,7 +58,6 @@
#include <pwd.h>
#include <time.h>
#include <sys/param.h>
#include <kconfiggroup.h>
static bool expandTilde(QString&);
@ -1070,19 +1068,7 @@ QString KUrlCompletionPrivate::listDirectories(
if (dirListThread)
dirListThread->requestTermination();
QStringList dirs;
QStringList::ConstIterator end = dirList.constEnd();
for (QStringList::ConstIterator it = dirList.constBegin();
it != end;
++it) {
KUrl url;
url.setPath(*it);
if (KAuthorized::authorizeUrlAction(QLatin1String("list"), KUrl(), url))
dirs.append(*it);
}
dirListThread = new DirectoryListThread(this, dirs, filter, only_exe, only_dir,
dirListThread = new DirectoryListThread(this, dirList, filter, only_exe, only_dir,
no_hidden, append_slash_to_dir);
dirListThread->start();
dirListThread->wait(200);

View file

@ -22,7 +22,6 @@
#include <kapplication.h>
#include <ktoolinvocation.h>
#include <kauthorized.h>
#include <kmessagebox.h>
#include <kcmdlineargs.h>
#include <kdebug.h>

View file

@ -24,11 +24,6 @@
#include "kcmultidialog.h"
#include "kcmultidialog_p.h"
#include <QtCore/QStringList>
#include <QtCore/QProcess>
#include <kauthorized.h>
#include <kguiitem.h>
#include <kicon.h>
#include <klocale.h>
@ -38,14 +33,13 @@
#include <kdebug.h>
#include <kmessagebox.h>
#include <kurl.h>
#include "auth/kauthaction.h"
#include "kcolorscheme.h"
#include "kcmoduleloader.h"
#include "kcmoduleproxy.h"
#include <QtCore/QStringList>
#include <QtCore/QProcess>
bool KCMultiDialogPrivate::resolveChanges(KCModuleProxy *currentProxy)
{
Q_Q(KCMultiDialog);
@ -124,37 +118,19 @@ void KCMultiDialogPrivate::_k_clientChanged()
if (q->button(KDialog::Apply)) {
q->disconnect(q, SIGNAL(applyClicked()), q, SLOT(slotApplyClicked()));
q->disconnect(q->button(KDialog::Apply), SIGNAL(authorized(KAuth::Action*)), q, SLOT(slotApplyClicked()));
q->button(KDialog::Apply)->setEnabled(change);
}
if (q->button(KDialog::Ok)) {
q->disconnect(q, SIGNAL(okClicked()), q, SLOT(slotOkClicked()));
q->disconnect(q->button(KDialog::Ok), SIGNAL(authorized(KAuth::Action*)), q, SLOT(slotOkClicked()));
}
if (activeModule->realModule()->needsAuthorization()) {
if (q->button(KDialog::Apply)) {
q->button(KDialog::Apply)->setAuthAction(activeModule->realModule()->authAction());
activeModule->realModule()->authAction()->setParentWidget(activeModule->realModule());
q->connect(q->button(KDialog::Apply), SIGNAL(authorized(KAuth::Action*)), SLOT(slotApplyClicked()));
}
if (q->button(KDialog::Apply)) {
q->connect(q, SIGNAL(applyClicked()), SLOT(slotApplyClicked()));
}
if (q->button(KDialog::Ok)) {
q->button(KDialog::Ok)->setAuthAction(activeModule->realModule()->authAction());
activeModule->realModule()->authAction()->setParentWidget(activeModule->realModule());
q->connect(q->button(KDialog::Ok), SIGNAL(authorized(KAuth::Action*)), SLOT(slotOkClicked()));
}
} else {
if (q->button(KDialog::Apply)) {
q->connect(q, SIGNAL(applyClicked()), SLOT(slotApplyClicked()));
q->button(KDialog::Apply)->setAuthAction(0);
}
if (q->button(KDialog::Ok)) {
q->connect(q, SIGNAL(okClicked()), SLOT(slotOkClicked()));
q->button(KDialog::Ok)->setAuthAction(0);
}
if (q->button(KDialog::Ok)) {
q->connect(q, SIGNAL(okClicked()), SLOT(slotOkClicked()));
}
}
@ -374,8 +350,6 @@ KPageWidgetItem* KCMultiDialog::addModule( const KCModuleInfo& moduleInfo,
if ( !moduleInfo.service() )
return 0;
//KAuthorized::authorizeControlModule( moduleInfo.service()->menuId() ) is
//checked in noDisplay already
if ( moduleInfo.service()->noDisplay() )
return 0;

View file

@ -19,7 +19,7 @@
#include "kpowermanager.h"
#include "kconfig.h"
#include "kconfiggroup.h"
#include "kauthaction.h"
#include "kauthorization.h"
#include "kstandarddirs.h"
#include "kdebug.h"
@ -130,12 +130,13 @@ bool KPowerManager::setCPUGovernor(const QString &governor)
return false;
}
KAuth::Action helperaction("org.kde.kpowermanager.helper.setgovernor");
helperaction.setHelperID("org.kde.kpowermanager.helper");
helperaction.addArgument("governor", governor);
KAuth::ActionReply helperreply = helperaction.execute();
// qDebug() << helperreply.errorCode() << helperreply.errorDescription();
return (helperreply == KAuth::ActionReply::SuccessReply);
QVariantMap helperargs;
helperargs.insert("governor", governor);
int helperreply = KAuthorization::execute(
QString::fromLatin1("org.kde.kpowermanager.helper"),
QString::fromLatin1("setgovernor"), helperargs
);
return (helperreply == KAuthorization::NoError);
}
bool KPowerManager::isEnabled()

View file

@ -17,15 +17,16 @@
*/
#include "kpowermanager_helper.h"
#include "kauthhelpersupport.h"
#include <QFile>
#include <QDir>
ActionReply KPowerManagerHelper::setgovernor(const QVariantMap &parameters)
#include <kdebug.h>
int KPowerManagerHelper::setgovernor(const QVariantMap &parameters)
{
if (!parameters.contains("governor")) {
return KAuth::ActionReply::HelperErrorReply;
return KAuthorization::HelperError;
}
const QByteArray governorbytes = parameters.value("governor").toByteArray();
@ -36,30 +37,24 @@ ActionReply KPowerManagerHelper::setgovernor(const QVariantMap &parameters)
continue;
}
if (!cpufile.open(QFile::WriteOnly)) {
KAuth::ActionReply errorreply(KAuth::ActionReply::HelperError);
errorreply.setErrorDescription(
kWarning() <<
QString::fromLatin1("Could not open: %1 (%2)")
.arg(cpufile.fileName())
.arg(cpufile.errorString()
)
);
errorreply.setErrorCode(1);
return errorreply;
);
return KAuthorization::HelperError;
}
if (cpufile.write(governorbytes) != governorbytes.size()) {
KAuth::ActionReply errorreply(KAuth::ActionReply::HelperError);
errorreply.setErrorDescription(
kWarning() <<
QString::fromLatin1("Could not write to: %1 (%2)")
.arg(cpufile.fileName())
.arg(cpufile.errorString()
)
);
errorreply.setErrorCode(2);
return errorreply;
);
return KAuthorization::HelperError;
}
}
return KAuth::ActionReply::SuccessReply;
return KAuthorization::NoError;
}
KDE4_AUTH_HELPER_MAIN("org.kde.kpowermanager.helper", KPowerManagerHelper)
K_AUTH_MAIN("org.kde.kpowermanager.helper", KPowerManagerHelper)

View file

@ -19,16 +19,13 @@
#ifndef KPOWERMANAGER_HELPER_H
#define KPOWERMANAGER_HELPER_H
#include <kauthactionreply.h>
#include <kauthorization.h>
// methods return type must be ActionReply otherwise QMetaObject::invokeMethod() fails
using namespace KAuth;
class KPowerManagerHelper : public QObject
class KPowerManagerHelper : public KAuthorization
{
Q_OBJECT
public slots:
ActionReply setgovernor(const QVariantMap &parameters);
int setgovernor(const QVariantMap &parameters);
};
#endif // KPOWERMANAGER_HELPER_H

View file

@ -50,7 +50,6 @@
#include <kaction.h>
#include <kactioncollection.h>
#include <kauthorized.h>
#include <kcolorscheme.h>
#include <kdialog.h>
#include <kdesktopfile.h>

View file

@ -36,7 +36,6 @@
#include <QGraphicsLinearLayout>
#include <kaction.h>
#include <kauthorized.h>
#include <kicon.h>
#include <kmenu.h>
#include <kmessagebox.h>

View file

@ -35,7 +35,6 @@
#include <cmath>
#include <kaction.h>
#include <kauthorized.h>
#include <kdebug.h>
#include <kglobal.h>
#include <klocale.h>