From 5c3f853a04a0c1a2b360391a9f27e7c0fd9f42bd Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 31 Jul 2021 08:32:35 +0200 Subject: Room: Mark dependent Q_PROPERTYs as STORED false hasUnreadMessages is derived from unreadCount; isFavourite/isLowPriority effectively depend on tagNames. --- lib/room.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/room.h b/lib/room.h index 0ab18ef7..52ba2eab 100644 --- a/lib/room.h +++ b/lib/room.h @@ -107,7 +107,7 @@ class Room : public QObject { Q_PROPERTY(QString readMarkerEventId READ readMarkerEventId WRITE markMessagesAsRead NOTIFY readMarkerMoved) Q_PROPERTY(bool hasUnreadMessages READ hasUnreadMessages NOTIFY - unreadMessagesChanged) + unreadMessagesChanged STORED false) Q_PROPERTY(int unreadCount READ unreadCount NOTIFY unreadMessagesChanged) Q_PROPERTY(int highlightCount READ highlightCount NOTIFY highlightCountChanged RESET resetHighlightCount) @@ -116,8 +116,8 @@ class Room : public QObject { Q_PROPERTY(bool allHistoryLoaded READ allHistoryLoaded NOTIFY addedMessages STORED false) Q_PROPERTY(QStringList tagNames READ tagNames NOTIFY tagsChanged) - Q_PROPERTY(bool isFavourite READ isFavourite NOTIFY tagsChanged) - Q_PROPERTY(bool isLowPriority READ isLowPriority NOTIFY tagsChanged) + Q_PROPERTY(bool isFavourite READ isFavourite NOTIFY tagsChanged STORED false) + Q_PROPERTY(bool isLowPriority READ isLowPriority NOTIFY tagsChanged STORED false) Q_PROPERTY(GetRoomEventsJob* eventsHistoryJob READ eventsHistoryJob NOTIFY eventsHistoryJobChanged) -- cgit v1.2.3 From ea1e849f617f62b3d209b2019e0daa3c6bed50f0 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 2 Aug 2021 09:02:31 +0200 Subject: More doc-comments --- lib/events/roomevent.h | 4 ++++ lib/events/roommessageevent.h | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'lib') diff --git a/lib/events/roomevent.h b/lib/events/roomevent.h index fea509c0..3abd56c0 100644 --- a/lib/events/roomevent.h +++ b/lib/events/roomevent.h @@ -37,6 +37,10 @@ public: } QString roomId() const; QString senderId() const; + //! \brief Determine whether the event has been replaced + //! + //! \return true if this event has been overridden by another event + //! with `"rel_type": "m.replace"`; false otherwise bool isReplaced() const; QString replacedBy() const; bool isRedacted() const { return bool(_redactedBecause); } diff --git a/lib/events/roommessageevent.h b/lib/events/roommessageevent.h index 7bcda2ba..88d3b74c 100644 --- a/lib/events/roommessageevent.h +++ b/lib/events/roommessageevent.h @@ -62,9 +62,26 @@ public: _content.data()); } QMimeType mimeType() const; + //! \brief Determine whether the message has text content + //! + //! \return true, if the message type is one of m.text, m.notice, m.emote, + //! or the message type is unspecified (in which case plainBody() + //! can still be examined); false otherwise bool hasTextContent() const; + //! \brief Determine whether the message has a file/attachment + //! + //! \return true, if the message has a data structure corresponding to + //! a file (such as m.file or m.audio); false otherwise bool hasFileContent() const; + //! \brief Determine whether the message has a thumbnail + //! + //! \return true, if the message has a data structure corresponding to + //! a thumbnail (the message type may be one for visual content, + //! such as m.image, or generic binary content, i.e. m.file); + //! false otherwise bool hasThumbnail() const; + //! \brief Obtain id of an event replaced by the current one + //! \sa RoomEvent::isReplaced, RoomEvent::replacedBy QString replacedEvent() const; static QString rawMsgTypeForUrl(const QUrl& url); -- cgit v1.2.3 From 72643d2f90aa929ec5e44159f717057fdad56cbd Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 2 Aug 2021 09:04:06 +0200 Subject: Fix lack of percent encoding in User::load() Users with slashes in their ids do it at their own peril of course but to encode the id in the URL is a good thing in any case. Too bad it's pretty invisible and has to be dealt with case by case, instead of GTAD magically sticking QUrl::toPercentEncoding() where appropriate in the generated code. --- lib/user.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/user.cpp b/lib/user.cpp index c97e33a4..04afed2b 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -65,7 +65,8 @@ User::~User() = default; void User::load() { - auto *profileJob = connection()->callApi(id()); + auto* profileJob = + connection()->callApi(QUrl::toPercentEncoding(id())); connect(profileJob, &BaseJob::result, this, [this, profileJob] { d->defaultName = profileJob->displayname(); d->defaultAvatar = Avatar(QUrl(profileJob->avatarUrl())); -- cgit v1.2.3 From f7cbefe5ad626ae1798a5d7bb7546e89ad336acd Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 7 Aug 2021 16:55:06 +0200 Subject: API files: reformat after .clang-format change See 000b5730. --- lib/csapi/admin.h | 5 +---- lib/csapi/content-repo.h | 35 +++++++---------------------------- lib/csapi/create_room.h | 5 +---- lib/csapi/device_management.h | 5 +---- lib/csapi/directory.h | 5 +---- lib/csapi/event_context.h | 20 ++++---------------- lib/csapi/filter.h | 10 ++-------- lib/csapi/joining.h | 10 ++-------- lib/csapi/keys.h | 5 +---- lib/csapi/knocking.h | 5 +---- lib/csapi/list_public_rooms.h | 20 ++++---------------- lib/csapi/login.h | 10 ++-------- lib/csapi/message_pagination.h | 20 ++++---------------- lib/csapi/notifications.h | 5 +---- lib/csapi/openid.h | 5 +---- lib/csapi/peeking_events.h | 15 +++------------ lib/csapi/presence.h | 10 ++-------- lib/csapi/profile.h | 10 ++-------- lib/csapi/pushrules.h | 10 ++-------- lib/csapi/redaction.h | 5 +---- lib/csapi/registration.h | 10 ++-------- lib/csapi/room_send.h | 5 +---- lib/csapi/room_state.h | 5 +---- lib/csapi/rooms.h | 12 ++---------- lib/csapi/users.h | 5 +---- lib/csapi/voip.h | 5 +---- lib/csapi/whoami.h | 10 ++-------- 27 files changed, 53 insertions(+), 214 deletions(-) (limited to 'lib') diff --git a/lib/csapi/admin.h b/lib/csapi/admin.h index d4fe639b..570bf24a 100644 --- a/lib/csapi/admin.h +++ b/lib/csapi/admin.h @@ -74,10 +74,7 @@ public: // Result properties /// The Matrix user ID of the user. - QString userId() const - { - return loadFromJson("user_id"_ls); - } + QString userId() const { return loadFromJson("user_id"_ls); } /// Each key is an identifier for one of the user's devices. QHash devices() const diff --git a/lib/csapi/content-repo.h b/lib/csapi/content-repo.h index a41453b2..f3d7309a 100644 --- a/lib/csapi/content-repo.h +++ b/lib/csapi/content-repo.h @@ -72,10 +72,7 @@ public: // Result properties /// The content type of the file that was previously uploaded. - QString contentType() const - { - return reply()->rawHeader("Content-Type"); - } + QString contentType() const { return reply()->rawHeader("Content-Type"); } /// The name of the file that was previously uploaded, if set. QString contentDisposition() const @@ -84,10 +81,7 @@ public: } /// The content that was previously uploaded. - QIODevice* data() - { - return reply(); - } + QIODevice* data() { return reply(); } }; /*! \brief Download content from the content repository overriding the file name @@ -132,10 +126,7 @@ public: // Result properties /// The content type of the file that was previously uploaded. - QString contentType() const - { - return reply()->rawHeader("Content-Type"); - } + QString contentType() const { return reply()->rawHeader("Content-Type"); } /// The `fileName` requested or the name of the file that was previously /// uploaded, if set. @@ -145,10 +136,7 @@ public: } /// The content that was previously uploaded. - QIODevice* data() - { - return reply(); - } + QIODevice* data() { return reply(); } }; /*! \brief Download a thumbnail of content from the content repository @@ -202,16 +190,10 @@ public: // Result properties /// The content type of the thumbnail. - QString contentType() const - { - return reply()->rawHeader("Content-Type"); - } + QString contentType() const { return reply()->rawHeader("Content-Type"); } /// A thumbnail of the requested content. - QIODevice* data() - { - return reply(); - } + QIODevice* data() { return reply(); } }; /*! \brief Get information about a URL for a client @@ -257,10 +239,7 @@ public: /// An [MXC URI](/client-server-api/#matrix-content-mxc-uris) to the image. /// Omitted if there is no image. - QString ogImage() const - { - return loadFromJson("og:image"_ls); - } + QString ogImage() const { return loadFromJson("og:image"_ls); } }; /*! \brief Get the configuration for the content repository. diff --git a/lib/csapi/create_room.h b/lib/csapi/create_room.h index 8c6af7d4..81dfbffc 100644 --- a/lib/csapi/create_room.h +++ b/lib/csapi/create_room.h @@ -268,10 +268,7 @@ public: // Result properties /// The created room's ID. - QString roomId() const - { - return loadFromJson("room_id"_ls); - } + QString roomId() const { return loadFromJson("room_id"_ls); } }; template <> diff --git a/lib/csapi/device_management.h b/lib/csapi/device_management.h index e2acea18..7fb69873 100644 --- a/lib/csapi/device_management.h +++ b/lib/csapi/device_management.h @@ -59,10 +59,7 @@ public: // Result properties /// Device information - Device device() const - { - return fromJson(jsonData()); - } + Device device() const { return fromJson(jsonData()); } }; /*! \brief Update a device diff --git a/lib/csapi/directory.h b/lib/csapi/directory.h index 00215cae..93a31595 100644 --- a/lib/csapi/directory.h +++ b/lib/csapi/directory.h @@ -51,10 +51,7 @@ public: // Result properties /// The room ID for this room alias. - QString roomId() const - { - return loadFromJson("room_id"_ls); - } + QString roomId() const { return loadFromJson("room_id"_ls); } /// A list of servers that are aware of this room alias. QStringList servers() const diff --git a/lib/csapi/event_context.h b/lib/csapi/event_context.h index 6a49769f..4e50edf3 100644 --- a/lib/csapi/event_context.h +++ b/lib/csapi/event_context.h @@ -58,16 +58,10 @@ public: // Result properties /// A token that can be used to paginate backwards with. - QString begin() const - { - return loadFromJson("start"_ls); - } + QString begin() const { return loadFromJson("start"_ls); } /// A token that can be used to paginate forwards with. - QString end() const - { - return loadFromJson("end"_ls); - } + QString end() const { return loadFromJson("end"_ls); } /// A list of room events that happened just before the /// requested event, in reverse-chronological order. @@ -77,10 +71,7 @@ public: } /// Details of the requested event. - RoomEventPtr event() - { - return takeFromJson("event"_ls); - } + RoomEventPtr event() { return takeFromJson("event"_ls); } /// A list of room events that happened just after the /// requested event, in chronological order. @@ -90,10 +81,7 @@ public: } /// The state of the room at the last event returned. - StateEvents state() - { - return takeFromJson("state"_ls); - } + StateEvents state() { return takeFromJson("state"_ls); } }; } // namespace Quotient diff --git a/lib/csapi/filter.h b/lib/csapi/filter.h index 7e9e14ee..01bec36b 100644 --- a/lib/csapi/filter.h +++ b/lib/csapi/filter.h @@ -35,10 +35,7 @@ public: /// with a `{` as this character is used to determine /// if the filter provided is inline JSON or a previously /// declared filter by homeservers on some APIs. - QString filterId() const - { - return loadFromJson("filter_id"_ls); - } + QString filterId() const { return loadFromJson("filter_id"_ls); } }; /*! \brief Download a filter @@ -67,10 +64,7 @@ public: // Result properties /// The filter definition. - Filter filter() const - { - return fromJson(jsonData()); - } + Filter filter() const { return fromJson(jsonData()); } }; } // namespace Quotient diff --git a/lib/csapi/joining.h b/lib/csapi/joining.h index 6dcd1351..d0199b11 100644 --- a/lib/csapi/joining.h +++ b/lib/csapi/joining.h @@ -49,10 +49,7 @@ public: // Result properties /// The joined room ID. - QString roomId() const - { - return loadFromJson("room_id"_ls); - } + QString roomId() const { return loadFromJson("room_id"_ls); } }; /*! \brief Start the requesting user participating in a particular room. @@ -98,10 +95,7 @@ public: // Result properties /// The joined room ID. - QString roomId() const - { - return loadFromJson("room_id"_ls); - } + QString roomId() const { return loadFromJson("room_id"_ls); } }; } // namespace Quotient diff --git a/lib/csapi/keys.h b/lib/csapi/keys.h index 53ba6495..7db09e8d 100644 --- a/lib/csapi/keys.h +++ b/lib/csapi/keys.h @@ -267,10 +267,7 @@ public: /// The Matrix User IDs of all users who may have left all /// the end-to-end encrypted rooms they previously shared /// with the user. - QStringList left() const - { - return loadFromJson("left"_ls); - } + QStringList left() const { return loadFromJson("left"_ls); } }; } // namespace Quotient diff --git a/lib/csapi/knocking.h b/lib/csapi/knocking.h index 607b55a9..1108cb64 100644 --- a/lib/csapi/knocking.h +++ b/lib/csapi/knocking.h @@ -49,10 +49,7 @@ public: // Result properties /// The knocked room ID. - QString roomId() const - { - return loadFromJson("room_id"_ls); - } + QString roomId() const { return loadFromJson("room_id"_ls); } }; } // namespace Quotient diff --git a/lib/csapi/list_public_rooms.h b/lib/csapi/list_public_rooms.h index 1c73c0af..963c8b56 100644 --- a/lib/csapi/list_public_rooms.h +++ b/lib/csapi/list_public_rooms.h @@ -111,18 +111,12 @@ public: /// A pagination token for the response. The absence of this token /// means there are no more results to fetch and the client should /// stop paginating. - QString nextBatch() const - { - return loadFromJson("next_batch"_ls); - } + QString nextBatch() const { return loadFromJson("next_batch"_ls); } /// A pagination token that allows fetching previous results. The /// absence of this token means there are no results before this /// batch, i.e. this is the first batch. - QString prevBatch() const - { - return loadFromJson("prev_batch"_ls); - } + QString prevBatch() const { return loadFromJson("prev_batch"_ls); } /// An estimate on the total number of public rooms, if the /// server has an estimate. @@ -196,18 +190,12 @@ public: /// A pagination token for the response. The absence of this token /// means there are no more results to fetch and the client should /// stop paginating. - QString nextBatch() const - { - return loadFromJson("next_batch"_ls); - } + QString nextBatch() const { return loadFromJson("next_batch"_ls); } /// A pagination token that allows fetching previous results. The /// absence of this token means there are no results before this /// batch, i.e. this is the first batch. - QString prevBatch() const - { - return loadFromJson("prev_batch"_ls); - } + QString prevBatch() const { return loadFromJson("prev_batch"_ls); } /// An estimate on the total number of public rooms, if the /// server has an estimate. diff --git a/lib/csapi/login.h b/lib/csapi/login.h index ce783af2..b35db1eb 100644 --- a/lib/csapi/login.h +++ b/lib/csapi/login.h @@ -121,10 +121,7 @@ public: // Result properties /// The fully-qualified Matrix ID for the account. - QString userId() const - { - return loadFromJson("user_id"_ls); - } + QString userId() const { return loadFromJson("user_id"_ls); } /// An access token for the account. /// This access token can then be used to authorize other requests. @@ -146,10 +143,7 @@ public: /// ID of the logged-in device. Will be the same as the /// corresponding parameter in the request, if one was specified. - QString deviceId() const - { - return loadFromJson("device_id"_ls); - } + QString deviceId() const { return loadFromJson("device_id"_ls); } /// Optional client configuration provided by the server. If present, /// clients SHOULD use the provided object to reconfigure themselves, diff --git a/lib/csapi/message_pagination.h b/lib/csapi/message_pagination.h index 020ef543..363e4d99 100644 --- a/lib/csapi/message_pagination.h +++ b/lib/csapi/message_pagination.h @@ -66,26 +66,17 @@ public: /// The token the pagination starts from. If `dir=b` this will be /// the token supplied in `from`. - QString begin() const - { - return loadFromJson("start"_ls); - } + QString begin() const { return loadFromJson("start"_ls); } /// The token the pagination ends at. If `dir=b` this token should /// be used again to request even earlier events. - QString end() const - { - return loadFromJson("end"_ls); - } + QString end() const { return loadFromJson("end"_ls); } /// A list of room events. The order depends on the `dir` parameter. /// For `dir=b` events will be in reverse-chronological order, /// for `dir=f` in chronological order, so that events start /// at the `from` point. - RoomEvents chunk() - { - return takeFromJson("chunk"_ls); - } + RoomEvents chunk() { return takeFromJson("chunk"_ls); } /// A list of state events relevant to showing the `chunk`. For example, if /// `lazy_load_members` is enabled in the filter then this may contain @@ -95,10 +86,7 @@ public: /// may remove membership events which would have already been /// sent to the client in prior calls to this endpoint, assuming /// the membership of those members has not changed. - StateEvents state() - { - return takeFromJson("state"_ls); - } + StateEvents state() { return takeFromJson("state"_ls); } }; } // namespace Quotient diff --git a/lib/csapi/notifications.h b/lib/csapi/notifications.h index 0cc165ce..0c38fe6b 100644 --- a/lib/csapi/notifications.h +++ b/lib/csapi/notifications.h @@ -71,10 +71,7 @@ public: /// The token to supply in the `from` param of the next /// `/notifications` request in order to request more /// events. If this is absent, there are no more results. - QString nextToken() const - { - return loadFromJson("next_token"_ls); - } + QString nextToken() const { return loadFromJson("next_token"_ls); } /// The list of events that triggered notifications. std::vector notifications() diff --git a/lib/csapi/openid.h b/lib/csapi/openid.h index 88218c20..0be39c8c 100644 --- a/lib/csapi/openid.h +++ b/lib/csapi/openid.h @@ -43,10 +43,7 @@ public: /// Specification](http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse) /// with the only difference being the lack of an `id_token`. Instead, /// the Matrix homeserver's name is provided. - OpenidToken tokenData() const - { - return fromJson(jsonData()); - } + OpenidToken tokenData() const { return fromJson(jsonData()); } }; } // namespace Quotient diff --git a/lib/csapi/peeking_events.h b/lib/csapi/peeking_events.h index 1eee880f..885ff340 100644 --- a/lib/csapi/peeking_events.h +++ b/lib/csapi/peeking_events.h @@ -53,23 +53,14 @@ public: /// A token which correlates to the first value in `chunk`. This /// is usually the same token supplied to `from=`. - QString begin() const - { - return loadFromJson("start"_ls); - } + QString begin() const { return loadFromJson("start"_ls); } /// A token which correlates to the last value in `chunk`. This /// token should be used in the next request to `/events`. - QString end() const - { - return loadFromJson("end"_ls); - } + QString end() const { return loadFromJson("end"_ls); } /// An array of events. - RoomEvents chunk() - { - return takeFromJson("chunk"_ls); - } + RoomEvents chunk() { return takeFromJson("chunk"_ls); } }; } // namespace Quotient diff --git a/lib/csapi/presence.h b/lib/csapi/presence.h index c817ad9f..4ab50e25 100644 --- a/lib/csapi/presence.h +++ b/lib/csapi/presence.h @@ -55,10 +55,7 @@ public: // Result properties /// This user's presence. - QString presence() const - { - return loadFromJson("presence"_ls); - } + QString presence() const { return loadFromJson("presence"_ls); } /// The length of time in milliseconds since an action was performed /// by this user. @@ -68,10 +65,7 @@ public: } /// The state message for this user if one was set. - QString statusMsg() const - { - return loadFromJson("status_msg"_ls); - } + QString statusMsg() const { return loadFromJson("status_msg"_ls); } /// Whether the user is currently active Omittable currentlyActive() const diff --git a/lib/csapi/profile.h b/lib/csapi/profile.h index 3cda34f8..8bbe4f8c 100644 --- a/lib/csapi/profile.h +++ b/lib/csapi/profile.h @@ -101,10 +101,7 @@ public: // Result properties /// The user's avatar URL if they have set one, otherwise not present. - QString avatarUrl() const - { - return loadFromJson("avatar_url"_ls); - } + QString avatarUrl() const { return loadFromJson("avatar_url"_ls); } }; /*! \brief Get this user's profile information. @@ -133,10 +130,7 @@ public: // Result properties /// The user's avatar URL if they have set one, otherwise not present. - QString avatarUrl() const - { - return loadFromJson("avatar_url"_ls); - } + QString avatarUrl() const { return loadFromJson("avatar_url"_ls); } /// The user's display name if they have set one, otherwise not present. QString displayname() const diff --git a/lib/csapi/pushrules.h b/lib/csapi/pushrules.h index 90d2ce79..a5eb48f0 100644 --- a/lib/csapi/pushrules.h +++ b/lib/csapi/pushrules.h @@ -72,10 +72,7 @@ public: /// The specific push rule. This will also include keys specific to the /// rule itself such as the rule's `actions` and `conditions` if set. - PushRule pushRule() const - { - return fromJson(jsonData()); - } + PushRule pushRule() const { return fromJson(jsonData()); } }; /*! \brief Delete a push rule. @@ -191,10 +188,7 @@ public: // Result properties /// Whether the push rule is enabled or not. - bool enabled() const - { - return loadFromJson("enabled"_ls); - } + bool enabled() const { return loadFromJson("enabled"_ls); } }; /*! \brief Enable or disable a push rule. diff --git a/lib/csapi/redaction.h b/lib/csapi/redaction.h index f12e6b71..f0db9f9f 100644 --- a/lib/csapi/redaction.h +++ b/lib/csapi/redaction.h @@ -46,10 +46,7 @@ public: // Result properties /// A unique identifier for the event. - QString eventId() const - { - return loadFromJson("event_id"_ls); - } + QString eventId() const { return loadFromJson("event_id"_ls); } }; } // namespace Quotient diff --git a/lib/csapi/registration.h b/lib/csapi/registration.h index 0ad8b101..c1614f20 100644 --- a/lib/csapi/registration.h +++ b/lib/csapi/registration.h @@ -108,10 +108,7 @@ public: /// /// Any user ID returned by this API must conform to the grammar given in /// the [Matrix specification](/appendices/#user-identifiers). - QString userId() const - { - return loadFromJson("user_id"_ls); - } + QString userId() const { return loadFromJson("user_id"_ls); } /// An access token for the account. /// This access token can then be used to authorize other requests. @@ -135,10 +132,7 @@ public: /// ID of the registered device. Will be the same as the /// corresponding parameter in the request, if one was specified. /// Required if the `inhibit_login` option is false. - QString deviceId() const - { - return loadFromJson("device_id"_ls); - } + QString deviceId() const { return loadFromJson("device_id"_ls); } }; /*! \brief Begins the validation process for an email to be used during diff --git a/lib/csapi/room_send.h b/lib/csapi/room_send.h index a9e7ca13..96f5beca 100644 --- a/lib/csapi/room_send.h +++ b/lib/csapi/room_send.h @@ -49,10 +49,7 @@ public: // Result properties /// A unique identifier for the event. - QString eventId() const - { - return loadFromJson("event_id"_ls); - } + QString eventId() const { return loadFromJson("event_id"_ls); } }; } // namespace Quotient diff --git a/lib/csapi/room_state.h b/lib/csapi/room_state.h index 99eb4fc9..f95af223 100644 --- a/lib/csapi/room_state.h +++ b/lib/csapi/room_state.h @@ -71,10 +71,7 @@ public: // Result properties /// A unique identifier for the event. - QString eventId() const - { - return loadFromJson("event_id"_ls); - } + QString eventId() const { return loadFromJson("event_id"_ls); } }; } // namespace Quotient diff --git a/lib/csapi/rooms.h b/lib/csapi/rooms.h index 179d7a27..51af2c65 100644 --- a/lib/csapi/rooms.h +++ b/lib/csapi/rooms.h @@ -38,11 +38,7 @@ public: // Result properties /// The full event. - EventPtr event() - - { - return fromJson(jsonData()); - } + EventPtr event() { return fromJson(jsonData()); } }; /*! \brief Get the state identified by the type and key. @@ -103,11 +99,7 @@ public: // Result properties /// The current state of the room - StateEvents events() - - { - return fromJson(jsonData()); - } + StateEvents events() { return fromJson(jsonData()); } }; /*! \brief Get the m.room.member events for the room. diff --git a/lib/csapi/users.h b/lib/csapi/users.h index 772a6365..eab18f6c 100644 --- a/lib/csapi/users.h +++ b/lib/csapi/users.h @@ -66,10 +66,7 @@ public: } /// Indicates if the result list has been truncated by the limit. - bool limited() const - { - return loadFromJson("limited"_ls); - } + bool limited() const { return loadFromJson("limited"_ls); } }; template <> diff --git a/lib/csapi/voip.h b/lib/csapi/voip.h index 85ab8b41..087ebbbd 100644 --- a/lib/csapi/voip.h +++ b/lib/csapi/voip.h @@ -28,10 +28,7 @@ public: // Result properties /// The TURN server credentials. - QJsonObject data() const - { - return fromJson(jsonData()); - } + QJsonObject data() const { return fromJson(jsonData()); } }; } // namespace Quotient diff --git a/lib/csapi/whoami.h b/lib/csapi/whoami.h index 203742c9..319f82c5 100644 --- a/lib/csapi/whoami.h +++ b/lib/csapi/whoami.h @@ -34,19 +34,13 @@ public: // Result properties /// The user ID that owns the access token. - QString userId() const - { - return loadFromJson("user_id"_ls); - } + QString userId() const { return loadFromJson("user_id"_ls); } /// Device ID associated with the access token. If no device /// is associated with the access token (such as in the case /// of application services) then this field can be omitted. /// Otherwise this is required. - QString deviceId() const - { - return loadFromJson("device_id"_ls); - } + QString deviceId() const { return loadFromJson("device_id"_ls); } }; } // namespace Quotient -- cgit v1.2.3 From f81aa4d723577ce30518424510e45ef39ff0e29e Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 7 Aug 2021 18:59:33 +0200 Subject: Drop an out-of-date comment BaseJob::loadFromJson() does just fine without QStringViews. [skip ci] --- lib/jobs/basejob.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index d33d542e..7ce4b808 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -180,7 +180,7 @@ public: * If there's no top-level JSON object in the response or if there's * no node with the key \p keyName, \p defaultValue is returned. */ - template // Waiting for QStringViews... + template T loadFromJson(const StrT& keyName, T&& defaultValue = {}) const { const auto& jv = jsonData().value(keyName); -- cgit v1.2.3 From 35ce036407e1865402d01070e9680a9cda4f361c Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 7 Aug 2021 22:06:42 +0200 Subject: converters.h: (actually) enable QUrl; drop unused types QUrl can now be converted even with QT_NO_URL_CAST_FROM_STRING; and it can also be put to queries. QByteArray did not really need conversion in JSON context; and QJsonObject is/was never used in queries. --- lib/converters.h | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/converters.h b/lib/converters.h index af6c0192..cc6378e4 100644 --- a/lib/converters.h +++ b/lib/converters.h @@ -151,10 +151,17 @@ struct JsonConverter { }; template <> -struct JsonConverter : JsonConverter { - static auto dump(const QUrl& url) // Override on top of that for QString +struct JsonConverter { + static auto load(const QJsonValue& jv) + { + // QT_NO_URL_CAST_FROM_STRING makes this a bit more verbose + QUrl url; + url.setUrl(jv.toString()); + return url; + } + static auto dump(const QUrl& url) { - return JsonConverter::dump(url.toString(QUrl::FullyEncoded)); + return url.toString(QUrl::FullyEncoded); } }; @@ -163,15 +170,6 @@ struct JsonConverter : public TrivialJsonDumper { static auto load(const QJsonValue& jv) { return jv.toArray(); } }; -template <> -struct JsonConverter { - static QString dump(const QByteArray& ba) { return ba.constData(); } - static auto load(const QJsonValue& jv) - { - return fromJson(jv).toLatin1(); - } -}; - template <> struct JsonConverter { static QJsonValue dump(const QVariant& v); @@ -304,16 +302,15 @@ namespace _impl { q.addQueryItem(k, v ? QStringLiteral("true") : QStringLiteral("false")); } - inline void addTo(QUrlQuery& q, const QString& k, const QStringList& vals) + inline void addTo(QUrlQuery& q, const QString& k, const QUrl& v) { - for (const auto& v : vals) - q.addQueryItem(k, v); + q.addQueryItem(k, v.toEncoded()); } - inline void addTo(QUrlQuery& q, const QString&, const QJsonObject& vals) + inline void addTo(QUrlQuery& q, const QString& k, const QStringList& vals) { - for (auto it = vals.begin(); it != vals.end(); ++it) - q.addQueryItem(it.key(), it.value().toString()); + for (const auto& v : vals) + q.addQueryItem(k, v); } // This one is for types that don't have isEmpty() and for all types -- cgit v1.2.3 From bf6303c41264d913ca049009034aa948464b8f30 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 7 Aug 2021 22:14:06 +0200 Subject: User::avatar: add const --- lib/user.cpp | 6 +++--- lib/user.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/user.cpp b/lib/user.cpp index 04afed2b..a7e0efd9 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -197,18 +197,18 @@ const Avatar& User::avatarObject(const Room* room) const return d->otherAvatars.try_emplace(mediaId, url).first->second; } -QImage User::avatar(int dimension, const Room* room) +QImage User::avatar(int dimension, const Room* room) const { return avatar(dimension, dimension, room); } -QImage User::avatar(int width, int height, const Room* room) +QImage User::avatar(int width, int height, const Room* room) const { return avatar(width, height, room, [] {}); } QImage User::avatar(int width, int height, const Room* room, - const Avatar::get_callback_t& callback) + const Avatar::get_callback_t& callback) const { return avatarObject(room).get(connection(), width, height, callback); } diff --git a/lib/user.h b/lib/user.h index e4560843..4ff62951 100644 --- a/lib/user.h +++ b/lib/user.h @@ -99,11 +99,11 @@ public: */ const Avatar& avatarObject(const Room* room = nullptr) const; Q_INVOKABLE QImage avatar(int dimension, - const Quotient::Room* room = nullptr); + const Quotient::Room* room = nullptr) const; Q_INVOKABLE QImage avatar(int requestedWidth, int requestedHeight, - const Quotient::Room* room = nullptr); + const Quotient::Room* room = nullptr) const; QImage avatar(int width, int height, const Room* room, - const Avatar::get_callback_t& callback); + const Avatar::get_callback_t& callback) const; QString avatarMediaId(const Room* room = nullptr) const; QUrl avatarUrl(const Room* room = nullptr) const; -- cgit v1.2.3 From bd649c591fa020fde0bd56a63c13025097b831ae Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 7 Aug 2021 22:12:46 +0200 Subject: Update generated files This uses API definition files from https://github.com/matrix-org/matrix-doc/pull/3236, and additionally makes uploadFile>content_uri to have 'format: uri' (as suggested in the PR review). Only use this commit with the next one; alone it breaks the build. --- lib/csapi/content-repo.cpp | 6 +++--- lib/csapi/content-repo.h | 11 ++++------- lib/csapi/definitions/public_rooms_response.h | 2 +- lib/csapi/definitions/request_token_response.h | 2 +- lib/csapi/definitions/wellknown/homeserver.h | 2 +- lib/csapi/definitions/wellknown/identity_server.h | 2 +- lib/csapi/profile.cpp | 2 +- lib/csapi/profile.h | 6 +++--- lib/csapi/pusher.h | 4 ++-- lib/csapi/rooms.h | 2 +- lib/csapi/search.h | 2 +- lib/csapi/users.h | 2 +- 12 files changed, 20 insertions(+), 23 deletions(-) (limited to 'lib') diff --git a/lib/csapi/content-repo.cpp b/lib/csapi/content-repo.cpp index e913bfd1..00bc9706 100644 --- a/lib/csapi/content-repo.cpp +++ b/lib/csapi/content-repo.cpp @@ -122,7 +122,7 @@ GetContentThumbnailJob::GetContentThumbnailJob(const QString& serverName, setExpectedContentTypes({ "image/jpeg", "image/png" }); } -auto queryToGetUrlPreview(const QString& url, Omittable ts) +auto queryToGetUrlPreview(const QUrl& url, Omittable ts) { QUrlQuery _q; addParam<>(_q, QStringLiteral("url"), url); @@ -130,7 +130,7 @@ auto queryToGetUrlPreview(const QString& url, Omittable ts) return _q; } -QUrl GetUrlPreviewJob::makeRequestUrl(QUrl baseUrl, const QString& url, +QUrl GetUrlPreviewJob::makeRequestUrl(QUrl baseUrl, const QUrl& url, Omittable ts) { return BaseJob::makeRequestUrl(std::move(baseUrl), @@ -139,7 +139,7 @@ QUrl GetUrlPreviewJob::makeRequestUrl(QUrl baseUrl, const QString& url, queryToGetUrlPreview(url, ts)); } -GetUrlPreviewJob::GetUrlPreviewJob(const QString& url, Omittable ts) +GetUrlPreviewJob::GetUrlPreviewJob(const QUrl& url, Omittable ts) : BaseJob(HttpVerb::Get, QStringLiteral("GetUrlPreviewJob"), QStringLiteral("/_matrix/media/r0") % "/preview_url", queryToGetUrlPreview(url, ts)) diff --git a/lib/csapi/content-repo.h b/lib/csapi/content-repo.h index f3d7309a..28409f5c 100644 --- a/lib/csapi/content-repo.h +++ b/lib/csapi/content-repo.h @@ -34,10 +34,7 @@ public: /// The [MXC URI](/client-server-api/#matrix-content-mxc-uris) to the /// uploaded content. - QString contentUri() const - { - return loadFromJson("content_uri"_ls); - } + QUrl contentUri() const { return loadFromJson("content_uri"_ls); } }; /*! \brief Download content from the content repository. @@ -219,14 +216,14 @@ public: * return a newer version if it does not have the requested version * available. */ - explicit GetUrlPreviewJob(const QString& url, Omittable ts = none); + explicit GetUrlPreviewJob(const QUrl& url, Omittable ts = none); /*! \brief Construct a URL without creating a full-fledged job object * * This function can be used when a URL for GetUrlPreviewJob * is necessary but the job itself isn't. */ - static QUrl makeRequestUrl(QUrl baseUrl, const QString& url, + static QUrl makeRequestUrl(QUrl baseUrl, const QUrl& url, Omittable ts = none); // Result properties @@ -239,7 +236,7 @@ public: /// An [MXC URI](/client-server-api/#matrix-content-mxc-uris) to the image. /// Omitted if there is no image. - QString ogImage() const { return loadFromJson("og:image"_ls); } + QUrl ogImage() const { return loadFromJson("og:image"_ls); } }; /*! \brief Get the configuration for the content repository. diff --git a/lib/csapi/definitions/public_rooms_response.h b/lib/csapi/definitions/public_rooms_response.h index 34b447d2..2938b4ec 100644 --- a/lib/csapi/definitions/public_rooms_response.h +++ b/lib/csapi/definitions/public_rooms_response.h @@ -36,7 +36,7 @@ struct PublicRoomsChunk { bool guestCanJoin; /// The URL for the room's avatar, if one is set. - QString avatarUrl; + QUrl avatarUrl; /// The room's join rule. When not present, the room is assumed to /// be `public`. Note that rooms with `invite` join rules are not diff --git a/lib/csapi/definitions/request_token_response.h b/lib/csapi/definitions/request_token_response.h index f9981100..d5fbbadb 100644 --- a/lib/csapi/definitions/request_token_response.h +++ b/lib/csapi/definitions/request_token_response.h @@ -25,7 +25,7 @@ struct RequestTokenResponse { /// will happen without the client's involvement provided the homeserver /// advertises this specification version in the `/versions` response /// (ie: r0.5.0). - QString submitUrl; + QUrl submitUrl; }; template <> diff --git a/lib/csapi/definitions/wellknown/homeserver.h b/lib/csapi/definitions/wellknown/homeserver.h index 5cfaca24..b7db4182 100644 --- a/lib/csapi/definitions/wellknown/homeserver.h +++ b/lib/csapi/definitions/wellknown/homeserver.h @@ -10,7 +10,7 @@ namespace Quotient { /// Used by clients to discover homeserver information. struct HomeserverInformation { /// The base URL for the homeserver for client-server connections. - QString baseUrl; + QUrl baseUrl; }; template <> diff --git a/lib/csapi/definitions/wellknown/identity_server.h b/lib/csapi/definitions/wellknown/identity_server.h index 3bd07bd1..885e3d34 100644 --- a/lib/csapi/definitions/wellknown/identity_server.h +++ b/lib/csapi/definitions/wellknown/identity_server.h @@ -10,7 +10,7 @@ namespace Quotient { /// Used by clients to discover identity server information. struct IdentityServerInformation { /// The base URL for the identity server for client-server connections. - QString baseUrl; + QUrl baseUrl; }; template <> diff --git a/lib/csapi/profile.cpp b/lib/csapi/profile.cpp index 8436b8e6..745fa488 100644 --- a/lib/csapi/profile.cpp +++ b/lib/csapi/profile.cpp @@ -33,7 +33,7 @@ GetDisplayNameJob::GetDisplayNameJob(const QString& userId) false) {} -SetAvatarUrlJob::SetAvatarUrlJob(const QString& userId, const QString& avatarUrl) +SetAvatarUrlJob::SetAvatarUrlJob(const QString& userId, const QUrl& avatarUrl) : BaseJob(HttpVerb::Put, QStringLiteral("SetAvatarUrlJob"), QStringLiteral("/_matrix/client/r0") % "/profile/" % userId % "/avatar_url") diff --git a/lib/csapi/profile.h b/lib/csapi/profile.h index 8bbe4f8c..7f9c9e95 100644 --- a/lib/csapi/profile.h +++ b/lib/csapi/profile.h @@ -73,7 +73,7 @@ public: * \param avatarUrl * The new avatar URL for this user. */ - explicit SetAvatarUrlJob(const QString& userId, const QString& avatarUrl); + explicit SetAvatarUrlJob(const QString& userId, const QUrl& avatarUrl); }; /*! \brief Get the user's avatar URL. @@ -101,7 +101,7 @@ public: // Result properties /// The user's avatar URL if they have set one, otherwise not present. - QString avatarUrl() const { return loadFromJson("avatar_url"_ls); } + QUrl avatarUrl() const { return loadFromJson("avatar_url"_ls); } }; /*! \brief Get this user's profile information. @@ -130,7 +130,7 @@ public: // Result properties /// The user's avatar URL if they have set one, otherwise not present. - QString avatarUrl() const { return loadFromJson("avatar_url"_ls); } + QUrl avatarUrl() const { return loadFromJson("avatar_url"_ls); } /// The user's display name if they have set one, otherwise not present. QString displayname() const diff --git a/lib/csapi/pusher.h b/lib/csapi/pusher.h index 13c9ec25..622b0df6 100644 --- a/lib/csapi/pusher.h +++ b/lib/csapi/pusher.h @@ -21,7 +21,7 @@ public: struct PusherData { /// Required if `kind` is `http`. The URL to use to send /// notifications to. - QString url; + QUrl url; /// The format to use when sending notifications to the Push /// Gateway. QString format; @@ -119,7 +119,7 @@ public: /// Required if `kind` is `http`. The URL to use to send /// notifications to. MUST be an HTTPS URL with a path of /// `/_matrix/push/v1/notify`. - QString url; + QUrl url; /// The format to send notifications in to Push Gateways if the /// `kind` is `http`. The details about what fields the /// homeserver should send to the push gateway are defined in the diff --git a/lib/csapi/rooms.h b/lib/csapi/rooms.h index 51af2c65..2620582b 100644 --- a/lib/csapi/rooms.h +++ b/lib/csapi/rooms.h @@ -175,7 +175,7 @@ public: /// The display name of the user this object is representing. QString displayName; /// The mxc avatar url of the user this object is representing. - QString avatarUrl; + QUrl avatarUrl; }; // Construction/destruction diff --git a/lib/csapi/search.h b/lib/csapi/search.h index b56d9154..3d02752a 100644 --- a/lib/csapi/search.h +++ b/lib/csapi/search.h @@ -81,7 +81,7 @@ public: /// Performs a full text search across different categories. QString displayname; /// Performs a full text search across different categories. - QString avatarUrl; + QUrl avatarUrl; }; /// Context for result, if requested. diff --git a/lib/csapi/users.h b/lib/csapi/users.h index eab18f6c..ec186592 100644 --- a/lib/csapi/users.h +++ b/lib/csapi/users.h @@ -41,7 +41,7 @@ public: /// The display name of the user, if one exists. QString displayName; /// The avatar url, as an MXC, if one exists. - QString avatarUrl; + QUrl avatarUrl; }; // Construction/destruction -- cgit v1.2.3 From e5a760371a158bec6a70353b96614611adecc4bc Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 7 Aug 2021 22:13:42 +0200 Subject: Update non-generated code to work with QUrls in CS API --- lib/avatar.h | 2 +- lib/user.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/avatar.h b/lib/avatar.h index be125c17..37e1eeef 100644 --- a/lib/avatar.h +++ b/lib/avatar.h @@ -21,7 +21,7 @@ public: Avatar& operator=(Avatar&&); using get_callback_t = std::function; - using upload_callback_t = std::function; + using upload_callback_t = std::function; QImage get(Connection* connection, int dimension, get_callback_t callback) const; diff --git a/lib/user.cpp b/lib/user.cpp index 04afed2b..797576db 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -135,17 +135,17 @@ template inline bool User::doSetAvatar(SourceT&& source) { return d->defaultAvatar.upload( - connection(), source, [this](const QString& contentUri) { + connection(), source, [this](const QUrl& contentUri) { auto* j = connection()->callApi(id(), contentUri); connect(j, &BaseJob::success, this, - [this, newUrl = QUrl(contentUri)] { - if (newUrl == d->defaultAvatar.url()) { - d->defaultAvatar.updateUrl(newUrl); + [this, contentUri] { + if (contentUri == d->defaultAvatar.url()) { + d->defaultAvatar.updateUrl(contentUri); emit defaultAvatarChanged(); } else qCWarning(MAIN) << "User" << id() << "already has avatar URL set to" - << newUrl.toDisplayString(); + << contentUri.toDisplayString(); }); }); } @@ -162,7 +162,7 @@ bool User::setAvatar(QIODevice* source) void User::removeAvatar() { - connection()->callApi(id(), ""); + connection()->callApi(id(), QUrl()); } void User::requestDirectChat() { connection()->requestDirectChat(this); } -- cgit v1.2.3 From 5276e4321c6b3348fc5b1d3d16f93131d9676e76 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 24 Jul 2021 21:06:13 +0200 Subject: Room::Private::sync/historyEdge() Move Room::sync/historyEdge() implementation to Room::Private, so that internal logic could use the same readable shortcuts without q-> prefixes, instead of timeline.crend() and timeline.cend() that are much less readable. --- lib/room.cpp | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/room.cpp b/lib/room.cpp index 47a0ec94..9fe70678 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -101,8 +101,8 @@ public: UnorderedMap baseState; /// State event stubs - events without content, just type and state key static decltype(baseState) stubbedState; - /// The state of the room at timeline position after-maxTimelineIndex() - /// \sa Room::syncEdge + /// The state of the room at syncEdge() + /// \sa syncEdge QHash currentState; /// Servers with aliases for this room except the one of the local user /// \sa Room::remoteAliases @@ -198,6 +198,8 @@ public: /// A point in the timeline corresponding to baseState rev_iter_t timelineBase() const { return q->findInTimeline(-1); } + rev_iter_t historyEdge() const { return timeline.crend(); } + Timeline::const_iterator syncEdge() const { return timeline.cend(); } void getPreviousContent(int limit = 10, const QString &filter = {}); @@ -638,7 +640,7 @@ void Room::Private::updateUnreadCount(const rev_iter_t& from, // unreadMessages and might need to promote the read marker further // over local-origin messages. auto readMarker = q->readMarker(); - if (readMarker == timeline.crend() && q->allHistoryLoaded()) + if (readMarker == historyEdge() && q->allHistoryLoaded()) --readMarker; // Read marker not found in the timeline, initialise it if (readMarker >= from && readMarker < to) { promoteReadMarker(q->localUser(), readMarker, true); @@ -682,7 +684,7 @@ Room::Changes Room::Private::promoteReadMarker(User* u, // iterators return Change::NoChange; - Q_ASSERT(newMarker < timeline.crend()); + Q_ASSERT(newMarker < historyEdge()); // Try to auto-promote the read marker over the user's own messages // (switch to direct iterators for that). @@ -697,7 +699,7 @@ Room::Changes Room::Private::promoteReadMarker(User* u, QElapsedTimer et; et.start(); unreadMessages = - int(count_if(eagerMarker, timeline.cend(), + int(count_if(eagerMarker, syncEdge(), [this](const auto& ti) { return isEventNotable(ti); })); if (et.nsecsElapsed() > profilerMinNsecs() / 10) qCDebug(PROFILER) << "Recounting unread messages took" << et; @@ -771,12 +773,9 @@ bool Room::hasUnreadMessages() const { return unreadCount() >= 0; } int Room::unreadCount() const { return d->unreadMessages; } -Room::rev_iter_t Room::historyEdge() const { return d->timeline.crend(); } +Room::rev_iter_t Room::historyEdge() const { return d->historyEdge(); } -Room::Timeline::const_iterator Room::syncEdge() const -{ - return d->timeline.cend(); -} +Room::Timeline::const_iterator Room::syncEdge() const { return d->syncEdge(); } TimelineItem::index_t Room::minTimelineIndex() const { @@ -855,7 +854,7 @@ void Room::Private::getAllMembers() // the full members list was requested. if (!timeline.empty()) for (auto it = q->findInTimeline(nextIndex).base(); - it != timeline.cend(); ++it) + it != syncEdge(); ++it) if (is(**it)) roomChanges |= q->processStateEvent(**it); if (roomChanges & MembersChange) @@ -2357,7 +2356,7 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events) emit q->aboutToAddNewMessages(eventsSpan); auto insertedSize = moveEventsToTimeline(eventsSpan, Newer); totalInserted += insertedSize; - auto firstInserted = timeline.cend() - insertedSize; + auto firstInserted = syncEdge() - insertedSize; q->onAddNewTimelineEvents(firstInserted); emit q->addedMessages(firstInserted->index(), timeline.back().index()); @@ -2387,20 +2386,20 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events) unsyncedEvents.erase(unsyncedEvents.begin() + pendingEvtIdx); if (auto insertedSize = moveEventsToTimeline({ remoteEcho, it }, Newer)) { totalInserted += insertedSize; - q->onAddNewTimelineEvents(timeline.cend() - insertedSize); + q->onAddNewTimelineEvents(syncEdge() - insertedSize); } emit q->pendingEventMerged(); } // Events merged and transferred from `events` to `timeline` now. - const auto from = timeline.cend() - totalInserted; + const auto from = syncEdge() - totalInserted; if (q->supportsCalls()) - for (auto it = from; it != timeline.cend(); ++it) + for (auto it = from; it != syncEdge(); ++it) if (const auto* evt = it->viewAs()) emit q->callEvent(q, evt); if (totalInserted > 0) { - for (auto it = from; it != timeline.cend(); ++it) { + for (auto it = from; it != syncEdge(); ++it) { if (const auto* reaction = it->viewAs()) { const auto& relation = reaction->relation(); relations[{ relation.eventId, relation.type }] << reaction; @@ -2420,7 +2419,7 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events) // the new message events. if (const auto senderId = (*from)->senderId(); !senderId.isEmpty()) { auto* const firstWriter = q->user(senderId); - if (q->readMarker(firstWriter) != timeline.crend()) { + if (q->readMarker(firstWriter) != historyEdge()) { roomChanges |= promoteReadMarker(firstWriter, rev_iter_t(from) - 1); qCDebug(MESSAGES) @@ -2461,14 +2460,14 @@ void Room::Private::addHistoricalMessageEvents(RoomEvents&& events) emit q->aboutToAddHistoricalMessages(events); const auto insertedSize = moveEventsToTimeline(events, Older); - const auto from = timeline.crend() - insertedSize; + const auto from = historyEdge() - insertedSize; qCDebug(STATE) << "Room" << displayname << "received" << insertedSize << "past events; the oldest event is now" << timeline.front(); q->onAddHistoricalTimelineEvents(from); emit q->addedMessages(timeline.front().index(), from->index()); - for (auto it = from; it != timeline.crend(); ++it) { + for (auto it = from; it != historyEdge(); ++it) { if (const auto* reaction = it->viewAs()) { const auto& relation = reaction->relation(); relations[{ relation.eventId, relation.type }] << reaction; @@ -2476,7 +2475,7 @@ void Room::Private::addHistoricalMessageEvents(RoomEvents&& events) } } if (from <= q->readMarker()) - updateUnreadCount(from, timeline.crend()); + updateUnreadCount(from, historyEdge()); Q_ASSERT(timeline.size() == timelineSize + insertedSize); if (insertedSize > 9 || et.nsecsElapsed() >= profilerMinNsecs()) -- cgit v1.2.3 From f46e19924a1c0a5ac3f1d2a489f8017a5e143fda Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 10 Aug 2021 15:23:08 +0200 Subject: Turn EventStatus from a class to a namespace This wrapper only exists for an enum inside of it and dates back to times when Qt meta-object system did not support free-standing enums. --- lib/eventitem.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/eventitem.h b/lib/eventitem.h index 1986ba77..a5f381f0 100644 --- a/lib/eventitem.h +++ b/lib/eventitem.h @@ -11,9 +11,9 @@ namespace Quotient { class StateEventBase; -class EventStatus { - Q_GADGET -public: +namespace EventStatus { + Q_NAMESPACE + /** Special marks an event can assume * * This is used to hint at a special status of some events in UI. @@ -32,8 +32,8 @@ public: Hidden = 0x100, //< The event should not be shown in the timeline }; Q_DECLARE_FLAGS(Status, Code) - Q_FLAG(Status) -}; + Q_FLAG_NS(Status) +} // namespace EventStatus class EventItemBase { public: @@ -148,4 +148,4 @@ inline QDebug& operator<<(QDebug& d, const TimelineItem& ti) return d; } } // namespace Quotient -Q_DECLARE_METATYPE(Quotient::EventStatus) +//Q_DECLARE_METATYPE(Quotient::EventStatus) -- cgit v1.2.3 From 14d896c9d659d3d3c4f9c4d6eeb50e59a2a002a9 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 21 Aug 2021 11:40:45 +0200 Subject: Cleanup --- lib/eventitem.h | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/eventitem.h b/lib/eventitem.h index a5f381f0..a70a3c3e 100644 --- a/lib/eventitem.h +++ b/lib/eventitem.h @@ -148,4 +148,3 @@ inline QDebug& operator<<(QDebug& d, const TimelineItem& ti) return d; } } // namespace Quotient -//Q_DECLARE_METATYPE(Quotient::EventStatus) -- cgit v1.2.3 From ed24065f2e9b8fce059c54137c04b790c6ce4fd1 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 22 Aug 2021 20:05:41 +0200 Subject: Regenerate API files --- lib/csapi/account-data.cpp | 4 ++-- lib/csapi/administrative_contact.cpp | 4 ++-- lib/csapi/content-repo.cpp | 2 +- lib/csapi/cross_signing.cpp | 2 +- lib/csapi/filter.cpp | 2 +- lib/csapi/openid.cpp | 2 +- lib/csapi/receipts.cpp | 2 +- lib/csapi/registration.cpp | 8 ++++---- lib/csapi/room_send.cpp | 2 +- lib/csapi/room_state.cpp | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/csapi/account-data.cpp b/lib/csapi/account-data.cpp index 6a40e908..80deb8f1 100644 --- a/lib/csapi/account-data.cpp +++ b/lib/csapi/account-data.cpp @@ -14,7 +14,7 @@ SetAccountDataJob::SetAccountDataJob(const QString& userId, const QString& type, QStringLiteral("/_matrix/client/r0") % "/user/" % userId % "/account_data/" % type) { - setRequestData(Data(toJson(content))); + setRequestData(RequestData(toJson(content))); } QUrl GetAccountDataJob::makeRequestUrl(QUrl baseUrl, const QString& userId, @@ -39,7 +39,7 @@ SetAccountDataPerRoomJob::SetAccountDataPerRoomJob(const QString& userId, QStringLiteral("/_matrix/client/r0") % "/user/" % userId % "/rooms/" % roomId % "/account_data/" % type) { - setRequestData(Data(toJson(content))); + setRequestData(RequestData(toJson(content))); } QUrl GetAccountDataPerRoomJob::makeRequestUrl(QUrl baseUrl, diff --git a/lib/csapi/administrative_contact.cpp b/lib/csapi/administrative_contact.cpp index fa4f475a..04360299 100644 --- a/lib/csapi/administrative_contact.cpp +++ b/lib/csapi/administrative_contact.cpp @@ -89,7 +89,7 @@ RequestTokenTo3PIDEmailJob::RequestTokenTo3PIDEmailJob( % "/account/3pid/email/requestToken", false) { - setRequestData(Data(toJson(body))); + setRequestData(RequestData(toJson(body))); } RequestTokenTo3PIDMSISDNJob::RequestTokenTo3PIDMSISDNJob( @@ -99,5 +99,5 @@ RequestTokenTo3PIDMSISDNJob::RequestTokenTo3PIDMSISDNJob( % "/account/3pid/msisdn/requestToken", false) { - setRequestData(Data(toJson(body))); + setRequestData(RequestData(toJson(body))); } diff --git a/lib/csapi/content-repo.cpp b/lib/csapi/content-repo.cpp index 00bc9706..2d82437b 100644 --- a/lib/csapi/content-repo.cpp +++ b/lib/csapi/content-repo.cpp @@ -22,7 +22,7 @@ UploadContentJob::UploadContentJob(QIODevice* content, const QString& filename, queryToUploadContent(filename)) { setRequestHeader("Content-Type", contentType.toLatin1()); - setRequestData(Data(content)); + setRequestData(RequestData(content)); addExpectedKey("content_uri"); } diff --git a/lib/csapi/cross_signing.cpp b/lib/csapi/cross_signing.cpp index 9bfc026a..ed2b15c0 100644 --- a/lib/csapi/cross_signing.cpp +++ b/lib/csapi/cross_signing.cpp @@ -30,5 +30,5 @@ UploadCrossSigningSignaturesJob::UploadCrossSigningSignaturesJob( : BaseJob(HttpVerb::Post, QStringLiteral("UploadCrossSigningSignaturesJob"), QStringLiteral("/_matrix/client/r0") % "/keys/signatures/upload") { - setRequestData(Data(toJson(signatures))); + setRequestData(RequestData(toJson(signatures))); } diff --git a/lib/csapi/filter.cpp b/lib/csapi/filter.cpp index bb3a893f..6b8863cc 100644 --- a/lib/csapi/filter.cpp +++ b/lib/csapi/filter.cpp @@ -13,7 +13,7 @@ DefineFilterJob::DefineFilterJob(const QString& userId, const Filter& filter) QStringLiteral("/_matrix/client/r0") % "/user/" % userId % "/filter") { - setRequestData(Data(toJson(filter))); + setRequestData(RequestData(toJson(filter))); addExpectedKey("filter_id"); } diff --git a/lib/csapi/openid.cpp b/lib/csapi/openid.cpp index 3941e9c0..0447db79 100644 --- a/lib/csapi/openid.cpp +++ b/lib/csapi/openid.cpp @@ -14,5 +14,5 @@ RequestOpenIdTokenJob::RequestOpenIdTokenJob(const QString& userId, QStringLiteral("/_matrix/client/r0") % "/user/" % userId % "/openid/request_token") { - setRequestData(Data(toJson(body))); + setRequestData(RequestData(toJson(body))); } diff --git a/lib/csapi/receipts.cpp b/lib/csapi/receipts.cpp index 00d1c28a..47b18174 100644 --- a/lib/csapi/receipts.cpp +++ b/lib/csapi/receipts.cpp @@ -15,5 +15,5 @@ PostReceiptJob::PostReceiptJob(const QString& roomId, const QString& receiptType QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId % "/receipt/" % receiptType % "/" % eventId) { - setRequestData(Data(toJson(receipt))); + setRequestData(RequestData(toJson(receipt))); } diff --git a/lib/csapi/registration.cpp b/lib/csapi/registration.cpp index 38649e63..c3617bfc 100644 --- a/lib/csapi/registration.cpp +++ b/lib/csapi/registration.cpp @@ -44,7 +44,7 @@ RequestTokenToRegisterEmailJob::RequestTokenToRegisterEmailJob( % "/register/email/requestToken", false) { - setRequestData(Data(toJson(body))); + setRequestData(RequestData(toJson(body))); } RequestTokenToRegisterMSISDNJob::RequestTokenToRegisterMSISDNJob( @@ -54,7 +54,7 @@ RequestTokenToRegisterMSISDNJob::RequestTokenToRegisterMSISDNJob( % "/register/msisdn/requestToken", false) { - setRequestData(Data(toJson(body))); + setRequestData(RequestData(toJson(body))); } ChangePasswordJob::ChangePasswordJob(const QString& newPassword, @@ -78,7 +78,7 @@ RequestTokenToResetPasswordEmailJob::RequestTokenToResetPasswordEmailJob( % "/account/password/email/requestToken", false) { - setRequestData(Data(toJson(body))); + setRequestData(RequestData(toJson(body))); } RequestTokenToResetPasswordMSISDNJob::RequestTokenToResetPasswordMSISDNJob( @@ -89,7 +89,7 @@ RequestTokenToResetPasswordMSISDNJob::RequestTokenToResetPasswordMSISDNJob( % "/account/password/msisdn/requestToken", false) { - setRequestData(Data(toJson(body))); + setRequestData(RequestData(toJson(body))); } DeactivateAccountJob::DeactivateAccountJob( diff --git a/lib/csapi/room_send.cpp b/lib/csapi/room_send.cpp index 63986c56..9fd8cb96 100644 --- a/lib/csapi/room_send.cpp +++ b/lib/csapi/room_send.cpp @@ -14,6 +14,6 @@ SendMessageJob::SendMessageJob(const QString& roomId, const QString& eventType, QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId % "/send/" % eventType % "/" % txnId) { - setRequestData(Data(toJson(body))); + setRequestData(RequestData(toJson(body))); addExpectedKey("event_id"); } diff --git a/lib/csapi/room_state.cpp b/lib/csapi/room_state.cpp index e18108ac..37e897fa 100644 --- a/lib/csapi/room_state.cpp +++ b/lib/csapi/room_state.cpp @@ -16,6 +16,6 @@ SetRoomStateWithKeyJob::SetRoomStateWithKeyJob(const QString& roomId, QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId % "/state/" % eventType % "/" % stateKey) { - setRequestData(Data(toJson(body))); + setRequestData(RequestData(toJson(body))); addExpectedKey("event_id"); } -- cgit v1.2.3 From 40548a7995147f3f99212928ae27047de7a79618 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 22 Aug 2021 20:10:49 +0200 Subject: Deprecate BaseJob::Data The grand plan is to get rid of `BaseJob` and turn job invocations to function calls returning `QFuture`. `RequestData` will stay though, feeding data into those calls. --- lib/jobs/basejob.cpp | 17 ++++++++++------- lib/jobs/basejob.h | 10 ++++++---- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 400a9243..239cef28 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -71,8 +71,8 @@ public: // Using an idiom from clang-tidy: // http://clang.llvm.org/extra/clang-tidy/checks/modernize-pass-by-value.html - Private(HttpVerb v, QString endpoint, const QUrlQuery& q, Data&& data, - bool nt) + Private(HttpVerb v, QString endpoint, const QUrlQuery& q, + RequestData&& data, bool nt) : verb(v) , apiEndpoint(std::move(endpoint)) , requestQuery(q) @@ -109,7 +109,7 @@ public: QString apiEndpoint; QHash requestHeaders; QUrlQuery requestQuery; - Data requestData; + RequestData requestData; bool needsToken; bool inBackground = false; @@ -168,11 +168,11 @@ public: BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, bool needsToken) - : BaseJob(verb, name, endpoint, QUrlQuery {}, Data {}, needsToken) + : BaseJob(verb, name, endpoint, QUrlQuery {}, RequestData {}, needsToken) {} BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, - const QUrlQuery &query, Data&& data, bool needsToken) + const QUrlQuery& query, RequestData&& data, bool needsToken) : d(new Private(verb, endpoint, query, std::move(data), needsToken)) { setObjectName(name); @@ -224,9 +224,12 @@ void BaseJob::setRequestQuery(const QUrlQuery& query) d->requestQuery = query; } -const BaseJob::Data& BaseJob::requestData() const { return d->requestData; } +const RequestData& BaseJob::requestData() const { return d->requestData; } -void BaseJob::setRequestData(Data&& data) { std::swap(d->requestData, data); } +void BaseJob::setRequestData(RequestData&& data) +{ + std::swap(d->requestData, data); +} const QByteArrayList& BaseJob::expectedContentTypes() const { diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 7ce4b808..7750fb8b 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -72,7 +72,8 @@ public: }; Q_ENUM(StatusCode) - using Data = RequestData; + using Data Q_DECL_DEPRECATED_X("Use Quotient::RequestData instead") // + = RequestData; /*! * This structure stores the status of a server call job. The status @@ -125,7 +126,8 @@ public: BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, bool needsToken = true); BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, - const QUrlQuery& query, Data&& data = {}, bool needsToken = true); + const QUrlQuery& query, RequestData&& data = {}, + bool needsToken = true); QUrl requestUrl() const; bool isBackground() const; @@ -330,8 +332,8 @@ protected: void setRequestHeaders(const headers_t& headers); const QUrlQuery& query() const; void setRequestQuery(const QUrlQuery& query); - const Data& requestData() const; - void setRequestData(Data&& data); + const RequestData& requestData() const; + void setRequestData(RequestData&& data); const QByteArrayList& expectedContentTypes() const; void addExpectedContentType(const QByteArray& contentType); void setExpectedContentTypes(const QByteArrayList& contentTypes); -- cgit v1.2.3 From c50420a0f2df7a7bf291312c38ac43e2c9f58141 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 22 Aug 2021 20:15:04 +0200 Subject: Drop QMatrixClient namespace alias --- lib/avatar.h | 2 -- lib/jobs/requestdata.h | 2 -- lib/logging.h | 2 -- 3 files changed, 6 deletions(-) (limited to 'lib') diff --git a/lib/avatar.h b/lib/avatar.h index 37e1eeef..d4634aea 100644 --- a/lib/avatar.h +++ b/lib/avatar.h @@ -42,5 +42,3 @@ private: std::unique_ptr d; }; } // namespace Quotient -/// \deprecated Use namespace Quotient instead -namespace QMatrixClient = Quotient; diff --git a/lib/jobs/requestdata.h b/lib/jobs/requestdata.h index 21657631..4f05e5ff 100644 --- a/lib/jobs/requestdata.h +++ b/lib/jobs/requestdata.h @@ -35,5 +35,3 @@ private: std::unique_ptr _source; }; } // namespace Quotient -/// \deprecated Use namespace Quotient instead -namespace QMatrixClient = Quotient; diff --git a/lib/logging.h b/lib/logging.h index 264215e1..1d1394e8 100644 --- a/lib/logging.h +++ b/lib/logging.h @@ -67,8 +67,6 @@ inline qint64 profilerMinNsecs() * 1000; } } // namespace Quotient -/// \deprecated Use namespace Quotient instead -namespace QMatrixClient = Quotient; inline QDebug operator<<(QDebug debug_object, const QElapsedTimer& et) { -- cgit v1.2.3 From c26015503aa0fbca37abdfc4870ac94bb7befeee Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 22 Aug 2021 20:19:15 +0200 Subject: Drop other stuff deprecated pre- or early 0.6 BaseJob: StatusCode::JsonParseError Connection: resolved() and reconnected() signals; roomMap(); postReceipt() User: bridged() and rawName() ConnectionData: setHost() and setPort() StateEventBase: prev_content() --- lib/connection.cpp | 21 --------------------- lib/connection.h | 45 --------------------------------------------- lib/connectiondata.cpp | 12 ------------ lib/connectiondata.h | 4 ---- lib/events/stateevent.h | 4 ---- lib/jobs/basejob.h | 2 -- lib/user.cpp | 4 ---- lib/user.h | 18 +----------------- 8 files changed, 1 insertion(+), 109 deletions(-) (limited to 'lib') diff --git a/lib/connection.cpp b/lib/connection.cpp index 7dd04aaa..222c3b71 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -314,8 +314,6 @@ void Connection::resolveServer(const QString& mxid) setHomeserver(maybeBaseUrl); } Q_ASSERT(d->loginFlowsJob != nullptr); // Ensured by setHomeserver() - connect(d->loginFlowsJob, &BaseJob::success, this, - &Connection::resolved); connect(d->loginFlowsJob, &BaseJob::failure, this, [this] { qCWarning(MAIN) << "Homeserver base URL sanity check failed"; emit resolveError(tr("The homeserver doesn't seem to be working")); @@ -795,11 +793,6 @@ void Connection::stopSync() QString Connection::nextBatchToken() const { return d->data->lastEvent(); } -PostReceiptJob* Connection::postReceipt(Room* room, RoomEvent* event) -{ - return callApi(room->id(), "m.read", event->id()); -} - JoinRoomJob* Connection::joinRoom(const QString& roomAlias, const QStringList& serverNames) { @@ -1239,20 +1232,6 @@ int Connection::millisToReconnect() const return d->syncJob ? d->syncJob->millisToRetry() : 0; } -QHash, Room*> Connection::roomMap() const -{ - // Copy-on-write-and-remove-elements is faster than copying elements one by - // one. - QHash, Room*> roomMap = d->roomMap; - for (auto it = roomMap.begin(); it != roomMap.end();) { - if (it.value()->joinState() == JoinState::Leave) - it = roomMap.erase(it); - else - ++it; - } - return roomMap; -} - QVector Connection::allRooms() const { QVector result; diff --git a/lib/connection.h b/lib/connection.h index a7a071f3..ecbb1a19 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -138,15 +138,6 @@ public: explicit Connection(const QUrl& server, QObject* parent = nullptr); ~Connection() override; - /// Get all Invited and Joined rooms - /*! - * \return a hashmap from a composite key - room name and whether - * it's an Invite rather than Join - to room pointers - * \sa allRooms, rooms, roomsWithTag - */ - [[deprecated("Use allRooms(), roomsWithTag() or rooms(joinStates) instead")]] - QHash, Room*> roomMap() const; - /// Get all rooms known within this Connection /*! * This includes Invite, Join and Leave rooms, in no particular order. @@ -524,30 +515,12 @@ public Q_SLOTS: */ void assumeIdentity(const QString& mxId, const QString& accessToken, const QString& deviceId); - /*! \deprecated Use loginWithPassword instead */ - void connectToServer(const QString& userId, const QString& password, - const QString& initialDeviceName, - const QString& deviceId = {}) - { - loginWithPassword(userId, password, initialDeviceName, deviceId); - } - /*! \deprecated - * Use assumeIdentity() if you have an access token or - * loginWithToken() if you have a login token. - */ - void connectWithToken(const QString& userId, const QString& accessToken, - const QString& deviceId) - { - assumeIdentity(userId, accessToken, deviceId); - } /// Explicitly request capabilities from the server void reloadCapabilities(); /// Find out if capabilites are still loading from the server bool loadingCapabilities() const; - /** @deprecated Use stopSync() instead */ - void disconnectFromServer() { stopSync(); } void logout(); void sync(int timeout = -1); @@ -662,24 +635,7 @@ public Q_SLOTS: /** \deprecated Do not use this directly, use Room::leaveRoom() instead */ virtual LeaveRoomJob* leaveRoom(Room* room); - // Old API that will be abolished any time soon. DO NOT USE. - - /** @deprecated Use callApi() or Room::postReceipt() instead - */ - virtual PostReceiptJob* postReceipt(Room* room, RoomEvent* event); - Q_SIGNALS: - /** - * @deprecated - * This was a signal resulting from a successful resolveServer(). - * Since Connection now provides setHomeserver(), the HS URL - * may change even without resolveServer() invocation. Use - * loginFLowsChanged() instead of resolved(). You can also use - * loginWith*() and assumeIdentity() without the HS URL set in - * advance (i.e. without calling resolveServer), as they trigger - * server name resolution from MXID if the server URL is not valid. - */ - void resolved(); void resolveError(QString error); void homeserverChanged(QUrl baseUrl); @@ -687,7 +643,6 @@ Q_SIGNALS: void capabilitiesLoaded(); void connected(); - void reconnected(); //< \deprecated Use connected() instead void loggedOut(); /** Login data or state have changed * diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index e54d909b..87ad4577 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -118,18 +118,6 @@ void ConnectionData::setToken(QByteArray token) d->accessToken = std::move(token); } -void ConnectionData::setHost(QString host) -{ - d->baseUrl.setHost(host); - qCDebug(MAIN) << "updated baseUrl to" << d->baseUrl; -} - -void ConnectionData::setPort(int port) -{ - d->baseUrl.setPort(port); - qCDebug(MAIN) << "updated baseUrl to" << d->baseUrl; -} - const QString& ConnectionData::deviceId() const { return d->deviceId; } const QString& ConnectionData::userId() const { return d->userId; } diff --git a/lib/connectiondata.h b/lib/connectiondata.h index 7dd96f26..e16a2dac 100644 --- a/lib/connectiondata.h +++ b/lib/connectiondata.h @@ -31,10 +31,6 @@ public: void setBaseUrl(QUrl baseUrl); void setToken(QByteArray accessToken); - [[deprecated("Use setBaseUrl() instead")]] - void setHost(QString host); - [[deprecated("Use setBaseUrl() instead")]] - void setPort(int port); void setDeviceId(const QString& deviceId); void setUserId(const QString& userId); void setNeedsToken(const QString& requestName); diff --git a/lib/events/stateevent.h b/lib/events/stateevent.h index 1415f709..bc414a5f 100644 --- a/lib/events/stateevent.h +++ b/lib/events/stateevent.h @@ -100,10 +100,6 @@ public: visitor(_content); editJson()[ContentKeyL] = _content.toJson(); } - [[deprecated("Use prevContent instead")]] const ContentT* prev_content() const - { - return prevContent(); - } const ContentT* prevContent() const { return _prev ? &_prev->content : nullptr; diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 7750fb8b..835cd822 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -52,8 +52,6 @@ public: IncorrectRequestError = IncorrectRequest, IncorrectResponse, IncorrectResponseError = IncorrectResponse, - JsonParseError //< \deprecated Use IncorrectResponse instead - = IncorrectResponse, TooManyRequests, TooManyRequestsError = TooManyRequests, RateLimited = TooManyRequests, diff --git a/lib/user.cpp b/lib/user.cpp index a4abed37..60920a59 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -93,8 +93,6 @@ QString User::name(const Room* room) const return room ? room->memberName(id()) : d->defaultName; } -QString User::rawName(const Room* room) const { return name(room); } - void User::rename(const QString& newName) { const auto actualNewName = sanitized(newName); @@ -185,8 +183,6 @@ QString User::fullName(const Room* room) const return displayName.isEmpty() ? id() : (displayName % " (" % id() % ')'); } -QString User::bridged() const { return {}; } - const Avatar& User::avatarObject(const Room* room) const { if (!room) diff --git a/lib/user.h b/lib/user.h index 4ff62951..78b72bf2 100644 --- a/lib/user.h +++ b/lib/user.h @@ -22,7 +22,6 @@ class User : public QObject { Q_PROPERTY(QString name READ name NOTIFY defaultNameChanged) Q_PROPERTY(QString displayName READ displayname NOTIFY defaultNameChanged STORED false) Q_PROPERTY(QString fullName READ fullName NOTIFY defaultNameChanged STORED false) - Q_PROPERTY(QString bridgeName READ bridged NOTIFY defaultNameChanged STORED false) Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY defaultAvatarChanged STORED false) Q_PROPERTY(QUrl avatarUrl READ avatarUrl NOTIFY defaultAvatarChanged) public: @@ -40,18 +39,10 @@ public: * This may be empty if the user didn't choose the name or cleared * it. If the user is bridged, the bridge postfix (such as '(IRC)') * is stripped out. No disambiguation for the room is done. - * \sa displayName, rawName + * \sa displayName */ QString name(const Room* room = nullptr) const; - /** Get the user name along with the bridge postfix - * This function is similar to name() but appends the bridge postfix - * (such as '(IRC)') to the user name. No disambiguation is done. - * \sa name, displayName - */ - [[deprecated("Bridge postfixes exist no more, use name() instead")]] - QString rawName(const Room* room = nullptr) const; - /** Get the displayed user name * When \p room is null, this method returns result of name() if * the name is non-empty; otherwise it returns user id. @@ -70,13 +61,6 @@ public: */ QString fullName(const Room* room = nullptr) const; - /** - * Returns the name of bridge the user is connected from or empty. - */ - [[deprecated("Bridged status is no more supported; this always returns" - " an empty string")]] - QString bridged() const; - /** Whether the user is a guest * As of now, the function relies on the convention used in Synapse * that guests and only guests have all-numeric IDs. This may or -- cgit v1.2.3 From 776feaa5eeaffe78773aec9a4431fef147fa95c4 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 22 Aug 2021 20:21:06 +0200 Subject: Use Q_DECL_DEPRECATED_X instead of \deprecated doc-comment This still works with older moc yet produces actual warnings when compiling C++ code. --- lib/room.cpp | 4 ++-- lib/room.h | 22 +++++++--------------- 2 files changed, 9 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/room.cpp b/lib/room.cpp index 9fe70678..398b3ec8 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1236,7 +1236,7 @@ QList Room::membersLeft() const { return d->membersLeft; } QList Room::users() const { return d->membersMap.values(); } -[[deprecated]] QStringList Room::memberNames() const +QStringList Room::memberNames() const { return safeMemberNames(); } @@ -1507,7 +1507,7 @@ QString Room::disambiguatedMemberName(const QString& mxId) const QString Room::safeMemberName(const QString& userId) const { - return sanitized(roomMembername(userId)); + return sanitized(disambiguatedMemberName(userId)); } QString Room::htmlSafeMemberName(const QString& userId) const diff --git a/lib/room.h b/lib/room.h index 52ba2eab..de0c7504 100644 --- a/lib/room.h +++ b/lib/room.h @@ -192,7 +192,7 @@ public: QList membersLeft() const; Q_INVOKABLE QList users() const; - [[deprecated("Use safeMemberNames() or htmlSafeMemberNames() instead")]] + Q_DECL_DEPRECATED_X("Use safeMemberNames() or htmlSafeMemberNames() instead") // QStringList memberNames() const; QStringList safeMemberNames() const; QStringList htmlSafeMemberNames() const; @@ -235,13 +235,12 @@ public: /** * \brief Check the join state of a given user in this room * - * \deprecated Use memberState and check against a mask - * * \note Banned and invited users are not tracked separately for now (Leave * will be returned for them). * * \return Join if the user is a room member; Leave otherwise */ + Q_DECL_DEPRECATED_X("Use memberState and check against the mask") // Q_INVOKABLE Quotient::JoinState memberJoinState(Quotient::User* user) const; //! \brief Check the join state of a given user in this room @@ -254,18 +253,11 @@ public: //! \sa safeMemberName, htmlSafeMemberName Q_INVOKABLE QString memberName(const QString& mxId) const; - /*! - * \brief Get a disambiguated name for the given user in the room context - * - * \deprecated use safeMemberName() instead - */ + //! \brief Get a disambiguated name for the given user in the room context + Q_DECL_DEPRECATED_X("Use safeMemberName() instead") Q_INVOKABLE QString roomMembername(const Quotient::User* u) const; - /*! - * \brief Get a disambiguated name for a user with this id in the room - * context - * - * \deprecated use safeMemberName() instead - */ + //! \brief Get a disambiguated name for a user with this id in the room + Q_DECL_DEPRECATED_X("Use safeMemberName() instead") Q_INVOKABLE QString roomMembername(const QString& userId) const; /*! @@ -552,7 +544,7 @@ public Q_SLOTS: QString postFile(const QString& plainText, EventContent::TypedBase* content); #if QT_VERSION_MAJOR < 6 - /// \deprecated Use postFile(QString, MessageEventType, EventContent) instead + Q_DECL_DEPRECATED_X("Use postFile(QString, MessageEventType, EventContent)") // QString postFile(const QString& plainText, const QUrl& localPath, bool asGenericFile = false); #endif -- cgit v1.2.3 From 395f3758e810fed6cd276a356fd5f0e955c5477e Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 22 Aug 2021 20:22:36 +0200 Subject: Settings: no more setToken() and accessToken(); deprecate clearAccessToken() Access tokens should be stored with Qt Keychain that's about to come; and these methods were deprecated since before 0.5. --- lib/settings.cpp | 13 ------------- lib/settings.h | 8 +------- 2 files changed, 1 insertion(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/settings.cpp b/lib/settings.cpp index 1d36db27..ed9082b0 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -126,19 +126,6 @@ void AccountSettings::setHomeserver(const QUrl& url) QString AccountSettings::userId() const { return group().section('/', -1); } -QString AccountSettings::accessToken() const -{ - return value(AccessTokenKey).toString(); -} - -void AccountSettings::setAccessToken(const QString& accessToken) -{ - qCWarning(MAIN) << "Saving access_token to QSettings is insecure." - " Developers, do it manually or contribute to share " - "QtKeychain logic to libQuotient."; - setValue(AccessTokenKey, accessToken); -} - void AccountSettings::clearAccessToken() { legacySettings.remove(AccessTokenKey); diff --git a/lib/settings.h b/lib/settings.h index 84c54802..3f4dc123 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -131,8 +131,6 @@ class AccountSettings : public SettingsGroup { QTNT_DECLARE_SETTING(QString, deviceId, setDeviceId) QTNT_DECLARE_SETTING(QString, deviceName, setDeviceName) QTNT_DECLARE_SETTING(bool, keepLoggedIn, setKeepLoggedIn) - /** \deprecated \sa setAccessToken */ - Q_PROPERTY(QString accessToken READ accessToken WRITE setAccessToken) Q_PROPERTY(QByteArray encryptionAccountPickle READ encryptionAccountPickle WRITE setEncryptionAccountPickle) public: @@ -147,11 +145,7 @@ public: QUrl homeserver() const; void setHomeserver(const QUrl& url); - /** \deprecated \sa setToken */ - QString accessToken() const; - /** \deprecated Storing accessToken in QSettings is unsafe, - * see quotient-im/Quaternion#181 */ - void setAccessToken(const QString& accessToken); + Q_DECL_DEPRECATED_X("Access tokens are not stored in QSettings any more") Q_INVOKABLE void clearAccessToken(); QByteArray encryptionAccountPickle(); -- cgit v1.2.3 From fd42d1dbd29800ef53ab9997c948f39a92aa8bff Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 22 Aug 2021 20:23:42 +0200 Subject: RoomEvent: drop timestamp() Use originTimestamp(); the corresponding Q_PROPERTY was not renamed (in error) so it is now. --- lib/events/roomevent.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/events/roomevent.h b/lib/events/roomevent.h index 3abd56c0..3174764f 100644 --- a/lib/events/roomevent.h +++ b/lib/events/roomevent.h @@ -14,7 +14,9 @@ class RedactionEvent; class RoomEvent : public Event { Q_GADGET Q_PROPERTY(QString id READ id) - Q_PROPERTY(QDateTime timestamp READ timestamp CONSTANT) + //! \deprecated Use originTimestamp instead + Q_PROPERTY(QDateTime timestamp READ originTimestamp CONSTANT) + Q_PROPERTY(QDateTime originTimestamp READ originTimestamp CONSTANT) Q_PROPERTY(QString roomId READ roomId CONSTANT) Q_PROPERTY(QString senderId READ senderId CONSTANT) Q_PROPERTY(QString redactionReason READ redactionReason) @@ -32,9 +34,6 @@ public: QString id() const; QDateTime originTimestamp() const; - [[deprecated("Use originTimestamp()")]] QDateTime timestamp() const { - return originTimestamp(); - } QString roomId() const; QString senderId() const; //! \brief Determine whether the event has been replaced -- cgit v1.2.3 From 93cee89f9a99e51275ac9cd304180499b0543eea Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 22 Aug 2021 20:45:53 +0200 Subject: Fix building with MSVC --- lib/jobs/basejob.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 835cd822..29443c53 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -70,7 +70,10 @@ public: }; Q_ENUM(StatusCode) - using Data Q_DECL_DEPRECATED_X("Use Quotient::RequestData instead") // + using Data +#ifndef Q_CC_MSVC + Q_DECL_DEPRECATED_X("Use Quotient::RequestData instead") +#endif = RequestData; /*! -- cgit v1.2.3 From 3cbc13a33c81a75e18c415bd31cc2156461ffa1f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 22 Aug 2021 20:58:18 +0200 Subject: User::isGuest(): fix a clazy warning --- lib/user.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/user.cpp b/lib/user.cpp index a4abed37..2706b2c0 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -82,7 +82,7 @@ bool User::isGuest() const Q_ASSERT(!d->id.isEmpty() && d->id.startsWith('@')); auto it = std::find_if_not(d->id.cbegin() + 1, d->id.cend(), [](QChar c) { return c.isDigit(); }); - Q_ASSERT(it != d->id.end()); + Q_ASSERT(it != d->id.cend()); return *it == ':'; } -- cgit v1.2.3 From 6953e55361f600a591c08b9cd287a350230b3ef8 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 23 Aug 2021 08:42:49 +0200 Subject: Room: isMember(); memberState() only needs user id Room::memberJoinState() was only used to check if the user has joined the room (it couldn't be used for anything else), meaning that its best replacement is actually not memberState() but isMember() introduced hereby. It's also better to pass user ids instead of User objects to memberState() and isMember() since that is enough to check membership. # Conflicts: # lib/room.cpp # lib/room.h --- lib/room.cpp | 29 +++++++++++++++++------------ lib/room.h | 7 +++++-- 2 files changed, 22 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/room.cpp b/lib/room.cpp index 398b3ec8..45f1af53 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -590,9 +590,14 @@ JoinState Room::memberJoinState(User* user) const : JoinState::Leave; } -Membership Room::memberState(User* user) const +Membership Room::memberState(const QString& userId) const { - return d->getCurrentState(user->id())->membership(); + return d->getCurrentState(userId)->membership(); +} + +bool Room::isMember(const QString& userId) const +{ + return memberState(userId) == Membership::Join; } JoinState Room::joinState() const { return d->joinState; } @@ -2698,11 +2703,10 @@ Room::Changes Room::processEphemeralEvent(EventPtr&& event) et.start(); if (auto* evt = eventCast(event)) { d->usersTyping.clear(); - for (const auto& userId : evt->users()) { - auto u = user(userId); - if (memberJoinState(u) == JoinState::Join) - d->usersTyping.append(u); - } + for (const auto& userId : evt->users()) + if (isMember(userId)) + d->usersTyping.append(user(userId)); + if (evt->users().size() > 3 || et.nsecsElapsed() >= profilerMinNsecs()) qCDebug(PROFILER) << "*** Room::processEphemeralEvent(typing):" << evt->users().size() << "users," << et; @@ -2726,9 +2730,9 @@ Room::Changes Room::processEphemeralEvent(EventPtr&& event) for (const Receipt& r : p.receipts) { if (r.userId == connection()->userId()) continue; // FIXME, #185 - auto u = user(r.userId); - if (memberJoinState(u) == JoinState::Join) - changes |= d->promoteReadMarker(u, newMarker); + if (isMember(r.userId)) + changes |= + d->promoteReadMarker(user(r.userId), newMarker); } } else { qCDebug(EPHEMERAL) << "Event" << p.evtId @@ -2740,9 +2744,10 @@ Room::Changes Room::processEphemeralEvent(EventPtr&& event) for (const Receipt& r : p.receipts) { if (r.userId == connection()->userId()) continue; // FIXME, #185 + if (!isMember(r.userId)) + continue; auto u = user(r.userId); - if (memberJoinState(u) == JoinState::Join - && readMarker(u) == historyEdge()) + if (readMarker(u) == historyEdge()) changes |= d->setLastReadEvent(u, p.evtId); } } diff --git a/lib/room.h b/lib/room.h index de0c7504..179295d0 100644 --- a/lib/room.h +++ b/lib/room.h @@ -240,13 +240,16 @@ public: * * \return Join if the user is a room member; Leave otherwise */ - Q_DECL_DEPRECATED_X("Use memberState and check against the mask") // + Q_DECL_DEPRECATED_X("Use isMember() instead") Q_INVOKABLE Quotient::JoinState memberJoinState(Quotient::User* user) const; //! \brief Check the join state of a given user in this room //! //! \return the given user's state with respect to the room - Q_INVOKABLE Quotient::Membership memberState(User* user) const; + Q_INVOKABLE Quotient::Membership memberState(const QString& userId) const; + + //! Check whether a user with the given id is a member of the room + Q_INVOKABLE bool isMember(const QString& userId) const; //! \brief Get a display name (without disambiguation) for the given member //! -- cgit v1.2.3 From 8d21c8a6579ad9c63e331ffb42e3ed81b9c73caf Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Tue, 24 Aug 2021 23:59:48 +0200 Subject: Add AccountRegistry Basic session management class; Created from Quaternion's AccountRegistry and NeoChat's AccountListModel. The connections can be accessed by the user's id, this technically limits it to one connection for each matrix account. --- lib/accountregistry.cpp | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/accountregistry.h | 45 +++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 lib/accountregistry.cpp create mode 100644 lib/accountregistry.h (limited to 'lib') diff --git a/lib/accountregistry.cpp b/lib/accountregistry.cpp new file mode 100644 index 00000000..3a022f14 --- /dev/null +++ b/lib/accountregistry.cpp @@ -0,0 +1,98 @@ +// SPDX-FileCopyrightText: Kitsune Ral +// SPDX-FileCopyrightText: Tobias Fella +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "accountregistry.h" + +#include "connection.h" + +using namespace Quotient; + +void AccountRegistry::add(Connection* c) +{ + if (m_accounts.contains(c)) + return; + beginInsertRows(QModelIndex(), m_accounts.size(), m_accounts.size()); + m_accounts += c; + endInsertRows(); +} + +void AccountRegistry::drop(Connection* c) +{ + beginRemoveRows(QModelIndex(), m_accounts.indexOf(c), m_accounts.indexOf(c)); + m_accounts.removeOne(c); + endRemoveRows(); + Q_ASSERT(!m_accounts.contains(c)); +} + +bool AccountRegistry::isLoggedIn(const QString &userId) const +{ + return std::any_of(m_accounts.cbegin(), m_accounts.cend(), + [&userId](Connection* a) { return a->userId() == userId; }); +} + +bool AccountRegistry::contains(Connection *c) const +{ + return m_accounts.contains(c); +} + +AccountRegistry::AccountRegistry() +{} + +QVariant AccountRegistry::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return {}; + } + + if (index.row() >= m_accounts.count()) { + return {}; + } + + auto account = m_accounts[index.row()]; + + if (role == ConnectionRole) { + return QVariant::fromValue(account); + } + + return {}; +} + +int AccountRegistry::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + + return m_accounts.count(); +} + +QHash AccountRegistry::roleNames() const +{ + return {{ConnectionRole, "connection"}}; +} + +bool AccountRegistry::isEmpty() const +{ + return m_accounts.isEmpty(); +} + +int AccountRegistry::count() const +{ + return m_accounts.count(); +} + +const QVector AccountRegistry::accounts() const +{ + return m_accounts; +} + +Connection* AccountRegistry::get(const QString& userId) +{ + for (const auto &connection : m_accounts) { + if(connection->userId() == userId) { + return connection; + } + } + return nullptr; +} \ No newline at end of file diff --git a/lib/accountregistry.h b/lib/accountregistry.h new file mode 100644 index 00000000..e87da3e8 --- /dev/null +++ b/lib/accountregistry.h @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: 2020 Kitsune Ral +// SPDX-FileCopyrightText: Tobias Fella +// SPDX-License-Identifier: LGPL-2.1-or-later + +#pragma once + +#include +#include +#include + +namespace Quotient { +class Connection; + +class AccountRegistry : public QAbstractListModel { + Q_OBJECT +public: + enum EventRoles { + ConnectionRole = Qt::UserRole + 1, + }; + + static AccountRegistry &instance() { + static AccountRegistry _instance; + return _instance; + } + + const QVector accounts() const; + void add(Connection* a); + void drop(Connection* a); + bool isLoggedIn(const QString& userId) const; + bool isEmpty() const; + int count() const; + bool contains(Connection*) const; + Connection* get(const QString& userId); + + [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; + + [[nodiscard]] QHash roleNames() const override; + +private: + AccountRegistry(); + + QVector m_accounts; +}; +} \ No newline at end of file -- cgit v1.2.3 From f005f3b69651bd6d6f58879804e1281f6c08177a Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 30 Aug 2021 12:33:56 +0200 Subject: SettingsGroup, AccountSettings: simplify constructors The parameter packs intended to pass organisation/application names to QSettings never worked that way since Quotient::Settings didn't have that parameter pack in its constructor. On the other hand, setting organisation/application name using static methods before constructing the first settings object has been working just fine so far. If someone needs to create a settings object with customised org/app name for some reason (sneaking settings from other apps?), those can be brought back in a working manner and without breaking API/ABI even. --- lib/settings.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/settings.h b/lib/settings.h index 3f4dc123..efd0d714 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -78,9 +78,8 @@ protected: class SettingsGroup : public Settings { public: - template - explicit SettingsGroup(QString path, ArgTs&&... qsettingsArgs) - : Settings(std::forward(qsettingsArgs)...) + explicit SettingsGroup(QString path, QObject* parent = nullptr) + : Settings(parent) , groupPath(std::move(path)) {} @@ -134,10 +133,8 @@ class AccountSettings : public SettingsGroup { Q_PROPERTY(QByteArray encryptionAccountPickle READ encryptionAccountPickle WRITE setEncryptionAccountPickle) public: - template - explicit AccountSettings(const QString& accountId, ArgTs&&... qsettingsArgs) - : SettingsGroup("Accounts/" + accountId, - std::forward(qsettingsArgs)...) + explicit AccountSettings(const QString& accountId, QObject* parent = nullptr) + : SettingsGroup("Accounts/" + accountId, parent) {} QString userId() const; -- cgit v1.2.3 From 06a8ef6ebed5962117121486059ba46dc7f6d4f9 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 30 Aug 2021 12:35:27 +0200 Subject: Room: displayNameForHtml This is useful for cases when the room display name is returned to QML that doesn't have an equivalent of QString::toHtmlEscaped(). --- lib/room.cpp | 5 +++++ lib/room.h | 2 ++ 2 files changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/room.cpp b/lib/room.cpp index 45f1af53..890da13d 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -549,6 +549,11 @@ QString Room::canonicalAlias() const QString Room::displayName() const { return d->displayname; } +QString Room::displayNameForHtml() const +{ + return displayName().toHtmlEscaped(); +} + void Room::refreshDisplayName() { d->updateDisplayname(); } QString Room::topic() const diff --git a/lib/room.h b/lib/room.h index 179295d0..d3a7466d 100644 --- a/lib/room.h +++ b/lib/room.h @@ -85,6 +85,7 @@ class Room : public QObject { Q_PROPERTY(QStringList altAliases READ altAliases NOTIFY namesChanged) Q_PROPERTY(QString canonicalAlias READ canonicalAlias NOTIFY namesChanged) Q_PROPERTY(QString displayName READ displayName NOTIFY displaynameChanged) + Q_PROPERTY(QString displayNameForHtml READ displayNameForHtml NOTIFY displaynameChanged) Q_PROPERTY(QString topic READ topic NOTIFY topicChanged) Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY avatarChanged STORED false) @@ -183,6 +184,7 @@ public: //! Get a list of both canonical and alternative aliases QStringList aliases() const; QString displayName() const; + QString displayNameForHtml() const; QString topic() const; QString avatarMediaId() const; QUrl avatarUrl() const; -- cgit v1.2.3 From e2de07628f61c565ac8c85fa3aae84a5fa6feba3 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Tue, 31 Aug 2021 15:06:46 +0200 Subject: Add functions and macros to query for Quotient's version --- lib/util.cpp | 20 ++++++++++++++++++++ lib/util.h | 5 +++++ 2 files changed, 25 insertions(+) (limited to 'lib') diff --git a/lib/util.cpp b/lib/util.cpp index 904bfd5a..3de1d169 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -119,6 +119,26 @@ QString Quotient::serverPart(const QString& mxId) return parser.match(mxId).captured(1); } +QString Quotient::versionString() +{ + return QStringLiteral(Quotient_VERSION_STRING); +} + +int Quotient::majorVersion() +{ + return Quotient_VERSION_MAJOR; +} + +int Quotient::minorVersion() +{ + return Quotient_VERSION_MINOR; +} + +int Quotient::patchVersion() +{ + return Quotient_VERSION_PATCH; +} + // Tests for function_traits<> using namespace Quotient; diff --git a/lib/util.h b/lib/util.h index 78fc9ab7..5bfe6841 100644 --- a/lib/util.h +++ b/lib/util.h @@ -318,4 +318,9 @@ qreal stringToHueF(const QString& s); /** Extract the serverpart from MXID */ QString serverPart(const QString& mxId); + +QString versionString(); +int majorVersion(); +int minorVersion(); +int patchVersion(); } // namespace Quotient -- cgit v1.2.3 From c813a084b6dc8206a9c7305bbb236e23edcb49e5 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 24 Aug 2021 18:38:45 +0200 Subject: Fix building with MSVC Turned out it was broken, and I was looking the other way. --- lib/jobs/basejob.cpp | 4 ++-- lib/quotient_common.h | 31 +++++++++++++------------------ 2 files changed, 15 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 239cef28..6346db9d 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -156,8 +156,8 @@ public: { // FIXME: use std::array {} when Apple stdlib gets deduction guides for it static const auto verbs = - to_array({ QStringLiteral("GET"), QStringLiteral("PUT"), - QStringLiteral("POST"), QStringLiteral("DELETE") }); + make_array(QStringLiteral("GET"), QStringLiteral("PUT"), + QStringLiteral("POST"), QStringLiteral("DELETE")); const auto verbWord = verbs.at(size_t(verb)); return verbWord % ' ' % (reply ? reply->url().toString(QUrl::RemoveQuery) diff --git a/lib/quotient_common.h b/lib/quotient_common.h index d225ad63..bb2e6a6b 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -10,22 +10,17 @@ namespace Quotient { Q_NAMESPACE -namespace impl { - template - constexpr std::array, N> - to_array_impl(T (&&a)[N], std::index_sequence) - { - return { {std::move(a[I])...} }; - } -} // std::array {} needs explicit template parameters on macOS because -// Apple stdlib doesn't have deduction guides for std::array; to alleviate that, -// to_array() is borrowed from C++20 (thanks to cppreference for the possible -// implementation: https://en.cppreference.com/w/cpp/container/array/to_array) -template -constexpr auto to_array(T (&& items)[N]) +// Apple stdlib doesn't have deduction guides for std::array. C++20 has +// to_array() but that can't be borrowed, this time because of MSVC: +// https://developercommunity.visualstudio.com/t/vc-ice-p1-initc-line-3652-from-stdto-array/1464038 +// Therefore a simpler (but also slightly more wobbly - it resolves the element +// type using std::common_type<>) make_array facility is implemented here. +template +constexpr auto make_array(Ts&&... items) { - return impl::to_array_impl(std::move(items), std::make_index_sequence{}); + return std::array, sizeof...(items)>( + { std::forward(items)... }); } // TODO: code like this should be generated from the CS API definition @@ -49,9 +44,9 @@ enum class Membership : unsigned int { Q_DECLARE_FLAGS(MembershipMask, Membership) Q_FLAG_NS(MembershipMask) -constexpr inline auto MembershipStrings = to_array( +constexpr inline auto MembershipStrings = make_array( // The order MUST be the same as the order in the original enum - { "join", "leave", "invite", "knock", "ban" }); + "join", "leave", "invite", "knock", "ban"); //! \brief Local user join-state names //! @@ -68,10 +63,10 @@ enum class JoinState : std::underlying_type_t { Q_DECLARE_FLAGS(JoinStates, JoinState) Q_FLAG_NS(JoinStates) -constexpr inline auto JoinStateStrings = to_array({ +constexpr inline auto JoinStateStrings = make_array( MembershipStrings[0], MembershipStrings[1], MembershipStrings[2], MembershipStrings[3] /* same as MembershipStrings, sans "ban" */ -}); +); //! \brief Network job running policy flags //! -- cgit v1.2.3 From 4bab0f2ef2c68b478d669f90557d6bef6332e823 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Tue, 31 Aug 2021 21:47:10 +0200 Subject: Implement the mxc protocol in the NetworkAccessManager Allows images to be loaded using the NetworkAccessManager instead of an ImageProvider --- lib/mxcreply.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++ lib/mxcreply.h | 29 +++++++++++++++++++++++ lib/networkaccessmanager.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++ lib/networkaccessmanager.h | 6 +++++ 4 files changed, 145 insertions(+) create mode 100644 lib/mxcreply.cpp create mode 100644 lib/mxcreply.h (limited to 'lib') diff --git a/lib/mxcreply.cpp b/lib/mxcreply.cpp new file mode 100644 index 00000000..49ebe603 --- /dev/null +++ b/lib/mxcreply.cpp @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: Tobias Fella +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "mxcreply.h" + +#include +#include "connection.h" +#include "room.h" +#include "networkaccessmanager.h" +#include "events/stickerevent.h" + +using namespace Quotient; + +class MxcReply::Private +{ +public: + QNetworkReply *m_reply = nullptr; +}; + +MxcReply::MxcReply(QNetworkReply* reply) +{ + reply->setParent(this); + d->m_reply = reply; + connect(d->m_reply, &QNetworkReply::finished, this, [this]() { + setError(d->m_reply->error(), d->m_reply->errorString()); + Q_EMIT finished(); + }); +} + +MxcReply::MxcReply(QNetworkReply* reply, Room* room, const QString &eventId) + : d(std::make_unique()) +{ + reply->setParent(this); + d->m_reply = reply; + connect(d->m_reply, &QNetworkReply::finished, this, [this, eventId]() { + setError(d->m_reply->error(), d->m_reply->errorString()); + Q_EMIT finished(); + }); +} + +bool MxcReply::isSequential() const +{ + return true; +} + +qint64 MxcReply::readData(char *data, qint64 maxSize) +{ + return d->m_reply->read(data, maxSize); +} + +void MxcReply::abort() +{ + d->m_reply->abort(); +} \ No newline at end of file diff --git a/lib/mxcreply.h b/lib/mxcreply.h new file mode 100644 index 00000000..26dea2d0 --- /dev/null +++ b/lib/mxcreply.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Tobias Fella +// SPDX-License-Identifier: LGPL-2.1-or-later + +#pragma once + +#include +#include + +namespace Quotient { +class Room; +class Connection; +class MxcReply : public QNetworkReply +{ +public: + MxcReply(QNetworkReply* reply, Room* room, const QString &eventId); + MxcReply(QNetworkReply* reply); + + bool isSequential() const override; + +public slots: + void abort() override; + +protected: + qint64 readData(char *data, qint64 maxSize) override; +private: + class Private; + std::unique_ptr d; +}; +} \ No newline at end of file diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index a94ead34..e4132957 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -5,6 +5,11 @@ #include #include +#include "accountregistry.h" +#include "mxcreply.h" +#include "connection.h" + +#include "room.h" using namespace Quotient; @@ -56,7 +61,58 @@ NetworkAccessManager::~NetworkAccessManager() = default; QNetworkReply* NetworkAccessManager::createRequest( Operation op, const QNetworkRequest& request, QIODevice* outgoingData) { + if(request.url().scheme() == QStringLiteral("mxc")) { + const auto fragment = request.url().fragment(); + const auto fragmentParts = fragment.split(QLatin1Char('/')); + const auto mediaId = request.url().toString(QUrl::RemoveScheme | QUrl::RemoveFragment); + if(fragmentParts.size() == 3) { + auto connection = AccountRegistry::instance().get(fragmentParts[0]); + if(!connection) { + qWarning() << "Connection not found"; + return nullptr; + } + auto room = connection->room(fragmentParts[1]); + if(!room) { + qWarning() << "Room not found"; + return nullptr; + } + QNetworkRequest r(request); + r.setUrl(QUrl(QStringLiteral("%1/_matrix/media/r0/download/%2").arg(connection->homeserver().toString(), mediaId))); + auto reply = createRequest(QNetworkAccessManager::GetOperation, r); + return new MxcReply(reply, room, fragmentParts[2]); + } else if(fragmentParts.size() == 1) { + auto connection = AccountRegistry::instance().get(fragment); + if(!connection) { + qWarning() << "Connection not found"; + return nullptr; + } + QNetworkRequest r(request); + r.setUrl(QUrl(QStringLiteral("%1/_matrix/media/r0/download/%2").arg(connection->homeserver().toString(), mediaId))); + auto reply = createRequest(QNetworkAccessManager::GetOperation, r); + return new MxcReply(reply); + } else { + qWarning() << "Invalid request"; + return nullptr; + } + } auto reply = QNetworkAccessManager::createRequest(op, request, outgoingData); reply->ignoreSslErrors(d->ignoredSslErrors); return reply; } + +QStringList NetworkAccessManager::supportedSchemesImplementation() const +{ + auto schemes = QNetworkAccessManager::supportedSchemesImplementation(); + schemes += QStringLiteral("mxc"); + return schemes; +} + +QUrl NetworkAccessManager::urlForRoomEvent(Room *room, const QString &eventId, const QString &mediaId) +{ + return QUrl(QStringLiteral("mxc:%1#%2/%3/%4").arg(mediaId, room->connection()->userId(), room->id(), eventId)); +} + +QUrl NetworkAccessManager::urlForFile(Connection *connection, const QString &mediaId) +{ + return QUrl(QStringLiteral("mxc:%1#%2").arg(mediaId, connection->userId())); +} \ No newline at end of file diff --git a/lib/networkaccessmanager.h b/lib/networkaccessmanager.h index 47729a1b..5d262f98 100644 --- a/lib/networkaccessmanager.h +++ b/lib/networkaccessmanager.h @@ -8,6 +8,8 @@ #include namespace Quotient { +class Room; +class Connection; class NetworkAccessManager : public QNetworkAccessManager { Q_OBJECT public: @@ -21,6 +23,10 @@ public: /** Get a pointer to the singleton */ static NetworkAccessManager* instance(); +public Q_SLOTS: + QStringList supportedSchemesImplementation() const; + QUrl urlForRoomEvent(Room *room, const QString &eventId, const QString &mediaId); + QUrl urlForFile(Connection *connection, const QString &mediaId); private: QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData = Q_NULLPTR) override; -- cgit v1.2.3 From 67186252eac4f3890d5abae31e74efee956b2f5d Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Sun, 5 Sep 2021 22:52:41 +0200 Subject: Create a NAM for each thread --- lib/networkaccessmanager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index e4132957..7368de7e 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "accountregistry.h" #include "mxcreply.h" #include "connection.h" @@ -52,8 +53,11 @@ static NetworkAccessManager* createNam() NetworkAccessManager* NetworkAccessManager::instance() { - static auto* nam = createNam(); - return nam; + static QThreadStorage storage; + if(!storage.hasLocalData()) { + storage.setLocalData(createNam()); + } + return storage.localData(); } NetworkAccessManager::~NetworkAccessManager() = default; -- cgit v1.2.3 From 6d3bc1667e084fa2fc7b2c547374d2c62a29e8df Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Tue, 7 Sep 2021 16:17:23 +0200 Subject: Fix showing non-animated Images --- lib/mxcreply.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/mxcreply.cpp b/lib/mxcreply.cpp index 49ebe603..f389ac85 100644 --- a/lib/mxcreply.cpp +++ b/lib/mxcreply.cpp @@ -23,6 +23,7 @@ MxcReply::MxcReply(QNetworkReply* reply) d->m_reply = reply; connect(d->m_reply, &QNetworkReply::finished, this, [this]() { setError(d->m_reply->error(), d->m_reply->errorString()); + setOpenMode(ReadOnly); Q_EMIT finished(); }); } @@ -34,6 +35,7 @@ MxcReply::MxcReply(QNetworkReply* reply, Room* room, const QString &eventId) d->m_reply = reply; connect(d->m_reply, &QNetworkReply::finished, this, [this, eventId]() { setError(d->m_reply->error(), d->m_reply->errorString()); + setOpenMode(ReadOnly); Q_EMIT finished(); }); } -- cgit v1.2.3 From 9e548e0625a819052cd10d5c4bf129dde649a6a4 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Thu, 9 Sep 2021 19:27:57 +0200 Subject: Straighten up file transfer cancellation There was a mess with fileTransferCancelled(); it was only emitted when a download (but not an upload) was cancelled; besides, in case of downloads a file transfer info structure was getting deleted whereas uploads left a file transfer in Cancelled status. This all now converges on: - fileTransferFailed() for both failures and cancellations (to simplify slot connection, and also to follow the practice in, e.g., Qt Network). - the file transfer info structure is kept around in Cancelled status, following the logic used for failures. There's no particular cleanup which may become a problem if one uploads and cancels many times (download file transfers are keyed to event ids, mitigating the problem); this will be fixed in another commit. Closes #503. Closes #504. --- lib/room.cpp | 18 ++++++++++++------ lib/room.h | 3 ++- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/room.cpp b/lib/room.cpp index 890da13d..c6cca2ea 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1708,6 +1708,12 @@ QString Room::retryMessage(const QString& txnId) return d->doSendEvent(it->event()); } +// Lambda defers actual tr() invocation to the moment when translations are +// initialised +const auto FileTransferCancelledMsg = [] { + return Room::tr("File transfer cancelled"); +}; + void Room::discardMessage(const QString& txnId) { auto it = std::find_if(d->unsyncedEvents.begin(), d->unsyncedEvents.end(), @@ -1722,7 +1728,7 @@ void Room::discardMessage(const QString& txnId) if (isJobPending(transferIt->job)) { transferIt->status = FileTransferInfo::Cancelled; transferIt->job->abandon(); - emit fileTransferFailed(txnId, tr("File upload cancelled")); + emit fileTransferFailed(txnId, FileTransferCancelledMsg()); } else if (transferIt->status == FileTransferInfo::Completed) { qCWarning(MAIN) << "File for transaction" << txnId @@ -1790,7 +1796,7 @@ QString Room::Private::doPostFile(RoomEventPtr&& msgEvent, const QUrl& localUrl) "cancelled"; } }); - connect(q, &Room::fileTransferCancelled, transferJob, + connect(q, &Room::fileTransferFailed, transferJob, [this, txnId](const QString& tId) { if (tId != txnId) return; @@ -2079,16 +2085,16 @@ void Room::downloadFile(const QString& eventId, const QUrl& localFilename) void Room::cancelFileTransfer(const QString& id) { - const auto it = d->fileTransfers.constFind(id); - if (it == d->fileTransfers.cend()) { + const auto it = d->fileTransfers.find(id); + if (it == d->fileTransfers.end()) { qCWarning(MAIN) << "No information on file transfer" << id << "in room" << d->id; return; } if (isJobPending(it->job)) it->job->abandon(); - d->fileTransfers.remove(id); - emit fileTransferCancelled(id); + it->status = FileTransferInfo::Cancelled; + emit fileTransferFailed(id, FileTransferCancelledMsg()); } void Room::Private::dropDuplicateEvents(RoomEvents& events) const diff --git a/lib/room.h b/lib/room.h index d3a7466d..4e55dbaf 100644 --- a/lib/room.h +++ b/lib/room.h @@ -712,7 +712,8 @@ Q_SIGNALS: void fileTransferProgress(QString id, qint64 progress, qint64 total); void fileTransferCompleted(QString id, QUrl localFile, QUrl mxcUrl); void fileTransferFailed(QString id, QString errorMessage = {}); - void fileTransferCancelled(QString id); + // fileTransferCancelled() is no more here; use fileTransferFailed() and + // check the transfer status instead void callEvent(Quotient::Room* room, const Quotient::RoomEvent* event); -- cgit v1.2.3 From c1015d78fc90972a87b02a7863a9148c446c94b1 Mon Sep 17 00:00:00 2001 From: Tobias Fella <9750016+TobiasFella@users.noreply.github.com> Date: Fri, 10 Sep 2021 17:36:11 +0200 Subject: Update lib/networkaccessmanager.cpp Co-authored-by: Alexey Rusakov --- lib/networkaccessmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index 7368de7e..9f423cc3 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -69,7 +69,7 @@ QNetworkReply* NetworkAccessManager::createRequest( const auto fragment = request.url().fragment(); const auto fragmentParts = fragment.split(QLatin1Char('/')); const auto mediaId = request.url().toString(QUrl::RemoveScheme | QUrl::RemoveFragment); - if(fragmentParts.size() == 3) { + if (fragmentParts.size() == 3) { auto connection = AccountRegistry::instance().get(fragmentParts[0]); if(!connection) { qWarning() << "Connection not found"; -- cgit v1.2.3 From 3b383a6dcb75531ca7efcaa4afa28b92dbe15e3e Mon Sep 17 00:00:00 2001 From: Tobias Fella <9750016+TobiasFella@users.noreply.github.com> Date: Fri, 10 Sep 2021 17:36:19 +0200 Subject: Update lib/networkaccessmanager.cpp Co-authored-by: Alexey Rusakov --- lib/networkaccessmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index 9f423cc3..710ade4e 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -53,7 +53,7 @@ static NetworkAccessManager* createNam() NetworkAccessManager* NetworkAccessManager::instance() { - static QThreadStorage storage; + static QThreadStorage storage; if(!storage.hasLocalData()) { storage.setLocalData(createNam()); } -- cgit v1.2.3 From 8dfa505066a03cc8450527699634fda71cbd8915 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Fri, 10 Sep 2021 17:55:20 +0200 Subject: Return a failed MxcReply on invalid requests --- lib/mxcreply.cpp | 15 +++++++++++++++ lib/mxcreply.h | 1 + lib/networkaccessmanager.cpp | 8 ++++---- 3 files changed, 20 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/mxcreply.cpp b/lib/mxcreply.cpp index f389ac85..7819367e 100644 --- a/lib/mxcreply.cpp +++ b/lib/mxcreply.cpp @@ -4,6 +4,7 @@ #include "mxcreply.h" #include +#include #include "connection.h" #include "room.h" #include "networkaccessmanager.h" @@ -40,6 +41,20 @@ MxcReply::MxcReply(QNetworkReply* reply, Room* room, const QString &eventId) }); } +MxcReply::MxcReply() +{ + QTimer::singleShot(0, this, [this](){ + setError(QNetworkReply::ProtocolInvalidOperationError, QStringLiteral("Invalid Request")); + setFinished(true); +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + Q_EMIT errorOccurred(QNetworkReply::ProtocolInvalidOperationError); +#else + Q_EMIT error(QNetworkReply::ProtocolInvalidOperationError); +#endif + Q_EMIT finished(); + }); +} + bool MxcReply::isSequential() const { return true; diff --git a/lib/mxcreply.h b/lib/mxcreply.h index 26dea2d0..ac3ac4f4 100644 --- a/lib/mxcreply.h +++ b/lib/mxcreply.h @@ -14,6 +14,7 @@ class MxcReply : public QNetworkReply public: MxcReply(QNetworkReply* reply, Room* room, const QString &eventId); MxcReply(QNetworkReply* reply); + MxcReply(); bool isSequential() const override; diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index 710ade4e..f37e26b6 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -73,12 +73,12 @@ QNetworkReply* NetworkAccessManager::createRequest( auto connection = AccountRegistry::instance().get(fragmentParts[0]); if(!connection) { qWarning() << "Connection not found"; - return nullptr; + return new MxcReply(); } auto room = connection->room(fragmentParts[1]); if(!room) { qWarning() << "Room not found"; - return nullptr; + return new MxcReply(); } QNetworkRequest r(request); r.setUrl(QUrl(QStringLiteral("%1/_matrix/media/r0/download/%2").arg(connection->homeserver().toString(), mediaId))); @@ -88,7 +88,7 @@ QNetworkReply* NetworkAccessManager::createRequest( auto connection = AccountRegistry::instance().get(fragment); if(!connection) { qWarning() << "Connection not found"; - return nullptr; + return new MxcReply(); } QNetworkRequest r(request); r.setUrl(QUrl(QStringLiteral("%1/_matrix/media/r0/download/%2").arg(connection->homeserver().toString(), mediaId))); @@ -96,7 +96,7 @@ QNetworkReply* NetworkAccessManager::createRequest( return new MxcReply(reply); } else { qWarning() << "Invalid request"; - return nullptr; + return new MxcReply(); } } auto reply = QNetworkAccessManager::createRequest(op, request, outgoingData); -- cgit v1.2.3 From 4106a073d03b4ba9176da24c6b169c5fc2c79fb4 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Fri, 10 Sep 2021 22:10:16 +0200 Subject: Percent-encode all the things --- lib/networkaccessmanager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index f37e26b6..dc1c139c 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -70,7 +70,7 @@ QNetworkReply* NetworkAccessManager::createRequest( const auto fragmentParts = fragment.split(QLatin1Char('/')); const auto mediaId = request.url().toString(QUrl::RemoveScheme | QUrl::RemoveFragment); if (fragmentParts.size() == 3) { - auto connection = AccountRegistry::instance().get(fragmentParts[0]); + auto connection = AccountRegistry::instance().get(QUrl::fromPercentEncoding(fragmentParts[0].toLatin1())); if(!connection) { qWarning() << "Connection not found"; return new MxcReply(); @@ -83,7 +83,7 @@ QNetworkReply* NetworkAccessManager::createRequest( QNetworkRequest r(request); r.setUrl(QUrl(QStringLiteral("%1/_matrix/media/r0/download/%2").arg(connection->homeserver().toString(), mediaId))); auto reply = createRequest(QNetworkAccessManager::GetOperation, r); - return new MxcReply(reply, room, fragmentParts[2]); + return new MxcReply(reply, room, QUrl::fromPercentEncoding(fragmentParts[2].toLatin1())); } else if(fragmentParts.size() == 1) { auto connection = AccountRegistry::instance().get(fragment); if(!connection) { @@ -113,10 +113,10 @@ QStringList NetworkAccessManager::supportedSchemesImplementation() const QUrl NetworkAccessManager::urlForRoomEvent(Room *room, const QString &eventId, const QString &mediaId) { - return QUrl(QStringLiteral("mxc:%1#%2/%3/%4").arg(mediaId, room->connection()->userId(), room->id(), eventId)); + return QUrl(QStringLiteral("mxc:%1#%2/%3/%4").arg(mediaId, QString(QUrl::toPercentEncoding(room->connection()->userId())), room->id(), QString(QUrl::toPercentEncoding(eventId)))); } QUrl NetworkAccessManager::urlForFile(Connection *connection, const QString &mediaId) { - return QUrl(QStringLiteral("mxc:%1#%2").arg(mediaId, connection->userId())); + return QUrl(QStringLiteral("mxc:%1#%2").arg(mediaId, QString(QUrl::toPercentEncoding(connection->userId())))); } \ No newline at end of file -- cgit v1.2.3 From df46414a4e16d608049610935aeabab222e06d72 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 10 Sep 2021 21:53:22 +0200 Subject: Add "quotient.network" logging category --- lib/logging.cpp | 1 + lib/logging.h | 1 + 2 files changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/logging.cpp b/lib/logging.cpp index ffcc851c..15eac69d 100644 --- a/lib/logging.cpp +++ b/lib/logging.cpp @@ -17,4 +17,5 @@ LOGGING_CATEGORY(E2EE, "quotient.e2ee") LOGGING_CATEGORY(JOBS, "quotient.jobs") LOGGING_CATEGORY(SYNCJOB, "quotient.jobs.sync") LOGGING_CATEGORY(THUMBNAILJOB, "quotient.jobs.thumbnail") +LOGGING_CATEGORY(NETWORK, "quotient.network") LOGGING_CATEGORY(PROFILER, "quotient.profiler") diff --git a/lib/logging.h b/lib/logging.h index 1d1394e8..7e0da975 100644 --- a/lib/logging.h +++ b/lib/logging.h @@ -17,6 +17,7 @@ Q_DECLARE_LOGGING_CATEGORY(E2EE) Q_DECLARE_LOGGING_CATEGORY(JOBS) Q_DECLARE_LOGGING_CATEGORY(SYNCJOB) Q_DECLARE_LOGGING_CATEGORY(THUMBNAILJOB) +Q_DECLARE_LOGGING_CATEGORY(NETWORK) Q_DECLARE_LOGGING_CATEGORY(PROFILER) namespace Quotient { -- cgit v1.2.3 From 2bf18a64d236c2364e12d4c2f1a9464cc6a2ebf9 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Fri, 10 Sep 2021 22:38:10 +0200 Subject: Move URL creation to Room/Connection; use query instead of fragment The query is easier to manipulate; and the original mxc URL is not used for the real network request anyway. --- lib/connection.cpp | 9 ++++ lib/connection.h | 2 + lib/networkaccessmanager.cpp | 97 ++++++++++++++++++++++++-------------------- lib/networkaccessmanager.h | 3 +- lib/room.cpp | 11 +++++ lib/room.h | 3 ++ 6 files changed, 80 insertions(+), 45 deletions(-) (limited to 'lib') diff --git a/lib/connection.cpp b/lib/connection.cpp index 222c3b71..51946b2f 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -836,6 +836,15 @@ inline auto splitMediaId(const QString& mediaId) return idParts; } +QUrl Connection::makeMediaUrl(QUrl mxcUrl) const +{ + Q_ASSERT(mxcUrl.scheme() == "mxc"); + QUrlQuery q(mxcUrl.query()); + q.addQueryItem(QStringLiteral("user_id"), userId()); + mxcUrl.setQuery(q); + return mxcUrl; +} + MediaThumbnailJob* Connection::getThumbnail(const QString& mediaId, QSize requestedSize, RunningPolicy policy) diff --git a/lib/connection.h b/lib/connection.h index ecbb1a19..1a6ca9b0 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -529,6 +529,8 @@ public Q_SLOTS: void stopSync(); QString nextBatchToken() const; + Q_INVOKABLE QUrl makeMediaUrl(QUrl mxcUrl) const; + virtual MediaThumbnailJob* getThumbnail(const QString& mediaId, QSize requestedSize, RunningPolicy policy = BackgroundRequest); diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index dc1c139c..3b0dc92b 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -3,24 +3,43 @@ #include "networkaccessmanager.h" -#include -#include -#include +#include "connection.h" +#include "room.h" #include "accountregistry.h" #include "mxcreply.h" -#include "connection.h" -#include "room.h" +#include +#include +#include +#include using namespace Quotient; class NetworkAccessManager::Private { public: + explicit Private(NetworkAccessManager* q) + : q(q) + {} + + QNetworkReply* createImplRequest(Operation op, + const QNetworkRequest& outerRequest, + Connection* connection) + { + Q_ASSERT(outerRequest.url().scheme() == "mxc"); + QNetworkRequest r(outerRequest); + r.setUrl(QUrl(QStringLiteral("%1/_matrix/media/r0/download/%2") + .arg(connection->homeserver().toString(), + outerRequest.url().authority() + + outerRequest.url().path()))); + return q->createRequest(op, r); + } + + NetworkAccessManager* q; QList ignoredSslErrors; }; NetworkAccessManager::NetworkAccessManager(QObject* parent) - : QNetworkAccessManager(parent), d(std::make_unique()) + : QNetworkAccessManager(parent), d(std::make_unique(this)) {} QList NetworkAccessManager::ignoredSslErrors() const @@ -54,6 +73,8 @@ static NetworkAccessManager* createNam() NetworkAccessManager* NetworkAccessManager::instance() { static QThreadStorage storage; + // FIXME: createNam() returns an object parented to + // QCoreApplication::instance() that lives in the main thread if(!storage.hasLocalData()) { storage.setLocalData(createNam()); } @@ -65,38 +86,38 @@ NetworkAccessManager::~NetworkAccessManager() = default; QNetworkReply* NetworkAccessManager::createRequest( Operation op, const QNetworkRequest& request, QIODevice* outgoingData) { - if(request.url().scheme() == QStringLiteral("mxc")) { - const auto fragment = request.url().fragment(); - const auto fragmentParts = fragment.split(QLatin1Char('/')); - const auto mediaId = request.url().toString(QUrl::RemoveScheme | QUrl::RemoveFragment); - if (fragmentParts.size() == 3) { - auto connection = AccountRegistry::instance().get(QUrl::fromPercentEncoding(fragmentParts[0].toLatin1())); - if(!connection) { - qWarning() << "Connection not found"; + const auto& mxcUrl = request.url(); + if (mxcUrl.scheme() == "mxc") { + const QUrlQuery query(mxcUrl.query()); + const auto accountId = query.queryItemValue(QStringLiteral("user_id")); + if (accountId.isEmpty()) { + // Using QSettings here because Quotient::NetworkSettings + // doesn't provide multithreading guarantees + static thread_local QSettings s; + if (!s.value("Network/allow_direct_media_requests").toBool()) { return new MxcReply(); } - auto room = connection->room(fragmentParts[1]); - if(!room) { - qWarning() << "Room not found"; + // TODO: Make the best effort with a direct unauthenticated request + // to the media server + } else { + auto* const connection = AccountRegistry::instance().get(accountId); + if (!connection) { + qCWarning(NETWORK) << "Connection not found"; return new MxcReply(); } - QNetworkRequest r(request); - r.setUrl(QUrl(QStringLiteral("%1/_matrix/media/r0/download/%2").arg(connection->homeserver().toString(), mediaId))); - auto reply = createRequest(QNetworkAccessManager::GetOperation, r); - return new MxcReply(reply, room, QUrl::fromPercentEncoding(fragmentParts[2].toLatin1())); - } else if(fragmentParts.size() == 1) { - auto connection = AccountRegistry::instance().get(fragment); - if(!connection) { - qWarning() << "Connection not found"; - return new MxcReply(); + const auto roomId = query.queryItemValue(QStringLiteral("room_id")); + if (!roomId.isEmpty()) { + auto room = connection->room(roomId); + if (!room) { + qCWarning(NETWORK) << "Room not found"; + return new MxcReply(); + } + return new MxcReply( + d->createImplRequest(op, request, connection), room, + query.queryItemValue(QStringLiteral("event_id"))); } - QNetworkRequest r(request); - r.setUrl(QUrl(QStringLiteral("%1/_matrix/media/r0/download/%2").arg(connection->homeserver().toString(), mediaId))); - auto reply = createRequest(QNetworkAccessManager::GetOperation, r); - return new MxcReply(reply); - } else { - qWarning() << "Invalid request"; - return new MxcReply(); + return new MxcReply( + d->createImplRequest(op, request, connection)); } } auto reply = QNetworkAccessManager::createRequest(op, request, outgoingData); @@ -110,13 +131,3 @@ QStringList NetworkAccessManager::supportedSchemesImplementation() const schemes += QStringLiteral("mxc"); return schemes; } - -QUrl NetworkAccessManager::urlForRoomEvent(Room *room, const QString &eventId, const QString &mediaId) -{ - return QUrl(QStringLiteral("mxc:%1#%2/%3/%4").arg(mediaId, QString(QUrl::toPercentEncoding(room->connection()->userId())), room->id(), QString(QUrl::toPercentEncoding(eventId)))); -} - -QUrl NetworkAccessManager::urlForFile(Connection *connection, const QString &mediaId) -{ - return QUrl(QStringLiteral("mxc:%1#%2").arg(mediaId, QString(QUrl::toPercentEncoding(connection->userId())))); -} \ No newline at end of file diff --git a/lib/networkaccessmanager.h b/lib/networkaccessmanager.h index 5d262f98..87bc12a1 100644 --- a/lib/networkaccessmanager.h +++ b/lib/networkaccessmanager.h @@ -25,8 +25,7 @@ public: public Q_SLOTS: QStringList supportedSchemesImplementation() const; - QUrl urlForRoomEvent(Room *room, const QString &eventId, const QString &mediaId); - QUrl urlForFile(Connection *connection, const QString &mediaId); + private: QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData = Q_NULLPTR) override; diff --git a/lib/room.cpp b/lib/room.cpp index 890da13d..72b37f62 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1116,6 +1116,17 @@ QList Room::directChatUsers() const return connection()->directChatUsers(this); } +QUrl Room::makeMediaUrl(const QString& eventId, const QUrl& mxcUrl) const +{ + auto url = connection()->makeMediaUrl(mxcUrl); + QUrlQuery q(url.query()); + Q_ASSERT(q.hasQueryItem("user_id")); + q.addQueryItem("room_id", id()); + q.addQueryItem("event_id", eventId); + url.setQuery(q); + return url; +} + QString safeFileName(QString rawName) { return rawName.replace(QRegularExpression("[/\\<>|\"*?:]"), "_"); diff --git a/lib/room.h b/lib/room.h index d3a7466d..9daca076 100644 --- a/lib/room.h +++ b/lib/room.h @@ -458,6 +458,9 @@ public: /// Get the list of users this room is a direct chat with QList directChatUsers() const; + Q_INVOKABLE QUrl makeMediaUrl(const QString& eventId, + const QUrl &mxcUrl) const; + Q_INVOKABLE QUrl urlToThumbnail(const QString& eventId) const; Q_INVOKABLE QUrl urlToDownload(const QString& eventId) const; -- cgit v1.2.3 From 4babd9b2f1ba1d8c8c58c2f728cc4875ecf144c7 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 11 Sep 2021 11:14:04 +0200 Subject: Don't parent NAM to QCoreApplication QThreadStorage accepts ownership over stored objects. --- lib/networkaccessmanager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index 3b0dc92b..d35b2ec8 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -59,7 +59,7 @@ void NetworkAccessManager::clearIgnoredSslErrors() static NetworkAccessManager* createNam() { - auto nam = new NetworkAccessManager(QCoreApplication::instance()); + auto nam = new NetworkAccessManager(); #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) // See #109; in newer Qt, bearer management is deprecated altogether NetworkAccessManager::connect(nam, @@ -73,8 +73,6 @@ static NetworkAccessManager* createNam() NetworkAccessManager* NetworkAccessManager::instance() { static QThreadStorage storage; - // FIXME: createNam() returns an object parented to - // QCoreApplication::instance() that lives in the main thread if(!storage.hasLocalData()) { storage.setLocalData(createNam()); } -- cgit v1.2.3 From 6597866ead7a3eb03cfcbbd99b547de1bb72867e Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 11 Sep 2021 13:05:40 +0200 Subject: Further tweaks to MxcReply - QNetworkReply::isSequential() already returns `true`, there's no need to overload it again. - Use `Q_SLOTS` instead of `slots` because it's an external library interface and clients may use other libraries using `slots` identifier; - Use `emit` instead of `Q_EMIT` because this is a part of internal implementation and if we ever use a library that has an `emit` identifier, a massive search-replace will be in order anyway. - Use `QMetaObject::invokeMethod()` with a queued connection as a clearer way to achieve the same goal as `QTimer::singleShot(0, ...)`. --- lib/mxcreply.cpp | 37 +++++++++++++++++-------------------- lib/mxcreply.h | 15 +++++++-------- 2 files changed, 24 insertions(+), 28 deletions(-) (limited to 'lib') diff --git a/lib/mxcreply.cpp b/lib/mxcreply.cpp index 7819367e..daa4af9a 100644 --- a/lib/mxcreply.cpp +++ b/lib/mxcreply.cpp @@ -3,12 +3,7 @@ #include "mxcreply.h" -#include -#include -#include "connection.h" #include "room.h" -#include "networkaccessmanager.h" -#include "events/stickerevent.h" using namespace Quotient; @@ -34,30 +29,32 @@ MxcReply::MxcReply(QNetworkReply* reply, Room* room, const QString &eventId) { reply->setParent(this); d->m_reply = reply; - connect(d->m_reply, &QNetworkReply::finished, this, [this, eventId]() { + connect(d->m_reply, &QNetworkReply::finished, this, [this, room, eventId]() { setError(d->m_reply->error(), d->m_reply->errorString()); setOpenMode(ReadOnly); - Q_EMIT finished(); + emit finished(); }); } -MxcReply::MxcReply() -{ - QTimer::singleShot(0, this, [this](){ - setError(QNetworkReply::ProtocolInvalidOperationError, QStringLiteral("Invalid Request")); - setFinished(true); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - Q_EMIT errorOccurred(QNetworkReply::ProtocolInvalidOperationError); +#define ERROR_SIGNAL errorOccurred #else - Q_EMIT error(QNetworkReply::ProtocolInvalidOperationError); +#define ERROR_SIGNAL error #endif - Q_EMIT finished(); - }); -} -bool MxcReply::isSequential() const +MxcReply::MxcReply() { - return true; + static const auto BadRequestPhrase = tr("Bad Request"); + QMetaObject::invokeMethod(this, [this]() { + setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 400); + setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, + BadRequestPhrase); + setError(QNetworkReply::ProtocolInvalidOperationError, + BadRequestPhrase); + setFinished(true); + emit ERROR_SIGNAL(QNetworkReply::ProtocolInvalidOperationError); + emit finished(); + }, Qt::QueuedConnection); } qint64 MxcReply::readData(char *data, qint64 maxSize) @@ -68,4 +65,4 @@ qint64 MxcReply::readData(char *data, qint64 maxSize) void MxcReply::abort() { d->m_reply->abort(); -} \ No newline at end of file +} diff --git a/lib/mxcreply.h b/lib/mxcreply.h index ac3ac4f4..efaf01c6 100644 --- a/lib/mxcreply.h +++ b/lib/mxcreply.h @@ -8,23 +8,22 @@ namespace Quotient { class Room; -class Connection; + class MxcReply : public QNetworkReply { public: - MxcReply(QNetworkReply* reply, Room* room, const QString &eventId); - MxcReply(QNetworkReply* reply); - MxcReply(); - - bool isSequential() const override; + explicit MxcReply(); + explicit MxcReply(QNetworkReply *reply); + MxcReply(QNetworkReply* reply, Room* room, const QString& eventId); -public slots: +public Q_SLOTS: void abort() override; protected: qint64 readData(char *data, qint64 maxSize) override; + private: class Private; std::unique_ptr d; }; -} \ No newline at end of file +} -- cgit v1.2.3 From 9da6b25a26403952e5a76b043076ba302c8d3c30 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sat, 11 Sep 2021 20:35:00 +0200 Subject: BaseJob: deprecate endpoint accessors; query returns an object To provide more room for internal changes in BaseJob. --- lib/jobs/basejob.cpp | 24 ++++++++++-------------- lib/jobs/basejob.h | 4 +++- 2 files changed, 13 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 6346db9d..85066024 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -194,12 +194,12 @@ QUrl BaseJob::requestUrl() const { return d->reply ? d->reply->url() : QUrl(); } bool BaseJob::isBackground() const { return d->inBackground; } -const QString& BaseJob::apiEndpoint() const { return d->apiEndpoint; } +//const QString& BaseJob::apiEndpoint() const { return d->apiUrl.path(); } -void BaseJob::setApiEndpoint(const QString& apiEndpoint) -{ - d->apiEndpoint = apiEndpoint; -} +//void BaseJob::setApiEndpoint(const QString& apiEndpoint) +//{ +// d->apiEndpoint = apiEndpoint; +//} const BaseJob::headers_t& BaseJob::requestHeaders() const { @@ -217,7 +217,7 @@ void BaseJob::setRequestHeaders(const BaseJob::headers_t& headers) d->requestHeaders = headers; } -const QUrlQuery& BaseJob::query() const { return d->requestQuery; } +QUrlQuery BaseJob::query() const { return d->requestQuery; } void BaseJob::setRequestQuery(const QUrlQuery& query) { @@ -262,14 +262,10 @@ QNetworkReply* BaseJob::reply() { return d->reply.data(); } QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QString& path, const QUrlQuery& query) { - auto pathBase = baseUrl.path(); - // QUrl::adjusted(QUrl::StripTrailingSlashes) doesn't help with root '/' - while (pathBase.endsWith('/')) - pathBase.chop(1); - if (!path.startsWith('/')) // Normally API files do start with '/' - pathBase.push_back('/'); // so this shouldn't be needed these days - - baseUrl.setPath(pathBase + path, QUrl::TolerantMode); + // Make sure the added path is relative even if it's not (the official + // API definitions have the leading slash though it's not really correct). + baseUrl = baseUrl.resolved( + QUrl(path.mid(path.startsWith('/')), QUrl::TolerantMode)); baseUrl.setQuery(query); return baseUrl; } diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 29443c53..663c121c 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -325,13 +325,15 @@ Q_SIGNALS: protected: using headers_t = QHash; + Q_DECL_DEPRECATED_X("Deprecated due to being unused") const QString& apiEndpoint() const; + Q_DECL_DEPRECATED_X("Deprecated due to being unused") void setApiEndpoint(const QString& apiEndpoint); const headers_t& requestHeaders() const; void setRequestHeader(const headers_t::key_type& headerName, const headers_t::mapped_type& headerValue); void setRequestHeaders(const headers_t& headers); - const QUrlQuery& query() const; + QUrlQuery query() const; void setRequestQuery(const QUrlQuery& query); const RequestData& requestData() const; void setRequestData(RequestData&& data); -- cgit v1.2.3 From 0209be8305aa38722a3d25593ae71fbb3ac05e52 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Sat, 11 Sep 2021 16:18:35 +0200 Subject: Add convenience function for activating encryption and fix EncryptionEvent constructor --- lib/events/encryptionevent.cpp | 8 ++++++++ lib/events/encryptionevent.h | 4 +--- lib/room.cpp | 9 +++++++++ lib/room.h | 6 ++++++ 4 files changed, 24 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/events/encryptionevent.cpp b/lib/events/encryptionevent.cpp index 490a5e8a..aa05a96e 100644 --- a/lib/events/encryptionevent.cpp +++ b/lib/events/encryptionevent.cpp @@ -39,6 +39,14 @@ EncryptionEventContent::EncryptionEventContent(const QJsonObject& json) , rotationPeriodMsgs(json[RotationPeriodMsgsKeyL].toInt(100)) {} +EncryptionEventContent::EncryptionEventContent(EncryptionType et) + : encryption(et) +{ + if(encryption != Undefined) { + algorithm = encryptionStrings[encryption]; + } +} + void EncryptionEventContent::fillJson(QJsonObject* o) const { Q_ASSERT(o); diff --git a/lib/events/encryptionevent.h b/lib/events/encryptionevent.h index 65ee4187..14439fcc 100644 --- a/lib/events/encryptionevent.h +++ b/lib/events/encryptionevent.h @@ -12,9 +12,7 @@ class EncryptionEventContent : public EventContent::Base { public: enum EncryptionType : size_t { MegolmV1AesSha2 = 0, Undefined }; - explicit EncryptionEventContent(EncryptionType et = Undefined) - : encryption(et) - {} + explicit EncryptionEventContent(EncryptionType et = Undefined); explicit EncryptionEventContent(const QJsonObject& json); EncryptionType encryption; diff --git a/lib/room.cpp b/lib/room.cpp index c6cca2ea..ced313a4 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -3009,3 +3009,12 @@ bool MemberSorter::operator()(User* u1, QStringView u2name) const return n1.localeAwareCompare(n2) < 0; } + +void Room::activateEncryption() +{ + if(usesEncryption()) { + qCWarning(E2EE) << "Room" << objectName() << "is already encrypted"; + return; + } + setState(EncryptionEventContent::MegolmV1AesSha2); +} diff --git a/lib/room.h b/lib/room.h index 4e55dbaf..c18d0b36 100644 --- a/lib/room.h +++ b/lib/room.h @@ -604,6 +604,12 @@ public Q_SLOTS: void answerCall(const QString& callId, const QString& sdp); void hangupCall(const QString& callId); + /** + * Activates encryption for this room. + * Warning: Cannot be undone + */ + void activateEncryption(); + Q_SIGNALS: /// Initial set of state events has been loaded /** -- cgit v1.2.3 From 2c61b463fa0608626a58aed79ebecb3bbd8c41d3 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 12 Sep 2021 04:36:13 +0200 Subject: NAM::createRequest(): more logging --- lib/networkaccessmanager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index d35b2ec8..57618329 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -93,6 +93,7 @@ QNetworkReply* NetworkAccessManager::createRequest( // doesn't provide multithreading guarantees static thread_local QSettings s; if (!s.value("Network/allow_direct_media_requests").toBool()) { + qCWarning(NETWORK) << "No connection specified"; return new MxcReply(); } // TODO: Make the best effort with a direct unauthenticated request @@ -100,14 +101,14 @@ QNetworkReply* NetworkAccessManager::createRequest( } else { auto* const connection = AccountRegistry::instance().get(accountId); if (!connection) { - qCWarning(NETWORK) << "Connection not found"; + qCWarning(NETWORK) << "Connection" << accountId << "not found"; return new MxcReply(); } const auto roomId = query.queryItemValue(QStringLiteral("room_id")); if (!roomId.isEmpty()) { auto room = connection->room(roomId); if (!room) { - qCWarning(NETWORK) << "Room not found"; + qCWarning(NETWORK) << "Room" << roomId << "not found"; return new MxcReply(); } return new MxcReply( -- cgit v1.2.3 From 77b69eb370e1cdbc33e44121f4f8483e19cad7d8 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 12 Sep 2021 04:37:08 +0200 Subject: MxcReply: make sure to create a Private object --- lib/mxcreply.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/mxcreply.cpp b/lib/mxcreply.cpp index daa4af9a..0b6643fc 100644 --- a/lib/mxcreply.cpp +++ b/lib/mxcreply.cpp @@ -10,13 +10,16 @@ using namespace Quotient; class MxcReply::Private { public: - QNetworkReply *m_reply = nullptr; + explicit Private(QNetworkReply* r = nullptr) + : m_reply(r) + {} + QNetworkReply* m_reply; }; MxcReply::MxcReply(QNetworkReply* reply) + : d(std::make_unique(reply)) { reply->setParent(this); - d->m_reply = reply; connect(d->m_reply, &QNetworkReply::finished, this, [this]() { setError(d->m_reply->error(), d->m_reply->errorString()); setOpenMode(ReadOnly); @@ -25,10 +28,9 @@ MxcReply::MxcReply(QNetworkReply* reply) } MxcReply::MxcReply(QNetworkReply* reply, Room* room, const QString &eventId) - : d(std::make_unique()) + : d(std::make_unique(reply)) { reply->setParent(this); - d->m_reply = reply; connect(d->m_reply, &QNetworkReply::finished, this, [this, room, eventId]() { setError(d->m_reply->error(), d->m_reply->errorString()); setOpenMode(ReadOnly); -- cgit v1.2.3 From 06a4fbb5c0ad0fadba1e5924f73d067850a78312 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 12 Sep 2021 04:38:23 +0200 Subject: Connection: update AccountRegistry Clients don't need to do it themselves. --- lib/connection.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/connection.cpp b/lib/connection.cpp index 51946b2f..4abf5097 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -13,6 +13,7 @@ #include "room.h" #include "settings.h" #include "user.h" +#include "accountregistry.h" // NB: since Qt 6, moc_connection.cpp needs Room and User fully defined #include "moc_connection.cpp" @@ -258,6 +259,7 @@ Connection::~Connection() { qCDebug(MAIN) << "deconstructing connection object for" << userId(); stopSync(); + AccountRegistry::instance().drop(this); } void Connection::resolveServer(const QString& mxid) @@ -441,6 +443,7 @@ void Connection::Private::completeSetup(const QString& mxId) qCDebug(MAIN) << "Using server" << data->baseUrl().toDisplayString() << "by user" << data->userId() << "from device" << data->deviceId(); + AccountRegistry::instance().add(q); #ifndef Quotient_E2EE_ENABLED qCWarning(E2EE) << "End-to-end encryption (E2EE) support is turned off."; #else // Quotient_E2EE_ENABLED -- cgit v1.2.3 From 59c9ca720093f2931c2eee1c0d5806d7e2e0c85f Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Mon, 13 Sep 2021 16:05:46 +0200 Subject: Add room types to RoomCreateEvent --- lib/events/roomcreateevent.cpp | 21 +++++++++++++++++++++ lib/events/roomcreateevent.h | 2 ++ lib/quotient_common.h | 10 ++++++++++ 3 files changed, 33 insertions(+) (limited to 'lib') diff --git a/lib/events/roomcreateevent.cpp b/lib/events/roomcreateevent.cpp index 6558bade..ff93041c 100644 --- a/lib/events/roomcreateevent.cpp +++ b/lib/events/roomcreateevent.cpp @@ -5,6 +5,22 @@ using namespace Quotient; +template <> +struct Quotient::JsonConverter { + static RoomType load(const QJsonValue& jv) + { + const auto& roomTypeString = jv.toString(); + for (auto it = RoomTypeStrings.begin(); it != RoomTypeStrings.end(); + ++it) + if (roomTypeString == *it) + return RoomType(it - RoomTypeStrings.begin()); + + if (!roomTypeString.isEmpty()) + qCWarning(EVENTS) << "Unknown Room Type: " << roomTypeString; + return RoomType::Undefined; + } +}; + bool RoomCreateEvent::isFederated() const { return fromJson(contentJson()["m.federate"_ls]); @@ -26,3 +42,8 @@ bool RoomCreateEvent::isUpgrade() const { return contentJson().contains("predecessor"_ls); } + +RoomType RoomCreateEvent::roomType() const +{ + return fromJson(contentJson()["type"_ls]); +} diff --git a/lib/events/roomcreateevent.h b/lib/events/roomcreateevent.h index 05e623ed..b3ad287c 100644 --- a/lib/events/roomcreateevent.h +++ b/lib/events/roomcreateevent.h @@ -4,6 +4,7 @@ #pragma once #include "stateevent.h" +#include "quotient_common.h" namespace Quotient { class RoomCreateEvent : public StateEventBase { @@ -24,6 +25,7 @@ public: QString version() const; Predecessor predecessor() const; bool isUpgrade() const; + RoomType roomType() const; }; REGISTER_EVENT_TYPE(RoomCreateEvent) } // namespace Quotient diff --git a/lib/quotient_common.h b/lib/quotient_common.h index bb2e6a6b..4444a111 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -88,6 +88,16 @@ enum UriResolveResult : short { }; Q_ENUM_NS(UriResolveResult) +enum RoomType { + Space, + Undefined, +}; +Q_ENUM_NS(RoomType); + +constexpr inline auto RoomTypeStrings = make_array( + "m.space" +); + } // namespace Quotient Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::MembershipMask) Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::JoinStates) -- cgit v1.2.3 From fe9425f313e7c172095ff9355743427337b7ea78 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Mon, 13 Sep 2021 19:14:19 +0200 Subject: Add the encryptedfile to the eventcontent --- lib/events/encryptedfile.h | 88 +++++++++++++++++++++++++++++++++++++++++ lib/events/eventcontent.cpp | 20 +++++++--- lib/events/eventcontent.h | 17 ++++++-- lib/events/roomavatarevent.h | 2 +- lib/events/roommessageevent.cpp | 8 ++-- 5 files changed, 121 insertions(+), 14 deletions(-) create mode 100644 lib/events/encryptedfile.h (limited to 'lib') diff --git a/lib/events/encryptedfile.h b/lib/events/encryptedfile.h new file mode 100644 index 00000000..24ac9de1 --- /dev/null +++ b/lib/events/encryptedfile.h @@ -0,0 +1,88 @@ +// SPDX-FileCopyrightText: 2021 Carl Schwan +// +// SPDX-License-Identifier: LGPl-2.1-or-later + +#pragma once + +#include "converters.h" + +namespace Quotient { +/** + * JSON Web Key object as specified in + * https://spec.matrix.org/unstable/client-server-api/#extensions-to-mroommessage-msgtypes + * The only currently relevant member is `k`, the rest needs to be set to the defaults specified in the spec. + */ +struct JWK +{ + Q_GADGET + Q_PROPERTY(QString kty MEMBER kty CONSTANT) + Q_PROPERTY(QStringList keyOps MEMBER keyOps CONSTANT) + Q_PROPERTY(QString alg MEMBER alg CONSTANT) + Q_PROPERTY(QString k MEMBER k CONSTANT) + Q_PROPERTY(bool ext MEMBER ext CONSTANT) + +public: + QString kty; + QStringList keyOps; + QString alg; + QString k; + bool ext; +}; + +struct EncryptedFile +{ + Q_GADGET + Q_PROPERTY(QUrl url MEMBER url CONSTANT) + Q_PROPERTY(JWK key MEMBER key CONSTANT) + Q_PROPERTY(QString iv MEMBER iv CONSTANT) + Q_PROPERTY(QHash hashes MEMBER hashes CONSTANT) + Q_PROPERTY(QString v MEMBER v CONSTANT) + +public: + QUrl url; + JWK key; + QString iv; + QHash hashes; + QString v; +}; + +template <> +struct JsonObjectConverter { + static void dumpTo(QJsonObject& jo, const EncryptedFile& pod) + { + addParam<>(jo, QStringLiteral("url"), pod.url); + addParam<>(jo, QStringLiteral("key"), pod.key); + addParam<>(jo, QStringLiteral("iv"), pod.iv); + addParam<>(jo, QStringLiteral("hashes"), pod.hashes); + addParam<>(jo, QStringLiteral("v"), pod.v); + } + static void fillFrom(const QJsonObject& jo, EncryptedFile& pod) + { + fromJson(jo.value("url"_ls), pod.url); + fromJson(jo.value("key"_ls), pod.key); + fromJson(jo.value("iv"_ls), pod.iv); + fromJson(jo.value("hashes"_ls), pod.hashes); + fromJson(jo.value("v"_ls), pod.v); + } +}; + +template <> +struct JsonObjectConverter { + static void dumpTo(QJsonObject& jo, const JWK& pod) + { + addParam<>(jo, QStringLiteral("kty"), pod.kty); + addParam<>(jo, QStringLiteral("key_ops"), pod.keyOps); + addParam<>(jo, QStringLiteral("alg"), pod.alg); + addParam<>(jo, QStringLiteral("k"), pod.k); + addParam<>(jo, QStringLiteral("ext"), pod.ext); + } + static void fillFrom(const QJsonObject& jo, JWK& pod) + { + fromJson(jo.value("kty"_ls), pod.kty); + fromJson(jo.value("key_ops"_ls), pod.keyOps); + fromJson(jo.value("alg"_ls), pod.alg); + fromJson(jo.value("k"_ls), pod.k); + fromJson(jo.value("ext"_ls), pod.ext); + } +}; +} // namespace Quotient diff --git a/lib/events/eventcontent.cpp b/lib/events/eventcontent.cpp index 1f28f195..22878d4c 100644 --- a/lib/events/eventcontent.cpp +++ b/lib/events/eventcontent.cpp @@ -30,11 +30,12 @@ FileInfo::FileInfo(const QFileInfo &fi) } FileInfo::FileInfo(QUrl u, qint64 payloadSize, const QMimeType& mimeType, - QString originalFilename) + Omittable file, QString originalFilename) : mimeType(mimeType) , url(move(u)) , payloadSize(payloadSize) , originalName(move(originalFilename)) + , file(file) { if (!isValid()) qCWarning(MESSAGES) @@ -44,6 +45,7 @@ FileInfo::FileInfo(QUrl u, qint64 payloadSize, const QMimeType& mimeType, } FileInfo::FileInfo(QUrl mxcUrl, const QJsonObject& infoJson, + const Omittable &file, QString originalFilename) : originalInfoJson(infoJson) , mimeType( @@ -51,7 +53,11 @@ FileInfo::FileInfo(QUrl mxcUrl, const QJsonObject& infoJson, , url(move(mxcUrl)) , payloadSize(fromJson(infoJson["size"_ls])) , originalName(move(originalFilename)) + , file(file) { + if(url.isEmpty() && file.has_value()) { + url = file->url; + } if (!mimeType.isValid()) mimeType = QMimeDatabase().mimeTypeForData(QByteArray()); } @@ -76,14 +82,15 @@ ImageInfo::ImageInfo(const QFileInfo& fi, QSize imageSize) {} ImageInfo::ImageInfo(const QUrl& mxcUrl, qint64 fileSize, const QMimeType& type, - QSize imageSize, const QString& originalFilename) - : FileInfo(mxcUrl, fileSize, type, originalFilename) + QSize imageSize, const Omittable &file, const QString& originalFilename) + : FileInfo(mxcUrl, fileSize, type, file, originalFilename) , imageSize(imageSize) {} ImageInfo::ImageInfo(const QUrl& mxcUrl, const QJsonObject& infoJson, + const Omittable &file, const QString& originalFilename) - : FileInfo(mxcUrl, infoJson, originalFilename) + : FileInfo(mxcUrl, infoJson, file, originalFilename) , imageSize(infoJson["w"_ls].toInt(), infoJson["h"_ls].toInt()) {} @@ -96,9 +103,10 @@ void ImageInfo::fillInfoJson(QJsonObject* infoJson) const infoJson->insert(QStringLiteral("h"), imageSize.height()); } -Thumbnail::Thumbnail(const QJsonObject& infoJson) +Thumbnail::Thumbnail(const QJsonObject& infoJson, const Omittable &file) : ImageInfo(QUrl(infoJson["thumbnail_url"_ls].toString()), - infoJson["thumbnail_info"_ls].toObject()) + infoJson["thumbnail_info"_ls].toObject(), + file) {} void Thumbnail::fillInfoJson(QJsonObject* infoJson) const diff --git a/lib/events/eventcontent.h b/lib/events/eventcontent.h index 40ec3a49..f609a603 100644 --- a/lib/events/eventcontent.h +++ b/lib/events/eventcontent.h @@ -12,6 +12,8 @@ #include #include +#include "encryptedfile.h" + class QFileInfo; namespace Quotient { @@ -80,8 +82,10 @@ namespace EventContent { explicit FileInfo(const QFileInfo& fi); explicit FileInfo(QUrl mxcUrl, qint64 payloadSize = -1, const QMimeType& mimeType = {}, + Omittable file = none, QString originalFilename = {}); FileInfo(QUrl mxcUrl, const QJsonObject& infoJson, + const Omittable &file, QString originalFilename = {}); bool isValid() const; @@ -103,6 +107,7 @@ namespace EventContent { QUrl url; qint64 payloadSize; QString originalName; + Omittable file = none; }; template @@ -122,8 +127,10 @@ namespace EventContent { explicit ImageInfo(const QFileInfo& fi, QSize imageSize = {}); explicit ImageInfo(const QUrl& mxcUrl, qint64 fileSize = -1, const QMimeType& type = {}, QSize imageSize = {}, + const Omittable &file = none, const QString& originalFilename = {}); ImageInfo(const QUrl& mxcUrl, const QJsonObject& infoJson, + const Omittable &encryptedFile, const QString& originalFilename = {}); void fillInfoJson(QJsonObject* infoJson) const; @@ -142,7 +149,7 @@ namespace EventContent { class Thumbnail : public ImageInfo { public: Thumbnail() = default; // Allow empty thumbnails - Thumbnail(const QJsonObject& infoJson); + Thumbnail(const QJsonObject& infoJson, const Omittable &file = none); Thumbnail(const ImageInfo& info) : ImageInfo(info) {} using ImageInfo::ImageInfo; @@ -182,7 +189,7 @@ namespace EventContent { explicit UrlBasedContent(const QJsonObject& json) : TypedBase(json) , InfoT(QUrl(json["url"].toString()), json["info"].toObject(), - json["filename"].toString()) + fromJson>(json["file"]), json["filename"].toString()) { // A small hack to facilitate links creation in QML. originalJson.insert("mediaId", InfoT::mediaId()); @@ -196,7 +203,11 @@ namespace EventContent { void fillJson(QJsonObject* json) const override { Q_ASSERT(json); - json->insert("url", InfoT::url.toString()); + if (!InfoT::file.has_value()) { + json->insert("url", InfoT::url.toString()); + } else { + json->insert("file", Quotient::toJson(*InfoT::file)); + } if (!InfoT::originalName.isEmpty()) json->insert("filename", InfoT::originalName); json->insert("info", toInfoJson(*this)); diff --git a/lib/events/roomavatarevent.h b/lib/events/roomavatarevent.h index 3fa11a0f..8618ba31 100644 --- a/lib/events/roomavatarevent.h +++ b/lib/events/roomavatarevent.h @@ -25,7 +25,7 @@ public: const QSize& imageSize = {}, const QString& originalFilename = {}) : RoomAvatarEvent(EventContent::ImageContent { - mxcUrl, fileSize, mimeType, imageSize, originalFilename }) + mxcUrl, fileSize, mimeType, imageSize, none, originalFilename }) {} QUrl url() const { return content().url; } diff --git a/lib/events/roommessageevent.cpp b/lib/events/roommessageevent.cpp index 71f85363..9b46594e 100644 --- a/lib/events/roommessageevent.cpp +++ b/lib/events/roommessageevent.cpp @@ -145,21 +145,21 @@ TypedBase* contentFromFile(const QFileInfo& file, bool asGenericFile) auto mimeTypeName = mimeType.name(); if (mimeTypeName.startsWith("image/")) return new ImageContent(localUrl, file.size(), mimeType, - QImageReader(filePath).size(), + QImageReader(filePath).size(), none, file.fileName()); // duration can only be obtained asynchronously and can only be reliably // done by starting to play the file. Left for a future implementation. if (mimeTypeName.startsWith("video/")) return new VideoContent(localUrl, file.size(), mimeType, - QMediaResource(localUrl).resolution(), + QMediaResource(localUrl).resolution(), none, file.fileName()); if (mimeTypeName.startsWith("audio/")) - return new AudioContent(localUrl, file.size(), mimeType, + return new AudioContent(localUrl, file.size(), mimeType, none, file.fileName()); } - return new FileContent(localUrl, file.size(), mimeType, file.fileName()); + return new FileContent(localUrl, file.size(), mimeType, none, file.fileName()); } RoomMessageEvent::RoomMessageEvent(const QString& plainBody, -- cgit v1.2.3 From 92024f20fd8cfe4adb586b1d477969e45ba9ab4d Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 28 Sep 2021 08:41:06 +0200 Subject: SyncData: drop a shortcut that led to ignoring invites Fixes #510. --- lib/syncdata.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/syncdata.cpp b/lib/syncdata.cpp index d3c270b5..4edc9564 100644 --- a/lib/syncdata.cpp +++ b/lib/syncdata.cpp @@ -173,12 +173,7 @@ void SyncData::parseJson(const QJsonObject& json, const QString& baseDir) auto rooms = json.value("rooms"_ls).toObject(); auto totalRooms = 0; auto totalEvents = 0; - // The first comparison shortcuts the loop when not all states are there - // in the response (anything except "join" is only occasional, and "join" - // intentionally comes first in the enum). - for (size_t i = 0; - static_cast(i) < rooms.size() && i < JoinStateStrings.size(); ++i) - { + for (size_t i = 0; i < JoinStateStrings.size(); ++i) { // This assumes that MemberState values go over powers of 2: 1,2,4,... const auto joinState = JoinState(1U << i); const auto rs = rooms.value(JoinStateStrings[i]).toObject(); -- cgit v1.2.3 From 4c3efb82b9f47ca92973089413da994619ddeb5c Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 03:18:39 +0200 Subject: AccountRegistry: minor code cleanup --- lib/accountregistry.cpp | 5 ++--- lib/accountregistry.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/accountregistry.cpp b/lib/accountregistry.cpp index 3a022f14..a292ed45 100644 --- a/lib/accountregistry.cpp +++ b/lib/accountregistry.cpp @@ -36,8 +36,7 @@ bool AccountRegistry::contains(Connection *c) const return m_accounts.contains(c); } -AccountRegistry::AccountRegistry() -{} +AccountRegistry::AccountRegistry() = default; QVariant AccountRegistry::data(const QModelIndex &index, int role) const { @@ -95,4 +94,4 @@ Connection* AccountRegistry::get(const QString& userId) } } return nullptr; -} \ No newline at end of file +} diff --git a/lib/accountregistry.h b/lib/accountregistry.h index e87da3e8..5efda459 100644 --- a/lib/accountregistry.h +++ b/lib/accountregistry.h @@ -42,4 +42,4 @@ private: QVector m_accounts; }; -} \ No newline at end of file +} -- cgit v1.2.3 From bd71b075e699ab4dda92d72bac77cbfeb6217625 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 3 Oct 2021 19:43:03 +0200 Subject: prettyPrint(): tighten up Matrix identifier regex It was too permissive on characters before the identifier and also allowed the domain name to start on dash, which should not occur. Closes #512. --- lib/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/util.cpp b/lib/util.cpp index 3de1d169..8067f561 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -44,7 +44,7 @@ void Quotient::linkifyUrls(QString& htmlEscapedText) // https://matrix.org/docs/spec/appendices.html#identifier-grammar static const QRegularExpression MxIdRegExp( QStringLiteral( - R"((^|[^<>/])([!#@][-a-z0-9_=#/.]{1,252}:(?:\w|\.|-)+\.\w+(?::\d{1,5})?))"), + R"((^|[][[:space:](){}`'";])([!#@][-a-z0-9_=#/.]{1,252}:\w(?:\w|\.|-)*\.\w+(?::\d{1,5})?))"), RegExpOptions); Q_ASSERT(FullUrlRegExp.isValid() && EmailAddressRegExp.isValid() && MxIdRegExp.isValid()); -- cgit v1.2.3 From c49de691291147233f24c9db17c0c1a3e2b73dde Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 09:53:53 +0200 Subject: Further tighten the linkifier in prettyPrint() --- lib/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/util.cpp b/lib/util.cpp index 8067f561..993152dd 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -33,7 +33,7 @@ void Quotient::linkifyUrls(QString& htmlEscapedText) // comma or dot static const QRegularExpression FullUrlRegExp( QStringLiteral( - R"(\b((www\.(?!\.)(?!(\w|\.|-)+@)|(https?|ftp|magnet|matrix):(//)?)(&(?![lg]t;)|[^&\s<>'"])+(&(?![lg]t;)|[^&!,.\s<>'"\]):])))"), + R"(\b((www\.(?!\.)(?!(\w|\.|-)+@)|(https?|ftp):(//)?\w|(magnet|matrix):)(&(?![lg]t;)|[^&\s<>'"])+(&(?![lg]t;)|[^&!,.\s<>'"\]):])))"), RegExpOptions); // email address: // [word chars, dots or dashes]@[word chars, dots or dashes].[word chars] -- cgit v1.2.3 From 73c1c8747b0c00524239724bb7cf00776448c5c7 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 09:54:45 +0200 Subject: quotient_common.h: remove a stray semicolon --- lib/quotient_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/quotient_common.h b/lib/quotient_common.h index 4444a111..13bf7246 100644 --- a/lib/quotient_common.h +++ b/lib/quotient_common.h @@ -92,7 +92,7 @@ enum RoomType { Space, Undefined, }; -Q_ENUM_NS(RoomType); +Q_ENUM_NS(RoomType) constexpr inline auto RoomTypeStrings = make_array( "m.space" -- cgit v1.2.3 From c16813c5209f0421ec773a98cf935a2eb2ea3d7c Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 11:05:10 +0200 Subject: Move away wrap_in_function to private interface This has always been merely a workaround to enable connectUntil/connectSingleShot and was never intended to be used elsewhere, let alone in clients. --- lib/qt_connection_util.h | 17 ++++++++++++++--- lib/util.h | 12 ------------ 2 files changed, 14 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/qt_connection_util.h b/lib/qt_connection_util.h index c6fa037a..9370d2eb 100644 --- a/lib/qt_connection_util.h +++ b/lib/qt_connection_util.h @@ -73,6 +73,17 @@ namespace _impl { }), connType); } + + // TODO: get rid of it as soon as Apple Clang gets proper deduction guides + // for std::function<> + // ...or consider using QtPrivate magic used by QObject::connect() + // ...for inspiration, also check a possible std::not_fn implementation + // at https://en.cppreference.com/w/cpp/utility/functional/not_fn + template + inline auto wrap_in_function(FnT&& f) + { + return typename function_traits::function_type(std::forward(f)); + } } // namespace _impl /*! \brief Create a connection that self-disconnects when its "slot" returns true @@ -90,7 +101,7 @@ inline auto connectUntil(SenderT* sender, SignalT signal, ContextT* context, const FunctorT& slot, Qt::ConnectionType connType = Qt::AutoConnection) { - return _impl::connectUntil(sender, signal, context, wrap_in_function(slot), + return _impl::connectUntil(sender, signal, context, _impl::wrap_in_function(slot), connType); } @@ -101,7 +112,7 @@ inline auto connectSingleShot(SenderT* sender, SignalT signal, Qt::ConnectionType connType = Qt::AutoConnection) { return _impl::connectSingleShot( - sender, signal, context, wrap_in_function(slot), connType); + sender, signal, context, _impl::wrap_in_function(slot), connType); } // Specialisation for usual Qt slots passed as pointers-to-members. @@ -114,7 +125,7 @@ inline auto connectSingleShot(SenderT* sender, SignalT signal, { // TODO: when switching to C++20, use std::bind_front() instead return _impl::connectSingleShot(sender, signal, receiver, - wrap_in_function( + _impl::wrap_in_function( [receiver, slot](const ArgTs&... args) { (receiver->*slot)(args...); }), diff --git a/lib/util.h b/lib/util.h index 5bfe6841..c6171b91 100644 --- a/lib/util.h +++ b/lib/util.h @@ -219,18 +219,6 @@ template using fn_arg_t = std::tuple_element_t::arg_types>; -// TODO: get rid of it as soon as Apple Clang gets proper deduction guides -// for std::function<> -// ...or consider using QtPrivate magic used by QObject::connect() -// since wrap_in_function() is actually made for qt_connection_util.h -// ...for inspiration, also check a possible std::not_fn implementation at -// https://en.cppreference.com/w/cpp/utility/functional/not_fn -template -inline auto wrap_in_function(FnT&& f) -{ - return typename function_traits::function_type(std::forward(f)); -} - inline constexpr auto operator"" _ls(const char* s, std::size_t size) { return QLatin1String(s, int(size)); -- cgit v1.2.3 From 677c73263f434d1564695a8128d75fefd1a7b50b Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 11:06:05 +0200 Subject: Drop old compatibility code libQuotient 0.7 really requires Qt 5.12, nothing earlier will work. --- lib/qt_connection_util.h | 5 ----- lib/util.cpp | 3 --- 2 files changed, 8 deletions(-) (limited to 'lib') diff --git a/lib/qt_connection_util.h b/lib/qt_connection_util.h index 9370d2eb..ffefb2a2 100644 --- a/lib/qt_connection_util.h +++ b/lib/qt_connection_util.h @@ -19,12 +19,7 @@ namespace _impl { decorated_slot_tt decoratedSlot, Qt::ConnectionType connType) { - // See https://bugreports.qt.io/browse/QTBUG-60339 -#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) - auto pc = std::make_shared(); -#else auto pc = std::make_unique(); -#endif auto& c = *pc; // Resolve a reference before pc is moved to lambda // Perfect forwarding doesn't work through signal-slot connections - diff --git a/lib/util.cpp b/lib/util.cpp index 993152dd..2dfb09a6 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -14,9 +14,6 @@ static const auto RegExpOptions = QRegularExpression::CaseInsensitiveOption -#if QT_VERSION < QT_VERSION_CHECK(5, 12, 0) - | QRegularExpression::OptimizeOnFirstUsageOption // Default since 5.12 -#endif | QRegularExpression::UseUnicodePropertiesOption; // Converts all that looks like a URL into HTML links -- cgit v1.2.3 From df5606ebd360d753b6261133254408aadbbb7f7f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 11:07:47 +0200 Subject: Make connectSingleShot() a tiny wrapper on Qt 6 Qt 6 has Qt::SingleShotConnection; connectSingleShot remains just for the sake of compatibility across Qt 5 and Qt 6. If you target Qt 6 only, feel free to use the Qt facility directly. --- lib/qt_connection_util.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/qt_connection_util.h b/lib/qt_connection_util.h index ffefb2a2..46294499 100644 --- a/lib/qt_connection_util.h +++ b/lib/qt_connection_util.h @@ -106,6 +106,11 @@ inline auto connectSingleShot(SenderT* sender, SignalT signal, ContextT* context, const FunctorT& slot, Qt::ConnectionType connType = Qt::AutoConnection) { +#if QT_VERSION_MAJOR >= 6 + return QObject::connect(sender, signal, context, slot, + Qt::ConnectionType(connType + | Qt::SingleShotConnection)); +#else return _impl::connectSingleShot( sender, signal, context, _impl::wrap_in_function(slot), connType); } @@ -125,6 +130,7 @@ inline auto connectSingleShot(SenderT* sender, SignalT signal, (receiver->*slot)(args...); }), connType); +#endif } /*! \brief A guard pointer that disconnects an interested object upon destruction -- cgit v1.2.3 From 96f31d7d8ed1c9ab905c24ac039079aea622f4dc Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 18:39:21 +0200 Subject: BaseJob: percent-encode variable path parts This is meant to spare clients from having to percent-encode room aliases, v3 event ids etc. that happen to hit the endpoint path. It is unfair to expect clients to do that since they are not supposed to care about the shape of CS API, which parameter should be encoded in which way. The trick (together with the slightly updated GTAD configuration) is to percent-encode parts that happen to be QStrings and not `const char[]`'s while passing all constant parts as plain C character literals. This also allows to make it more certain that the path is correctly encoded by passing and storing QByteArray's wherever the path is already encoded, and only use QStrings (next to const char arrays) before that. Since the change alters the API contract (even if that contract was crappy), some crude detection of percent-encoded stuff on input is inserted; if input is already percent-encoded, a warning is put to the logs, alerting developers about the change. --- lib/jobs/basejob.cpp | 51 +++++++++++++++++++++++++++++++++++---------------- lib/jobs/basejob.h | 21 ++++++++++++++++++--- lib/jobs/syncjob.cpp | 2 +- 3 files changed, 54 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 85066024..73762e4f 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -71,7 +71,7 @@ public: // Using an idiom from clang-tidy: // http://clang.llvm.org/extra/clang-tidy/checks/modernize-pass-by-value.html - Private(HttpVerb v, QString endpoint, const QUrlQuery& q, + Private(HttpVerb v, QByteArray endpoint, const QUrlQuery& q, RequestData&& data, bool nt) : verb(v) , apiEndpoint(std::move(endpoint)) @@ -106,7 +106,7 @@ public: // Contents for the network request HttpVerb verb; - QString apiEndpoint; + QByteArray apiEndpoint; QHash requestHeaders; QUrlQuery requestQuery; RequestData requestData; @@ -166,14 +166,36 @@ public: } }; -BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, +inline bool isHex(QChar c) +{ + return c.isDigit() || (c >= u'A' && c <= u'F') || (c >= u'a' && c <= u'f'); +} + +QByteArray BaseJob::encodeIfParam(const QString& paramPart) +{ + const auto percentIndex = paramPart.indexOf('%'); + if (percentIndex != -1 && paramPart.size() > percentIndex + 2 + && isHex(paramPart[percentIndex + 1]) + && isHex(paramPart[percentIndex + 2])) { + qCWarning(JOBS) + << "Developers, upfront percent-encoding of job parameters is " + "deprecated since libQuotient 0.7; the string involved is" + << paramPart; + return QUrl(paramPart, QUrl::TolerantMode).toEncoded(); + } + return QUrl::toPercentEncoding(paramPart); +} + +BaseJob::BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint, bool needsToken) - : BaseJob(verb, name, endpoint, QUrlQuery {}, RequestData {}, needsToken) + : BaseJob(verb, name, std::move(endpoint), QUrlQuery {}, RequestData {}, + needsToken) {} -BaseJob::BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, +BaseJob::BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint, const QUrlQuery& query, RequestData&& data, bool needsToken) - : d(new Private(verb, endpoint, query, std::move(data), needsToken)) + : d(new Private(verb, std::move(endpoint), query, std::move(data), + needsToken)) { setObjectName(name); connect(&d->timer, &QTimer::timeout, this, &BaseJob::timeout); @@ -194,13 +216,6 @@ QUrl BaseJob::requestUrl() const { return d->reply ? d->reply->url() : QUrl(); } bool BaseJob::isBackground() const { return d->inBackground; } -//const QString& BaseJob::apiEndpoint() const { return d->apiUrl.path(); } - -//void BaseJob::setApiEndpoint(const QString& apiEndpoint) -//{ -// d->apiEndpoint = apiEndpoint; -//} - const BaseJob::headers_t& BaseJob::requestHeaders() const { return d->requestHeaders; @@ -259,13 +274,17 @@ const QNetworkReply* BaseJob::reply() const { return d->reply.data(); } QNetworkReply* BaseJob::reply() { return d->reply.data(); } -QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QString& path, +QUrl BaseJob::makeRequestUrl(QUrl baseUrl, const QByteArray& encodedPath, const QUrlQuery& query) { // Make sure the added path is relative even if it's not (the official // API definitions have the leading slash though it's not really correct). - baseUrl = baseUrl.resolved( - QUrl(path.mid(path.startsWith('/')), QUrl::TolerantMode)); + const auto pathUrl = + QUrl::fromEncoded(encodedPath.mid(encodedPath.startsWith('/')), + QUrl::StrictMode); + Q_ASSERT_X(pathUrl.isValid(), __FUNCTION__, + qPrintable(pathUrl.errorString())); + baseUrl = baseUrl.resolved(pathUrl); baseUrl.setQuery(query); return baseUrl; } diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 663c121c..81455307 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -9,6 +9,7 @@ #include "../converters.h" #include +#include class QNetworkReply; class QSslError; @@ -23,6 +24,14 @@ class BaseJob : public QObject { Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT) Q_PROPERTY(int maxRetries READ maxRetries WRITE setMaxRetries) Q_PROPERTY(int statusCode READ error NOTIFY statusChanged) + + static QByteArray encodeIfParam(const QString& paramPart); + template + static inline auto encodeIfParam(const char (&constPart)[N]) + { + return constPart; + } + public: /*! The status code of a job * @@ -70,6 +79,12 @@ public: }; Q_ENUM(StatusCode) + template + static QByteArray makePath(StrTs&&... parts) + { + return (QByteArray() % ... % encodeIfParam(parts)); + } + using Data #ifndef Q_CC_MSVC Q_DECL_DEPRECATED_X("Use Quotient::RequestData instead") @@ -124,9 +139,9 @@ public: }; public: - BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, + BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint, bool needsToken = true); - BaseJob(HttpVerb verb, const QString& name, const QString& endpoint, + BaseJob(HttpVerb verb, const QString& name, QByteArray endpoint, const QUrlQuery& query, RequestData&& data = {}, bool needsToken = true); @@ -352,7 +367,7 @@ protected: * The function ensures exactly one '/' between the path component of * \p baseUrl and \p path. The query component of \p baseUrl is ignored. */ - static QUrl makeRequestUrl(QUrl baseUrl, const QString& path, + static QUrl makeRequestUrl(QUrl baseUrl, const QByteArray &encodedPath, const QUrlQuery& query = {}); /*! Prepares the job for execution diff --git a/lib/jobs/syncjob.cpp b/lib/jobs/syncjob.cpp index 59a34ef3..9b1b46f0 100644 --- a/lib/jobs/syncjob.cpp +++ b/lib/jobs/syncjob.cpp @@ -10,7 +10,7 @@ static size_t jobId = 0; SyncJob::SyncJob(const QString& since, const QString& filter, int timeout, const QString& presence) : BaseJob(HttpVerb::Get, QStringLiteral("SyncJob-%1").arg(++jobId), - QStringLiteral("_matrix/client/r0/sync")) + "_matrix/client/r0/sync") { setLoggingCategory(SYNCJOB); QUrlQuery query; -- cgit v1.2.3 From 1fd25fe944b67c55435ed4d4d8fd1cbb0989bb5f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 18:40:48 +0200 Subject: Regenerate CS API files upon the previous commit --- lib/csapi/account-data.cpp | 28 ++++++++-------- lib/csapi/admin.cpp | 8 ++--- lib/csapi/administrative_contact.cpp | 27 +++++++-------- lib/csapi/appservice_room_directory.cpp | 6 ++-- lib/csapi/banning.cpp | 7 ++-- lib/csapi/capabilities.cpp | 9 ++--- lib/csapi/content-repo.cpp | 41 ++++++++++------------- lib/csapi/create_room.cpp | 4 +-- lib/csapi/cross_signing.cpp | 7 ++-- lib/csapi/device_management.cpp | 19 +++++------ lib/csapi/directory.cpp | 26 ++++++--------- lib/csapi/event_context.cpp | 11 +++--- lib/csapi/filter.cpp | 13 +++----- lib/csapi/inviting.cpp | 5 +-- lib/csapi/joining.cpp | 6 ++-- lib/csapi/keys.cpp | 14 ++++---- lib/csapi/kicking.cpp | 4 +-- lib/csapi/knocking.cpp | 4 +-- lib/csapi/leaving.cpp | 12 +++---- lib/csapi/list_joined_rooms.cpp | 9 ++--- lib/csapi/list_public_rooms.cpp | 20 +++++------ lib/csapi/login.cpp | 9 ++--- lib/csapi/logout.cpp | 14 +++----- lib/csapi/message_pagination.cpp | 7 ++-- lib/csapi/notifications.cpp | 8 ++--- lib/csapi/openid.cpp | 6 ++-- lib/csapi/peeking_events.cpp | 7 ++-- lib/csapi/presence.cpp | 12 +++---- lib/csapi/profile.cpp | 28 ++++++---------- lib/csapi/pusher.cpp | 9 ++--- lib/csapi/pushrules.cpp | 59 +++++++++++++++------------------ lib/csapi/read_markers.cpp | 5 +-- lib/csapi/receipts.cpp | 6 ++-- lib/csapi/redaction.cpp | 6 ++-- lib/csapi/registration.cpp | 28 +++++++--------- lib/csapi/report_content.cpp | 6 ++-- lib/csapi/room_send.cpp | 6 ++-- lib/csapi/room_state.cpp | 6 ++-- lib/csapi/room_upgrades.cpp | 5 +-- lib/csapi/rooms.cpp | 41 ++++++++++------------- lib/csapi/search.cpp | 4 +-- lib/csapi/sso_login_redirect.cpp | 15 ++++----- lib/csapi/tags.cpp | 24 ++++++-------- lib/csapi/third_party_lookup.cpp | 41 ++++++++++------------- lib/csapi/third_party_membership.cpp | 5 +-- lib/csapi/to_device.cpp | 6 ++-- lib/csapi/typing.cpp | 6 ++-- lib/csapi/users.cpp | 4 +-- lib/csapi/versions.cpp | 7 ++-- lib/csapi/voip.cpp | 9 ++--- lib/csapi/wellknown.cpp | 7 ++-- lib/csapi/whoami.cpp | 9 ++--- 52 files changed, 265 insertions(+), 420 deletions(-) (limited to 'lib') diff --git a/lib/csapi/account-data.cpp b/lib/csapi/account-data.cpp index 80deb8f1..09fc8d40 100644 --- a/lib/csapi/account-data.cpp +++ b/lib/csapi/account-data.cpp @@ -4,15 +4,13 @@ #include "account-data.h" -#include - using namespace Quotient; SetAccountDataJob::SetAccountDataJob(const QString& userId, const QString& type, const QJsonObject& content) : BaseJob(HttpVerb::Put, QStringLiteral("SetAccountDataJob"), - QStringLiteral("/_matrix/client/r0") % "/user/" % userId - % "/account_data/" % type) + makePath("/_matrix/client/r0", "/user/", userId, "/account_data/", + type)) { setRequestData(RequestData(toJson(content))); } @@ -21,14 +19,14 @@ QUrl GetAccountDataJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& type) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") % "/user/" - % userId % "/account_data/" % type); + makePath("/_matrix/client/r0", "/user/", + userId, "/account_data/", type)); } GetAccountDataJob::GetAccountDataJob(const QString& userId, const QString& type) : BaseJob(HttpVerb::Get, QStringLiteral("GetAccountDataJob"), - QStringLiteral("/_matrix/client/r0") % "/user/" % userId - % "/account_data/" % type) + makePath("/_matrix/client/r0", "/user/", userId, "/account_data/", + type)) {} SetAccountDataPerRoomJob::SetAccountDataPerRoomJob(const QString& userId, @@ -36,8 +34,8 @@ SetAccountDataPerRoomJob::SetAccountDataPerRoomJob(const QString& userId, const QString& type, const QJsonObject& content) : BaseJob(HttpVerb::Put, QStringLiteral("SetAccountDataPerRoomJob"), - QStringLiteral("/_matrix/client/r0") % "/user/" % userId - % "/rooms/" % roomId % "/account_data/" % type) + makePath("/_matrix/client/r0", "/user/", userId, "/rooms/", + roomId, "/account_data/", type)) { setRequestData(RequestData(toJson(content))); } @@ -48,15 +46,15 @@ QUrl GetAccountDataPerRoomJob::makeRequestUrl(QUrl baseUrl, const QString& type) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/user/" % userId % "/rooms/" % roomId - % "/account_data/" % type); + makePath("/_matrix/client/r0", "/user/", + userId, "/rooms/", roomId, + "/account_data/", type)); } GetAccountDataPerRoomJob::GetAccountDataPerRoomJob(const QString& userId, const QString& roomId, const QString& type) : BaseJob(HttpVerb::Get, QStringLiteral("GetAccountDataPerRoomJob"), - QStringLiteral("/_matrix/client/r0") % "/user/" % userId - % "/rooms/" % roomId % "/account_data/" % type) + makePath("/_matrix/client/r0", "/user/", userId, "/rooms/", + roomId, "/account_data/", type)) {} diff --git a/lib/csapi/admin.cpp b/lib/csapi/admin.cpp index 9619c441..81dd0624 100644 --- a/lib/csapi/admin.cpp +++ b/lib/csapi/admin.cpp @@ -4,18 +4,16 @@ #include "admin.h" -#include - using namespace Quotient; QUrl GetWhoIsJob::makeRequestUrl(QUrl baseUrl, const QString& userId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/admin/whois/" % userId); + makePath("/_matrix/client/r0", + "/admin/whois/", userId)); } GetWhoIsJob::GetWhoIsJob(const QString& userId) : BaseJob(HttpVerb::Get, QStringLiteral("GetWhoIsJob"), - QStringLiteral("/_matrix/client/r0") % "/admin/whois/" % userId) + makePath("/_matrix/client/r0", "/admin/whois/", userId)) {} diff --git a/lib/csapi/administrative_contact.cpp b/lib/csapi/administrative_contact.cpp index 04360299..589c9fc1 100644 --- a/lib/csapi/administrative_contact.cpp +++ b/lib/csapi/administrative_contact.cpp @@ -4,25 +4,22 @@ #include "administrative_contact.h" -#include - using namespace Quotient; QUrl GetAccount3PIDsJob::makeRequestUrl(QUrl baseUrl) { - return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/account/3pid"); + return BaseJob::makeRequestUrl( + std::move(baseUrl), makePath("/_matrix/client/r0", "/account/3pid")); } GetAccount3PIDsJob::GetAccount3PIDsJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetAccount3PIDsJob"), - QStringLiteral("/_matrix/client/r0") % "/account/3pid") + makePath("/_matrix/client/r0", "/account/3pid")) {} Post3PIDsJob::Post3PIDsJob(const ThreePidCredentials& threePidCreds) : BaseJob(HttpVerb::Post, QStringLiteral("Post3PIDsJob"), - QStringLiteral("/_matrix/client/r0") % "/account/3pid") + makePath("/_matrix/client/r0", "/account/3pid")) { QJsonObject _data; addParam<>(_data, QStringLiteral("three_pid_creds"), threePidCreds); @@ -32,7 +29,7 @@ Post3PIDsJob::Post3PIDsJob(const ThreePidCredentials& threePidCreds) Add3PIDJob::Add3PIDJob(const QString& clientSecret, const QString& sid, const Omittable& auth) : BaseJob(HttpVerb::Post, QStringLiteral("Add3PIDJob"), - QStringLiteral("/_matrix/client/r0") % "/account/3pid/add") + makePath("/_matrix/client/r0", "/account/3pid/add")) { QJsonObject _data; addParam(_data, QStringLiteral("auth"), auth); @@ -44,7 +41,7 @@ Add3PIDJob::Add3PIDJob(const QString& clientSecret, const QString& sid, Bind3PIDJob::Bind3PIDJob(const QString& clientSecret, const QString& idServer, const QString& idAccessToken, const QString& sid) : BaseJob(HttpVerb::Post, QStringLiteral("Bind3PIDJob"), - QStringLiteral("/_matrix/client/r0") % "/account/3pid/bind") + makePath("/_matrix/client/r0", "/account/3pid/bind")) { QJsonObject _data; addParam<>(_data, QStringLiteral("client_secret"), clientSecret); @@ -58,7 +55,7 @@ Delete3pidFromAccountJob::Delete3pidFromAccountJob(const QString& medium, const QString& address, const QString& idServer) : BaseJob(HttpVerb::Post, QStringLiteral("Delete3pidFromAccountJob"), - QStringLiteral("/_matrix/client/r0") % "/account/3pid/delete") + makePath("/_matrix/client/r0", "/account/3pid/delete")) { QJsonObject _data; addParam(_data, QStringLiteral("id_server"), idServer); @@ -72,7 +69,7 @@ Unbind3pidFromAccountJob::Unbind3pidFromAccountJob(const QString& medium, const QString& address, const QString& idServer) : BaseJob(HttpVerb::Post, QStringLiteral("Unbind3pidFromAccountJob"), - QStringLiteral("/_matrix/client/r0") % "/account/3pid/unbind") + makePath("/_matrix/client/r0", "/account/3pid/unbind")) { QJsonObject _data; addParam(_data, QStringLiteral("id_server"), idServer); @@ -85,8 +82,8 @@ Unbind3pidFromAccountJob::Unbind3pidFromAccountJob(const QString& medium, RequestTokenTo3PIDEmailJob::RequestTokenTo3PIDEmailJob( const EmailValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenTo3PIDEmailJob"), - QStringLiteral("/_matrix/client/r0") - % "/account/3pid/email/requestToken", + makePath("/_matrix/client/r0", + "/account/3pid/email/requestToken"), false) { setRequestData(RequestData(toJson(body))); @@ -95,8 +92,8 @@ RequestTokenTo3PIDEmailJob::RequestTokenTo3PIDEmailJob( RequestTokenTo3PIDMSISDNJob::RequestTokenTo3PIDMSISDNJob( const MsisdnValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenTo3PIDMSISDNJob"), - QStringLiteral("/_matrix/client/r0") - % "/account/3pid/msisdn/requestToken", + makePath("/_matrix/client/r0", + "/account/3pid/msisdn/requestToken"), false) { setRequestData(RequestData(toJson(body))); diff --git a/lib/csapi/appservice_room_directory.cpp b/lib/csapi/appservice_room_directory.cpp index 4d87e4af..40d784c6 100644 --- a/lib/csapi/appservice_room_directory.cpp +++ b/lib/csapi/appservice_room_directory.cpp @@ -4,16 +4,14 @@ #include "appservice_room_directory.h" -#include - using namespace Quotient; UpdateAppserviceRoomDirectoryVisibilityJob::UpdateAppserviceRoomDirectoryVisibilityJob( const QString& networkId, const QString& roomId, const QString& visibility) : BaseJob(HttpVerb::Put, QStringLiteral("UpdateAppserviceRoomDirectoryVisibilityJob"), - QStringLiteral("/_matrix/client/r0") - % "/directory/list/appservice/" % networkId % "/" % roomId) + makePath("/_matrix/client/r0", "/directory/list/appservice/", + networkId, "/", roomId)) { QJsonObject _data; addParam<>(_data, QStringLiteral("visibility"), visibility); diff --git a/lib/csapi/banning.cpp b/lib/csapi/banning.cpp index 8e0add1a..472128bb 100644 --- a/lib/csapi/banning.cpp +++ b/lib/csapi/banning.cpp @@ -4,14 +4,12 @@ #include "banning.h" -#include - using namespace Quotient; BanJob::BanJob(const QString& roomId, const QString& userId, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("BanJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId % "/ban") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/ban")) { QJsonObject _data; addParam<>(_data, QStringLiteral("user_id"), userId); @@ -22,8 +20,7 @@ BanJob::BanJob(const QString& roomId, const QString& userId, UnbanJob::UnbanJob(const QString& roomId, const QString& userId, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("UnbanJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/unban") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/unban")) { QJsonObject _data; addParam<>(_data, QStringLiteral("user_id"), userId); diff --git a/lib/csapi/capabilities.cpp b/lib/csapi/capabilities.cpp index 33a53cad..bc21e462 100644 --- a/lib/csapi/capabilities.cpp +++ b/lib/csapi/capabilities.cpp @@ -4,20 +4,17 @@ #include "capabilities.h" -#include - using namespace Quotient; QUrl GetCapabilitiesJob::makeRequestUrl(QUrl baseUrl) { - return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/capabilities"); + return BaseJob::makeRequestUrl( + std::move(baseUrl), makePath("/_matrix/client/r0", "/capabilities")); } GetCapabilitiesJob::GetCapabilitiesJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetCapabilitiesJob"), - QStringLiteral("/_matrix/client/r0") % "/capabilities") + makePath("/_matrix/client/r0", "/capabilities")) { addExpectedKey("capabilities"); } diff --git a/lib/csapi/content-repo.cpp b/lib/csapi/content-repo.cpp index 2d82437b..6d1e38b6 100644 --- a/lib/csapi/content-repo.cpp +++ b/lib/csapi/content-repo.cpp @@ -4,8 +4,6 @@ #include "content-repo.h" -#include - using namespace Quotient; auto queryToUploadContent(const QString& filename) @@ -18,7 +16,7 @@ auto queryToUploadContent(const QString& filename) UploadContentJob::UploadContentJob(QIODevice* content, const QString& filename, const QString& contentType) : BaseJob(HttpVerb::Post, QStringLiteral("UploadContentJob"), - QStringLiteral("/_matrix/media/r0") % "/upload", + makePath("/_matrix/media/r0", "/upload"), queryToUploadContent(filename)) { setRequestHeader("Content-Type", contentType.toLatin1()); @@ -37,17 +35,16 @@ QUrl GetContentJob::makeRequestUrl(QUrl baseUrl, const QString& serverName, const QString& mediaId, bool allowRemote) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/media/r0") - % "/download/" % serverName % "/" - % mediaId, + makePath("/_matrix/media/r0", "/download/", + serverName, "/", mediaId), queryToGetContent(allowRemote)); } GetContentJob::GetContentJob(const QString& serverName, const QString& mediaId, bool allowRemote) : BaseJob(HttpVerb::Get, QStringLiteral("GetContentJob"), - QStringLiteral("/_matrix/media/r0") % "/download/" % serverName - % "/" % mediaId, + makePath("/_matrix/media/r0", "/download/", serverName, "/", + mediaId), queryToGetContent(allowRemote), {}, false) { setExpectedContentTypes({ "*/*" }); @@ -67,9 +64,9 @@ QUrl GetContentOverrideNameJob::makeRequestUrl(QUrl baseUrl, bool allowRemote) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/media/r0") - % "/download/" % serverName % "/" - % mediaId % "/" % fileName, + makePath("/_matrix/media/r0", "/download/", + serverName, "/", mediaId, "/", + fileName), queryToGetContentOverrideName(allowRemote)); } @@ -78,8 +75,8 @@ GetContentOverrideNameJob::GetContentOverrideNameJob(const QString& serverName, const QString& fileName, bool allowRemote) : BaseJob(HttpVerb::Get, QStringLiteral("GetContentOverrideNameJob"), - QStringLiteral("/_matrix/media/r0") % "/download/" % serverName - % "/" % mediaId % "/" % fileName, + makePath("/_matrix/media/r0", "/download/", serverName, "/", + mediaId, "/", fileName), queryToGetContentOverrideName(allowRemote), {}, false) { setExpectedContentTypes({ "*/*" }); @@ -104,8 +101,7 @@ QUrl GetContentThumbnailJob::makeRequestUrl(QUrl baseUrl, { return BaseJob::makeRequestUrl( std::move(baseUrl), - QStringLiteral("/_matrix/media/r0") % "/thumbnail/" % serverName % "/" - % mediaId, + makePath("/_matrix/media/r0", "/thumbnail/", serverName, "/", mediaId), queryToGetContentThumbnail(width, height, method, allowRemote)); } @@ -114,8 +110,8 @@ GetContentThumbnailJob::GetContentThumbnailJob(const QString& serverName, int height, const QString& method, bool allowRemote) : BaseJob(HttpVerb::Get, QStringLiteral("GetContentThumbnailJob"), - QStringLiteral("/_matrix/media/r0") % "/thumbnail/" % serverName - % "/" % mediaId, + makePath("/_matrix/media/r0", "/thumbnail/", serverName, "/", + mediaId), queryToGetContentThumbnail(width, height, method, allowRemote), {}, false) { @@ -134,25 +130,24 @@ QUrl GetUrlPreviewJob::makeRequestUrl(QUrl baseUrl, const QUrl& url, Omittable ts) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/media/r0") - % "/preview_url", + makePath("/_matrix/media/r0", + "/preview_url"), queryToGetUrlPreview(url, ts)); } GetUrlPreviewJob::GetUrlPreviewJob(const QUrl& url, Omittable ts) : BaseJob(HttpVerb::Get, QStringLiteral("GetUrlPreviewJob"), - QStringLiteral("/_matrix/media/r0") % "/preview_url", + makePath("/_matrix/media/r0", "/preview_url"), queryToGetUrlPreview(url, ts)) {} QUrl GetConfigJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/media/r0") - % "/config"); + makePath("/_matrix/media/r0", "/config")); } GetConfigJob::GetConfigJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetConfigJob"), - QStringLiteral("/_matrix/media/r0") % "/config") + makePath("/_matrix/media/r0", "/config")) {} diff --git a/lib/csapi/create_room.cpp b/lib/csapi/create_room.cpp index a94f9951..9aaef87f 100644 --- a/lib/csapi/create_room.cpp +++ b/lib/csapi/create_room.cpp @@ -4,8 +4,6 @@ #include "create_room.h" -#include - using namespace Quotient; CreateRoomJob::CreateRoomJob(const QString& visibility, @@ -18,7 +16,7 @@ CreateRoomJob::CreateRoomJob(const QString& visibility, const QString& preset, Omittable isDirect, const QJsonObject& powerLevelContentOverride) : BaseJob(HttpVerb::Post, QStringLiteral("CreateRoomJob"), - QStringLiteral("/_matrix/client/r0") % "/createRoom") + makePath("/_matrix/client/r0", "/createRoom")) { QJsonObject _data; addParam(_data, QStringLiteral("visibility"), visibility); diff --git a/lib/csapi/cross_signing.cpp b/lib/csapi/cross_signing.cpp index ed2b15c0..1fa0e949 100644 --- a/lib/csapi/cross_signing.cpp +++ b/lib/csapi/cross_signing.cpp @@ -4,8 +4,6 @@ #include "cross_signing.h" -#include - using namespace Quotient; UploadCrossSigningKeysJob::UploadCrossSigningKeysJob( @@ -13,8 +11,7 @@ UploadCrossSigningKeysJob::UploadCrossSigningKeysJob( const Omittable& selfSigningKey, const Omittable& userSigningKey) : BaseJob(HttpVerb::Post, QStringLiteral("UploadCrossSigningKeysJob"), - QStringLiteral("/_matrix/client/r0") - % "/keys/device_signing/upload") + makePath("/_matrix/client/r0", "/keys/device_signing/upload")) { QJsonObject _data; addParam(_data, QStringLiteral("master_key"), masterKey); @@ -28,7 +25,7 @@ UploadCrossSigningKeysJob::UploadCrossSigningKeysJob( UploadCrossSigningSignaturesJob::UploadCrossSigningSignaturesJob( const QHash>& signatures) : BaseJob(HttpVerb::Post, QStringLiteral("UploadCrossSigningSignaturesJob"), - QStringLiteral("/_matrix/client/r0") % "/keys/signatures/upload") + makePath("/_matrix/client/r0", "/keys/signatures/upload")) { setRequestData(RequestData(toJson(signatures))); } diff --git a/lib/csapi/device_management.cpp b/lib/csapi/device_management.cpp index eac9a545..da6dbc76 100644 --- a/lib/csapi/device_management.cpp +++ b/lib/csapi/device_management.cpp @@ -4,38 +4,35 @@ #include "device_management.h" -#include - using namespace Quotient; QUrl GetDevicesJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/devices"); + makePath("/_matrix/client/r0", "/devices")); } GetDevicesJob::GetDevicesJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetDevicesJob"), - QStringLiteral("/_matrix/client/r0") % "/devices") + makePath("/_matrix/client/r0", "/devices")) {} QUrl GetDeviceJob::makeRequestUrl(QUrl baseUrl, const QString& deviceId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/devices/" % deviceId); + makePath("/_matrix/client/r0", "/devices/", + deviceId)); } GetDeviceJob::GetDeviceJob(const QString& deviceId) : BaseJob(HttpVerb::Get, QStringLiteral("GetDeviceJob"), - QStringLiteral("/_matrix/client/r0") % "/devices/" % deviceId) + makePath("/_matrix/client/r0", "/devices/", deviceId)) {} UpdateDeviceJob::UpdateDeviceJob(const QString& deviceId, const QString& displayName) : BaseJob(HttpVerb::Put, QStringLiteral("UpdateDeviceJob"), - QStringLiteral("/_matrix/client/r0") % "/devices/" % deviceId) + makePath("/_matrix/client/r0", "/devices/", deviceId)) { QJsonObject _data; addParam(_data, QStringLiteral("display_name"), displayName); @@ -45,7 +42,7 @@ UpdateDeviceJob::UpdateDeviceJob(const QString& deviceId, DeleteDeviceJob::DeleteDeviceJob(const QString& deviceId, const Omittable& auth) : BaseJob(HttpVerb::Delete, QStringLiteral("DeleteDeviceJob"), - QStringLiteral("/_matrix/client/r0") % "/devices/" % deviceId) + makePath("/_matrix/client/r0", "/devices/", deviceId)) { QJsonObject _data; addParam(_data, QStringLiteral("auth"), auth); @@ -55,7 +52,7 @@ DeleteDeviceJob::DeleteDeviceJob(const QString& deviceId, DeleteDevicesJob::DeleteDevicesJob(const QStringList& devices, const Omittable& auth) : BaseJob(HttpVerb::Post, QStringLiteral("DeleteDevicesJob"), - QStringLiteral("/_matrix/client/r0") % "/delete_devices") + makePath("/_matrix/client/r0", "/delete_devices")) { QJsonObject _data; addParam<>(_data, QStringLiteral("devices"), devices); diff --git a/lib/csapi/directory.cpp b/lib/csapi/directory.cpp index 25ea82e2..b351b4ef 100644 --- a/lib/csapi/directory.cpp +++ b/lib/csapi/directory.cpp @@ -4,14 +4,11 @@ #include "directory.h" -#include - using namespace Quotient; SetRoomAliasJob::SetRoomAliasJob(const QString& roomAlias, const QString& roomId) : BaseJob(HttpVerb::Put, QStringLiteral("SetRoomAliasJob"), - QStringLiteral("/_matrix/client/r0") % "/directory/room/" - % roomAlias) + makePath("/_matrix/client/r0", "/directory/room/", roomAlias)) { QJsonObject _data; addParam<>(_data, QStringLiteral("room_id"), roomId); @@ -21,41 +18,38 @@ SetRoomAliasJob::SetRoomAliasJob(const QString& roomAlias, const QString& roomId QUrl GetRoomIdByAliasJob::makeRequestUrl(QUrl baseUrl, const QString& roomAlias) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/directory/room/" % roomAlias); + makePath("/_matrix/client/r0", + "/directory/room/", roomAlias)); } GetRoomIdByAliasJob::GetRoomIdByAliasJob(const QString& roomAlias) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomIdByAliasJob"), - QStringLiteral("/_matrix/client/r0") % "/directory/room/" - % roomAlias, + makePath("/_matrix/client/r0", "/directory/room/", roomAlias), false) {} QUrl DeleteRoomAliasJob::makeRequestUrl(QUrl baseUrl, const QString& roomAlias) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/directory/room/" % roomAlias); + makePath("/_matrix/client/r0", + "/directory/room/", roomAlias)); } DeleteRoomAliasJob::DeleteRoomAliasJob(const QString& roomAlias) : BaseJob(HttpVerb::Delete, QStringLiteral("DeleteRoomAliasJob"), - QStringLiteral("/_matrix/client/r0") % "/directory/room/" - % roomAlias) + makePath("/_matrix/client/r0", "/directory/room/", roomAlias)) {} QUrl GetLocalAliasesJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/rooms/" % roomId % "/aliases"); + makePath("/_matrix/client/r0", "/rooms/", + roomId, "/aliases")); } GetLocalAliasesJob::GetLocalAliasesJob(const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("GetLocalAliasesJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/aliases") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/aliases")) { addExpectedKey("aliases"); } diff --git a/lib/csapi/event_context.cpp b/lib/csapi/event_context.cpp index 3f4cd61e..877838e2 100644 --- a/lib/csapi/event_context.cpp +++ b/lib/csapi/event_context.cpp @@ -4,8 +4,6 @@ #include "event_context.h" -#include - using namespace Quotient; auto queryToGetEventContext(Omittable limit, const QString& filter) @@ -22,9 +20,8 @@ QUrl GetEventContextJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& filter) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/rooms/" % roomId % "/context/" - % eventId, + makePath("/_matrix/client/r0", "/rooms/", + roomId, "/context/", eventId), queryToGetEventContext(limit, filter)); } @@ -33,7 +30,7 @@ GetEventContextJob::GetEventContextJob(const QString& roomId, Omittable limit, const QString& filter) : BaseJob(HttpVerb::Get, QStringLiteral("GetEventContextJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/context/" % eventId, + makePath("/_matrix/client/r0", "/rooms/", roomId, "/context/", + eventId), queryToGetEventContext(limit, filter)) {} diff --git a/lib/csapi/filter.cpp b/lib/csapi/filter.cpp index 6b8863cc..38c68be7 100644 --- a/lib/csapi/filter.cpp +++ b/lib/csapi/filter.cpp @@ -4,14 +4,11 @@ #include "filter.h" -#include - using namespace Quotient; DefineFilterJob::DefineFilterJob(const QString& userId, const Filter& filter) : BaseJob(HttpVerb::Post, QStringLiteral("DefineFilterJob"), - QStringLiteral("/_matrix/client/r0") % "/user/" % userId - % "/filter") + makePath("/_matrix/client/r0", "/user/", userId, "/filter")) { setRequestData(RequestData(toJson(filter))); addExpectedKey("filter_id"); @@ -21,12 +18,12 @@ QUrl GetFilterJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& filterId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") % "/user/" - % userId % "/filter/" % filterId); + makePath("/_matrix/client/r0", "/user/", + userId, "/filter/", filterId)); } GetFilterJob::GetFilterJob(const QString& userId, const QString& filterId) : BaseJob(HttpVerb::Get, QStringLiteral("GetFilterJob"), - QStringLiteral("/_matrix/client/r0") % "/user/" % userId - % "/filter/" % filterId) + makePath("/_matrix/client/r0", "/user/", userId, "/filter/", + filterId)) {} diff --git a/lib/csapi/inviting.cpp b/lib/csapi/inviting.cpp index 1e2554f4..39d24611 100644 --- a/lib/csapi/inviting.cpp +++ b/lib/csapi/inviting.cpp @@ -4,15 +4,12 @@ #include "inviting.h" -#include - using namespace Quotient; InviteUserJob::InviteUserJob(const QString& roomId, const QString& userId, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("InviteUserJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/invite") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/invite")) { QJsonObject _data; addParam<>(_data, QStringLiteral("user_id"), userId); diff --git a/lib/csapi/joining.cpp b/lib/csapi/joining.cpp index f5266f0b..373c1c6a 100644 --- a/lib/csapi/joining.cpp +++ b/lib/csapi/joining.cpp @@ -4,15 +4,13 @@ #include "joining.h" -#include - using namespace Quotient; JoinRoomByIdJob::JoinRoomByIdJob( const QString& roomId, const Omittable& thirdPartySigned, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("JoinRoomByIdJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId % "/join") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/join")) { QJsonObject _data; addParam(_data, QStringLiteral("third_party_signed"), @@ -34,7 +32,7 @@ JoinRoomJob::JoinRoomJob(const QString& roomIdOrAlias, const Omittable& thirdPartySigned, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("JoinRoomJob"), - QStringLiteral("/_matrix/client/r0") % "/join/" % roomIdOrAlias, + makePath("/_matrix/client/r0", "/join/", roomIdOrAlias), queryToJoinRoom(serverName)) { QJsonObject _data; diff --git a/lib/csapi/keys.cpp b/lib/csapi/keys.cpp index ba5d8e12..d6bd2fab 100644 --- a/lib/csapi/keys.cpp +++ b/lib/csapi/keys.cpp @@ -4,14 +4,12 @@ #include "keys.h" -#include - using namespace Quotient; UploadKeysJob::UploadKeysJob(const Omittable& deviceKeys, const QHash& oneTimeKeys) : BaseJob(HttpVerb::Post, QStringLiteral("UploadKeysJob"), - QStringLiteral("/_matrix/client/r0") % "/keys/upload") + makePath("/_matrix/client/r0", "/keys/upload")) { QJsonObject _data; addParam(_data, QStringLiteral("device_keys"), deviceKeys); @@ -23,7 +21,7 @@ UploadKeysJob::UploadKeysJob(const Omittable& deviceKeys, QueryKeysJob::QueryKeysJob(const QHash& deviceKeys, Omittable timeout, const QString& token) : BaseJob(HttpVerb::Post, QStringLiteral("QueryKeysJob"), - QStringLiteral("/_matrix/client/r0") % "/keys/query") + makePath("/_matrix/client/r0", "/keys/query")) { QJsonObject _data; addParam(_data, QStringLiteral("timeout"), timeout); @@ -36,7 +34,7 @@ ClaimKeysJob::ClaimKeysJob( const QHash>& oneTimeKeys, Omittable timeout) : BaseJob(HttpVerb::Post, QStringLiteral("ClaimKeysJob"), - QStringLiteral("/_matrix/client/r0") % "/keys/claim") + makePath("/_matrix/client/r0", "/keys/claim")) { QJsonObject _data; addParam(_data, QStringLiteral("timeout"), timeout); @@ -57,13 +55,13 @@ QUrl GetKeysChangesJob::makeRequestUrl(QUrl baseUrl, const QString& from, const QString& to) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/keys/changes", + makePath("/_matrix/client/r0", + "/keys/changes"), queryToGetKeysChanges(from, to)); } GetKeysChangesJob::GetKeysChangesJob(const QString& from, const QString& to) : BaseJob(HttpVerb::Get, QStringLiteral("GetKeysChangesJob"), - QStringLiteral("/_matrix/client/r0") % "/keys/changes", + makePath("/_matrix/client/r0", "/keys/changes"), queryToGetKeysChanges(from, to)) {} diff --git a/lib/csapi/kicking.cpp b/lib/csapi/kicking.cpp index 7de5ce01..433e592c 100644 --- a/lib/csapi/kicking.cpp +++ b/lib/csapi/kicking.cpp @@ -4,14 +4,12 @@ #include "kicking.h" -#include - using namespace Quotient; KickJob::KickJob(const QString& roomId, const QString& userId, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("KickJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId % "/kick") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/kick")) { QJsonObject _data; addParam<>(_data, QStringLiteral("user_id"), userId); diff --git a/lib/csapi/knocking.cpp b/lib/csapi/knocking.cpp index 788bb378..73e13e6e 100644 --- a/lib/csapi/knocking.cpp +++ b/lib/csapi/knocking.cpp @@ -4,8 +4,6 @@ #include "knocking.h" -#include - using namespace Quotient; auto queryToKnockRoom(const QStringList& serverName) @@ -18,7 +16,7 @@ auto queryToKnockRoom(const QStringList& serverName) KnockRoomJob::KnockRoomJob(const QString& roomIdOrAlias, const QStringList& serverName, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("KnockRoomJob"), - QStringLiteral("/_matrix/client/r0") % "/knock/" % roomIdOrAlias, + makePath("/_matrix/client/r0", "/knock/", roomIdOrAlias), queryToKnockRoom(serverName)) { QJsonObject _data; diff --git a/lib/csapi/leaving.cpp b/lib/csapi/leaving.cpp index f4c5f120..0e5386be 100644 --- a/lib/csapi/leaving.cpp +++ b/lib/csapi/leaving.cpp @@ -4,14 +4,11 @@ #include "leaving.h" -#include - using namespace Quotient; LeaveRoomJob::LeaveRoomJob(const QString& roomId, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("LeaveRoomJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/leave") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/leave")) { QJsonObject _data; addParam(_data, QStringLiteral("reason"), reason); @@ -21,12 +18,11 @@ LeaveRoomJob::LeaveRoomJob(const QString& roomId, const QString& reason) QUrl ForgetRoomJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/rooms/" % roomId % "/forget"); + makePath("/_matrix/client/r0", "/rooms/", + roomId, "/forget")); } ForgetRoomJob::ForgetRoomJob(const QString& roomId) : BaseJob(HttpVerb::Post, QStringLiteral("ForgetRoomJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/forget") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/forget")) {} diff --git a/lib/csapi/list_joined_rooms.cpp b/lib/csapi/list_joined_rooms.cpp index 8d7e267f..22ba04da 100644 --- a/lib/csapi/list_joined_rooms.cpp +++ b/lib/csapi/list_joined_rooms.cpp @@ -4,20 +4,17 @@ #include "list_joined_rooms.h" -#include - using namespace Quotient; QUrl GetJoinedRoomsJob::makeRequestUrl(QUrl baseUrl) { - return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/joined_rooms"); + return BaseJob::makeRequestUrl( + std::move(baseUrl), makePath("/_matrix/client/r0", "/joined_rooms")); } GetJoinedRoomsJob::GetJoinedRoomsJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetJoinedRoomsJob"), - QStringLiteral("/_matrix/client/r0") % "/joined_rooms") + makePath("/_matrix/client/r0", "/joined_rooms")) { addExpectedKey("joined_rooms"); } diff --git a/lib/csapi/list_public_rooms.cpp b/lib/csapi/list_public_rooms.cpp index a4bcb934..25f8da5c 100644 --- a/lib/csapi/list_public_rooms.cpp +++ b/lib/csapi/list_public_rooms.cpp @@ -4,31 +4,27 @@ #include "list_public_rooms.h" -#include - using namespace Quotient; QUrl GetRoomVisibilityOnDirectoryJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/directory/list/room/" % roomId); + makePath("/_matrix/client/r0", + "/directory/list/room/", roomId)); } GetRoomVisibilityOnDirectoryJob::GetRoomVisibilityOnDirectoryJob( const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomVisibilityOnDirectoryJob"), - QStringLiteral("/_matrix/client/r0") % "/directory/list/room/" - % roomId, + makePath("/_matrix/client/r0", "/directory/list/room/", roomId), false) {} SetRoomVisibilityOnDirectoryJob::SetRoomVisibilityOnDirectoryJob( const QString& roomId, const QString& visibility) : BaseJob(HttpVerb::Put, QStringLiteral("SetRoomVisibilityOnDirectoryJob"), - QStringLiteral("/_matrix/client/r0") % "/directory/list/room/" - % roomId) + makePath("/_matrix/client/r0", "/directory/list/room/", roomId)) { QJsonObject _data; addParam(_data, QStringLiteral("visibility"), visibility); @@ -50,15 +46,15 @@ QUrl GetPublicRoomsJob::makeRequestUrl(QUrl baseUrl, Omittable limit, const QString& server) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/publicRooms", + makePath("/_matrix/client/r0", + "/publicRooms"), queryToGetPublicRooms(limit, since, server)); } GetPublicRoomsJob::GetPublicRoomsJob(Omittable limit, const QString& since, const QString& server) : BaseJob(HttpVerb::Get, QStringLiteral("GetPublicRoomsJob"), - QStringLiteral("/_matrix/client/r0") % "/publicRooms", + makePath("/_matrix/client/r0", "/publicRooms"), queryToGetPublicRooms(limit, since, server), {}, false) { addExpectedKey("chunk"); @@ -78,7 +74,7 @@ QueryPublicRoomsJob::QueryPublicRoomsJob(const QString& server, Omittable includeAllNetworks, const QString& thirdPartyInstanceId) : BaseJob(HttpVerb::Post, QStringLiteral("QueryPublicRoomsJob"), - QStringLiteral("/_matrix/client/r0") % "/publicRooms", + makePath("/_matrix/client/r0", "/publicRooms"), queryToQueryPublicRooms(server)) { QJsonObject _data; diff --git a/lib/csapi/login.cpp b/lib/csapi/login.cpp index a5bac9ea..71fd93c5 100644 --- a/lib/csapi/login.cpp +++ b/lib/csapi/login.cpp @@ -4,20 +4,17 @@ #include "login.h" -#include - using namespace Quotient; QUrl GetLoginFlowsJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/login"); + makePath("/_matrix/client/r0", "/login")); } GetLoginFlowsJob::GetLoginFlowsJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetLoginFlowsJob"), - QStringLiteral("/_matrix/client/r0") % "/login", false) + makePath("/_matrix/client/r0", "/login"), false) {} LoginJob::LoginJob(const QString& type, @@ -26,7 +23,7 @@ LoginJob::LoginJob(const QString& type, const QString& deviceId, const QString& initialDeviceDisplayName) : BaseJob(HttpVerb::Post, QStringLiteral("LoginJob"), - QStringLiteral("/_matrix/client/r0") % "/login", false) + makePath("/_matrix/client/r0", "/login"), false) { QJsonObject _data; addParam<>(_data, QStringLiteral("type"), type); diff --git a/lib/csapi/logout.cpp b/lib/csapi/logout.cpp index 9583b8ec..e8083e31 100644 --- a/lib/csapi/logout.cpp +++ b/lib/csapi/logout.cpp @@ -4,30 +4,26 @@ #include "logout.h" -#include - using namespace Quotient; QUrl LogoutJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/logout"); + makePath("/_matrix/client/r0", "/logout")); } LogoutJob::LogoutJob() : BaseJob(HttpVerb::Post, QStringLiteral("LogoutJob"), - QStringLiteral("/_matrix/client/r0") % "/logout") + makePath("/_matrix/client/r0", "/logout")) {} QUrl LogoutAllJob::makeRequestUrl(QUrl baseUrl) { - return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/logout/all"); + return BaseJob::makeRequestUrl( + std::move(baseUrl), makePath("/_matrix/client/r0", "/logout/all")); } LogoutAllJob::LogoutAllJob() : BaseJob(HttpVerb::Post, QStringLiteral("LogoutAllJob"), - QStringLiteral("/_matrix/client/r0") % "/logout/all") + makePath("/_matrix/client/r0", "/logout/all")) {} diff --git a/lib/csapi/message_pagination.cpp b/lib/csapi/message_pagination.cpp index 441e4dea..1a93b75b 100644 --- a/lib/csapi/message_pagination.cpp +++ b/lib/csapi/message_pagination.cpp @@ -4,8 +4,6 @@ #include "message_pagination.h" -#include - using namespace Quotient; auto queryToGetRoomEvents(const QString& from, const QString& to, @@ -28,7 +26,7 @@ QUrl GetRoomEventsJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, { return BaseJob::makeRequestUrl( std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId % "/messages", + makePath("/_matrix/client/r0", "/rooms/", roomId, "/messages"), queryToGetRoomEvents(from, to, dir, limit, filter)); } @@ -36,7 +34,6 @@ GetRoomEventsJob::GetRoomEventsJob(const QString& roomId, const QString& from, const QString& dir, const QString& to, Omittable limit, const QString& filter) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomEventsJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/messages", + makePath("/_matrix/client/r0", "/rooms/", roomId, "/messages"), queryToGetRoomEvents(from, to, dir, limit, filter)) {} diff --git a/lib/csapi/notifications.cpp b/lib/csapi/notifications.cpp index a38e46f5..1e523c6f 100644 --- a/lib/csapi/notifications.cpp +++ b/lib/csapi/notifications.cpp @@ -4,8 +4,6 @@ #include "notifications.h" -#include - using namespace Quotient; auto queryToGetNotifications(const QString& from, Omittable limit, @@ -23,8 +21,8 @@ QUrl GetNotificationsJob::makeRequestUrl(QUrl baseUrl, const QString& from, const QString& only) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/notifications", + makePath("/_matrix/client/r0", + "/notifications"), queryToGetNotifications(from, limit, only)); } @@ -32,7 +30,7 @@ GetNotificationsJob::GetNotificationsJob(const QString& from, Omittable limit, const QString& only) : BaseJob(HttpVerb::Get, QStringLiteral("GetNotificationsJob"), - QStringLiteral("/_matrix/client/r0") % "/notifications", + makePath("/_matrix/client/r0", "/notifications"), queryToGetNotifications(from, limit, only)) { addExpectedKey("notifications"); diff --git a/lib/csapi/openid.cpp b/lib/csapi/openid.cpp index 0447db79..5c93a2d7 100644 --- a/lib/csapi/openid.cpp +++ b/lib/csapi/openid.cpp @@ -4,15 +4,13 @@ #include "openid.h" -#include - using namespace Quotient; RequestOpenIdTokenJob::RequestOpenIdTokenJob(const QString& userId, const QJsonObject& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestOpenIdTokenJob"), - QStringLiteral("/_matrix/client/r0") % "/user/" % userId - % "/openid/request_token") + makePath("/_matrix/client/r0", "/user/", userId, + "/openid/request_token")) { setRequestData(RequestData(toJson(body))); } diff --git a/lib/csapi/peeking_events.cpp b/lib/csapi/peeking_events.cpp index ad2f9afe..eb5d22fa 100644 --- a/lib/csapi/peeking_events.cpp +++ b/lib/csapi/peeking_events.cpp @@ -4,8 +4,6 @@ #include "peeking_events.h" -#include - using namespace Quotient; auto queryToPeekEvents(const QString& from, Omittable timeout, @@ -22,14 +20,13 @@ QUrl PeekEventsJob::makeRequestUrl(QUrl baseUrl, const QString& from, Omittable timeout, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/events", + makePath("/_matrix/client/r0", "/events"), queryToPeekEvents(from, timeout, roomId)); } PeekEventsJob::PeekEventsJob(const QString& from, Omittable timeout, const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("PeekEventsJob"), - QStringLiteral("/_matrix/client/r0") % "/events", + makePath("/_matrix/client/r0", "/events"), queryToPeekEvents(from, timeout, roomId)) {} diff --git a/lib/csapi/presence.cpp b/lib/csapi/presence.cpp index 58d0d157..4f77c466 100644 --- a/lib/csapi/presence.cpp +++ b/lib/csapi/presence.cpp @@ -4,15 +4,12 @@ #include "presence.h" -#include - using namespace Quotient; SetPresenceJob::SetPresenceJob(const QString& userId, const QString& presence, const QString& statusMsg) : BaseJob(HttpVerb::Put, QStringLiteral("SetPresenceJob"), - QStringLiteral("/_matrix/client/r0") % "/presence/" % userId - % "/status") + makePath("/_matrix/client/r0", "/presence/", userId, "/status")) { QJsonObject _data; addParam<>(_data, QStringLiteral("presence"), presence); @@ -23,14 +20,13 @@ SetPresenceJob::SetPresenceJob(const QString& userId, const QString& presence, QUrl GetPresenceJob::makeRequestUrl(QUrl baseUrl, const QString& userId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/presence/" % userId % "/status"); + makePath("/_matrix/client/r0", "/presence/", + userId, "/status")); } GetPresenceJob::GetPresenceJob(const QString& userId) : BaseJob(HttpVerb::Get, QStringLiteral("GetPresenceJob"), - QStringLiteral("/_matrix/client/r0") % "/presence/" % userId - % "/status") + makePath("/_matrix/client/r0", "/presence/", userId, "/status")) { addExpectedKey("presence"); } diff --git a/lib/csapi/profile.cpp b/lib/csapi/profile.cpp index 745fa488..64ac84ca 100644 --- a/lib/csapi/profile.cpp +++ b/lib/csapi/profile.cpp @@ -4,15 +4,12 @@ #include "profile.h" -#include - using namespace Quotient; SetDisplayNameJob::SetDisplayNameJob(const QString& userId, const QString& displayname) : BaseJob(HttpVerb::Put, QStringLiteral("SetDisplayNameJob"), - QStringLiteral("/_matrix/client/r0") % "/profile/" % userId - % "/displayname") + makePath("/_matrix/client/r0", "/profile/", userId, "/displayname")) { QJsonObject _data; addParam<>(_data, QStringLiteral("displayname"), displayname); @@ -22,21 +19,19 @@ SetDisplayNameJob::SetDisplayNameJob(const QString& userId, QUrl GetDisplayNameJob::makeRequestUrl(QUrl baseUrl, const QString& userId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/profile/" % userId % "/displayname"); + makePath("/_matrix/client/r0", "/profile/", + userId, "/displayname")); } GetDisplayNameJob::GetDisplayNameJob(const QString& userId) : BaseJob(HttpVerb::Get, QStringLiteral("GetDisplayNameJob"), - QStringLiteral("/_matrix/client/r0") % "/profile/" % userId - % "/displayname", + makePath("/_matrix/client/r0", "/profile/", userId, "/displayname"), false) {} SetAvatarUrlJob::SetAvatarUrlJob(const QString& userId, const QUrl& avatarUrl) : BaseJob(HttpVerb::Put, QStringLiteral("SetAvatarUrlJob"), - QStringLiteral("/_matrix/client/r0") % "/profile/" % userId - % "/avatar_url") + makePath("/_matrix/client/r0", "/profile/", userId, "/avatar_url")) { QJsonObject _data; addParam<>(_data, QStringLiteral("avatar_url"), avatarUrl); @@ -46,25 +41,24 @@ SetAvatarUrlJob::SetAvatarUrlJob(const QString& userId, const QUrl& avatarUrl) QUrl GetAvatarUrlJob::makeRequestUrl(QUrl baseUrl, const QString& userId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/profile/" % userId % "/avatar_url"); + makePath("/_matrix/client/r0", "/profile/", + userId, "/avatar_url")); } GetAvatarUrlJob::GetAvatarUrlJob(const QString& userId) : BaseJob(HttpVerb::Get, QStringLiteral("GetAvatarUrlJob"), - QStringLiteral("/_matrix/client/r0") % "/profile/" % userId - % "/avatar_url", + makePath("/_matrix/client/r0", "/profile/", userId, "/avatar_url"), false) {} QUrl GetUserProfileJob::makeRequestUrl(QUrl baseUrl, const QString& userId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/profile/" % userId); + makePath("/_matrix/client/r0", "/profile/", + userId)); } GetUserProfileJob::GetUserProfileJob(const QString& userId) : BaseJob(HttpVerb::Get, QStringLiteral("GetUserProfileJob"), - QStringLiteral("/_matrix/client/r0") % "/profile/" % userId, false) + makePath("/_matrix/client/r0", "/profile/", userId), false) {} diff --git a/lib/csapi/pusher.cpp b/lib/csapi/pusher.cpp index 028022c5..ef4b3767 100644 --- a/lib/csapi/pusher.cpp +++ b/lib/csapi/pusher.cpp @@ -4,20 +4,17 @@ #include "pusher.h" -#include - using namespace Quotient; QUrl GetPushersJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/pushers"); + makePath("/_matrix/client/r0", "/pushers")); } GetPushersJob::GetPushersJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetPushersJob"), - QStringLiteral("/_matrix/client/r0") % "/pushers") + makePath("/_matrix/client/r0", "/pushers")) {} PostPusherJob::PostPusherJob(const QString& pushkey, const QString& kind, @@ -26,7 +23,7 @@ PostPusherJob::PostPusherJob(const QString& pushkey, const QString& kind, const QString& lang, const PusherData& data, const QString& profileTag, Omittable append) : BaseJob(HttpVerb::Post, QStringLiteral("PostPusherJob"), - QStringLiteral("/_matrix/client/r0") % "/pushers/set") + makePath("/_matrix/client/r0", "/pushers/set")) { QJsonObject _data; addParam<>(_data, QStringLiteral("pushkey"), pushkey); diff --git a/lib/csapi/pushrules.cpp b/lib/csapi/pushrules.cpp index ab7d0038..0d840788 100644 --- a/lib/csapi/pushrules.cpp +++ b/lib/csapi/pushrules.cpp @@ -4,20 +4,17 @@ #include "pushrules.h" -#include - using namespace Quotient; QUrl GetPushRulesJob::makeRequestUrl(QUrl baseUrl) { - return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/pushrules"); + return BaseJob::makeRequestUrl( + std::move(baseUrl), makePath("/_matrix/client/r0", "/pushrules")); } GetPushRulesJob::GetPushRulesJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetPushRulesJob"), - QStringLiteral("/_matrix/client/r0") % "/pushrules") + makePath("/_matrix/client/r0", "/pushrules")) { addExpectedKey("global"); } @@ -26,16 +23,15 @@ QUrl GetPushRuleJob::makeRequestUrl(QUrl baseUrl, const QString& scope, const QString& kind, const QString& ruleId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/pushrules/" % scope % "/" % kind - % "/" % ruleId); + makePath("/_matrix/client/r0", "/pushrules/", + scope, "/", kind, "/", ruleId)); } GetPushRuleJob::GetPushRuleJob(const QString& scope, const QString& kind, const QString& ruleId) : BaseJob(HttpVerb::Get, QStringLiteral("GetPushRuleJob"), - QStringLiteral("/_matrix/client/r0") % "/pushrules/" % scope % "/" - % kind % "/" % ruleId) + makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + "/", ruleId)) {} QUrl DeletePushRuleJob::makeRequestUrl(QUrl baseUrl, const QString& scope, @@ -43,16 +39,15 @@ QUrl DeletePushRuleJob::makeRequestUrl(QUrl baseUrl, const QString& scope, const QString& ruleId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/pushrules/" % scope % "/" % kind - % "/" % ruleId); + makePath("/_matrix/client/r0", "/pushrules/", + scope, "/", kind, "/", ruleId)); } DeletePushRuleJob::DeletePushRuleJob(const QString& scope, const QString& kind, const QString& ruleId) : BaseJob(HttpVerb::Delete, QStringLiteral("DeletePushRuleJob"), - QStringLiteral("/_matrix/client/r0") % "/pushrules/" % scope % "/" - % kind % "/" % ruleId) + makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + "/", ruleId)) {} auto queryToSetPushRule(const QString& before, const QString& after) @@ -70,8 +65,8 @@ SetPushRuleJob::SetPushRuleJob(const QString& scope, const QString& kind, const QVector& conditions, const QString& pattern) : BaseJob(HttpVerb::Put, QStringLiteral("SetPushRuleJob"), - QStringLiteral("/_matrix/client/r0") % "/pushrules/" % scope % "/" - % kind % "/" % ruleId, + makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + "/", ruleId), queryToSetPushRule(before, after)) { QJsonObject _data; @@ -86,17 +81,17 @@ QUrl IsPushRuleEnabledJob::makeRequestUrl(QUrl baseUrl, const QString& scope, const QString& ruleId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/pushrules/" % scope % "/" % kind - % "/" % ruleId % "/enabled"); + makePath("/_matrix/client/r0", "/pushrules/", + scope, "/", kind, "/", ruleId, + "/enabled")); } IsPushRuleEnabledJob::IsPushRuleEnabledJob(const QString& scope, const QString& kind, const QString& ruleId) : BaseJob(HttpVerb::Get, QStringLiteral("IsPushRuleEnabledJob"), - QStringLiteral("/_matrix/client/r0") % "/pushrules/" % scope % "/" - % kind % "/" % ruleId % "/enabled") + makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + "/", ruleId, "/enabled")) { addExpectedKey("enabled"); } @@ -105,8 +100,8 @@ SetPushRuleEnabledJob::SetPushRuleEnabledJob(const QString& scope, const QString& kind, const QString& ruleId, bool enabled) : BaseJob(HttpVerb::Put, QStringLiteral("SetPushRuleEnabledJob"), - QStringLiteral("/_matrix/client/r0") % "/pushrules/" % scope % "/" - % kind % "/" % ruleId % "/enabled") + makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + "/", ruleId, "/enabled")) { QJsonObject _data; addParam<>(_data, QStringLiteral("enabled"), enabled); @@ -118,17 +113,17 @@ QUrl GetPushRuleActionsJob::makeRequestUrl(QUrl baseUrl, const QString& scope, const QString& ruleId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/pushrules/" % scope % "/" % kind - % "/" % ruleId % "/actions"); + makePath("/_matrix/client/r0", "/pushrules/", + scope, "/", kind, "/", ruleId, + "/actions")); } GetPushRuleActionsJob::GetPushRuleActionsJob(const QString& scope, const QString& kind, const QString& ruleId) : BaseJob(HttpVerb::Get, QStringLiteral("GetPushRuleActionsJob"), - QStringLiteral("/_matrix/client/r0") % "/pushrules/" % scope % "/" - % kind % "/" % ruleId % "/actions") + makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + "/", ruleId, "/actions")) { addExpectedKey("actions"); } @@ -138,8 +133,8 @@ SetPushRuleActionsJob::SetPushRuleActionsJob(const QString& scope, const QString& ruleId, const QVector& actions) : BaseJob(HttpVerb::Put, QStringLiteral("SetPushRuleActionsJob"), - QStringLiteral("/_matrix/client/r0") % "/pushrules/" % scope % "/" - % kind % "/" % ruleId % "/actions") + makePath("/_matrix/client/r0", "/pushrules/", scope, "/", kind, + "/", ruleId, "/actions")) { QJsonObject _data; addParam<>(_data, QStringLiteral("actions"), actions); diff --git a/lib/csapi/read_markers.cpp b/lib/csapi/read_markers.cpp index 39e4d148..f2edb71e 100644 --- a/lib/csapi/read_markers.cpp +++ b/lib/csapi/read_markers.cpp @@ -4,16 +4,13 @@ #include "read_markers.h" -#include - using namespace Quotient; SetReadMarkerJob::SetReadMarkerJob(const QString& roomId, const QString& mFullyRead, const QString& mRead) : BaseJob(HttpVerb::Post, QStringLiteral("SetReadMarkerJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/read_markers") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/read_markers")) { QJsonObject _data; addParam<>(_data, QStringLiteral("m.fully_read"), mFullyRead); diff --git a/lib/csapi/receipts.cpp b/lib/csapi/receipts.cpp index 47b18174..401c3bfe 100644 --- a/lib/csapi/receipts.cpp +++ b/lib/csapi/receipts.cpp @@ -4,16 +4,14 @@ #include "receipts.h" -#include - using namespace Quotient; PostReceiptJob::PostReceiptJob(const QString& roomId, const QString& receiptType, const QString& eventId, const QJsonObject& receipt) : BaseJob(HttpVerb::Post, QStringLiteral("PostReceiptJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/receipt/" % receiptType % "/" % eventId) + makePath("/_matrix/client/r0", "/rooms/", roomId, "/receipt/", + receiptType, "/", eventId)) { setRequestData(RequestData(toJson(receipt))); } diff --git a/lib/csapi/redaction.cpp b/lib/csapi/redaction.cpp index 91497064..acf1b0e4 100644 --- a/lib/csapi/redaction.cpp +++ b/lib/csapi/redaction.cpp @@ -4,15 +4,13 @@ #include "redaction.h" -#include - using namespace Quotient; RedactEventJob::RedactEventJob(const QString& roomId, const QString& eventId, const QString& txnId, const QString& reason) : BaseJob(HttpVerb::Put, QStringLiteral("RedactEventJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/redact/" % eventId % "/" % txnId) + makePath("/_matrix/client/r0", "/rooms/", roomId, "/redact/", + eventId, "/", txnId)) { QJsonObject _data; addParam(_data, QStringLiteral("reason"), reason); diff --git a/lib/csapi/registration.cpp b/lib/csapi/registration.cpp index c3617bfc..153abcee 100644 --- a/lib/csapi/registration.cpp +++ b/lib/csapi/registration.cpp @@ -4,8 +4,6 @@ #include "registration.h" -#include - using namespace Quotient; auto queryToRegister(const QString& kind) @@ -22,7 +20,7 @@ RegisterJob::RegisterJob(const QString& kind, const QString& initialDeviceDisplayName, Omittable inhibitLogin) : BaseJob(HttpVerb::Post, QStringLiteral("RegisterJob"), - QStringLiteral("/_matrix/client/r0") % "/register", + makePath("/_matrix/client/r0", "/register"), queryToRegister(kind), {}, false) { QJsonObject _data; @@ -40,8 +38,7 @@ RegisterJob::RegisterJob(const QString& kind, RequestTokenToRegisterEmailJob::RequestTokenToRegisterEmailJob( const EmailValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenToRegisterEmailJob"), - QStringLiteral("/_matrix/client/r0") - % "/register/email/requestToken", + makePath("/_matrix/client/r0", "/register/email/requestToken"), false) { setRequestData(RequestData(toJson(body))); @@ -50,8 +47,7 @@ RequestTokenToRegisterEmailJob::RequestTokenToRegisterEmailJob( RequestTokenToRegisterMSISDNJob::RequestTokenToRegisterMSISDNJob( const MsisdnValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenToRegisterMSISDNJob"), - QStringLiteral("/_matrix/client/r0") - % "/register/msisdn/requestToken", + makePath("/_matrix/client/r0", "/register/msisdn/requestToken"), false) { setRequestData(RequestData(toJson(body))); @@ -61,7 +57,7 @@ ChangePasswordJob::ChangePasswordJob(const QString& newPassword, bool logoutDevices, const Omittable& auth) : BaseJob(HttpVerb::Post, QStringLiteral("ChangePasswordJob"), - QStringLiteral("/_matrix/client/r0") % "/account/password") + makePath("/_matrix/client/r0", "/account/password")) { QJsonObject _data; addParam<>(_data, QStringLiteral("new_password"), newPassword); @@ -74,8 +70,8 @@ RequestTokenToResetPasswordEmailJob::RequestTokenToResetPasswordEmailJob( const EmailValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenToResetPasswordEmailJob"), - QStringLiteral("/_matrix/client/r0") - % "/account/password/email/requestToken", + makePath("/_matrix/client/r0", + "/account/password/email/requestToken"), false) { setRequestData(RequestData(toJson(body))); @@ -85,8 +81,8 @@ RequestTokenToResetPasswordMSISDNJob::RequestTokenToResetPasswordMSISDNJob( const MsisdnValidationData& body) : BaseJob(HttpVerb::Post, QStringLiteral("RequestTokenToResetPasswordMSISDNJob"), - QStringLiteral("/_matrix/client/r0") - % "/account/password/msisdn/requestToken", + makePath("/_matrix/client/r0", + "/account/password/msisdn/requestToken"), false) { setRequestData(RequestData(toJson(body))); @@ -95,7 +91,7 @@ RequestTokenToResetPasswordMSISDNJob::RequestTokenToResetPasswordMSISDNJob( DeactivateAccountJob::DeactivateAccountJob( const Omittable& auth, const QString& idServer) : BaseJob(HttpVerb::Post, QStringLiteral("DeactivateAccountJob"), - QStringLiteral("/_matrix/client/r0") % "/account/deactivate") + makePath("/_matrix/client/r0", "/account/deactivate")) { QJsonObject _data; addParam(_data, QStringLiteral("auth"), auth); @@ -115,13 +111,13 @@ QUrl CheckUsernameAvailabilityJob::makeRequestUrl(QUrl baseUrl, const QString& username) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/register/available", + makePath("/_matrix/client/r0", + "/register/available"), queryToCheckUsernameAvailability(username)); } CheckUsernameAvailabilityJob::CheckUsernameAvailabilityJob(const QString& username) : BaseJob(HttpVerb::Get, QStringLiteral("CheckUsernameAvailabilityJob"), - QStringLiteral("/_matrix/client/r0") % "/register/available", + makePath("/_matrix/client/r0", "/register/available"), queryToCheckUsernameAvailability(username), {}, false) {} diff --git a/lib/csapi/report_content.cpp b/lib/csapi/report_content.cpp index ea906380..0a76d5b8 100644 --- a/lib/csapi/report_content.cpp +++ b/lib/csapi/report_content.cpp @@ -4,15 +4,13 @@ #include "report_content.h" -#include - using namespace Quotient; ReportContentJob::ReportContentJob(const QString& roomId, const QString& eventId, Omittable score, const QString& reason) : BaseJob(HttpVerb::Post, QStringLiteral("ReportContentJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/report/" % eventId) + makePath("/_matrix/client/r0", "/rooms/", roomId, "/report/", + eventId)) { QJsonObject _data; addParam(_data, QStringLiteral("score"), score); diff --git a/lib/csapi/room_send.cpp b/lib/csapi/room_send.cpp index 9fd8cb96..f80f9300 100644 --- a/lib/csapi/room_send.cpp +++ b/lib/csapi/room_send.cpp @@ -4,15 +4,13 @@ #include "room_send.h" -#include - using namespace Quotient; SendMessageJob::SendMessageJob(const QString& roomId, const QString& eventType, const QString& txnId, const QJsonObject& body) : BaseJob(HttpVerb::Put, QStringLiteral("SendMessageJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/send/" % eventType % "/" % txnId) + makePath("/_matrix/client/r0", "/rooms/", roomId, "/send/", + eventType, "/", txnId)) { setRequestData(RequestData(toJson(body))); addExpectedKey("event_id"); diff --git a/lib/csapi/room_state.cpp b/lib/csapi/room_state.cpp index 37e897fa..f6d2e6ec 100644 --- a/lib/csapi/room_state.cpp +++ b/lib/csapi/room_state.cpp @@ -4,8 +4,6 @@ #include "room_state.h" -#include - using namespace Quotient; SetRoomStateWithKeyJob::SetRoomStateWithKeyJob(const QString& roomId, @@ -13,8 +11,8 @@ SetRoomStateWithKeyJob::SetRoomStateWithKeyJob(const QString& roomId, const QString& stateKey, const QJsonObject& body) : BaseJob(HttpVerb::Put, QStringLiteral("SetRoomStateWithKeyJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/state/" % eventType % "/" % stateKey) + makePath("/_matrix/client/r0", "/rooms/", roomId, "/state/", + eventType, "/", stateKey)) { setRequestData(RequestData(toJson(body))); addExpectedKey("event_id"); diff --git a/lib/csapi/room_upgrades.cpp b/lib/csapi/room_upgrades.cpp index e3791b08..d4129cfb 100644 --- a/lib/csapi/room_upgrades.cpp +++ b/lib/csapi/room_upgrades.cpp @@ -4,14 +4,11 @@ #include "room_upgrades.h" -#include - using namespace Quotient; UpgradeRoomJob::UpgradeRoomJob(const QString& roomId, const QString& newVersion) : BaseJob(HttpVerb::Post, QStringLiteral("UpgradeRoomJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/upgrade") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/upgrade")) { QJsonObject _data; addParam<>(_data, QStringLiteral("new_version"), newVersion); diff --git a/lib/csapi/rooms.cpp b/lib/csapi/rooms.cpp index 3dd87021..5310aa32 100644 --- a/lib/csapi/rooms.cpp +++ b/lib/csapi/rooms.cpp @@ -4,24 +4,21 @@ #include "rooms.h" -#include - using namespace Quotient; QUrl GetOneRoomEventJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& eventId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/rooms/" % roomId % "/event/" - % eventId); + makePath("/_matrix/client/r0", "/rooms/", + roomId, "/event/", eventId)); } GetOneRoomEventJob::GetOneRoomEventJob(const QString& roomId, const QString& eventId) : BaseJob(HttpVerb::Get, QStringLiteral("GetOneRoomEventJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/event/" % eventId) + makePath("/_matrix/client/r0", "/rooms/", roomId, "/event/", + eventId)) {} QUrl GetRoomStateWithKeyJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, @@ -29,30 +26,29 @@ QUrl GetRoomStateWithKeyJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, const QString& stateKey) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/rooms/" % roomId % "/state/" - % eventType % "/" % stateKey); + makePath("/_matrix/client/r0", "/rooms/", + roomId, "/state/", eventType, "/", + stateKey)); } GetRoomStateWithKeyJob::GetRoomStateWithKeyJob(const QString& roomId, const QString& eventType, const QString& stateKey) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomStateWithKeyJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/state/" % eventType % "/" % stateKey) + makePath("/_matrix/client/r0", "/rooms/", roomId, "/state/", + eventType, "/", stateKey)) {} QUrl GetRoomStateJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/rooms/" % roomId % "/state"); + makePath("/_matrix/client/r0", "/rooms/", + roomId, "/state")); } GetRoomStateJob::GetRoomStateJob(const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomStateJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/state") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/state")) {} auto queryToGetMembersByRoom(const QString& at, const QString& membership, @@ -72,7 +68,7 @@ QUrl GetMembersByRoomJob::makeRequestUrl(QUrl baseUrl, const QString& roomId, { return BaseJob::makeRequestUrl( std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId % "/members", + makePath("/_matrix/client/r0", "/rooms/", roomId, "/members"), queryToGetMembersByRoom(at, membership, notMembership)); } @@ -81,8 +77,7 @@ GetMembersByRoomJob::GetMembersByRoomJob(const QString& roomId, const QString& membership, const QString& notMembership) : BaseJob(HttpVerb::Get, QStringLiteral("GetMembersByRoomJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/members", + makePath("/_matrix/client/r0", "/rooms/", roomId, "/members"), queryToGetMembersByRoom(at, membership, notMembership)) {} @@ -90,12 +85,12 @@ QUrl GetJoinedMembersByRoomJob::makeRequestUrl(QUrl baseUrl, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/rooms/" % roomId % "/joined_members"); + makePath("/_matrix/client/r0", "/rooms/", + roomId, "/joined_members")); } GetJoinedMembersByRoomJob::GetJoinedMembersByRoomJob(const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("GetJoinedMembersByRoomJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/joined_members") + makePath("/_matrix/client/r0", "/rooms/", roomId, + "/joined_members")) {} diff --git a/lib/csapi/search.cpp b/lib/csapi/search.cpp index 05ad871e..295dd1cc 100644 --- a/lib/csapi/search.cpp +++ b/lib/csapi/search.cpp @@ -4,8 +4,6 @@ #include "search.h" -#include - using namespace Quotient; auto queryToSearch(const QString& nextBatch) @@ -18,7 +16,7 @@ auto queryToSearch(const QString& nextBatch) SearchJob::SearchJob(const Categories& searchCategories, const QString& nextBatch) : BaseJob(HttpVerb::Post, QStringLiteral("SearchJob"), - QStringLiteral("/_matrix/client/r0") % "/search", + makePath("/_matrix/client/r0", "/search"), queryToSearch(nextBatch)) { QJsonObject _data; diff --git a/lib/csapi/sso_login_redirect.cpp b/lib/csapi/sso_login_redirect.cpp index 92601b4d..871d6ff6 100644 --- a/lib/csapi/sso_login_redirect.cpp +++ b/lib/csapi/sso_login_redirect.cpp @@ -4,8 +4,6 @@ #include "sso_login_redirect.h" -#include - using namespace Quotient; auto queryToRedirectToSSO(const QString& redirectUrl) @@ -18,14 +16,14 @@ auto queryToRedirectToSSO(const QString& redirectUrl) QUrl RedirectToSSOJob::makeRequestUrl(QUrl baseUrl, const QString& redirectUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/login/sso/redirect", + makePath("/_matrix/client/r0", + "/login/sso/redirect"), queryToRedirectToSSO(redirectUrl)); } RedirectToSSOJob::RedirectToSSOJob(const QString& redirectUrl) : BaseJob(HttpVerb::Get, QStringLiteral("RedirectToSSOJob"), - QStringLiteral("/_matrix/client/r0") % "/login/sso/redirect", + makePath("/_matrix/client/r0", "/login/sso/redirect"), queryToRedirectToSSO(redirectUrl), {}, false) {} @@ -40,15 +38,14 @@ QUrl RedirectToIdPJob::makeRequestUrl(QUrl baseUrl, const QString& idpId, const QString& redirectUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/login/sso/redirect/" % idpId, + makePath("/_matrix/client/r0", + "/login/sso/redirect/", idpId), queryToRedirectToIdP(redirectUrl)); } RedirectToIdPJob::RedirectToIdPJob(const QString& idpId, const QString& redirectUrl) : BaseJob(HttpVerb::Get, QStringLiteral("RedirectToIdPJob"), - QStringLiteral("/_matrix/client/r0") % "/login/sso/redirect/" - % idpId, + makePath("/_matrix/client/r0", "/login/sso/redirect/", idpId), queryToRedirectToIdP(redirectUrl), {}, false) {} diff --git a/lib/csapi/tags.cpp b/lib/csapi/tags.cpp index dc22dc18..f717de6e 100644 --- a/lib/csapi/tags.cpp +++ b/lib/csapi/tags.cpp @@ -4,30 +4,28 @@ #include "tags.h" -#include - using namespace Quotient; QUrl GetRoomTagsJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& roomId) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") % "/user/" - % userId % "/rooms/" % roomId % "/tags"); + makePath("/_matrix/client/r0", "/user/", + userId, "/rooms/", roomId, "/tags")); } GetRoomTagsJob::GetRoomTagsJob(const QString& userId, const QString& roomId) : BaseJob(HttpVerb::Get, QStringLiteral("GetRoomTagsJob"), - QStringLiteral("/_matrix/client/r0") % "/user/" % userId - % "/rooms/" % roomId % "/tags") + makePath("/_matrix/client/r0", "/user/", userId, "/rooms/", + roomId, "/tags")) {} SetRoomTagJob::SetRoomTagJob(const QString& userId, const QString& roomId, const QString& tag, Omittable order, const QVariantHash& additionalProperties) : BaseJob(HttpVerb::Put, QStringLiteral("SetRoomTagJob"), - QStringLiteral("/_matrix/client/r0") % "/user/" % userId - % "/rooms/" % roomId % "/tags/" % tag) + makePath("/_matrix/client/r0", "/user/", userId, "/rooms/", + roomId, "/tags/", tag)) { QJsonObject _data; fillJson(_data, additionalProperties); @@ -39,14 +37,14 @@ QUrl DeleteRoomTagJob::makeRequestUrl(QUrl baseUrl, const QString& userId, const QString& roomId, const QString& tag) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/user/" % userId % "/rooms/" % roomId - % "/tags/" % tag); + makePath("/_matrix/client/r0", "/user/", + userId, "/rooms/", roomId, "/tags/", + tag)); } DeleteRoomTagJob::DeleteRoomTagJob(const QString& userId, const QString& roomId, const QString& tag) : BaseJob(HttpVerb::Delete, QStringLiteral("DeleteRoomTagJob"), - QStringLiteral("/_matrix/client/r0") % "/user/" % userId - % "/rooms/" % roomId % "/tags/" % tag) + makePath("/_matrix/client/r0", "/user/", userId, "/rooms/", + roomId, "/tags/", tag)) {} diff --git a/lib/csapi/third_party_lookup.cpp b/lib/csapi/third_party_lookup.cpp index 93687a76..4c930668 100644 --- a/lib/csapi/third_party_lookup.cpp +++ b/lib/csapi/third_party_lookup.cpp @@ -4,34 +4,31 @@ #include "third_party_lookup.h" -#include - using namespace Quotient; QUrl GetProtocolsJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/thirdparty/protocols"); + makePath("/_matrix/client/r0", + "/thirdparty/protocols")); } GetProtocolsJob::GetProtocolsJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetProtocolsJob"), - QStringLiteral("/_matrix/client/r0") % "/thirdparty/protocols") + makePath("/_matrix/client/r0", "/thirdparty/protocols")) {} QUrl GetProtocolMetadataJob::makeRequestUrl(QUrl baseUrl, const QString& protocol) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/thirdparty/protocol/" % protocol); + makePath("/_matrix/client/r0", + "/thirdparty/protocol/", protocol)); } GetProtocolMetadataJob::GetProtocolMetadataJob(const QString& protocol) : BaseJob(HttpVerb::Get, QStringLiteral("GetProtocolMetadataJob"), - QStringLiteral("/_matrix/client/r0") % "/thirdparty/protocol/" - % protocol) + makePath("/_matrix/client/r0", "/thirdparty/protocol/", protocol)) {} auto queryToQueryLocationByProtocol(const QString& searchFields) @@ -46,16 +43,15 @@ QUrl QueryLocationByProtocolJob::makeRequestUrl(QUrl baseUrl, const QString& searchFields) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/thirdparty/location/" % protocol, + makePath("/_matrix/client/r0", + "/thirdparty/location/", protocol), queryToQueryLocationByProtocol(searchFields)); } QueryLocationByProtocolJob::QueryLocationByProtocolJob( const QString& protocol, const QString& searchFields) : BaseJob(HttpVerb::Get, QStringLiteral("QueryLocationByProtocolJob"), - QStringLiteral("/_matrix/client/r0") % "/thirdparty/location/" - % protocol, + makePath("/_matrix/client/r0", "/thirdparty/location/", protocol), queryToQueryLocationByProtocol(searchFields)) {} @@ -71,16 +67,15 @@ QUrl QueryUserByProtocolJob::makeRequestUrl(QUrl baseUrl, const QString& fields) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/thirdparty/user/" % protocol, + makePath("/_matrix/client/r0", + "/thirdparty/user/", protocol), queryToQueryUserByProtocol(fields)); } QueryUserByProtocolJob::QueryUserByProtocolJob(const QString& protocol, const QString& fields) : BaseJob(HttpVerb::Get, QStringLiteral("QueryUserByProtocolJob"), - QStringLiteral("/_matrix/client/r0") % "/thirdparty/user/" - % protocol, + makePath("/_matrix/client/r0", "/thirdparty/user/", protocol), queryToQueryUserByProtocol(fields)) {} @@ -94,14 +89,14 @@ auto queryToQueryLocationByAlias(const QString& alias) QUrl QueryLocationByAliasJob::makeRequestUrl(QUrl baseUrl, const QString& alias) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/thirdparty/location", + makePath("/_matrix/client/r0", + "/thirdparty/location"), queryToQueryLocationByAlias(alias)); } QueryLocationByAliasJob::QueryLocationByAliasJob(const QString& alias) : BaseJob(HttpVerb::Get, QStringLiteral("QueryLocationByAliasJob"), - QStringLiteral("/_matrix/client/r0") % "/thirdparty/location", + makePath("/_matrix/client/r0", "/thirdparty/location"), queryToQueryLocationByAlias(alias)) {} @@ -115,13 +110,13 @@ auto queryToQueryUserByID(const QString& userid) QUrl QueryUserByIDJob::makeRequestUrl(QUrl baseUrl, const QString& userid) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/thirdparty/user", + makePath("/_matrix/client/r0", + "/thirdparty/user"), queryToQueryUserByID(userid)); } QueryUserByIDJob::QueryUserByIDJob(const QString& userid) : BaseJob(HttpVerb::Get, QStringLiteral("QueryUserByIDJob"), - QStringLiteral("/_matrix/client/r0") % "/thirdparty/user", + makePath("/_matrix/client/r0", "/thirdparty/user"), queryToQueryUserByID(userid)) {} diff --git a/lib/csapi/third_party_membership.cpp b/lib/csapi/third_party_membership.cpp index fda772d2..59275e41 100644 --- a/lib/csapi/third_party_membership.cpp +++ b/lib/csapi/third_party_membership.cpp @@ -4,16 +4,13 @@ #include "third_party_membership.h" -#include - using namespace Quotient; InviteBy3PIDJob::InviteBy3PIDJob(const QString& roomId, const QString& idServer, const QString& idAccessToken, const QString& medium, const QString& address) : BaseJob(HttpVerb::Post, QStringLiteral("InviteBy3PIDJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/invite") + makePath("/_matrix/client/r0", "/rooms/", roomId, "/invite")) { QJsonObject _data; addParam<>(_data, QStringLiteral("id_server"), idServer); diff --git a/lib/csapi/to_device.cpp b/lib/csapi/to_device.cpp index 3775174d..628e8314 100644 --- a/lib/csapi/to_device.cpp +++ b/lib/csapi/to_device.cpp @@ -4,16 +4,14 @@ #include "to_device.h" -#include - using namespace Quotient; SendToDeviceJob::SendToDeviceJob( const QString& eventType, const QString& txnId, const QHash>& messages) : BaseJob(HttpVerb::Put, QStringLiteral("SendToDeviceJob"), - QStringLiteral("/_matrix/client/r0") % "/sendToDevice/" - % eventType % "/" % txnId) + makePath("/_matrix/client/r0", "/sendToDevice/", eventType, "/", + txnId)) { QJsonObject _data; addParam<>(_data, QStringLiteral("messages"), messages); diff --git a/lib/csapi/typing.cpp b/lib/csapi/typing.cpp index 8e214053..c9673118 100644 --- a/lib/csapi/typing.cpp +++ b/lib/csapi/typing.cpp @@ -4,15 +4,13 @@ #include "typing.h" -#include - using namespace Quotient; SetTypingJob::SetTypingJob(const QString& userId, const QString& roomId, bool typing, Omittable timeout) : BaseJob(HttpVerb::Put, QStringLiteral("SetTypingJob"), - QStringLiteral("/_matrix/client/r0") % "/rooms/" % roomId - % "/typing/" % userId) + makePath("/_matrix/client/r0", "/rooms/", roomId, "/typing/", + userId)) { QJsonObject _data; addParam<>(_data, QStringLiteral("typing"), typing); diff --git a/lib/csapi/users.cpp b/lib/csapi/users.cpp index a0279d7e..48b727f0 100644 --- a/lib/csapi/users.cpp +++ b/lib/csapi/users.cpp @@ -4,14 +4,12 @@ #include "users.h" -#include - using namespace Quotient; SearchUserDirectoryJob::SearchUserDirectoryJob(const QString& searchTerm, Omittable limit) : BaseJob(HttpVerb::Post, QStringLiteral("SearchUserDirectoryJob"), - QStringLiteral("/_matrix/client/r0") % "/user_directory/search") + makePath("/_matrix/client/r0", "/user_directory/search")) { QJsonObject _data; addParam<>(_data, QStringLiteral("search_term"), searchTerm); diff --git a/lib/csapi/versions.cpp b/lib/csapi/versions.cpp index 9003e27f..a1efc33e 100644 --- a/lib/csapi/versions.cpp +++ b/lib/csapi/versions.cpp @@ -4,20 +4,17 @@ #include "versions.h" -#include - using namespace Quotient; QUrl GetVersionsJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client") - % "/versions"); + makePath("/_matrix/client", "/versions")); } GetVersionsJob::GetVersionsJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetVersionsJob"), - QStringLiteral("/_matrix/client") % "/versions", false) + makePath("/_matrix/client", "/versions"), false) { addExpectedKey("versions"); } diff --git a/lib/csapi/voip.cpp b/lib/csapi/voip.cpp index 43170057..c748ad94 100644 --- a/lib/csapi/voip.cpp +++ b/lib/csapi/voip.cpp @@ -4,18 +4,15 @@ #include "voip.h" -#include - using namespace Quotient; QUrl GetTurnServerJob::makeRequestUrl(QUrl baseUrl) { - return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/voip/turnServer"); + return BaseJob::makeRequestUrl( + std::move(baseUrl), makePath("/_matrix/client/r0", "/voip/turnServer")); } GetTurnServerJob::GetTurnServerJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetTurnServerJob"), - QStringLiteral("/_matrix/client/r0") % "/voip/turnServer") + makePath("/_matrix/client/r0", "/voip/turnServer")) {} diff --git a/lib/csapi/wellknown.cpp b/lib/csapi/wellknown.cpp index 1aa0a90b..0b441279 100644 --- a/lib/csapi/wellknown.cpp +++ b/lib/csapi/wellknown.cpp @@ -4,18 +4,15 @@ #include "wellknown.h" -#include - using namespace Quotient; QUrl GetWellknownJob::makeRequestUrl(QUrl baseUrl) { return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/.well-known") - % "/matrix/client"); + makePath("/.well-known", "/matrix/client")); } GetWellknownJob::GetWellknownJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetWellknownJob"), - QStringLiteral("/.well-known") % "/matrix/client", false) + makePath("/.well-known", "/matrix/client"), false) {} diff --git a/lib/csapi/whoami.cpp b/lib/csapi/whoami.cpp index 73f0298e..ed8a9817 100644 --- a/lib/csapi/whoami.cpp +++ b/lib/csapi/whoami.cpp @@ -4,20 +4,17 @@ #include "whoami.h" -#include - using namespace Quotient; QUrl GetTokenOwnerJob::makeRequestUrl(QUrl baseUrl) { - return BaseJob::makeRequestUrl(std::move(baseUrl), - QStringLiteral("/_matrix/client/r0") - % "/account/whoami"); + return BaseJob::makeRequestUrl( + std::move(baseUrl), makePath("/_matrix/client/r0", "/account/whoami")); } GetTokenOwnerJob::GetTokenOwnerJob() : BaseJob(HttpVerb::Get, QStringLiteral("GetTokenOwnerJob"), - QStringLiteral("/_matrix/client/r0") % "/account/whoami") + makePath("/_matrix/client/r0", "/account/whoami")) { addExpectedKey("user_id"); } -- cgit v1.2.3 From f89285a3bd7c093622be966823d0ae1254822905 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Mon, 4 Oct 2021 18:48:12 +0200 Subject: Room: use more modern Connection API --- lib/room.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/room.cpp b/lib/room.cpp index fb65fd84..a923bf9a 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1180,9 +1180,8 @@ QUrl Room::urlToThumbnail(const QString& eventId) const if (event->hasThumbnail()) { auto* thumbnail = event->content()->thumbnailInfo(); Q_ASSERT(thumbnail != nullptr); - return MediaThumbnailJob::makeRequestUrl(connection()->homeserver(), - thumbnail->url, - thumbnail->imageSize); + return connection()->getUrlForApi( + thumbnail->url, thumbnail->imageSize); } qCDebug(MAIN) << "Event" << eventId << "has no thumbnail"; return {}; @@ -1193,8 +1192,7 @@ QUrl Room::urlToDownload(const QString& eventId) const if (auto* event = d->getEventWithFile(eventId)) { auto* fileInfo = event->content()->fileInfo(); Q_ASSERT(fileInfo != nullptr); - return DownloadFileJob::makeRequestUrl(connection()->homeserver(), - fileInfo->url); + return connection()->getUrlForApi(fileInfo->url); } return {}; } -- cgit v1.2.3 From 67da887e864d292608e7132388f518596374af34 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 5 Oct 2021 03:43:22 +0200 Subject: BaseJob::StatusCode: officially deprecate most *Error enumerators --- lib/connection.cpp | 8 ++++---- lib/jobs/basejob.cpp | 42 +++++++++++++++++++++--------------------- lib/jobs/basejob.h | 34 ++++++++++++++++------------------ 3 files changed, 41 insertions(+), 43 deletions(-) (limited to 'lib') diff --git a/lib/connection.cpp b/lib/connection.cpp index 4abf5097..093362ab 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -288,7 +288,7 @@ void Connection::resolveServer(const QString& mxid) if (d->resolverJob->error() == BaseJob::Abandoned) return; - if (d->resolverJob->error() != BaseJob::NotFoundError) { + if (d->resolverJob->error() != BaseJob::NotFound) { if (!d->resolverJob->status().good()) { qCWarning(MAIN) << "Fetching .well-known file failed, FAIL_PROMPT"; @@ -401,7 +401,7 @@ void Connection::reloadCapabilities() " disabling version upgrade recommendations to reduce noise"; }); connect(d->capabilitiesJob, &BaseJob::failure, this, [this] { - if (d->capabilitiesJob->error() == BaseJob::IncorrectRequestError) + if (d->capabilitiesJob->error() == BaseJob::IncorrectRequest) qCDebug(MAIN) << "Server doesn't support /capabilities;" " version upgrade recommendations won't be issued"; }); @@ -1058,7 +1058,7 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) connect(leaveJob, &BaseJob::result, this, [this, leaveJob, forgetJob, room] { if (leaveJob->error() == BaseJob::Success - || leaveJob->error() == BaseJob::NotFoundError) { + || leaveJob->error() == BaseJob::NotFound) { run(forgetJob); // If the matching /sync response hasn't arrived yet, // mark the room for explicit deletion @@ -1077,7 +1077,7 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) connect(forgetJob, &BaseJob::result, this, [this, id, forgetJob] { // Leave room in case of success, or room not known by server if (forgetJob->error() == BaseJob::Success - || forgetJob->error() == BaseJob::NotFoundError) + || forgetJob->error() == BaseJob::NotFound) d->removeRoom(id); // Delete the room from roomMap else qCWarning(MAIN).nospace() << "Error forgetting room " << id << ": " diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 73762e4f..a7921c61 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -24,7 +24,7 @@ BaseJob::StatusCode BaseJob::Status::fromHttpCode(int httpCode) { // Based on https://en.wikipedia.org/wiki/List_of_HTTP_status_codes if (httpCode / 10 == 41) // 41x errors - return httpCode == 410 ? IncorrectRequestError : NotFoundError; + return httpCode == 410 ? IncorrectRequest : NotFound; switch (httpCode) { case 401: return Unauthorised; @@ -32,19 +32,19 @@ BaseJob::StatusCode BaseJob::Status::fromHttpCode(int httpCode) case 403: case 407: // clang-format on return ContentAccessError; case 404: - return NotFoundError; + return NotFound; // clang-format off case 400: case 405: case 406: case 426: case 428: case 505: // clang-format on case 494: // Unofficial nginx "Request header too large" case 497: // Unofficial nginx "HTTP request sent to HTTPS port" - return IncorrectRequestError; + return IncorrectRequest; case 429: - return TooManyRequestsError; + return TooManyRequests; case 501: case 510: - return RequestNotImplementedError; + return RequestNotImplemented; case 511: - return NetworkAuthRequiredError; + return NetworkAuthRequired; default: return NetworkError; } @@ -365,7 +365,7 @@ void BaseJob::initiate(ConnectionData* connData, bool inBackground) qCCritical(d->logCat) << "Developers, ensure the Connection is valid before using it"; Q_ASSERT(false); - setStatus(IncorrectRequestError, tr("Invalid server connection")); + setStatus(IncorrectRequest, tr("Invalid server connection")); } // The status is no good, finalise QTimer::singleShot(0, this, &BaseJob::finishJob); @@ -528,7 +528,7 @@ BaseJob::Status BaseJob::prepareError() // of if's below will fall through to `return NoError` at the end const auto& errorJson = jsonData(); const auto errCode = errorJson.value("errcode"_ls).toString(); - if (error() == TooManyRequestsError || errCode == "M_LIMIT_EXCEEDED") { + if (error() == TooManyRequests || errCode == "M_LIMIT_EXCEEDED") { QString msg = tr("Too many requests"); int64_t retryAfterMs = errorJson.value("retry_after_ms"_ls).toInt(-1); if (retryAfterMs >= 0) @@ -538,16 +538,16 @@ BaseJob::Status BaseJob::prepareError() d->connection->limitRate(milliseconds(retryAfterMs)); - return { TooManyRequestsError, msg }; + return { TooManyRequests, msg }; } if (errCode == "M_CONSENT_NOT_GIVEN") { d->errorUrl = QUrl(errorJson.value("consent_uri"_ls).toString()); - return { UserConsentRequiredError }; + return { UserConsentRequired }; } if (errCode == "M_UNSUPPORTED_ROOM_VERSION" || errCode == "M_INCOMPATIBLE_ROOM_VERSION") - return { UnsupportedRoomVersionError, + return { UnsupportedRoomVersion, errorJson.contains("room_version"_ls) ? tr("Requested room version: %1") .arg(errorJson.value("room_version"_ls).toString()) @@ -729,27 +729,27 @@ QString BaseJob::statusCaption() const return tr("Request was abandoned"); case NetworkError: return tr("Network problems"); - case TimeoutError: + case Timeout: return tr("Request timed out"); case Unauthorised: return tr("Unauthorised request"); case ContentAccessError: return tr("Access error"); - case NotFoundError: + case NotFound: return tr("Not found"); - case IncorrectRequestError: + case IncorrectRequest: return tr("Invalid request"); - case IncorrectResponseError: + case IncorrectResponse: return tr("Response could not be parsed"); - case TooManyRequestsError: + case TooManyRequests: return tr("Too many requests"); - case RequestNotImplementedError: + case RequestNotImplemented: return tr("Function not implemented by the server"); - case NetworkAuthRequiredError: + case NetworkAuthRequired: return tr("Network authentication required"); - case UserConsentRequiredError: + case UserConsentRequired: return tr("User consent required"); - case UnsupportedRoomVersionError: + case UnsupportedRoomVersion: return tr("The server does not support the needed room version"); default: return tr("Request failed"); @@ -811,7 +811,7 @@ void BaseJob::abandon() void BaseJob::timeout() { - setStatus(TimeoutError, "The job has timed out"); + setStatus(Timeout, "The job has timed out"); finishJob(); } diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 81455307..e0910a26 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -33,6 +33,10 @@ class BaseJob : public QObject { } public: +#define WITH_DEPRECATED_ERROR_VERSION(Recommended) \ + Recommended, Recommended##Error Q_DECL_ENUMERATOR_DEPRECATED_X( \ + "Use " #Recommended) = Recommended + /*! The status code of a job * * Every job is created in Unprepared status; upon calling prepare() @@ -43,7 +47,7 @@ public: */ enum StatusCode { Success = 0, - NoError = Success, // To be compatible with Qt conventions + NoError = Success, Pending = 1, WarningLevel = 20, //< Warnings have codes starting from this UnexpectedResponseType = 21, @@ -52,26 +56,18 @@ public: Abandoned = 50, //< A tiny period between abandoning and object deletion ErrorLevel = 100, //< Errors have codes starting from this NetworkError = 101, - Timeout, - TimeoutError = Timeout, + WITH_DEPRECATED_ERROR_VERSION(Timeout), Unauthorised, ContentAccessError, - NotFoundError, - IncorrectRequest, - IncorrectRequestError = IncorrectRequest, - IncorrectResponse, - IncorrectResponseError = IncorrectResponse, - TooManyRequests, - TooManyRequestsError = TooManyRequests, + WITH_DEPRECATED_ERROR_VERSION(NotFound), + WITH_DEPRECATED_ERROR_VERSION(IncorrectRequest), + WITH_DEPRECATED_ERROR_VERSION(IncorrectResponse), + WITH_DEPRECATED_ERROR_VERSION(TooManyRequests), RateLimited = TooManyRequests, - RequestNotImplemented, - RequestNotImplementedError = RequestNotImplemented, - UnsupportedRoomVersion, - UnsupportedRoomVersionError = UnsupportedRoomVersion, - NetworkAuthRequired, - NetworkAuthRequiredError = NetworkAuthRequired, - UserConsentRequired, - UserConsentRequiredError = UserConsentRequired, + WITH_DEPRECATED_ERROR_VERSION(RequestNotImplemented), + WITH_DEPRECATED_ERROR_VERSION(UnsupportedRoomVersion), + WITH_DEPRECATED_ERROR_VERSION(NetworkAuthRequired), + WITH_DEPRECATED_ERROR_VERSION(UserConsentRequired), CannotLeaveRoom, UserDeactivated, FileError, @@ -79,6 +75,8 @@ public: }; Q_ENUM(StatusCode) +#undef WITH_DEPRECATED_ERROR_VERSION + template static QByteArray makePath(StrTs&&... parts) { -- cgit v1.2.3 From 9cfd6ad6a4651280a12099d1a92432f07fc5aae0 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 5 Oct 2021 03:44:18 +0200 Subject: BaseJob: refresh error handling - BaseJob::prepareError() slightly updated to get the current status instead of checking the returned value outside in gotReply() - BaseJob::gotReply() no more reports on 429 Too Many Requests twice (the first time with dubious "Too Many Requests: Unknown error") --- lib/jobs/basejob.cpp | 46 +++++++++++++++++++++++----------------------- lib/jobs/basejob.h | 6 ++++-- 2 files changed, 27 insertions(+), 25 deletions(-) (limited to 'lib') diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index a7921c61..971fea7b 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -415,42 +415,42 @@ BaseJob::Status BaseJob::Private::parseJson() void BaseJob::gotReply() { - setStatus(checkReply(reply())); - - if (status().good() - && d->expectedContentTypes == QByteArrayList { "application/json" }) { + // Defer actually updating the status until it's finalised + auto statusSoFar = checkReply(reply()); + if (statusSoFar.good() + && d->expectedContentTypes == QByteArrayList { "application/json" }) // + { d->rawResponse = reply()->readAll(); - setStatus(d->parseJson()); - if (status().good() && !expectedKeys().empty()) { + statusSoFar = d->parseJson(); + if (statusSoFar.good() && !expectedKeys().empty()) { const auto& responseObject = jsonData(); QByteArrayList missingKeys; for (const auto& k: expectedKeys()) if (!responseObject.contains(k)) missingKeys.push_back(k); if (!missingKeys.empty()) - setStatus(IncorrectResponse, tr("Required JSON keys missing: ") - + missingKeys.join()); + statusSoFar = { IncorrectResponse, + tr("Required JSON keys missing: ") + + missingKeys.join() }; } + setStatus(statusSoFar); if (!status().good()) // Bad JSON in a "good" reply: bail out return; - } // else { + } // If the endpoint expects anything else than just (API-related) JSON // reply()->readAll() is not performed and the whole reply processing // is left to derived job classes: they may read it piecemeal or customise // per content type in prepareResult(), or even have read it already // (see, e.g., DownloadFileJob). - // } - - if (status().good()) + if (statusSoFar.good()) { setStatus(prepareResult()); - else { - d->rawResponse = reply()->readAll(); - qCDebug(d->logCat).noquote() - << "Error body (truncated if long):" << rawDataSample(500); - // Parse the error payload and update the status if needed - if (const auto newStatus = prepareError(); !newStatus.good()) - setStatus(newStatus); + return; } + + d->rawResponse = reply()->readAll(); + qCDebug(d->logCat).noquote() + << "Error body (truncated if long):" << rawDataSample(500); + setStatus(prepareError(statusSoFar)); } bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) @@ -515,7 +515,7 @@ BaseJob::Status BaseJob::checkReply(const QNetworkReply* reply) const BaseJob::Status BaseJob::prepareResult() { return Success; } -BaseJob::Status BaseJob::prepareError() +BaseJob::Status BaseJob::prepareError(Status currentStatus) { // Try to make sense of the error payload but be prepared for all kinds // of unexpected stuff (raw HTML, plain text, foreign JSON among those) @@ -525,7 +525,7 @@ BaseJob::Status BaseJob::prepareError() // By now, if d->parseJson() above succeeded then jsonData() will return // a valid JSON object - or an empty object otherwise (in which case most - // of if's below will fall through to `return NoError` at the end + // of if's below will fall through retaining the current status) const auto& errorJson = jsonData(); const auto errCode = errorJson.value("errcode"_ls).toString(); if (error() == TooManyRequests || errCode == "M_LIMIT_EXCEEDED") { @@ -560,9 +560,9 @@ BaseJob::Status BaseJob::prepareError() // Not localisable on the client side if (errorJson.contains("error"_ls)) // Keep the code, update the message - return { d->status.code, errorJson.value("error"_ls).toString() }; + return { currentStatus.code, errorJson.value("error"_ls).toString() }; - return NoError; // Retain the status if the error payload is not recognised + return currentStatus; // The error payload is not recognised } QJsonValue BaseJob::takeValueFromJson(const QString& key) diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index e0910a26..119d7cce 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -399,10 +399,12 @@ protected: * was not good (usually because of an unsuccessful HTTP code). * The base implementation assumes Matrix JSON error object in the body; * overrides are strongly recommended to call it for all stock Matrix - * responses as early as possible but in addition can process custom errors, + * responses as early as possible and only then process custom errors, * with JSON or non-JSON payload. + * + * \return updated (if necessary) job status */ - virtual Status prepareError(); + virtual Status prepareError(Status currentStatus); /*! \brief Get direct access to the JSON response object in the job * -- cgit v1.2.3 From 107471447a62663eaf97b4b982d8c3f3e1b3364e Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 5 Oct 2021 03:44:43 +0200 Subject: Connection: fix C++20 warnings --- lib/connection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/connection.cpp b/lib/connection.cpp index 093362ab..1fe0d2d0 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -341,7 +341,7 @@ void Connection::loginWithPassword(const QString& userId, const QString& initialDeviceName, const QString& deviceId) { - d->checkAndConnect(userId, [=] { + d->checkAndConnect(userId, [=,this] { d->loginToServer(LoginFlows::Password.type, makeUserIdentifier(userId), password, /*token*/ "", deviceId, initialDeviceName); }, LoginFlows::Password); @@ -1716,7 +1716,7 @@ void Connection::getTurnServers() { auto job = callApi(); connect(job, &GetTurnServerJob::success, this, - [=] { emit turnServersChanged(job->data()); }); + [this,job] { emit turnServersChanged(job->data()); }); } const QString Connection::SupportedRoomVersion::StableTag = -- cgit v1.2.3