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 <sstream>
17
18 #include "mms_decode_buffer.h"
19 #include "telephony_log_wrapper.h"
20 #include "securec.h"
21
22 namespace OHOS {
23 namespace Telephony {
24 using namespace std;
25
PeekOneByte(uint8_t & oneByte)26 bool MmsDecodeBuffer::PeekOneByte(uint8_t &oneByte)
27 {
28 if (curPosition_ >= totolLength_) {
29 TELEPHONY_LOGE("Decode buffer current position invalid.");
30 return false;
31 }
32 oneByte = pduBuffer_[curPosition_];
33 return true;
34 }
35
GetOneByte(uint8_t & oneByte)36 bool MmsDecodeBuffer::GetOneByte(uint8_t &oneByte)
37 {
38 if (curPosition_ >= totolLength_) {
39 TELEPHONY_LOGE("Decode buffer current position invalid.");
40 return false;
41 }
42 oneByte = pduBuffer_[curPosition_];
43 curPosition_++;
44 return true;
45 }
46
IncreasePointer(uint32_t offset)47 bool MmsDecodeBuffer::IncreasePointer(uint32_t offset)
48 {
49 if ((offset > totolLength_) || ((curPosition_ + offset) > totolLength_)) {
50 TELEPHONY_LOGE("Decode buffer current position invalid.");
51 return false;
52 }
53 curPosition_ += offset;
54 return true;
55 }
56
DecreasePointer(uint32_t offset)57 bool MmsDecodeBuffer::DecreasePointer(uint32_t offset)
58 {
59 if (offset > curPosition_) {
60 TELEPHONY_LOGE("Decode buffer current position invalid.");
61 return false;
62 }
63 curPosition_ -= offset;
64 return true;
65 }
66
67 /**
68 * @brief DecodeUintvar
69 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
70 * Uintvar-integer = 1*5 OCTET
71 * @param uintVar
72 * @param count
73 * @return true
74 * @return false
75 */
DecodeUintvar(uint32_t & uintVar,uint32_t & count)76 bool MmsDecodeBuffer::DecodeUintvar(uint32_t &uintVar, uint32_t &count)
77 {
78 const uint8_t setNotHighestBitZero = 0x80;
79 const uint8_t setHighestBitZero = 0x7f;
80
81 uint8_t oneByte = 0;
82 count = 0;
83 if (!GetOneByte(oneByte)) {
84 TELEPHONY_LOGE("Decode buffer GetOneByte fail.");
85 return false;
86 }
87 count++;
88 uintVar = 0;
89 while ((oneByte & setNotHighestBitZero) != 0) {
90 uintVar = uintVar << 0x07;
91 uintVar |= oneByte & setHighestBitZero;
92
93 if (!GetOneByte(oneByte)) {
94 TELEPHONY_LOGE("Decode buffer GetOneByte fail.");
95 return false;
96 }
97 count++;
98 }
99 uintVar = uintVar << 0x07;
100 uintVar |= oneByte & setHighestBitZero;
101 return true;
102 }
103
104 /**
105 * @brief DecodeShortLength
106 * wap-230-wsp-20010705-a.pdf section:8.4.2.2 Length
107 * Short-length = <Any octet 0-30>
108 * @param sValueLength
109 * @return true
110 * @return false
111 */
DecodeShortLength(uint8_t & sValueLength)112 bool MmsDecodeBuffer::DecodeShortLength(uint8_t &sValueLength)
113 {
114 uint8_t oneByte = 0;
115 const unsigned char minShortOctet = 30;
116 if (!GetOneByte(oneByte)) {
117 TELEPHONY_LOGE("Decode buffer GetOneByte fail.");
118 return false;
119 }
120 if (oneByte <= minShortOctet) {
121 sValueLength = oneByte;
122 return true;
123 }
124 return false;
125 }
126
127 /**
128 * @brief DecodeValueLengthReturnLen
129 * wap-230-wsp-20010705-a.pdf section:8.4.2.2 Length
130 * value-length = short-length | (Length-quote Length)
131 * short-length = <Any octet 0-30>
132 * Length-quote = <Octet 31>
133 * (Length-quote Length) = Length-quote + Uintvar-length
134 * @param valueLength
135 * @param length
136 * @return true
137 * @return false
138 */
DecodeValueLengthReturnLen(uint32_t & valueLength,uint32_t & length)139 bool MmsDecodeBuffer::DecodeValueLengthReturnLen(uint32_t &valueLength, uint32_t &length)
140 {
141 const uint8_t lengthQuote = 0x1f;
142 const uint8_t maxShortLength = 30;
143 length = 0;
144 uint32_t uintvar = 0;
145 uint8_t oneByte = 0;
146 valueLength = 0;
147 if (!GetOneByte(oneByte)) {
148 DecreasePointer(1);
149 TELEPHONY_LOGE("Decode buffer GetOneByte fail.");
150 return false;
151 }
152
153 if (oneByte <= maxShortLength) {
154 valueLength = oneByte;
155 length = 1;
156 return true;
157 } else if (oneByte == lengthQuote) {
158 /* Length-quote = 0x1F */
159 uint32_t count = 0;
160 if (!DecodeUintvar(uintvar, count)) {
161 TELEPHONY_LOGE("Decode buffer DecodeUintvar fail.");
162 return false;
163 }
164 valueLength = uintvar;
165 length = count + 1;
166 return true;
167 }
168 return false;
169 }
170
171 /**
172 * @brief DecodeValueLength
173 * wap-230-wsp-20010705-a section:8.4.2.2 Length
174 * value-length = short-length | (Length-quote Length)
175 * short-length = <Any octet 0-30>
176 * Length-quote = <Octet 31>
177 * (Length-quote Length) = Length-quote + Uintvar-length
178 * @param valueLength
179 * @return true
180 * @return false
181 */
DecodeValueLength(uint32_t & valueLength)182 bool MmsDecodeBuffer::DecodeValueLength(uint32_t &valueLength)
183 {
184 const uint8_t lengthQuote = 0x1f;
185 const uint8_t maxShortLength = 30;
186
187 uint32_t uintvar = 0;
188 uint8_t oneByte = 0;
189 valueLength = 0;
190 if (!GetOneByte(oneByte)) {
191 DecreasePointer(1);
192 TELEPHONY_LOGE("Decode buffer GetOneByte fail.");
193 return false;
194 }
195
196 if (oneByte <= maxShortLength) {
197 valueLength = oneByte;
198 return true;
199 } else if (oneByte == lengthQuote) {
200 /* Length-quote = 0x1F */
201 uint32_t count = 0;
202 if (!DecodeUintvar(uintvar, count)) {
203 TELEPHONY_LOGE("Decode buffer DecodeUintvar fail.");
204 return false;
205 }
206 valueLength = uintvar;
207 return true;
208 }
209 return false;
210 }
211
212 /**
213 * @brief CharIsToken
214 * RFC2616 section:2.2 Basic Rules
215 * CHAR = <any US-ASCII character (octets 0 - 127)>
216 * CTL = <any US-ASCII control character
217 * (octets 0 - 31) and DEL (127)>
218 * separators = "(" | ")" | "<" | ">" | "@"
219 * | "," | ";" | ":" | "\" | <">
220 * | "/" | "[" | "]" | "?" | "="
221 * | "{" | "}" | SP | HT
222 * @param oneByte
223 * @return true
224 * @return false
225 */
CharIsToken(uint8_t oneByte)226 bool MmsDecodeBuffer::CharIsToken(uint8_t oneByte)
227 {
228 const uint8_t minToken = 33;
229 const uint8_t maxToken = 126;
230 if (oneByte < minToken || oneByte > maxToken) {
231 return false;
232 }
233 switch (oneByte) {
234 case '"':
235 case '(':
236 case ')':
237 case ',':
238 case '/':
239 case ':':
240 case ';':
241 case '<':
242 case '=':
243 case '>':
244 case '?':
245 case '@':
246 case '[':
247 case '\\':
248 case ']':
249 case '{':
250 case '}':
251 return false;
252 default:
253 return true;
254 }
255 }
256
257 /**
258 * @brief DecodeTokenText
259 * wap-230-wsp-20010705-a section:8.4.2.2 Length
260 * Token-text = Token End-of-string
261 * End-of-string = <Octet 0>
262 * @param str
263 * @param len
264 * @return true
265 * @return false
266 */
DecodeTokenText(std::string & str,uint32_t & len)267 bool MmsDecodeBuffer::DecodeTokenText(std::string &str, uint32_t &len)
268 {
269 len = 0;
270 str.clear();
271 uint8_t oneByte = 0;
272 const uint8_t minToken = 33;
273 const uint8_t maxToken = 126;
274 if (!PeekOneByte(oneByte)) {
275 TELEPHONY_LOGE("Decode buffer PeekOneByte fail.");
276 return false;
277 }
278 if (oneByte < minToken || oneByte > maxToken) {
279 TELEPHONY_LOGE("Decode buffer DecodeTokenText fail.");
280 return false;
281 }
282 while (GetOneByte(oneByte)) {
283 if (oneByte != 0) {
284 if (CharIsToken(oneByte)) {
285 len++;
286 str += oneByte;
287 }
288 } else {
289 break;
290 }
291 }
292 return (len > 0) ? true : false;
293 }
294
295 /**
296 * @brief DecodeText
297 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
298 * Text-string = [Quote] *TEXT End-of-string
299 * Quote = <Octet 127>
300 * End-of-string = <Octet 0>
301 * @param str
302 * @param len
303 * @return true
304 * @return false
305 */
DecodeText(std::string & str,uint32_t & len)306 bool MmsDecodeBuffer::DecodeText(std::string &str, uint32_t &len)
307 {
308 uint8_t oneByte = 0;
309 const unsigned char quoteChar = 127;
310
311 len = 0;
312 str.clear();
313 if (!GetOneByte(oneByte)) {
314 TELEPHONY_LOGE("Decode buffer GetOneByte fail.");
315 return false;
316 }
317
318 // ignore quote
319 if (oneByte != quoteChar) {
320 this->DecreasePointer(1);
321 } else {
322 len++;
323 }
324
325 while (GetOneByte(oneByte)) {
326 if (oneByte != 0) {
327 str += oneByte;
328 len++;
329 } else {
330 break;
331 }
332 }
333 return (len > 0) ? true : false;
334 }
335
336 /**
337 * @brief DecodeQuotedText
338 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
339 * Quoted-string = <Octet 34> *TEXT End-of-string
340 * The TEXT encodes an RFC2616 Quoted-string with the enclosing quotation-marks <"> removed
341 * @param str
342 * @param len
343 * @return true
344 * @return false
345 */
DecodeQuotedText(std::string & str,uint32_t & len)346 bool MmsDecodeBuffer::DecodeQuotedText(std::string &str, uint32_t &len)
347 {
348 const uint8_t quotedFlag = 0x22;
349 uint8_t oneByte = 0;
350 len = 0;
351 str.clear();
352 while (GetOneByte(oneByte)) {
353 if (oneByte != 0) {
354 if (oneByte != quotedFlag) {
355 str += oneByte;
356 }
357 len++;
358 } else {
359 break;
360 }
361 }
362 return (len > 0) ? true : false;
363 }
364
365 /**
366 * @brief DecodeShortInteger
367 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
368 * Short-integer = OCTET
369 * Integers in range 0-127 shall be encoded as a one octet value with
370 * the most significant bit set to one (1xxx xxxx) and with the value
371 * in the remaining least significant bits
372 * @param sInteger
373 * @return true
374 * @return false
375 */
DecodeShortInteger(uint8_t & sInteger)376 bool MmsDecodeBuffer::DecodeShortInteger(uint8_t &sInteger)
377 {
378 const uint8_t setHighestBitZero = 0x7f;
379 const uint8_t maxShortInteger = 0x7f;
380 uint8_t oneByte = 0;
381 sInteger = 0;
382 if (!GetOneByte(oneByte)) {
383 TELEPHONY_LOGE("Decode buffer GetOneByte fail.");
384 return false;
385 }
386 if (oneByte > maxShortInteger) {
387 sInteger = oneByte & setHighestBitZero;
388 return true;
389 }
390 return false;
391 }
392
393 /**
394 * @brief DecodeLongInteger
395 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
396 * Long-integer = [Short-length] [Multi-octet-integer]
397 * Short-length = 1 byte
398 * Multi-octet-integer = <Short-length> bytes
399 * @param value
400 * @return true
401 * @return false
402 */
DecodeLongInteger(uint64_t & value)403 bool MmsDecodeBuffer::DecodeLongInteger(uint64_t &value)
404 {
405 unsigned char oneByte = 0;
406 uint64_t result = 0;
407 uint32_t valuelength = 0;
408 if (GetOneByte(oneByte) != true) {
409 TELEPHONY_LOGE("Decode buffer GetOneByte fail.");
410 return false;
411 }
412 if (oneByte > LONG_VALUE_LEN_MAX) {
413 TELEPHONY_LOGE("Decode buffer DecodeLongInteger fail.");
414 return false;
415 }
416 valuelength = oneByte;
417
418 for (uint32_t i = 0; i < valuelength; i++) {
419 if (GetOneByte(oneByte) != true) {
420 TELEPHONY_LOGE("Decode buffer GetOneByte fail.");
421 return false;
422 }
423 result = (result << 0x08);
424 result |= oneByte;
425 }
426 value = result;
427 return true;
428 }
429
430 /**
431 * @brief DecodeInteger
432 * wap-230-wsp-20010705-a section:8.4.2.3 Parameter Values
433 * Integer-Value = Short-integer | Long-integer
434 * @param iInteger
435 * @return true
436 * @return false
437 */
DecodeInteger(uint64_t & iInteger)438 bool MmsDecodeBuffer::DecodeInteger(uint64_t &iInteger)
439 {
440 iInteger = 0;
441 if (DecodeIsShortInt()) {
442 uint8_t sInteger = 0;
443 if (DecodeShortInteger(sInteger)) {
444 iInteger = sInteger;
445 return true;
446 }
447 } else {
448 if (DecodeLongInteger(iInteger)) {
449 return true;
450 }
451 }
452 return false;
453 }
454
455 /**
456 * @brief DecodeIsShortInt
457 * wap-230-wsp-20010705-a section:8.4.1.2 Field values
458 * (128 - 255) It is an encoded 7-bit value; this header has no more data
459 * @return true
460 * @return false
461 */
DecodeIsShortInt()462 bool MmsDecodeBuffer::DecodeIsShortInt()
463 {
464 const uint8_t maxShortInteger = 0x7f;
465 uint8_t oneByte = 0;
466 PeekOneByte(oneByte);
467 if (oneByte > maxShortInteger) {
468 return true;
469 }
470 return false;
471 }
472
473 /**
474 * @brief DecodeIsString
475 * wap-230-wsp-20010705-a section:8.4.1.2 Field values
476 * (32 - 127) The value is a text string, terminated by a zero octet (NUL character)
477 * @return true
478 * @return false
479 */
DecodeIsString()480 bool MmsDecodeBuffer::DecodeIsString()
481 {
482 const uint8_t minText = 0x20;
483 const uint8_t maxText = 0x7f;
484 uint8_t oneByte = 0;
485 PeekOneByte(oneByte);
486 if (minText <= oneByte && maxText >= oneByte) {
487 return true;
488 }
489 return false;
490 }
491
492 /**
493 * @brief DecodeIsValueLength
494 * wap-230-wsp-20010705-a section:8.4.1.2 Field values
495 * (0 - 30) This octet is followed by the indicated number (0 –30) of data octets
496 * 31 This octet is followed by a uintvar, which indicates the number of data octets after it
497 * @return true
498 * @return false
499 */
DecodeIsValueLength()500 bool MmsDecodeBuffer::DecodeIsValueLength()
501 {
502 const uint8_t lengthQuote = 0x1f;
503 uint8_t oneByte = 0;
504 PeekOneByte(oneByte);
505 if (oneByte <= lengthQuote) {
506 return true;
507 }
508 return false;
509 }
510
MarkPosition()511 void MmsDecodeBuffer::MarkPosition()
512 {
513 savePosition_ = curPosition_;
514 }
515
UnMarkPosition()516 void MmsDecodeBuffer::UnMarkPosition()
517 {
518 curPosition_ = savePosition_;
519 }
520
GetPdu()521 void MmsDecodeBuffer::GetPdu()
522 {
523 uint8_t hexOffset = 4;
524 uint32_t maxDisplayLength = 500;
525 char hexTable[] = "0123456789ABCDEF";
526 uint32_t size = GetSize();
527 if (size > maxDisplayLength) {
528 TELEPHONY_LOGE("size is too long");
529 return;
530 }
531 uint32_t pos = GetCurPosition();
532 TELEPHONY_LOGE("The pdu size is %{public}d and current pos is %{public}d.", size, pos);
533 uint32_t length = size - pos;
534 length--;
535 std::stringstream result;
536 for (uint8_t i = 0; i <= pos; i++) {
537 unsigned char temp = static_cast<unsigned char>(pduBuffer_[i]) >> hexOffset;
538 result << hexTable[temp] << hexTable[static_cast<unsigned char>(pduBuffer_[i]) & 0xf];
539 }
540 std::string resultCover = result.str();
541 for (uint8_t i = 0; i < length; i++) {
542 resultCover += '*';
543 }
544 TELEPHONY_LOGE("Decode fail pdu part is: %{public}s", resultCover.c_str());
545 }
546 } // namespace Telephony
547 } // namespace OHOS
548