File indexing completed on 2024-04-14 04:51:45

0001 /**
0002  * SPDX-FileCopyrightText: 2018 Simon Redman <simon@ergotech.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #pragma once
0008 
0009 class QObject;
0010 #include <QStandardPaths>
0011 
0012 #include <core/kdeconnectplugin.h>
0013 
0014 /**
0015  * Used to request the device send the unique ID and last-changed timestamp of every contact
0016  */
0017 #define PACKET_TYPE_CONTACTS_REQUEST_ALL_UIDS_TIMESTAMP QStringLiteral("kdeconnect.contacts.request_all_uids_timestamps")
0018 
0019 /**
0020  * Used to request the vcards for the contacts corresponding to a list of UIDs
0021  *
0022  * It shall contain the key "uids", which will have a list of uIDs (long int, as string)
0023  */
0024 #define PACKET_TYPE_CONTACTS_REQUEST_VCARDS_BY_UIDS QStringLiteral("kdeconnect.contacts.request_vcards_by_uid")
0025 
0026 /**
0027  * Response indicating the package contains a list of all contact uIDs and last-changed timestamps
0028  *
0029  * It shall contain the key "uids", which will mark a list of uIDs (long int, as string)
0030  * then, for each UID, there shall be a field with the key of that UID and the value of the timestamp (int, as string)
0031  *
0032  * For example:
0033  * ( 'uids' : ['1', '3', '15'],
0034  *  '1'  : '973486597',
0035  *  '3'  : '973485443',
0036  *  '15' : '973492390' )
0037  *
0038  * The returned IDs can be used in future requests for more information about the contact
0039  */
0040 #define PACKAGE_TYPE_CONTACTS_RESPONSE_UIDS_TIMESTAMPS QStringLiteral("kdeconnect.contacts.response_uids_timestamps")
0041 
0042 /**
0043  * Response indicating the package contains a list of contact vcards
0044  *
0045  * It shall contain the key "uids", which will mark a list of uIDs (long int, as string)
0046  * then, for each UID, there shall be a field with the key of that UID and the value of the remote's vcard for that contact
0047  *
0048  * For example:
0049  * ( 'uids' : ['1', '3', '15'],
0050  *  '1'  : 'BEGIN:VCARD\n....\nEND:VCARD',
0051  *  '3'  : 'BEGIN:VCARD\n....\nEND:VCARD',
0052  *  '15' : 'BEGIN:VCARD\n....\nEND:VCARD' )
0053  */
0054 #define PACKET_TYPE_CONTACTS_RESPONSE_VCARDS QStringLiteral("kdeconnect.contacts.response_vcards")
0055 
0056 /**
0057  * Where the synchronizer will write vcards and other metadata
0058  * TODO: Per-device folders since each device *will* have different uIDs
0059  */
0060 
0061 #ifdef Q_OS_WIN
0062 Q_GLOBAL_STATIC_WITH_ARGS(QString, vcardsLocation, (QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + QLatin1String("/Contacts")))
0063 #else
0064 Q_GLOBAL_STATIC_WITH_ARGS(QString, vcardsLocation, (QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/kpeoplevcard")))
0065 #endif
0066 
0067 #define VCARD_EXTENSION QStringLiteral(".vcf")
0068 #define METADATA_EXTENSION QStringLiteral(".meta")
0069 
0070 typedef QString uID;
0071 Q_DECLARE_METATYPE(uID)
0072 
0073 typedef QStringList uIDList_t;
0074 Q_DECLARE_METATYPE(uIDList_t)
0075 
0076 class ContactsPlugin : public KdeConnectPlugin
0077 {
0078     Q_OBJECT
0079     Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.contacts")
0080 
0081 public:
0082     explicit ContactsPlugin(QObject *parent, const QVariantList &args);
0083 
0084     void receivePacket(const NetworkPacket &np) override;
0085     void connected() override;
0086 
0087     QString dbusPath() const override;
0088 
0089 protected:
0090     /**
0091      * Path where this instance of the plugin stores its synchronized contacts
0092      */
0093     QString vcardsPath;
0094 
0095 public Q_SLOTS:
0096 
0097     /**
0098      *  Query the remote device for all its uIDs and last-changed timestamps, then:
0099      *      Delete any contacts which are known locally but not reported by the remote
0100      *      Update any contacts which are known locally but have an older timestamp
0101      *      Add any contacts which are not known locally but are reported by the remote
0102      */
0103     Q_SCRIPTABLE void synchronizeRemoteWithLocal();
0104 
0105 public:
0106 Q_SIGNALS:
0107     /**
0108      * Emitted to indicate that we have locally cached all remote contacts
0109      *
0110      * @param newContacts The list of just-synchronized contacts
0111      */
0112     Q_SCRIPTABLE void localCacheSynchronized(const uIDList_t &newContacts);
0113 
0114 protected:
0115     /**
0116      *  Handle a packet of type PACKAGE_TYPE_CONTACTS_RESPONSE_UIDS_TIMESTAMPS
0117      *
0118      *  For every uID in the reply:
0119      *      Delete any from local storage if it does not appear in the reply
0120      *      Compare the modified timestamp for each in the reply and update any which should have changed
0121      *      Request the details any IDs which were not locally cached
0122      */
0123     bool handleResponseUIDsTimestamps(const NetworkPacket &);
0124 
0125     /**
0126      *  Handle a packet of type PACKET_TYPE_CONTACTS_RESPONSE_VCARDS
0127      */
0128     bool handleResponseVCards(const NetworkPacket &);
0129 
0130     /**
0131      * Send a request-type packet which contains no body
0132      *
0133      * @return True if the send was successful, false otherwise
0134      */
0135     bool sendRequest(const QString &packetType);
0136 
0137     /**
0138      * Send a request-type packet which has a body with the key 'uids' and the value the list of
0139      * specified uIDs
0140      *
0141      * @param packageType Type of package to send
0142      * @param uIDs List of uIDs to request
0143      * @return True if the send was successful, false otherwise
0144      */
0145     bool sendRequestWithIDs(const QString &packetType, const uIDList_t &uIDs);
0146 };