Akonadi Contacts

qskypedialer.cpp
1 /*
2  This file is part of Akonadi Contact.
3 
4  SPDX-FileCopyrightText: 2009 Tobias Koenig <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "qskypedialer.h"
10 
11 #include <KLocalizedString>
12 #include <QDBusConnection>
13 #include <QDBusConnectionInterface>
14 #include <QDBusInterface>
15 #include <QDBusReply>
16 #include <QProcess>
17 #include <QStandardPaths>
18 
19 #if !defined(Q_OS_WIN)
20 #include <unistd.h>
21 #else
22 #include <windows.h>
23 #endif
24 
25 static bool isSkypeServiceRegistered()
26 {
27  const QString service(QStringLiteral("com.Skype.API"));
28 
30  if (interface->isServiceRegistered(service)) {
31  return true;
32  }
33 
34  interface = QDBusConnection::sessionBus().interface();
35  if (interface->isServiceRegistered(service)) {
36  return true;
37  }
38 
39  return false;
40 }
41 
42 static QDBusInterface *searchSkypeDBusInterface()
43 {
44  const QString service(QStringLiteral("com.Skype.API"));
45  const QString path(QStringLiteral("/com/Skype"));
46 
47  auto interface = new QDBusInterface(service, path, QString(), QDBusConnection::sessionBus());
48  if (!interface->isValid()) {
49  delete interface;
50  interface = new QDBusInterface(service, path, QString(), QDBusConnection::sessionBus());
51  }
52 
53  return interface;
54 }
55 
56 QSkypeDialer::QSkypeDialer(const QString &applicationName)
57  : QDialer(applicationName)
58 {
59 }
60 
61 QSkypeDialer::~QSkypeDialer()
62 {
63  delete mInterface;
64 }
65 
66 bool QSkypeDialer::initializeSkype()
67 {
68  if (mInterface && mInterface->isValid()) {
69  return true;
70  }
71 
72  // first check whether dbus interface is available yet
73  if (!isSkypeServiceRegistered()) {
74  // it could be skype is not running yet, so start it now
75  const QString progFullPath = QStandardPaths::findExecutable(QStringLiteral("skype"));
76  if (progFullPath.isEmpty() || !QProcess::startDetached(QStringLiteral("skype"), QStringList())) {
77  mErrorMessage = i18n("Unable to start skype process, check that skype executable is in your PATH variable.");
78  return false;
79  }
80 
81  const int runs = 100;
82  for (int i = 0; i < runs; ++i) {
83  if (!isSkypeServiceRegistered()) {
84 #if !defined(Q_OS_WIN)
85  ::sleep(2);
86 #else
87  Sleep(2000);
88 #endif
89  } else {
90  break;
91  }
92  }
93  }
94 
95  // check again for the dbus interface
96  mInterface = searchSkypeDBusInterface();
97 
98  if (!mInterface->isValid()) {
99  delete mInterface;
100  mInterface = nullptr;
101 
102  mErrorMessage = i18n("Skype Public API (D-Bus) seems to be disabled.");
103  return false;
104  }
105 
106  QDBusReply<QString> reply = mInterface->call(QStringLiteral("Invoke"), QStringLiteral("NAME %1").arg(mApplicationName));
107  if (reply.value() != QLatin1String("OK")) {
108  delete mInterface;
109  mInterface = nullptr;
110 
111  mErrorMessage = i18n("Skype registration failed.");
112  return false;
113  }
114 
115  reply = mInterface->call(QStringLiteral("Invoke"), QStringLiteral("PROTOCOL 1"));
116  if (reply.value() != QLatin1String("PROTOCOL 1")) {
117  delete mInterface;
118  mInterface = nullptr;
119 
120  mErrorMessage = i18n("Protocol mismatch.");
121  return false;
122  }
123 
124  return true;
125 }
126 
127 bool QSkypeDialer::dialNumber(const QString &number)
128 {
129  if (!initializeSkype()) {
130  return false;
131  }
132 
133  QDBusReply<QString> reply = mInterface->call(QStringLiteral("Invoke"), QStringLiteral("CALL %1").arg(number));
134 
135  return true;
136 }
137 
138 bool QSkypeDialer::sendSms(const QString &number, const QString &text)
139 {
140  if (!initializeSkype()) {
141  return false;
142  }
143 
144  // First we create a new SMS object that gets an ID. We need that ID later...
145  QDBusReply<QString> reply = mInterface->call(QStringLiteral("Invoke"), QStringLiteral("CREATE SMS OUTGOING %1").arg(number));
146  const QString messageId = reply.value().section(QLatin1Char(' '), 1, 1);
147 
148  // Set the SMS text
149  reply = mInterface->call(QStringLiteral("Invoke"), QStringLiteral("SET SMS %1 BODY %2").arg(messageId, text));
150 
151  // Send the SMS
152  reply = mInterface->call(QStringLiteral("Invoke"), QStringLiteral("ALTER SMS %1 SEND").arg(messageId));
153  if (reply.value().contains(QLatin1String("ERROR"))) {
154  mErrorMessage = reply.value();
155  // As sending the message failed (not enough Skype credit), lets delete the message
156  reply = mInterface->call(QStringLiteral("Invoke"), QStringLiteral("DELETE SMS %1").arg(messageId));
157  return false;
158  }
159 
160  return true;
161 }
QDBusReply< bool > isServiceRegistered(const QString &serviceName) const const
QString findExecutable(const QString &executableName, const QStringList &paths)
QString i18n(const char *text, const TYPE &arg...)
QDBusConnection sessionBus()
bool isEmpty() const const
QDBusConnectionInterface * interface() const const
bool startDetached(qint64 *pid)
QString path(const QString &relativePath)
bool isValid(QStringView ifopt)
QDBusReply::Type value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sat Apr 1 2023 04:09:05 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.