Line | Count | Source |
1 | | /* |
2 | | SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org> |
3 | | |
4 | | SPDX-License-Identifier: LGPL-2.0-or-later |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <qglobal.h> |
10 | | |
11 | | class QByteArray; |
12 | | class QByteArrayView; |
13 | | class QString; |
14 | | |
15 | | #include <cstdlib> |
16 | | |
17 | | // @cond PRIVATE |
18 | | |
19 | | /* Internal helper functions. Not part of the public API. */ |
20 | | |
21 | | namespace KMime |
22 | | { |
23 | | |
24 | | /** |
25 | | * Consult the charset cache. Only used for reducing mem usage by |
26 | | * keeping strings in a common repository. |
27 | | * @param name |
28 | | */ |
29 | | [[nodiscard]] QByteArray cachedCharset(const QByteArray &name); |
30 | | [[nodiscard]] QByteArray cachedCharset(QByteArrayView name); |
31 | | |
32 | | /** |
33 | | Finds the header end in @p src. Aligns the @p dataBegin if needed. |
34 | | @param dataBegin beginning of the data part of the header |
35 | | @param folded true if the headder is folded into multiple lines |
36 | | @returns the end index of the header, -1 if the @p dataBegin was -1. |
37 | | */ |
38 | | qsizetype findHeaderLineEnd(QByteArrayView src, qsizetype &dataBegin, bool *folded = nullptr); |
39 | | |
40 | | /** |
41 | | Tries to extract the header with name @p name from the string |
42 | | @p src, unfolding it if necessary. |
43 | | |
44 | | @param src the source string. |
45 | | @param name the name of the header to search for. |
46 | | |
47 | | @return the first instance of the header @p name in @p src |
48 | | or a null QByteArray if no such header was found. |
49 | | */ |
50 | | QByteArray extractHeader(const QByteArray &src, const QByteArray &name); |
51 | | |
52 | | /** |
53 | | Finds the first header of type @p name in @p src. |
54 | | @param end The end index of the header. |
55 | | @param dataBegin begin of the data part of the header, -1 if not found. |
56 | | @param folded true if the headder is folded into multiple lines |
57 | | @returns the begin index of the header, -1 if not found. |
58 | | */ |
59 | | qsizetype indexOfHeader(const QByteArray &src, const QByteArray &name, qsizetype &end, qsizetype &dataBegin, bool *folded = nullptr); |
60 | | |
61 | | /** |
62 | | * Uses current time, pid and random numbers to construct a string |
63 | | * that aims to be unique on a per-host basis (ie. for the local |
64 | | * part of a message-id or for multipart boundaries. |
65 | | * |
66 | | * @return the unique string. |
67 | | * @see multiPartBoundary |
68 | | */ |
69 | | extern QByteArray uniqueString(); |
70 | | |
71 | | /** |
72 | | Unfolds the given header if necessary. |
73 | | @param header The header to unfold. |
74 | | */ |
75 | | QByteArray unfoldHeader(const QByteArray &header); |
76 | | QByteArray unfoldHeader(const char *header, size_t headerSize); |
77 | | |
78 | | /** |
79 | | Folds the given header if necessary. |
80 | | @param header The header to fold. |
81 | | */ |
82 | | QByteArray foldHeader(const QByteArray &header); |
83 | | |
84 | | /** |
85 | | Removes quote (DQUOTE) characters and decodes "quoted-pairs" |
86 | | (ie. backslash-escaped characters) |
87 | | |
88 | | @param str the string to work on. |
89 | | @see addQuotes |
90 | | */ |
91 | | void removeQuotes(QByteArray &str); |
92 | | |
93 | | /** |
94 | | Removes quote (DQUOTE) characters and decodes "quoted-pairs" |
95 | | (ie. backslash-escaped characters) |
96 | | |
97 | | @param str the string to work on. |
98 | | @see addQuotes |
99 | | */ |
100 | | void removeQuotes(QString &str); |
101 | | |
102 | | /** |
103 | | Converts the given string into a quoted-string if the string contains |
104 | | any special characters (ie. one of ()<>@,.;:[]=\"). |
105 | | |
106 | | @param str us-ascii string to work on. |
107 | | @param forceQuotes if @c true, always add quote characters. |
108 | | */ |
109 | | void addQuotes(QByteArray &str, bool forceQuotes); |
110 | | |
111 | | /** |
112 | | * Overloaded method, behaves same as the above. |
113 | | * @param str us-ascii string to work on. |
114 | | * @param forceQuotes if @c true, always add quote characters. |
115 | | * @since 4.5 |
116 | | */ |
117 | | void addQuotes(QString &str, bool forceQuotes); |
118 | | |
119 | | /** |
120 | | * Makes sure that the bidirectional state at the end of the string is the |
121 | | * same as at the beginning of the string. |
122 | | * |
123 | | * This is useful so that Unicode control characters that can change the text |
124 | | * direction can not spill over to following strings. |
125 | | * |
126 | | * As an example, consider a mailbox in the form "display name" <local@domain.com>. |
127 | | * If the display name here contains unbalanced control characters that change the |
128 | | * text direction, it would also have an effect on the addrspec, which could lead to |
129 | | * spoofing. |
130 | | * |
131 | | * By passing the display name to this function, one can make sure that no change of |
132 | | * the bidi state can spill over to the next strings, in this case the addrspec. |
133 | | * |
134 | | * Example: The string "Hello <RLO>World" is unbalanced, as it contains a right-to-left |
135 | | * override character, which is never followed by a <PDF>, the "pop directional |
136 | | * formatting" character. This function adds the missing <PDF> at the end, and |
137 | | * the output of this function would be "Hello <RLO>World<PDF>". |
138 | | * |
139 | | * Example of spoofing: |
140 | | * Consider "Firstname Lastname<RLO>" <moc.mitciv@attacker.com>. Because of the RLO, |
141 | | * it is displayed as "Firstname Lastname <moc.rekcatta@victim.com>", which spoofs the |
142 | | * domain name. |
143 | | * By passing "Firstname Lastname<RLO>" to this function, one can balance the <RLO>, |
144 | | * leading to "Firstname Lastname<RLO><PDF>", so the whole mailbox is displayed |
145 | | * correctly as "Firstname Lastname" <moc.mitciv@attacker.com> again. |
146 | | * |
147 | | * See https://unicode.org/reports/tr9 for more information on bidi control chars. |
148 | | * |
149 | | * @param input the display name of a mailbox, which is checked for unbalanced Unicode |
150 | | * direction control characters |
151 | | * @return the display name which now contains a balanced state of direction control |
152 | | * characters |
153 | | * |
154 | | * Note that this function does not do any parsing related to mailboxes, it only works |
155 | | * on plain strings. Therefore, passing the complete mailbox will not lead to any results, |
156 | | * only the display name should be passed. |
157 | | * |
158 | | * @since 4.5 |
159 | | */ |
160 | | QString balanceBidiState(const QString &input); |
161 | | |
162 | | /** |
163 | | * Similar to the above function. Instead of trying to balance the Bidi chars, it outright |
164 | | * removes them from the string. |
165 | | * |
166 | | * @param input the display name of a mailbox, which is checked for unbalanced Unicode |
167 | | * direction control characters |
168 | | * Reason: KHTML seems to ignore the PDF character, so adding them doesn't fix things :( |
169 | | */ |
170 | | QString removeBidiControlChars(const QString &input); |
171 | | |
172 | | //@cond PRIVATE |
173 | | extern const unsigned char aTextMap[16]; |
174 | | extern const unsigned char tTextMap[16]; |
175 | | |
176 | | inline bool isOfSet(const unsigned char map[16], unsigned char ch) |
177 | 82.0M | { |
178 | 82.0M | return (ch < 128) && (map[ ch / 8 ] & 0x80 >> ch % 8); |
179 | 82.0M | } |
180 | | inline bool isAText(char ch) |
181 | 51.2M | { |
182 | 51.2M | return isOfSet(aTextMap, ch); |
183 | 51.2M | } |
184 | | inline bool isTText(char ch) |
185 | 30.7M | { |
186 | 30.7M | return isOfSet(tTextMap, ch); |
187 | 30.7M | } |
188 | | //@endcond |
189 | | |
190 | | } |
191 | | |
192 | | // @endcond |
193 | | |