~aleteoryx/muditaos

muditaos/module-utils/utility/Anonymize.cpp -rw-r--r-- 6.9 KiB
a405cad6Aleteoryx trim readme 6 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md

#include "Anonymize.hpp"

namespace utils::anonymize
{
    // Anonymized text will replace by this character
    constexpr auto anonymizationCharacter = '*';

    // Amount of 'anonymizationCharacter' used during anonymization can be fixed,
    // otherwise their amount depend on length of substring to anonymize
    constexpr auto isAmountOfAnonymizationCharactersFixed = false;
    constexpr auto fixedAmountOfAnonymizationCharacters   = 4;

    // Substrings to find logs for anonymization from the cellular logs
    constexpr auto cellularSubstringCPIN = "CPIN";
    constexpr auto cellularSubstringCLCC = "CLCC";
    constexpr auto cellularSubstringATD  = "ATD";
    constexpr auto cellularSubstringCPBR = "CPBR";
    constexpr auto cellularSubstringCSPN = "CSPN";
    constexpr auto cellularSubstringCOPS = "COPS";

    std::string anonymizeInQuotationMarks(const std::string &textToAnonymize, std::size_t singsToLeaveAtEnd)
    {
        constexpr auto quotesMark = '\"';
        std::size_t startPosition = 0;
        std::size_t endPosition   = 0;
        auto anonymizedText       = textToAnonymize;

        // Find the position of the substring within the input string
        while (startPosition < anonymizedText.length()) {
            startPosition = anonymizedText.find(quotesMark, startPosition);
            endPosition   = anonymizedText.find(quotesMark, startPosition + 1);

            if (startPosition != std::string::npos && endPosition != std::string::npos) {
                // Extract the substring between the quotes
                const auto &extractedSubstring =
                    anonymizedText.substr(startPosition + 1, endPosition - startPosition - 1);

                // Determine the length of the extracted substring
                const auto extractedLength = extractedSubstring.length();

                // Amount of signs to left can't be higher than extracted substring
                singsToLeaveAtEnd = std::min(extractedLength, singsToLeaveAtEnd);

                // Determine amount of anonymization characters
                const auto amountOfAnonymizationCharacters = isAmountOfAnonymizationCharactersFixed
                                                                 ? fixedAmountOfAnonymizationCharacters
                                                                 : extractedLength - singsToLeaveAtEnd;

                // Replace the substring with the appropriate number of '*' characters
                anonymizedText.replace(startPosition + 1,
                                       extractedLength - singsToLeaveAtEnd,
                                       amountOfAnonymizationCharacters,
                                       anonymizationCharacter);
                startPosition = endPosition + 1;
            }
            else {
                break;
            }
        }
        return anonymizedText;
    }

    std::string anonymizeNumbers(const std::string &textToAnonymize, std::size_t singsToLeaveAtEnd)
    {
        std::size_t startPosition = 0;
        std::size_t endPosition   = 0;
        auto isDigitFunction      = [](char c) { return std::isdigit(c); };
        auto anonymizedText       = textToAnonymize;
        auto startSubstring       = anonymizedText.begin();
        auto endSubstring         = anonymizedText.begin();

        while (startPosition < anonymizedText.length()) {
            // Find first number in string
            startSubstring = std::find_if(endSubstring, anonymizedText.end(), isDigitFunction);

            // If first number found then find last number and anonymize whole number in string
            if (startSubstring != anonymizedText.end()) {
                endSubstring = std::find_if_not(startSubstring, anonymizedText.end(), isDigitFunction);

                // Calculate positions
                startPosition = std::distance(anonymizedText.begin(), startSubstring);
                endPosition   = std::distance(anonymizedText.begin(), endSubstring);

                if (startPosition != std::string::npos && endPosition != std::string::npos) {
                    // Extract the substring contained only numbers
                    const auto &extractedSubstring =
                        anonymizedText.substr(startPosition + 1, endPosition - startPosition);

                    // Determine the length of the extracted substring
                    const auto extractedLength = extractedSubstring.length();

                    // Amount of signs to left can't be higher than extracted substring
                    singsToLeaveAtEnd = std::min(extractedLength, singsToLeaveAtEnd);

                    // Determine amount of anonymization characters
                    const auto amountOfAnonymizationCharacters = isAmountOfAnonymizationCharactersFixed
                                                                     ? fixedAmountOfAnonymizationCharacters
                                                                     : extractedLength - singsToLeaveAtEnd;

                    // Replace the substring with the appropriate number of '*' characters
                    anonymizedText.replace(startPosition,
                                           extractedLength - singsToLeaveAtEnd,
                                           amountOfAnonymizationCharacters,
                                           anonymizationCharacter);

                    startPosition = endPosition + 1;
                }
                else {
                    break;
                }
            }
            else {
                break;
            }
        }
        return anonymizedText;
    }

    std::string anonymizeCellularIfNecessary(const std::string &text)
    {
        std::map<std::string, std::function<std::string()>> anonymizeOption{
            {cellularSubstringCPIN,
             [&text]() { return anonymizeInQuotationMarks(text, SIGNS_TO_LEAVE_FOR_PIN_AND_PUK); }},
            {cellularSubstringCLCC,
             [&text]() { return anonymizeInQuotationMarks(text, SIGNS_TO_LEAVE_FOR_PHONE_NUMBERS); }},
            {cellularSubstringATD, [&text]() { return anonymizeNumbers(text, SIGNS_TO_LEAVE_FOR_PHONE_NUMBERS); }},
            {cellularSubstringCPBR,
             [&text]() { return anonymizeInQuotationMarks(text, SIGNS_TO_LEAVE_FOR_PHONE_NUMBERS); }},
            {cellularSubstringCSPN,
             [&text]() { return anonymizeInQuotationMarks(text, SIGNS_TO_LEAVE_FOR_NET_PROVIDER_NAME); }},
            {cellularSubstringCOPS,
             [&text]() { return anonymizeInQuotationMarks(text, SIGNS_TO_LEAVE_FOR_NET_PROVIDER_NAME); }}};

        for (const auto &[key, anonymizeFunction] : anonymizeOption) {
            if (text.find(key) != std::string::npos) {
                return anonymizeFunction();
            }
        }
        return text;
    }
} // namespace utils::anonymize