File indexing completed on 2023-12-10 04:56:57

0001 /*
0002  * Copyright (C) 2012 Dan Vrátil <dvratil@redhat.com>
0003  *
0004  * This library is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU Lesser General Public
0006  * License as published by the Free Software Foundation; either
0007  * version 2.1 of the License, or (at your option) any later version.
0008  *
0009  * This library is distributed in the hope that it will be useful,
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  * Lesser General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU Lesser General Public
0015  * License along with this library; if not, write to the Free Software
0016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
0017  */
0018 
0019 #include "actions.h"
0020 
0021 #include <TelepathyQt/Account>
0022 #include <TelepathyQt/ChannelRequestHints>
0023 #include <TelepathyQt/Contact>
0024 #include <TelepathyQt/PendingChannelRequest>
0025 #include <TelepathyQt/PendingFailure>
0026 #include <TelepathyQt/ReferencedHandles>
0027 
0028 #include <QMimeType>
0029 #include <KToolInvocation>
0030 #include "ktp-debug.h"
0031 #include <KLocalizedString>
0032 #include <KNotification>
0033 #include <KAboutData>
0034 
0035 #define PREFERRED_TEXT_CHAT_HANDLER QLatin1String("org.freedesktop.Telepathy.Client.KTp.TextUi")
0036 #define PREFERRED_FILE_TRANSFER_HANDLER QLatin1String("org.freedesktop.Telepathy.Client.KTp.FileTransfer")
0037 #define PREFERRED_AUDIO_VIDEO_HANDLER QLatin1String("org.freedesktop.Telepathy.Client.KTp.CallUi")
0038 #define PREFERRED_RFB_HANDLER QLatin1String("org.freedesktop.Telepathy.Client.krfb_rfb_handler")
0039 
0040 using namespace KTp;
0041 
0042 Tp::PendingChannelRequest* Actions::startChat(const Tp::AccountPtr &account,
0043                                               const QString &contactIdentifier,
0044                                               bool delegateToPreferredHandler)
0045 {
0046     if (account.isNull() || contactIdentifier.isEmpty()) {
0047         qCWarning(KTP_COMMONINTERNALS) << "Parameters invalid";
0048     }
0049 
0050     qCDebug(KTP_COMMONINTERNALS) << "Requesting text channel for contact id: " << contactIdentifier;
0051 
0052     Tp::ChannelRequestHints hints;
0053     if (delegateToPreferredHandler) {
0054       hints.setHint(QLatin1String("org.freedesktop.Telepathy.ChannelRequest"),
0055                     QLatin1String("DelegateToPreferredHandler"),
0056                     QVariant(true));
0057     }
0058 
0059     return account->ensureTextChat(contactIdentifier,
0060                                    QDateTime::currentDateTime(),
0061                                    PREFERRED_TEXT_CHAT_HANDLER,
0062                                    hints);
0063 }
0064 
0065 Tp::PendingChannelRequest* Actions::startChat(const Tp::AccountPtr &account,
0066                                               const Tp::ContactPtr &contact,
0067                                               bool delegateToPreferredHandler)
0068 {
0069     if (account.isNull() || contact.isNull()) {
0070         qCWarning(KTP_COMMONINTERNALS) << "Parameters invalid";
0071     }
0072 
0073     qCDebug(KTP_COMMONINTERNALS) << "Requesting text channel for" << contact->id();
0074 
0075     Tp::ChannelRequestHints hints;
0076     if (delegateToPreferredHandler) {
0077       hints.setHint(QLatin1String("org.freedesktop.Telepathy.ChannelRequest"),
0078                     QLatin1String("DelegateToPreferredHandler"),
0079                     QVariant(true));
0080     }
0081 
0082     return account->ensureTextChat(contact,
0083                                    QDateTime::currentDateTime(),
0084                                    PREFERRED_TEXT_CHAT_HANDLER,
0085                                    hints);
0086 }
0087 
0088 Tp::PendingChannelRequest* Actions::startGroupChat(const Tp::AccountPtr &account,
0089                                                    const QString &roomName)
0090 {
0091     if (account.isNull() || roomName.isEmpty()) {
0092         qCWarning(KTP_COMMONINTERNALS) << "Parameters invalid";
0093     }
0094 
0095     qCDebug(KTP_COMMONINTERNALS) << "Requesting text chat room " << roomName;
0096 
0097     Tp::ChannelRequestHints hints;
0098     hints.setHint(QLatin1String("org.kde.telepathy"), QLatin1String("forceRaiseWindow"), QVariant(true));
0099 
0100     return account->ensureTextChatroom(roomName,
0101                                        QDateTime::currentDateTime(),
0102                                        PREFERRED_TEXT_CHAT_HANDLER,
0103                                        hints);
0104 }
0105 
0106 Tp::PendingChannelRequest* Actions::startAudioCall(const Tp::AccountPtr &account,
0107                                                    const Tp::ContactPtr &contact)
0108 {
0109     if (account.isNull() || contact.isNull()) {
0110         qCWarning(KTP_COMMONINTERNALS) << "Parameters invalid";
0111     }
0112 
0113     qCDebug(KTP_COMMONINTERNALS) << "Requesting audio channel for" << contact->id();
0114 
0115     return account->ensureAudioCall(contact,
0116                                     QLatin1String("audio"),
0117                                     QDateTime::currentDateTime(),
0118                                     PREFERRED_AUDIO_VIDEO_HANDLER);
0119 }
0120 
0121 Tp::PendingChannelRequest* Actions::startAudioVideoCall(const Tp::AccountPtr &account,
0122                                                         const Tp::ContactPtr &contact)
0123 {
0124     if (account.isNull() || contact.isNull()) {
0125         qCWarning(KTP_COMMONINTERNALS) << "Parameters invalid";
0126     }
0127 
0128     qCDebug(KTP_COMMONINTERNALS) << "Requesting audio-video channel for" << contact->id();
0129 
0130     return account->ensureAudioVideoCall(contact,
0131                                          QLatin1String("audio"),
0132                                          QLatin1String("video"),
0133                                          QDateTime::currentDateTime(),
0134                                          PREFERRED_AUDIO_VIDEO_HANDLER);
0135 }
0136 
0137 Tp::PendingChannelRequest* Actions::startDesktopSharing(const Tp::AccountPtr &account,
0138                                                         const Tp::ContactPtr &contact)
0139 {
0140     if (account.isNull() || contact.isNull()) {
0141         qCWarning(KTP_COMMONINTERNALS) << "Parameters invalid";
0142     }
0143 
0144     qCDebug(KTP_COMMONINTERNALS) << "Requesting stream tube for" << contact->id();
0145 
0146     return account->createStreamTube(contact,
0147                                      QLatin1String("rfb"),
0148                                      QDateTime::currentDateTime(),
0149                                      PREFERRED_RFB_HANDLER);
0150 }
0151 
0152 Tp::PendingChannelRequest* Actions::startFileTransfer(const Tp::AccountPtr &account,
0153                                                       const Tp::ContactPtr &contact,
0154                                                       const QString &filePath)
0155 {
0156     if (account.isNull() || contact.isNull()) {
0157         qCWarning(KTP_COMMONINTERNALS) << "Parameters invalid";
0158     }
0159 
0160     qCDebug(KTP_COMMONINTERNALS) << "Requesting file transfer of" << filePath << "to" << contact->id();
0161 
0162     QFileInfo fileInfo(filePath);
0163 
0164     Tp::FileTransferChannelCreationProperties fileTransferProperties;
0165 
0166     if (account->serviceName() == QLatin1String("google-talk") &&
0167         (fileInfo.suffix() == QLatin1String("exe") || fileInfo.suffix() == QLatin1String("ini"))) {
0168 
0169         qCDebug(KTP_COMMONINTERNALS) << "Google Talk forbids transfering files with suffix \"ini\" or \"exe\". Renaming.";
0170 
0171         QString fileName = fileInfo.fileName().append(QLatin1String("_"));
0172 
0173         QMimeDatabase db;
0174         fileTransferProperties = Tp::FileTransferChannelCreationProperties(fileName,
0175                                                                            db.mimeTypeForFile(filePath).name(),
0176                                                                            fileInfo.size());
0177 
0178         fileTransferProperties.setUri(QUrl::fromLocalFile(filePath).toString());
0179         fileTransferProperties.setLastModificationTime(fileInfo.lastModified());
0180 
0181         KNotification *notification = new KNotification (QLatin1String("googletalkExtensionsError"));
0182         notification->setText(i18n("Transferring files with .exe or .ini extension is not allowed by Google Talk. It was sent with filename <i>%1</i>", fileName));
0183         notification->setTitle(i18n("Transferred file renamed"));
0184 
0185         notification->setComponentName(QStringLiteral("ktelepathy"));
0186         notification->sendEvent();
0187 
0188     } else {
0189         QMimeDatabase db;
0190         fileTransferProperties = Tp::FileTransferChannelCreationProperties(
0191                                     filePath, db.mimeTypeForFile(filePath, QMimeDatabase::MatchContent).name());
0192     }
0193 
0194     return account->createFileTransfer(contact,
0195                                        fileTransferProperties,
0196                                        QDateTime::currentDateTime(),
0197                                        PREFERRED_FILE_TRANSFER_HANDLER);
0198 }
0199 
0200 Tp::PendingOperation* Actions::startFileTransfer(const Tp::AccountPtr &account,
0201                                                  const Tp::ContactPtr &contact,
0202                                                  const QUrl &url)
0203 {
0204     if (account.isNull() || contact.isNull() || url.isEmpty()) {
0205         qCWarning(KTP_COMMONINTERNALS) << "Parameters invalid";
0206     }
0207 
0208     qCDebug(KTP_COMMONINTERNALS) << "Requesting file transfer of" << url.toLocalFile() << "to" << contact->id();
0209 
0210     Tp::PendingOperation *ret = nullptr;
0211     if (url.isLocalFile()) {
0212         ret = startFileTransfer(account, contact, url.toLocalFile());
0213     } else {
0214         ret = new Tp::PendingFailure(QLatin1String("Failed file transfer"), QString(QLatin1String("You are only supposed to send local files, not %1")).arg(url.toString()), account);
0215     }
0216     return ret;
0217 }
0218 
0219 void Actions::openLogViewer(const Tp::AccountPtr &account,
0220                             const Tp::ContactPtr &contact)
0221 {
0222     if (account.isNull() || contact.isNull()) {
0223         qCWarning(KTP_COMMONINTERNALS) << "Parameters invalid";
0224         return;
0225     }
0226 
0227     openLogViewer(account, contact->id());
0228 }
0229 
0230 void Actions::openLogViewer(const QUrl &uri)
0231 {
0232     qCDebug(KTP_COMMONINTERNALS) << "Opening logviewer for" << uri;
0233 
0234     QStringList arguments;
0235     arguments << QLatin1String("--") << uri.toString();
0236 
0237     KToolInvocation::kdeinitExec(QLatin1String("ktp-log-viewer"), arguments);
0238 }
0239 
0240 void Actions::openLogViewer(const Tp::AccountPtr& account, const QString& targetId)
0241 {
0242     if (account.isNull() || targetId.isEmpty()) {
0243         qCWarning(KTP_COMMONINTERNALS) << " Parameters invalid";
0244         return;
0245     }
0246 
0247     qCDebug(KTP_COMMONINTERNALS) << "Opening logviewer for" << targetId;
0248 
0249     QStringList arguments;
0250     arguments << QLatin1String("--") << account->uniqueIdentifier() << targetId;
0251 
0252     /* Use "--" so that KCmdLineArgs does not parse UIDs starting with "-" as arguments */
0253     KToolInvocation::kdeinitExec(QLatin1String("ktp-log-viewer"), arguments);
0254 }
0255 
0256 
0257 const QVariantMap createHintsForCollabRequest(const Actions::DocumentList& documents, bool needOpenEditor)
0258 {
0259     QVariantMap hints;
0260     hints.insert(QLatin1String("initialDocumentsSize"), documents.size());
0261     for ( int i = 0; i < documents.size(); i++ ) {
0262         const QString key(QLatin1String("initialDocument") + QString::number(i));
0263         hints.insert(key, documents.at(i).fileName());
0264         if ( needOpenEditor ) {
0265             hints.insert(key + QLatin1String("_source"), documents.at(i).url());
0266         }
0267     }
0268     if ( needOpenEditor ) {
0269         hints.insert(QLatin1String("needToOpenDocument"), QVariant(true));
0270     }
0271     return hints;
0272 }
0273 
0274 Tp::PendingChannelRequest* createCollabRequest(const Tp::AccountPtr account,
0275                                                const Actions::DocumentList documents,
0276                                                QVariantMap requestBase,
0277                                                bool needOpenEditor)
0278 {
0279     QVariantMap hints = createHintsForCollabRequest(documents, needOpenEditor);
0280 
0281     requestBase.insert(TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType"),
0282                     TP_QT_IFACE_CHANNEL_TYPE_STREAM_TUBE);
0283     requestBase.insert(TP_QT_IFACE_CHANNEL_TYPE_STREAM_TUBE + QLatin1String(".Service"),
0284                     QLatin1String("infinote"));
0285 
0286     Tp::PendingChannelRequest* channelRequest;
0287     channelRequest = account->ensureChannel(requestBase,
0288                                             QDateTime::currentDateTime(),
0289                                             QLatin1String("org.freedesktop.Telepathy.Client.KTp.infinoteServer"),
0290                                             hints);
0291 
0292     return channelRequest;
0293 }
0294 
0295 Tp::PendingChannelRequest* Actions::startCollaborativeEditing(const Tp::AccountPtr& account,
0296                                                               const Tp::ContactPtr& contact,
0297                                                               const DocumentList& documents,
0298                                                               bool needOpenEditor)
0299 {
0300     QVariantMap request;
0301     request.insert(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType"),
0302                 (uint) Tp::HandleTypeContact);
0303     request.insert(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle"),
0304                 contact->handle().at(0));
0305     return createCollabRequest(account, documents, request, needOpenEditor);
0306 }
0307 
0308 Tp::PendingChannelRequest* Actions::startCollaborativeEditing(const Tp::AccountPtr& account,
0309                                                               const QString& chatroom,
0310                                                               const DocumentList& documents,
0311                                                               bool needOpenEditor)
0312 {
0313     QVariantMap request;
0314     request.insert(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType"),
0315                 (uint) Tp::HandleTypeRoom);
0316     request.insert(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetID"),
0317                 chatroom);
0318     return createCollabRequest(account, documents, request, needOpenEditor);
0319 }