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