helper.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Copyright (C) 2015 Malte Veerman <malte.veerman@gmail.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. *
  18. */
  19. #include "helper.h"
  20. #include <QtCore/QFile>
  21. #include <QtCore/QTextStream>
  22. #include <QtCore/QFileInfo>
  23. #include <KAuth/KAuthHelperSupport>
  24. #include <KI18n/KLocalizedString>
  25. #ifndef NO_SYSTEMD
  26. #include <QtDBus/QDBusInterface>
  27. #include <QtDBus/QDBusMetaType>
  28. #include <QtDBus/QDBusReply>
  29. #include <QtDBus/QDBusVariant>
  30. #ifndef STANDARD_HELPER_ID
  31. #define STANDARD_HELPER_ID "org.kde.fancontrol.gui.helper"
  32. #endif
  33. using namespace KAuth;
  34. struct StringStruct
  35. {
  36. QString type;
  37. QString filename;
  38. QString destination;
  39. };
  40. typedef QList<StringStruct> StringStructArray;
  41. Q_DECLARE_METATYPE(StringStruct)
  42. Q_DECLARE_METATYPE(StringStructArray)
  43. QDBusArgument &operator<<(QDBusArgument &argument, const StringStruct &structure)
  44. {
  45. argument.beginStructure();
  46. argument << structure.type << structure.filename << structure.destination;
  47. argument.endStructure();
  48. return argument;
  49. }
  50. const QDBusArgument &operator>>(const QDBusArgument &argument, StringStruct &structure)
  51. {
  52. argument.beginStructure();
  53. argument >> structure.type >> structure.filename >> structure.destination;
  54. argument.endStructure();
  55. return argument;
  56. }
  57. #endif
  58. ActionReply Helper::action(const QVariantMap &arguments)
  59. {
  60. ActionReply reply;
  61. #ifndef NO_SYSTEMD
  62. if (arguments[QStringLiteral("action")] == "dbusaction")
  63. {
  64. qDBusRegisterMetaType<StringStruct>();
  65. qDBusRegisterMetaType<StringStructArray>();
  66. const auto method = arguments[QStringLiteral("method")].toString();
  67. const auto argsForCall = arguments[QStringLiteral("arguments")].toList();
  68. const auto systembus = QDBusConnection::systemBus();
  69. const auto iface = new QDBusInterface (QStringLiteral("org.freedesktop.systemd1"),
  70. QStringLiteral("/org/freedesktop/systemd1"),
  71. QStringLiteral("org.freedesktop.systemd1.Manager"),
  72. systembus,
  73. this);
  74. QDBusMessage dbusmessage;
  75. if (iface->isValid())
  76. {
  77. if (argsForCall.isEmpty())
  78. dbusmessage = iface->call(QDBus::AutoDetect, method);
  79. else
  80. dbusmessage = iface->callWithArgumentList(QDBus::AutoDetect, method, argsForCall);
  81. if (method != QStringLiteral("Reexecute"))
  82. {
  83. if (dbusmessage.type() == QDBusMessage::ErrorMessage)
  84. {
  85. reply = ActionReply::HelperErrorReply();
  86. reply.setErrorDescription(dbusmessage.errorMessage());
  87. }
  88. else if (dbusmessage.type() == QDBusMessage::ReplyMessage)
  89. {
  90. if (dbusmessage.signature() == QStringLiteral("a(sss)"))
  91. {
  92. QDBusReply<StringStructArray> dbusreply(dbusmessage);
  93. if (dbusreply.isValid())
  94. {
  95. QMap<QString, QVariant> map;
  96. map.insert(QStringLiteral("type"), dbusreply.value().value(0).type);
  97. map.insert(QStringLiteral("filename"), dbusreply.value().value(0).filename);
  98. map.insert(QStringLiteral("destination"), dbusreply.value().value(0).destination);
  99. reply.addData(QStringLiteral("reply"), map);
  100. }
  101. else
  102. {
  103. reply = ActionReply::HelperErrorReply();
  104. reply.setErrorDescription(dbusreply.error().message());
  105. }
  106. }
  107. else if (dbusmessage.signature() == QStringLiteral("ba(sss)"))
  108. {
  109. QDBusReply<bool> dbusreply(dbusmessage); //QDBusReply only extracts the first return argument("b")
  110. if (dbusreply.isValid())
  111. {
  112. QMap<QString, QVariant> map;
  113. map.insert(QStringLiteral("enableInfo"), dbusreply.value());
  114. auto changes = qdbus_cast<StringStructArray>(qvariant_cast<QDBusArgument>(dbusmessage.arguments().value(1))); //Extract the second argument("a(sss)")
  115. map.insert(QStringLiteral("type"), changes.value(0).type);
  116. map.insert(QStringLiteral("filename"), changes.value(0).filename);
  117. map.insert(QStringLiteral("destination"), changes.value(0).destination);
  118. reply.addData(QStringLiteral("reply"), map);
  119. }
  120. else
  121. {
  122. reply = ActionReply::HelperErrorReply();
  123. reply.setErrorDescription(dbusreply.error().message());
  124. }
  125. }
  126. else if (dbusmessage.signature() == QStringLiteral("o"))
  127. {
  128. QDBusReply<QDBusObjectPath> dbusreply(dbusmessage);
  129. if (dbusreply.isValid())
  130. {
  131. QMap<QString, QVariant> map;
  132. map.insert(QStringLiteral("job"), dbusreply.value().path());
  133. reply.addData(QStringLiteral("reply"), map);
  134. }
  135. else
  136. {
  137. reply = ActionReply::HelperErrorReply();
  138. reply.setErrorDescription(dbusreply.error().message());
  139. }
  140. }
  141. }
  142. }
  143. }
  144. else
  145. {
  146. reply = ActionReply::HelperErrorReply();
  147. reply.setErrorDescription(i18n("Could not create dbus interface"));
  148. }
  149. delete iface;
  150. }
  151. else
  152. #endif
  153. if (arguments[QStringLiteral("action")] == "read")
  154. {
  155. const auto filename = arguments[QStringLiteral("filename")].toString();
  156. if (!filename.startsWith(QStringLiteral("/etc")))
  157. {
  158. reply = ActionReply::HelperErrorReply();
  159. reply.setErrorDescription(QStringLiteral("File must be located in /etc"));
  160. return reply;
  161. }
  162. QFile file(filename);
  163. if (file.open(QIODevice::ReadOnly))
  164. {
  165. QTextStream stream(&file);
  166. const auto content = stream.readAll();
  167. reply.addData(QStringLiteral("content"), content);
  168. }
  169. else
  170. {
  171. reply = ActionReply::HelperErrorReply();
  172. reply.setErrorDescription(file.errorString());
  173. }
  174. }
  175. else if (arguments[QStringLiteral("action")] == "write")
  176. {
  177. const auto filename = arguments[QStringLiteral("filename")].toString();
  178. if (!filename.startsWith(QStringLiteral("/etc")))
  179. {
  180. reply = ActionReply::HelperErrorReply();
  181. reply.setErrorDescription(QStringLiteral("File must be located in /etc"));
  182. return reply;
  183. }
  184. QFile file(filename);
  185. if (file.open(QIODevice::WriteOnly))
  186. {
  187. QTextStream stream(&file);
  188. stream << arguments[QStringLiteral("content")].toString();
  189. }
  190. else
  191. {
  192. reply = ActionReply::HelperErrorReply();
  193. reply.setErrorDescription(file.errorString());
  194. }
  195. }
  196. else
  197. {
  198. reply = ActionReply::HelperErrorReply();
  199. reply.setErrorDescription(i18n("This action does not exist!"));
  200. }
  201. return reply;
  202. }
  203. KAUTH_HELPER_MAIN(STANDARD_HELPER_ID, Helper)