Skip to content

Commit 9827025

Browse files
authored
Merge #804(kitsune): Releasing 0.9 RC
2 parents 4a6f0bd + 4b2e394 commit 9827025

30 files changed

+566
-423
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ endif()
55

66
set(API_VERSION "0.9")
77
project(Quotient VERSION "${API_VERSION}.0" LANGUAGES CXX)
8-
set(PRE_STAGE "beta")
8+
set(PRE_STAGE "rc")
99
set(FULL_VERSION ${PROJECT_VERSION}~${PRE_STAGE})
1010

1111
message(STATUS)

CONTRIBUTING.md

Lines changed: 55 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ to make the review easier.
126126

127127
### C++ feature set
128128

129-
As of Quotient 0.9, the C++ standard for newly written code is C++20, save for a few exceptions
130-
that the currently supported toolchains still don't have, most notably:
129+
As of Quotient 0.9, the C++ standard for new code is C++20, except a few features that currently
130+
supported toolchains still don't have, most notably:
131131
- template parameteres for type aliases and aggregates still cannot be deduced yet, you have
132132
to explicitly specify those;
133133
- modules support, while formally there, is missing standard library header units; sticking with
@@ -151,22 +151,20 @@ use `// clang-format off` and `// clang-format on` to protect them.
151151

152152
Most fundamental things from `.clang-format`:
153153
* We (mostly) use Webkit style: 4-space indents, no tabs, no trailing spaces, no last empty lines.
154-
If you spot code that doesn't follow this, fix it on the spot, thank you.
154+
If you see code that doesn't follow this, fix it on the spot, thank you.
155155
* Prefer keeping lines within 100 characters. Slight overflows are ok if that
156156
helps readability. Ideally, just use `clang-format` to format lines.
157157

158158
### API conventions
159159

160-
All non-inline symbols (functions, classes/structs, even namespace-level static
161-
variables) that are intended for use in client code must be declared with
162-
`QUOTIENT_API` macro (the macro itself is defined in the dedicated
163-
`quotient_export.h` file). This is concerned with symbols visibility in
164-
dynamic/shared libraries: the macro marks these symbols for exporting in
165-
the library symbol table. If you forget to use this macro where needed you will
166-
get linkage errors if you're lucky, obscure runtime errors otherwise (such as
167-
split-brained singleton instances). You only need to use the macro on the
168-
namespace level; inner symbols (member functions, e.g.) are exported if
169-
their class is exported.
160+
All non-inline symbols (functions, classes/structs, even namespace-level static variables) that are
161+
intended for use in client code must be declared with `QUOTIENT_API` macro (the macro itself is
162+
defined in the dedicated `quotient_export.h` file) in order to export them in the library symbol
163+
table when it is compiled as dynamic/shared. If you forget to use this macro and a client
164+
application uses the symbol there will be linkage errors in a lucky case and obscure runtime errors
165+
(such as split-brained singleton instances) otherwise. You only need to use the macro
166+
on the namespace level; nested symbols (member functions, e.g.) are exported if their class is
167+
exported.
170168

171169
Some header files of the library are not intended to be (directly) included by
172170
clients - these header files have names ending with `_p.h` (e.g.
@@ -183,17 +181,14 @@ so tread carefully).
183181

184182
### Generated C++ code for CS API
185183

186-
The code in `Quotient/csapi`, `Quotient/identity` and
187-
`Quotient/application-service`, although stored in Git, is actually generated
188-
from the official Matrix Client-Server API definition files. Make sure to read
189-
[CODE_GENERATION.md](./CODE_GENERATION.md) before trying to change anything
190-
there.
184+
The code in `Quotient/csapi`, `Quotient/identity` and `Quotient/application-service`, although
185+
stored in Git, is actually generated from the official Matrix Client-Server API definition files.
186+
Make sure to read [CODE_GENERATION.md](./CODE_GENERATION.md) before trying to change anything there.
191187

192188

193189
## Documentation changes
194190

195-
Most of the documentation is in Markdown format. All Markdown files use the
196-
`.md` filename extension.
191+
Most of the documentation is in Markdown format; the file names use the `.md` extension.
197192

198193
Where reasonable, limit yourself to Markdown that will be accepted by different
199194
markdown processors (e.g., what is specified by CommonMark or the original
@@ -210,12 +205,10 @@ by GitHub when it renders issue or pull comments; in those cases
210205
unfortunately this other algorithm is *also* called GitHub-flavoured markdown.
211206
(Yes, it would be better if there were different names for different things.)
212207

213-
In your markdown, please don't use tab characters and avoid "bare" URLs.
214-
In a hyperlink, the link text and URL should be on the same line.
215-
Both in C/C++ code comments and Markdown documents, try to keep your lines
216-
within the 100-character limit _except hyperlinks_ (wrapping breaks them). Some
217-
historical text may not follow that rule - feel free to reformat those parts
218-
when you edit them.
208+
Don't use tab characters and avoid "bare" URLs. In a hyperlink, the link text and URL should be
209+
on the same line. Both in C/C++ code comments and Markdown documents, try to keep your lines
210+
within the 100-character limit _except hyperlinks_ (wrapping breaks them). Some historical text
211+
may not follow that rule - feel free to reformat those parts when you edit them.
219212

220213
Do not use trailing two spaces for line breaks, since these cannot be seen
221214
and may be silently removed by some tools. If, for whatever reason, a blank line
@@ -232,11 +225,11 @@ Further sections are for those who's going to actively hack on the library code.
232225

233226
### More on code style and formatting
234227

235-
* Do not use `struct` when you have protected or private members; only use it
236-
to define plain-old-data structures, with maybe just a function or two among
237-
public members but no substantial behaviour. If you need access control or
238-
specific logic tightly coupled to the data structure, make it a `class`
239-
instead and consider if you still want to keep its member variables public.
228+
* Prefer `class` over `struct` when you have protected or private members in the type; `struct` is
229+
meant for plain-old-data structures, with maybe just a function or two among public members
230+
but no substantial behaviour. If you need access control or specific logic tightly coupled to
231+
the data structure, make it a `class` and consider if you still want to keep its member variables
232+
public.
240233

241234
* For newly created classes, keep to
242235
[the rule of 3/5/0](http://en.cppreference.com/w/cpp/language/rule_of_three).
@@ -250,57 +243,44 @@ Further sections are for those who's going to actively hack on the library code.
250243
Classes without a default constructor are a problem too. Examples of that
251244
are `SyncRoomData` and `EventsArray<>`. Again, you can use STL containers
252245
for structures having those but consider the implications.
253-
* So, the implications. Because QML doesn't know about most of STL containers and cannot pull data
254-
out of them, you're only free to use STL containers in backend code (in the simplest case,
255-
within one .cpp file). The API exposing these containers can only be used from C++ code, with
256-
`std::vector` being a notable exception that QML knows about (but you still can't read
257-
uncopyable vectors such as `EventsArray<>`, as the previous bullet already said). For these
258-
cases you have to provide external means to iterate through the container and consume data
259-
from it; exposing a Qt item model is most natural to Qt code. If you don't provide such other
260-
means, expect questions at your pull request.
261-
* Notwithstanding the above (you're not going to use smart pointers with QML
262-
anyway), prefer `std::unique_ptr<>` over `QScopedPointer<>` as it gives
263-
stronger guarantees; also, some features of `QScopedPointer` are deprecated
264-
in Qt 6.
265-
266-
* Always use `QVector` instead of `QList` unless Qt's own API uses it - see the
267-
[great article by Marc Mutz on Qt containers](https://marcmutz.wordpress.com/effective-qt/containers/)
268-
for details. With Qt 6, these two become the same type matching what used
269-
to be `QVector` in Qt 5.
270-
271-
(Note: unfortunately, `QVector` is a type alias in Qt 6 and that breaks
272-
templated code because type deduction doesn't work with aliases. This breakage
273-
will go away as compilers adopt C++23 sufficiently but it may take a
274-
couple more years, as of this writing; in the meantime, the fix boils down
275-
to specifying the template parameter of `QVector` explicitly.)
246+
* So, the implications. QML doesn't know about most of STL containers and in any case requires
247+
data types passed to it (let alone from it) to be default-constructible and copyable. For that
248+
reason, STL containers can only be used in backend code that is not meant for consumption by
249+
QML. The only STL container mapped to QML as of Qt 6.6 is `std::vector`; and even then you
250+
still can't expose uncopyable vectors such as `EventsArray<>` to QML. For these cases you have
251+
to provide external means to iterate through the container and consume data from it; exposing
252+
a Qt item model is most natural to Qt code. If you don't provide such other means, expect
253+
questions at your pull request.
254+
* Prefer `std::unique_ptr<>` over `QScopedPointer<>`; `std::as_const()` to `qAsConst()`;
255+
`std::swap()` to `qSwap()` etc.; basically, do not use compat facilities provided by Qt if the
256+
standard library provides an _equivalent_ facility.
276257

277258
* When you write logs within the library always use logging categories defined in
278259
`logging_categories_p.h` instead of plain `qDebug()`, to avoid a log line being assigned
279260
the default category. `qCDebug(CATEGORY)` is the preferred form; `qDebug(CATEGORY)` (without `C`)
280261
is accepted as well. Do not add new logging categories without necessity; if you do, make sure
281262
to add the new category to `logging_categories_p.h`, so that there's a central reference for all
282-
of them (mentioned in README.md, by the way).
263+
of them (also listed in README.md, by the way).
283264

284265
### Comments
285266

286-
Whenever you add a new call to the library API that you expect to be used
287-
from client code, make sure to supply a proper doc-comment along with the call.
288-
Quotient uses the Doxygen C++-styled doc-comments (`//!`, `\brief`); some legacy
289-
code may use Javadoc (`/** ... */`, `@brief`) or C-styled Doxygen (`/*! ... */`)
290-
but that is not encouraged any more. Some parts are not documented at all;
291-
adding doc-comments to them and/or converting the existing ones to the assumed
292-
style is highly encouraged; it's also a nice and easy first-time contribution.
267+
Whenever you add or change the library API, make sure to supply a proper doc-comment along with
268+
the call. Quotient uses the Doxygen C++-styled doc-comments (`//!`, `\brief`); some legacy code
269+
may use Javadoc (`/** ... */`, `@brief`) or C-styled Doxygen (`/*! ... */`) but that is
270+
not encouraged any more. Some parts are not documented at all; adding doc-comments to them
271+
and/or converting the existing ones to the assumed style is highly encouraged; it's also a nice
272+
and easy first-time contribution.
293273

294-
Use `\brief` for the summary, and follow with details after
295-
an empty doc-comment line, using `\param`, `\return` etc. as necessary.
274+
Use `\brief` for the summary, and follow with details after an empty doc-comment line, using
275+
`\param`, `\return` etc. as necessary. Adding `\since` to indicate the first version when a
276+
symbol is introduce is nice, too.
296277

297278
When commenting in-code:
298-
* Don't restate what's happening in the code unless it's not really obvious.
299-
We assume the readers to have some command of C++ and Qt. If your code is
300-
not obvious, consider making it clearer itself before commenting.
279+
* Don't restate what's happening in the code. We assume the readers to have some command of C++
280+
and Qt. If your code is not obvious, consider making it clearer itself before commenting.
301281
* That said, both C++ and Qt have their arcane/novel features and dark corners, and education of
302282
code readers is a great thing. Use your experience to figure what might be not that well-known,
303-
and comment such cases: leave references to web pages, Quotient wiki etc. Do not comment `std::`
283+
and comment such cases: add references to web pages, Quotient wiki etc. Do not comment `std::`
304284
calls just because they are less known - readers are expected to know about cppreference.com and
305285
look it up.
306286
* More important than everything above - make sure to document not so much "what" but more "why"
@@ -316,17 +296,19 @@ have just started adding those to the new code (you guessed it; adding more
316296
tests to the old code is very welcome and also is a good exercise to get to
317297
know the library).
318298

319-
On top of that, libQuotient comes with a command-line end-to-end test suite
320-
called Quotest. Any significant addition to the library API should be
321-
accompanied by a respective test in `autotests/` and/or in Quotest.
299+
On top of autotests, libQuotient comes with a command-line end-to-end test suite called Quotest.
300+
Any significant addition to the library API should be accompanied by a respective test
301+
in `autotests/` and/or in Quotest.
322302

323303
To add a test to autotests:
304+
324305
- In a new `.cpp` file in `autotests/` (you don't need a header file), define a test class derived
325306
from `QObject` and write tests as member functions in its `private slots:` section. See other
326307
autotests to get an idea of what it should look like.
327308
- Add a `quotient_add_test` macro call with your test to `autotests/CMakeLists.txt`
328309

329310
To add a test to Quotest:
311+
330312
- In `quotest.cpp`, add a new test to the `TestSuite` class. Similar to Qt Test,
331313
each test in Quotest is a private slot; unlike Qt Test, you should use
332314
special macros, `TEST_DECL()` and `TEST_IMPL()`, to declare and define
@@ -348,8 +330,7 @@ from it).
348330

349331
### Security and privacy
350332

351-
Pay attention to security, and work *with*, not against, the usual security
352-
hardening practices.
333+
Pay attention to security, and work *with*, not against, the good security practices.
353334

354335
`char *` and similar unchecked C-style read/write arrays are forbidden - use Qt containers
355336
(`QString`/`QLatin1String` for strings, in particular) or `std::array<>`/`std::span<>` instead
@@ -429,7 +410,7 @@ If you want the IDE to be _really_ picky about your code you can use
429410
the following line for the Clang analyzer code model to enable most compiler
430411
warnings while keeping the number of false positives at bay (that does not
431412
include `clang-tidy`/`clazy` warnings - see the next section on those):
432-
`-Weverything -Werror=return-type -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++20-compat -Wno-unused-macros -Wno-newline-eof -Wno-exit-time-destructors -Wno-global-constructors -Wno-gnu-zero-variadic-macro-arguments -Wno-documentation -Wno-missing-prototypes -Wno-shadow-field-in-constructor -Wno-padded -Wno-weak-vtables -Wno-unknown-attributes -Wno-comma -Wno-shadow-uncaptured-local -Wno-switch-enum -Wno-pragma-once-outside-header -Wno-range-loop-bind-reference -Wno-unsafe-buffer-usage`
413+
`-Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++20-compat -Wno-unused-macros -Wno-newline-eof -Wno-exit-time-destructors -Wno-global-constructors -Wno-gnu-zero-variadic-macro-arguments -Wno-documentation -Wno-missing-prototypes -Wno-shadow-field-in-constructor -Wno-padded -Wno-weak-vtables -Wno-unknown-attributes -Wno-comma -Wno-shadow-uncaptured-local -Wno-switch-enum -Wno-pragma-once-outside-header -Wno-range-loop-bind-reference -Wno-unsafe-buffer-usage`
433414

434415
### Static analysis tools
435416

Quotient/application-service/definitions/protocol.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct QUOTIENT_API FieldType {
1212
//! may apply additional validation or filtering.
1313
QString regexp;
1414

15-
//! An placeholder serving as a valid example of the field value.
15+
//! A placeholder serving as a valid example of the field value.
1616
QString placeholder;
1717
};
1818

@@ -79,9 +79,9 @@ struct QUOTIENT_API ThirdPartyProtocol {
7979
//! A content URI representing an icon for the third-party protocol.
8080
QString icon;
8181

82-
//! The type definitions for the fields defined in the `user_fields` and
83-
//! `location_fields`. Each entry in those arrays MUST have an entry here. The
84-
//! `string` key for this object is field name itself.
82+
//! The type definitions for the fields defined in `user_fields` and
83+
//! `location_fields`. Each entry in those arrays MUST have an entry here.
84+
//! The `string` key for this object is the field name itself.
8585
//!
8686
//! May be an empty object if no fields are defined.
8787
QHash<QString, FieldType> fieldTypes;

Quotient/application-service/definitions/user.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
namespace Quotient {
88

99
struct QUOTIENT_API ThirdPartyUser {
10-
//! A Matrix User ID represting a third-party user.
10+
//! A Matrix User ID representing a third-party user.
1111
QString userid;
1212

1313
//! The protocol ID that the third-party location is a part of.

Quotient/connection.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -660,16 +660,14 @@ JobHandle<JoinRoomJob> Connection::joinRoom(const QString& roomAlias, const QStr
660660
// Upon completion, ensure a room object is created in case it hasn't come with a sync yet.
661661
// If the room object is not there, provideRoom() will create it in Join state. Using
662662
// the continuation ensures that the room is provided before any client connections.
663-
return callApi<JoinRoomJob>(roomAlias, serverNames).then([this](const QString& roomId) {
664-
provideRoom(roomId);
665-
});
663+
return callApi<JoinRoomJob>(roomAlias, serverNames, serverNames)
664+
.then([this](const QString& roomId) { provideRoom(roomId); });
666665
}
667666

668667
QFuture<Room*> Connection::joinAndGetRoom(const QString& roomAlias, const QStringList& serverNames)
669668
{
670-
return callApi<JoinRoomJob>(roomAlias, serverNames).then([this](const QString& roomId) {
671-
return provideRoom(roomId);
672-
});
669+
return callApi<JoinRoomJob>(roomAlias, serverNames, serverNames)
670+
.then([this](const QString& roomId) { return provideRoom(roomId); });
673671
}
674672

675673
LeaveRoomJob* Connection::leaveRoom(Room* room)

Quotient/connectionencryptiondata_p.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,15 @@ void ConnectionEncryptionData::saveDevicesList()
131131
auto query = database.prepareQuery(u"DELETE FROM tracked_users"_s);
132132
database.execute(query);
133133
query.prepare(u"INSERT INTO tracked_users(matrixId) VALUES(:matrixId);"_s);
134-
for (const auto& user : trackedUsers) {
134+
for (const auto& user : std::as_const(trackedUsers)) {
135135
query.bindValue(u":matrixId"_s, user);
136136
database.execute(query);
137137
}
138138

139139
query.prepare(u"DELETE FROM outdated_users"_s);
140140
database.execute(query);
141141
query.prepare(u"INSERT INTO outdated_users(matrixId) VALUES(:matrixId);"_s);
142-
for (const auto& user : outdatedUsers) {
142+
for (const auto& user : std::as_const(outdatedUsers)) {
143143
query.bindValue(u":matrixId"_s, user);
144144
database.execute(query);
145145
}
@@ -153,22 +153,28 @@ void ConnectionEncryptionData::saveDevicesList()
153153
database.prepareQuery(u"DELETE FROM tracked_devices WHERE matrixId=:matrixId;"_s);
154154
deleteQuery.bindValue(u":matrixId"_s, user);
155155
database.execute(deleteQuery);
156-
for (const auto& device : devices) {
156+
for (const auto& device : std::as_const(devices)) {
157157
const auto keys = device.keys.asKeyValueRange();
158158
deleteQuery.prepare(
159159
u"DELETE FROM tracked_devices WHERE matrixId=:matrixId AND deviceId=:deviceId;"_s);
160160
deleteQuery.bindValue(u":matrixId"_s, user);
161161
deleteQuery.bindValue(u":deviceId"_s, device.deviceId);
162162
database.execute(deleteQuery);
163163

164+
if (device.deviceId.isEmpty()) {
165+
qCCritical(E2EE) << "Clearing an invalid tracked device record with empty deviceId";
166+
continue;
167+
}
164168
const auto curveKeyIt = std::ranges::find_if(keys, [](const auto& p) {
165169
return p.first.startsWith("curve"_L1);
166170
});
167-
Q_ASSERT(curveKeyIt != keys.end());
168171
const auto edKeyIt = std::ranges::find_if(keys, [](const auto& p) {
169172
return p.first.startsWith("ed"_L1);
170173
});
171-
Q_ASSERT(edKeyIt != keys.end());
174+
if (curveKeyIt == keys.end() || edKeyIt == keys.end()) {
175+
qCCritical(E2EE) << "Clearing an invalid tracked device record due to keys missing";
176+
continue;
177+
}
172178

173179
query.bindValue(u":matrixId"_s, user);
174180
query.bindValue(u":deviceId"_s, device.deviceId);

0 commit comments

Comments
 (0)