Skip to content

Commit c8fb548

Browse files
authored
[EGD-3147] SMS incoming ASCII characters (#939)
1 parent 47fb873 commit c8fb548

File tree

8 files changed

+140
-2
lines changed

8 files changed

+140
-2
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* `[GUI][messages]` Fixed not showing number on deleting temporary contact
2323
* `[GUI]` Fixed filling Label with color
2424
* `[calculator]` Fix phone hanging when pressing '='.
25+
* `[messages][cellular]` Fixed special SMS handling -> ASCII instead of number.
2526

2627
## [0.44.1 2020-10-30]
2728

module-services/service-cellular/ServiceCellular.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1344,7 +1344,7 @@ bool ServiceCellular::receiveSMS(std::string messageNumber)
13441344

13451345
SMSRecord record;
13461346
record.body = decodedMessage;
1347-
record.number = utils::PhoneNumber(receivedNumber, utils::country::Id::UNKNOWN).getView();
1347+
record.number = utils::PhoneNumber::getReceivedNumberView(receivedNumber);
13481348
record.type = SMSType::INBOX;
13491349
record.date = messageDate;
13501350

module-utils/PhoneNumber.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,3 +328,10 @@ const PhoneNumber::View &PhoneNumber::getView() const
328328
{
329329
return viewSelf;
330330
}
331+
332+
const PhoneNumber::View PhoneNumber::getReceivedNumberView(const UTF8 &receivedNumber)
333+
{
334+
return (receivedNumber.isASCIICombination())
335+
? utils::PhoneNumber(receivedNumber.toASCII().value(), utils::country::Id::UNKNOWN).getView()
336+
: utils::PhoneNumber(receivedNumber, utils::country::Id::UNKNOWN).getView();
337+
}

module-utils/PhoneNumber.hpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <phonenumbers/phonenumberutil.h>
99

1010
#include <exception>
11-
#include <string>
11+
#include <module-utils/utf8/UTF8.hpp>
1212

1313
namespace utils
1414
{
@@ -347,6 +347,15 @@ namespace utils
347347
*/
348348
static View parse(const std::string &inputNumber);
349349

350+
/**
351+
* @brief Get lightweight representation of a PhoneNumber (see View class).
352+
*
353+
* @param received number - utf8 representation of received number
354+
* @return View - instance of View object which represents state of
355+
* PhoneNumber instance.
356+
*/
357+
static const View getReceivedNumberView(const UTF8 &receivedNumber);
358+
350359
private:
351360
View makeView(const std::string &input) const;
352361

module-utils/test/unittest_ucs2.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ TEST_CASE("UCS2 to UTF8 conversion")
1414
REQUIRE((uint32_t)('e') == decodedMessage[1]);
1515
REQUIRE((uint32_t)('s') == decodedMessage[2]);
1616
REQUIRE((uint32_t)('t') == decodedMessage[3]);
17+
18+
SECTION("UTF8 IS ASCII combination")
19+
{
20+
auto utf8 = UCS2(std::string("00380034003800370037003300380034003800340036003900380032")).toUTF8();
21+
REQUIRE(utf8.isASCIICombination());
22+
auto ascii = utf8.toASCII();
23+
REQUIRE(ascii == std::string("TWITTER"));
24+
}
25+
26+
SECTION("UTF8 IS NOT ASCII combination")
27+
{
28+
auto utf8 = UCS2(std::string("003200390031")).toUTF8();
29+
REQUIRE_FALSE(utf8.isASCIICombination());
30+
REQUIRE_FALSE(utf8.toASCII().has_value());
31+
}
1732
}
1833

1934
TEST_CASE("UCS2 from UTF8 emoji 😁")

module-utils/test/unittest_utf8.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,41 @@ TEST_CASE("UTF8: insert whole string which doesn't work")
339339
REQUIRE(lol == fin);
340340
REQUIRE(lol.length() == len);
341341
}
342+
343+
TEST_CASE("UTF8: Convert to ascii if is ascii combination")
344+
{
345+
UTF8 combination = "778568738465";
346+
REQUIRE(combination.isASCIICombination());
347+
REQUIRE(combination.toASCII() == std::string("MUDITA"));
348+
}
349+
350+
TEST_CASE("UTF8: Not ASCII combination")
351+
{
352+
SECTION("Pl number - 9 digits")
353+
{
354+
UTF8 combination = "600123456";
355+
REQUIRE_FALSE(combination.isASCIICombination());
356+
REQUIRE_FALSE(combination.toASCII().has_value());
357+
}
358+
359+
SECTION("Pl e164 number")
360+
{
361+
UTF8 combination = "+48600123456";
362+
REQUIRE_FALSE(combination.isASCIICombination());
363+
REQUIRE_FALSE(combination.toASCII().has_value());
364+
}
365+
366+
SECTION("Pl formatted number")
367+
{
368+
UTF8 combination = "600 123 456";
369+
REQUIRE_FALSE(combination.isASCIICombination());
370+
REQUIRE_FALSE(combination.toASCII().has_value());
371+
}
372+
373+
SECTION("Pl formatted int number")
374+
{
375+
UTF8 combination = "+48 600 123 456";
376+
REQUIRE_FALSE(combination.isASCIICombination());
377+
REQUIRE_FALSE(combination.toASCII().has_value());
378+
}
379+
}

module-utils/utf8/UTF8.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,3 +791,58 @@ std::ostream &operator<<(std::ostream &os, const UTF8 &el)
791791
os << el.c_str();
792792
return os;
793793
}
794+
795+
bool UTF8::isASCIICombination() const noexcept
796+
{
797+
const auto len = strlen(data.get());
798+
std::size_t i = 0;
799+
constexpr char asciiZero = '0';
800+
constexpr uint8_t firstCharacterFactor = 100;
801+
constexpr uint8_t secondCharacterFactor = 10;
802+
for (; i < len; i += 2) {
803+
int firstCharacter = 0;
804+
if (data[i] == '1') {
805+
firstCharacter = static_cast<int>(data[i] - asciiZero) * firstCharacterFactor;
806+
++i;
807+
}
808+
if (i + 1 >= len) {
809+
return false;
810+
}
811+
const auto combinedCharacters = static_cast<char>(
812+
firstCharacter + ((data[i] - asciiZero) * secondCharacterFactor) + (data[i + 1] - asciiZero));
813+
if (!std::isprint(combinedCharacters)) {
814+
return false;
815+
}
816+
}
817+
return i == len;
818+
}
819+
820+
std::optional<std::string> UTF8::toASCII() const noexcept
821+
{
822+
std::string ret{};
823+
const auto len = strlen(data.get());
824+
constexpr char asciiZero = '0';
825+
constexpr uint8_t firstCharacterFactor = 100;
826+
constexpr uint8_t secondCharacterFactor = 10;
827+
std::size_t i = 0;
828+
for (; i < len; i += 2) {
829+
int firstCharacter = 0;
830+
if (data[i] == '1') {
831+
firstCharacter = static_cast<int>(data[i] - asciiZero) * firstCharacterFactor;
832+
++i;
833+
}
834+
if (i + 1 >= len) {
835+
return std::nullopt;
836+
}
837+
const auto combinedCharacters = static_cast<char>(
838+
firstCharacter + ((data[i] - asciiZero) * secondCharacterFactor) + (data[i + 1] - asciiZero));
839+
if (!std::isprint(combinedCharacters)) {
840+
return std::nullopt;
841+
}
842+
ret.push_back(combinedCharacters);
843+
}
844+
845+
if (i != len)
846+
return std::nullopt;
847+
return ret;
848+
}

module-utils/utf8/UTF8.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <cstdint>
88
#include <iosfwd> // for forward declaration for ostream
99
#include <memory>
10+
#include <optional>
1011

1112
/// single utf8 character representation struct
1213
struct U8char
@@ -233,4 +234,16 @@ class UTF8
233234
* @return true if there was no error, false otherwise.
234235
*/
235236
static bool getStreamLength(const char *stream, uint32_t &size, uint32_t &count);
237+
/**
238+
* @brief Checks if numbers contained in the UTF8 creates ASCII character combination
239+
* eg. 778568738465 returns true
240+
* @return true if is acii combination, false otherwise
241+
*/
242+
[[nodiscard]] bool isASCIICombination() const noexcept;
243+
/**
244+
* @brief Converts UTF8 to ASCII character combination
245+
* eg. 778568738465 returns "MUDITA"
246+
* @return ASCII converted string
247+
*/
248+
[[nodiscard]] std::optional<std::string> toASCII() const noexcept;
236249
};

0 commit comments

Comments
 (0)