1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "mms_encode_buffer.h"
17
18 #include "mms_decode_buffer.h"
19 #include "securec.h"
20 #include "sms_constants_utils.h"
21 #include "telephony_log_wrapper.h"
22
23 namespace OHOS {
24 namespace Telephony {
25 using namespace std;
26 /**
27 * @brief DecodeInteger
28 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
29 * Uintvar-integer = 1*5 OCTET
30 * @param value
31 * @return true
32 * @return false
33 */
EncodeUintvar(uint32_t value)34 bool MmsEncodeBuffer::EncodeUintvar(uint32_t value)
35 {
36 const uint8_t setNotHighestBitZero = 0x80;
37 const uint8_t setHighestBitZero = 0x7f;
38 const uint8_t shiftUintBits = 7;
39 char reversed[8] = {0};
40 int len = 1;
41 reversed[0] = (char)value & setHighestBitZero;
42 value = value >> shiftUintBits;
43 while (value > 0) {
44 reversed[len] = setNotHighestBitZero | (value & setHighestBitZero);
45 len++;
46 value = value >> shiftUintBits;
47 }
48
49 int j = 0;
50 for (j = 0; j < len; j++) {
51 if (!WriteByte(reversed[len - j - 1])) {
52 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
53 return false;
54 }
55 }
56 return true;
57 }
58
WriteByte(uint8_t value)59 bool MmsEncodeBuffer::WriteByte(uint8_t value)
60 {
61 if (curPosition_ >= MMS_PDU_MAX_SIZE) {
62 TELEPHONY_LOGE("Encode buffer current position invalid.");
63 return false;
64 }
65 pduBuffer_[curPosition_++] = value;
66 return true;
67 }
68
WriteBuffer(MmsEncodeBuffer & buff)69 bool MmsEncodeBuffer::WriteBuffer(MmsEncodeBuffer &buff)
70 {
71 uint32_t len = buff.GetCurPosition();
72 if (curPosition_ + len >= MMS_PDU_MAX_SIZE) {
73 TELEPHONY_LOGE("Encode buffer current position invalid.");
74 return false;
75 }
76 if (memcpy_s(pduBuffer_.get() + curPosition_, len, buff.pduBuffer_.get(), len) != EOK) {
77 TELEPHONY_LOGE("Encode buffer memcpy_s fail.");
78 return false;
79 }
80 curPosition_ += buff.GetCurPosition();
81 return true;
82 }
83
WriteBuffer(std::unique_ptr<char[]> input,uint32_t length)84 bool MmsEncodeBuffer::WriteBuffer(std::unique_ptr<char[]> input, uint32_t length)
85 {
86 if (input == nullptr) {
87 TELEPHONY_LOGE("Encode buffer input is null.");
88 return false;
89 }
90
91 if (curPosition_ + length >= MMS_PDU_MAX_SIZE) {
92 TELEPHONY_LOGE("Encode buffer current position invalid.");
93 return false;
94 }
95 if (memcpy_s(pduBuffer_.get() + curPosition_, length, input.get(), length) != EOK) {
96 TELEPHONY_LOGE("Encode buffer memcpy_s fail.");
97 return false;
98 }
99 curPosition_ += length;
100 return true;
101 }
102
103 /**
104 * @brief EncodeShortLength
105 * wap-230-wsp-20010705-a.pdf section:8.4.2.2 Length
106 * Short-length = <Any octet 0-30>
107 * @param value
108 * @return true
109 * @return false
110 */
EncodeShortLength(uint8_t value)111 bool MmsEncodeBuffer::EncodeShortLength(uint8_t value)
112 {
113 const uint8_t minShortLength = 30;
114 if (value > minShortLength) {
115 TELEPHONY_LOGE("Encode buffer value invalid.");
116 return false;
117 }
118 if (!WriteByte(value)) {
119 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
120 return false;
121 }
122 return true;
123 }
124
125 /**
126 * @brief EncodeShortInteger
127 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
128 * Short-integer = OCTET
129 * Integers in range 0-127 shall be encoded as a one octet value with
130 * the most significant bit set to one (1xxx xxxx) and with the value
131 * in the remaining least significant bits
132 * @param value
133 * @return true
134 * @return false
135 */
EncodeShortInteger(uint8_t value)136 bool MmsEncodeBuffer::EncodeShortInteger(uint8_t value)
137 {
138 const uint8_t setHighestBitOne = 0x80;
139 if (!WriteByte(value | setHighestBitOne)) {
140 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
141 return false;
142 }
143 return true;
144 }
145
146 /**
147 * @brief EncodeOctet
148 * wap-230-wsp-20010705-a section:8.1.2 Variable Length Unsigned Integers
149 * octet 8 bits of opaque data
150 * @param value
151 * @return true
152 * @return false
153 */
EncodeOctet(uint8_t value)154 bool MmsEncodeBuffer::EncodeOctet(uint8_t value)
155 {
156 if (!WriteByte(value)) {
157 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
158 return false;
159 }
160 return true;
161 }
162
163 /**
164 * @brief EncodeValueLength
165 * wap-230-wsp-20010705-a section:8.4.2.2 Length
166 * value-length = short-length | (Length-quote Length)
167 * short-length = <Any octet 0-30>
168 * Length-quote = <Octet 31>
169 * (Length-quote Length) = Length-quote + Uintvar-length
170 * @param value
171 * @return true
172 * @return false
173 */
EncodeValueLength(uint32_t value)174 bool MmsEncodeBuffer::EncodeValueLength(uint32_t value)
175 {
176 const uint8_t lengthQuote = 0x1f;
177 const uint32_t maxShortLength = 30;
178
179 if (value <= maxShortLength) {
180 return EncodeShortLength(value);
181 }
182 if (!WriteByte(lengthQuote)) {
183 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
184 return false;
185 }
186 if (!EncodeUintvar(value)) {
187 TELEPHONY_LOGE("Encode buffer EncodeUintvar fail.");
188 return false;
189 }
190 return true;
191 }
192
EncodeInteger(uint32_t value)193 bool MmsEncodeBuffer::EncodeInteger(uint32_t value)
194 {
195 const uint32_t maxShortInteger = 127;
196 if (value <= maxShortInteger) {
197 return EncodeShortInteger(value);
198 } else {
199 return EncodeLongInteger(value);
200 }
201 return true;
202 }
203
204 /**
205 * @brief EncodeLongInteger
206 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
207 * Long-integer = [Short-length] [Multi-octet-integer]
208 * Short-length = 1 byte
209 * Multi-octet-integer = <Short-length> bytes
210 * @param value
211 * @return true
212 * @return false
213 */
EncodeLongInteger(uint64_t value)214 bool MmsEncodeBuffer::EncodeLongInteger(uint64_t value)
215 {
216 const uint64_t getLast8Bit = 0x000000FF;
217 const uint8_t rightMoveBits = 8;
218
219 uint64_t temp = value;
220 uint8_t count = 0;
221 uint8_t result[8] = {0};
222 while (temp > 0) {
223 result[count] = temp & getLast8Bit;
224 temp = temp >> rightMoveBits;
225 count++;
226 }
227
228 if (value == 0) {
229 count = 1;
230 }
231 if (!WriteByte(count)) {
232 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
233 return false;
234 }
235
236 for (int16_t i = static_cast<int16_t>(count) - 1; i >= 0; i--) {
237 if (!WriteByte(result[i])) {
238 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
239 return false;
240 }
241 }
242 return true;
243 }
244
245 /**
246 * @brief EncodeText
247 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
248 * Text-string = [Quote] *TEXT End-of-string
249 * Quote = <Octet 127>
250 * End-of-string = <Octet 0>
251 * @param value
252 * @return true
253 * @return false
254 */
EncodeText(std::string value)255 bool MmsEncodeBuffer::EncodeText(std::string value)
256 {
257 const uint8_t quoteText = 0x7f;
258 if (value.empty()) {
259 TELEPHONY_LOGI("Encode buffer value is empty string.");
260 return true;
261 }
262
263 if (value.at(0) > quoteText) {
264 if (!WriteByte(quoteText)) {
265 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
266 return false;
267 }
268 }
269 for (std::size_t i = 0; i < value.length(); i++) {
270 if (!WriteByte(value.at(i))) {
271 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
272 return false;
273 }
274 }
275 if (!WriteByte(0)) {
276 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
277 return false;
278 }
279 return true;
280 }
281
282 /**
283 * @brief EncodeQuotedText
284 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
285 * Quoted-string = <Octet 34> *TEXT End-of-string
286 * The TEXT encodes an RFC2616 Quoted-string with the enclosing quotation-marks <"> removed
287 * @param value
288 * @return true
289 * @return false
290 */
EncodeQuotedText(std::string value)291 bool MmsEncodeBuffer::EncodeQuotedText(std::string value)
292 {
293 if (value.empty()) {
294 return true;
295 }
296 if (!WriteByte('\"')) {
297 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
298 return false;
299 }
300 for (std::size_t i = 0; i < value.length(); i++) {
301 if (!WriteByte(value.at(i))) {
302 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
303 return false;
304 }
305 }
306 if (!WriteByte(0)) {
307 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
308 return false;
309 }
310 return true;
311 }
312
313 /**
314 * @brief EncodeTokenText
315 * wap-230-wsp-20010705-a section:8.4.2.2 Length
316 * Token-text = Token End-of-string
317 * End-of-string = <Octet 0>
318 * @param value
319 * @return true
320 * @return false
321 */
EncodeTokenText(std::string value)322 bool MmsEncodeBuffer::EncodeTokenText(std::string value)
323 {
324 if (value.empty()) {
325 return true;
326 }
327 for (std::size_t i = 0; i < value.length(); i++) {
328 if (!MmsDecodeBuffer::CharIsToken(value.at(i))) {
329 TELEPHONY_LOGE("Encode buffer EncodeTokenText fail.");
330 return false;
331 }
332 }
333 for (std::size_t i = 0; i < value.length(); i++) {
334 if (!WriteByte(value.at(i))) {
335 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
336 return false;
337 }
338 }
339 if (!WriteByte(0)) {
340 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
341 return false;
342 }
343 return true;
344 }
345 } // namespace Telephony
346 } // namespace OHOS
347