|
1 | 1 | #include <fmt/core.h>
|
2 | 2 | #include <oxenc/hex.h>
|
3 | 3 | #include <session/config/groups/keys.h>
|
| 4 | +#include <simdutf.h> |
4 | 5 | #include <sodium/crypto_sign_ed25519.h>
|
5 | 6 | #include <sodium/randombytes.h>
|
6 | 7 |
|
|
16 | 17 | #include "WebSocketResources.pb.h"
|
17 | 18 | #include "session/export.h"
|
18 | 19 |
|
19 |
| -namespace session { |
20 |
| - |
21 |
| -PRO_FEATURES get_pro_features_for_msg(size_t msg_size, PRO_EXTRA_FEATURES extra) { |
22 |
| - PRO_FEATURES result = PRO_FEATURES_NIL; |
23 |
| - |
24 |
| - if (msg_size > PRO_STANDARD_CHARACTER_LIMIT) |
25 |
| - result |= PRO_FEATURES_10K_CHARACTER_LIMIT; |
| 20 | +namespace { |
| 21 | +session::ProFeaturesForMsg pro_features_for_utf8_or_16( |
| 22 | + const void* utf, size_t utf_size, PRO_EXTRA_FEATURES extra, bool is_utf8) { |
| 23 | + session::ProFeaturesForMsg result = {}; |
| 24 | + simdutf::result validate = is_utf8 ? simdutf::validate_utf8_with_errors( |
| 25 | + reinterpret_cast<const char*>(utf), utf_size) |
| 26 | + : simdutf::validate_utf16_with_errors( |
| 27 | + reinterpret_cast<const char16_t*>(utf), utf_size); |
| 28 | + if (validate.is_ok()) { |
| 29 | + result.success = true; |
| 30 | + result.codepoint_count = |
| 31 | + is_utf8 ? simdutf::count_utf8(reinterpret_cast<const char*>(utf), utf_size) |
| 32 | + : simdutf::count_utf16(reinterpret_cast<const char16_t*>(utf), utf_size); |
| 33 | + if (result.codepoint_count > PRO_STANDARD_CHARACTER_LIMIT) |
| 34 | + result.features |= PRO_FEATURES_10K_CHARACTER_LIMIT; |
| 35 | + |
| 36 | + if (extra & PRO_EXTRA_FEATURES_ANIMATED_AVATAR) |
| 37 | + result.features |= PRO_FEATURES_ANIMATED_AVATAR; |
| 38 | + |
| 39 | + if (extra & PRO_EXTRA_FEATURES_PRO_BADGE) |
| 40 | + result.features |= PRO_FEATURES_PRO_BADGE; |
| 41 | + |
| 42 | + assert((result.features & ~PRO_FEATURES_ALL) == 0); |
| 43 | + } else { |
| 44 | + result.error = simdutf::error_to_string(validate.error); |
| 45 | + } |
| 46 | + return result; |
| 47 | +} |
| 48 | +}; // namespace |
26 | 49 |
|
27 |
| - if (extra & PRO_EXTRA_FEATURES_ANIMATED_AVATAR) |
28 |
| - result |= PRO_FEATURES_ANIMATED_AVATAR; |
| 50 | +namespace session { |
29 | 51 |
|
30 |
| - if (extra & PRO_EXTRA_FEATURES_PRO_BADGE) |
31 |
| - result |= PRO_FEATURES_PRO_BADGE; |
| 52 | +ProFeaturesForMsg pro_features_for_utf8( |
| 53 | + const char* utf, size_t utf_size, PRO_EXTRA_FEATURES extra) { |
| 54 | + ProFeaturesForMsg result = pro_features_for_utf8_or_16(utf, utf_size, extra, /*is_utf8*/ true); |
| 55 | + return result; |
| 56 | +} |
32 | 57 |
|
33 |
| - assert((result & ~PRO_FEATURES_ALL) == 0); |
| 58 | +ProFeaturesForMsg pro_features_for_utf16( |
| 59 | + const uint16_t* utf, size_t utf_size, PRO_EXTRA_FEATURES extra) { |
| 60 | + ProFeaturesForMsg result = pro_features_for_utf8_or_16(utf, utf_size, extra, /*is_utf8*/ false); |
34 | 61 | return result;
|
35 | 62 | }
|
36 | 63 |
|
@@ -390,8 +417,10 @@ DecryptedEnvelope decrypt_envelope(
|
390 | 417 | // the source is a Session public key (see: encrypt_for_destination)
|
391 | 418 | const std::string& source = envelope.source();
|
392 | 419 | if (source.size() != result.envelope.source.max_size())
|
393 |
| - throw std::runtime_error(fmt::format( |
394 |
| - "Parse envelope failed, source had unexpected size ({} bytes)", source.size())); |
| 420 | + throw std::runtime_error( |
| 421 | + fmt::format( |
| 422 | + "Parse envelope failed, source had unexpected size ({} bytes)", |
| 423 | + source.size())); |
395 | 424 | std::memcpy(result.envelope.source.data(), source.data(), source.size());
|
396 | 425 | result.envelope.flags |= ENVELOPE_FLAGS_SOURCE;
|
397 | 426 | }
|
@@ -546,8 +575,28 @@ DecryptedEnvelope decrypt_envelope(
|
546 | 575 | using namespace session;
|
547 | 576 |
|
548 | 577 | LIBSESSION_C_API
|
549 |
| -PRO_FEATURES session_protocol_get_pro_features_for_msg(size_t msg_size, PRO_EXTRA_FEATURES flags) { |
550 |
| - PRO_FEATURES result = get_pro_features_for_msg(msg_size, flags); |
| 578 | +session_protocol_pro_features_for_msg session_protocol_pro_features_for_utf8( |
| 579 | + const char* utf, size_t utf_size, PRO_EXTRA_FEATURES extra) { |
| 580 | + ProFeaturesForMsg result_cpp = pro_features_for_utf8_or_16(utf, utf_size, extra, /*is_utf8*/ true); |
| 581 | + session_protocol_pro_features_for_msg result = { |
| 582 | + .success = result_cpp.success, |
| 583 | + .error = {const_cast<char*>(result_cpp.error.data()), result_cpp.error.size()}, |
| 584 | + .features = result_cpp.features, |
| 585 | + .codepoint_count = result_cpp.codepoint_count, |
| 586 | + }; |
| 587 | + return result; |
| 588 | +} |
| 589 | + |
| 590 | +LIBSESSION_C_API |
| 591 | +session_protocol_pro_features_for_msg session_protocol_pro_features_for_utf16( |
| 592 | + const uint16_t* utf, size_t utf_size, PRO_EXTRA_FEATURES extra) { |
| 593 | + ProFeaturesForMsg result_cpp = pro_features_for_utf8_or_16(utf, utf_size, extra, /*is_utf8*/ false); |
| 594 | + session_protocol_pro_features_for_msg result = { |
| 595 | + .success = result_cpp.success, |
| 596 | + .error = {const_cast<char*>(result_cpp.error.data()), result_cpp.error.size()}, |
| 597 | + .features = result_cpp.features, |
| 598 | + .codepoint_count = result_cpp.codepoint_count, |
| 599 | + }; |
551 | 600 | return result;
|
552 | 601 | }
|
553 | 602 |
|
|
0 commit comments