23 #include <QtCore/qplugin.h>
26 #include <QtDBus/QDBusMessage>
27 #include <QtDBus/QDBusConnection>
36 #include "authadaptor.h"
38 Q_DECLARE_METATYPE(QTimer*)
45 void DBusHelperProxy::stopAction(
const QString &action,
const QString &helperID)
48 message = QDBusMessage::createMethodCall(helperID, QLatin1String(
"/"), QLatin1String(
"org.kde.auth"), QLatin1String(
"stopAction"));
52 message.setArguments(args);
54 QDBusConnection::systemBus().asyncCall(message);
60 QDataStream stream(&blob, QIODevice::WriteOnly);
64 QDBusConnection::systemBus().interface()->startService(helperID);
66 if (!QDBusConnection::systemBus().connect(helperID, QLatin1String(
"/"), QLatin1String(
"org.kde.auth"), QLatin1String(
"remoteSignal"),
this, SLOT(remoteSignalReceived(
int,
QString,QByteArray)))) {
71 message = QDBusMessage::createMethodCall(helperID, QLatin1String(
"/"), QLatin1String(
"org.kde.auth"), QLatin1String(
"performActions"));
74 args << blob << BackendsManager::authBackend()->callerID();
75 message.setArguments(args);
77 QDBusPendingCall reply = QDBusConnection::systemBus().asyncCall(message);
78 if (reply.reply().type() == QDBusMessage::ErrorMessage) {
87 if (!m_actionsInProgress.isEmpty()) {
88 return ActionReply::HelperBusyReply;
92 QDataStream stream(&blob, QIODevice::WriteOnly);
96 QDBusConnection::systemBus().interface()->startService(helperID);
98 if (!QDBusConnection::systemBus().connect(helperID, QLatin1String(
"/"), QLatin1String(
"org.kde.auth"), QLatin1String(
"remoteSignal"),
this, SLOT(remoteSignalReceived(
int,
QString,QByteArray)))) {
99 ActionReply errorReply = ActionReply::DBusErrorReply;
101 QDBusConnection::systemBus().lastError().
message()));
106 message = QDBusMessage::createMethodCall(helperID, QLatin1String(
"/"), QLatin1String(
"org.kde.auth"), QLatin1String(
"performAction"));
109 args << action << BackendsManager::authBackend()->callerID() << blob;
110 message.setArguments(args);
112 m_actionsInProgress.push_back(action);
115 QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(message);
116 QDBusPendingCallWatcher watcher(pendingCall,
this);
117 connect(&watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), &e, SLOT(quit()));
120 QDBusMessage reply = pendingCall.reply();
122 if (reply.type() == QDBusMessage::ErrorMessage) {
125 "Connection error: %1. Message error: %2", QDBusConnection::systemBus().lastError().
message(),
126 reply.errorMessage()));
127 qDebug() << reply.errorMessage();
130 m_actionsInProgress.removeOne(action);
135 if (reply.arguments().size() != 1) {
136 ActionReply errorReply = ActionReply::DBusErrorReply;
138 reply.arguments().size(), QDBusConnection::systemBus().lastError().message()));
141 m_actionsInProgress.removeOne(action);
146 return ActionReply::deserialize(reply.arguments().first().toByteArray());
151 if (!m_actionsInProgress.isEmpty()) {
155 QDBusConnection::systemBus().interface()->startService(helperID);
158 message = QDBusMessage::createMethodCall(helperID, QLatin1String(
"/"), QLatin1String(
"org.kde.auth"), QLatin1String(
"authorizeAction"));
161 args << action << BackendsManager::authBackend()->callerID();
162 message.setArguments(args);
164 m_actionsInProgress.push_back(action);
167 QDBusPendingCall pendingCall = QDBusConnection::systemBus().asyncCall(message);
168 QDBusPendingCallWatcher watcher(pendingCall,
this);
169 connect(&watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), &e, SLOT(quit()));
172 m_actionsInProgress.removeOne(action);
174 QDBusMessage reply = pendingCall.reply();
176 if (reply.type() == QDBusMessage::ErrorMessage || reply.arguments().size() != 1) {
183 bool DBusHelperProxy::initHelper(
const QString &name)
185 new AuthAdaptor(
this);
187 if (!QDBusConnection::systemBus().registerService(name)) {
191 if (!QDBusConnection::systemBus().registerObject(QLatin1String(
"/"),
this)) {
200 void DBusHelperProxy::setHelperResponder(
QObject *o)
205 void DBusHelperProxy::remoteSignalReceived(
int t,
const QString &action, QByteArray blob)
207 SignalType type = (SignalType)t;
208 QDataStream stream(&blob, QIODevice::ReadOnly);
210 if (type == ActionStarted) {
211 emit actionStarted(action);
212 }
else if (type == ActionPerformed) {
213 ActionReply reply = ActionReply::deserialize(blob);
215 m_actionsInProgress.removeOne(action);
216 emit actionPerformed(action, reply);
217 }
else if (type == DebugMessage) {
224 }
else if (type == ProgressStepIndicator) {
229 }
else if (type == ProgressStepData) {
237 void DBusHelperProxy::stopAction(
const QString &action)
241 #warning FIXME: The stop request should be action-specific rather than global
243 m_stopRequest =
true;
246 bool DBusHelperProxy::hasToStopAction()
249 loop.processEvents(QEventLoop::AllEvents);
251 return m_stopRequest;
254 void DBusHelperProxy::performActions(QByteArray blob,
const QByteArray &callerID)
256 QDataStream stream(&blob, QIODevice::ReadOnly);
262 while (i != actions.constEnd()) {
264 QDataStream stream(&blob, QIODevice::WriteOnly);
268 performAction(i->first, callerID, blob);
274 QByteArray DBusHelperProxy::performAction(
const QString &action,
const QByteArray &callerID, QByteArray arguments)
277 return ActionReply::NoResponderReply.serialized();
280 if (!m_currentAction.isEmpty()) {
281 return ActionReply::HelperBusyReply.serialized();
285 QDataStream s(&arguments, QIODevice::ReadOnly);
288 m_currentAction = action;
289 emit remoteSignal(ActionStarted, action, QByteArray());
291 e.processEvents(QEventLoop::AllEvents);
295 QTimer *timer = responder->property(
"__KAuth_Helper_Shutdown_Timer").value<QTimer*>();
298 if (BackendsManager::authBackend()->isCallerAuthorized(action, callerID)) {
300 if (slotname.startsWith(m_name + QLatin1Char(
'.'))) {
301 slotname = slotname.right(slotname.length() - m_name.length() - 1);
304 slotname.replace(QLatin1Char(
'.'), QLatin1Char(
'_'));
306 bool success = QMetaObject::invokeMethod(responder, slotname.toLatin1(), Qt::DirectConnection,
307 Q_RETURN_ARG(
ActionReply, retVal), Q_ARG(QVariantMap, args));
310 retVal = ActionReply::NoSuchActionReply;
314 retVal = ActionReply::AuthorizationDeniedReply;
319 emit remoteSignal(ActionPerformed, action, retVal.
serialized());
320 e.processEvents(QEventLoop::AllEvents);
321 m_currentAction.clear();
322 m_stopRequest =
false;
328 uint DBusHelperProxy::authorizeAction(
const QString& action,
const QByteArray& callerID)
330 if (!m_currentAction.isEmpty()) {
334 m_currentAction = action;
338 QTimer *timer = responder->property(
"__KAuth_Helper_Shutdown_Timer").value<QTimer*>();
341 if (BackendsManager::authBackend()->isCallerAuthorized(action, callerID)) {
342 retVal =
static_cast<uint
>(Action::Authorized);
344 retVal =
static_cast<uint
>(Action::Denied);
348 m_currentAction.clear();
354 void DBusHelperProxy::sendDebugMessage(
int level,
const char *msg)
357 QDataStream stream(&blob, QIODevice::WriteOnly);
359 stream << level << QString::fromLocal8Bit(msg);
361 emit remoteSignal(DebugMessage, m_currentAction, blob);
364 void DBusHelperProxy::sendProgressStep(
int step)
367 QDataStream stream(&blob, QIODevice::WriteOnly);
371 emit remoteSignal(ProgressStepIndicator, m_currentAction, blob);
374 void DBusHelperProxy::sendProgressStep(
const QVariantMap &data)
377 QDataStream stream(&blob, QIODevice::WriteOnly);
381 emit remoteSignal(ProgressStepData, m_currentAction, blob);
386 QtMsgType type = (QtMsgType)t;
389 qDebug(
"Debug message from helper: %s", message.toLatin1().data());
392 qWarning(
"Warning from helper: %s", message.toLatin1().data());
395 qCritical(
"Critical warning from helper: %s", message.toLatin1().data());
398 qFatal(
"Fatal error from helper: %s", message.toLatin1().data());
void message(KMessage::MessageType messageType, const QString &text, const QString &caption=QString())
Display a long message of a certain type.
QString i18n(const char *text)
Returns a localized version of a string.
void setErrorDescription(const QString &error)
Sets a human-readble description of the error.
AuthStatus
The three values returned by authorization methods.
static void debugMessageReceived(int t, const QString &message)
QByteArray serialized() const
Serialize the reply into a QByteArray.
Class that encapsulates a reply coming from the helper after executing an action. ...
void progressStep(int step)
Send a progressStep signal to the caller application.