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 "sms_wap_push_buffer.h"
17 
18 #include "securec.h"
19 #include "sms_constants_utils.h"
20 #include "string_utils.h"
21 #include "telephony_log_wrapper.h"
22 
23 namespace OHOS {
24 namespace Telephony {
SmsWapPushBuffer()25 SmsWapPushBuffer::SmsWapPushBuffer() {}
26 
~SmsWapPushBuffer()27 SmsWapPushBuffer::~SmsWapPushBuffer()
28 {
29     if (pduBuffer_ != nullptr) {
30         pduBuffer_.reset();
31     }
32 }
33 
ReadDataBuffer(uint32_t desLen)34 std::unique_ptr<char[]> SmsWapPushBuffer::ReadDataBuffer(uint32_t desLen)
35 {
36     return ReadDataBuffer(curPosition_, desLen);
37 }
38 
ReadDataBuffer(uint32_t offset,uint32_t desLen)39 std::unique_ptr<char[]> SmsWapPushBuffer::ReadDataBuffer(uint32_t offset, uint32_t desLen)
40 {
41     if ((desLen > totolLength_) || ((offset + desLen) > totolLength_)) {
42         return nullptr;
43     }
44     if (desLen > MMS_PDU_MAX_SIZE) {
45         TELEPHONY_LOGE("desLen over size error");
46         return nullptr;
47     }
48     std::unique_ptr<char[]> result = std::make_unique<char[]>(desLen);
49     if (result == nullptr) {
50         return nullptr;
51     }
52     if (memcpy_s(result.get(), desLen, &pduBuffer_[offset], desLen) != EOK) {
53         return nullptr;
54     }
55     return result;
56 }
57 
WriteRawStringBuffer(const std::string & inSrc)58 bool SmsWapPushBuffer::WriteRawStringBuffer(const std::string &inSrc)
59 {
60     uint32_t len = inSrc.length();
61     if (len > MMS_PDU_MAX_SIZE) {
62         TELEPHONY_LOGE("create wappush input source string over length error.");
63         return false;
64     }
65 
66     if (pduBuffer_) {
67         pduBuffer_.reset();
68     }
69 
70     pduBuffer_ = std::make_unique<char[]>(len);
71     if (!pduBuffer_) {
72         TELEPHONY_LOGE("wap push make unique fail.");
73         return false;
74     }
75     if (memcpy_s(pduBuffer_.get(), len, inSrc.data(), len) != EOK) {
76         TELEPHONY_LOGE("wap push memcpy_s fail.");
77         return false;
78     }
79     totolLength_ = len;
80     return true;
81 }
82 
WriteDataBuffer(std::unique_ptr<char[]> inBuff,uint32_t len)83 bool SmsWapPushBuffer::WriteDataBuffer(std::unique_ptr<char[]> inBuff, uint32_t len)
84 {
85     if (inBuff == nullptr) {
86         TELEPHONY_LOGE("wap push inBuff is null.");
87         return false;
88     }
89     if (len <= 0 || len > MMS_PDU_MAX_SIZE) {
90         TELEPHONY_LOGE("wap push len invalid .");
91         return false;
92     }
93 
94     if (pduBuffer_) {
95         pduBuffer_.reset();
96     }
97 
98     pduBuffer_ = std::make_unique<char[]>(len);
99     if (!pduBuffer_) {
100         TELEPHONY_LOGE("wap push make unique fail.");
101         return false;
102     }
103     if (memcpy_s(pduBuffer_.get(), len, inBuff.get(), len) != EOK) {
104         TELEPHONY_LOGE("wap push memcpy_s fail.");
105         return false;
106     }
107     totolLength_ = len;
108     return true;
109 }
110 
GetCurPosition() const111 uint32_t SmsWapPushBuffer::GetCurPosition() const
112 {
113     return curPosition_;
114 }
115 
GetSize() const116 uint32_t SmsWapPushBuffer::GetSize() const
117 {
118     return totolLength_;
119 }
120 
PeekOneByte(uint8_t & oneByte)121 bool SmsWapPushBuffer::PeekOneByte(uint8_t &oneByte)
122 {
123     if (curPosition_ >= totolLength_) {
124         TELEPHONY_LOGE("wap push current position invalid.");
125         return false;
126     }
127     oneByte = pduBuffer_[curPosition_];
128     return true;
129 }
130 
GetOneByte(uint8_t & oneByte)131 bool SmsWapPushBuffer::GetOneByte(uint8_t &oneByte)
132 {
133     if (curPosition_ >= totolLength_) {
134         TELEPHONY_LOGE("wap push current position invalid.");
135         return false;
136     }
137     oneByte = pduBuffer_[curPosition_];
138     curPosition_++;
139     return true;
140 }
141 
IncreasePointer(uint32_t offset)142 bool SmsWapPushBuffer::IncreasePointer(uint32_t offset)
143 {
144     if ((offset > totolLength_) || ((curPosition_ + offset) > totolLength_)) {
145         TELEPHONY_LOGE("wap push current position invalid.");
146         return false;
147     }
148     curPosition_ += offset;
149     return true;
150 }
151 
DecreasePointer(uint32_t offset)152 bool SmsWapPushBuffer::DecreasePointer(uint32_t offset)
153 {
154     if (offset > curPosition_) {
155         TELEPHONY_LOGE("wap push current position invalid.");
156         return false;
157     }
158     curPosition_ -= offset;
159     return true;
160 }
161 
162 /**
163  * @brief DecodeUintvar
164  * wap-230-wsp-20010705-a   section:8.4.2.1 Basic rules
165  * Uintvar-integer = 1*5 OCTET
166  * @param uintVar
167  * @param count
168  * @return true
169  * @return false
170  */
DecodeUintvar(uint32_t & uintVar,uint32_t & count)171 bool SmsWapPushBuffer::DecodeUintvar(uint32_t &uintVar, uint32_t &count)
172 {
173     const uint8_t setNotHighestBitZero = 0x80;
174     const uint8_t setHighestBitZero = 0x7f;
175 
176     count = 0;
177     uint8_t oneByte = 0;
178     if (!GetOneByte(oneByte)) {
179         TELEPHONY_LOGE("wap push GetOneByte fail.");
180         return false;
181     }
182     count++;
183     uintVar = 0;
184     while ((oneByte & setNotHighestBitZero) != 0) {
185         uintVar = uintVar << 0x07;
186         uintVar |= oneByte & setHighestBitZero;
187 
188         if (!GetOneByte(oneByte)) {
189             TELEPHONY_LOGE("wap push GetOneByte fail.");
190             return false;
191         }
192         count++;
193     }
194     uintVar = uintVar << 0x07;
195     uintVar |= oneByte & setHighestBitZero;
196     return true;
197 }
198 
199 /**
200  * @brief DecodeShortLength
201  * wap-230-wsp-20010705-a.pdf   section:8.4.2.2 Length
202  * Short-length = <Any octet 0-30>
203  * @param sValueLength
204  * @return true
205  * @return false
206  */
DecodeShortLength(uint8_t & sValueLength)207 bool SmsWapPushBuffer::DecodeShortLength(uint8_t &sValueLength)
208 {
209     const unsigned char minShortOctet = 30;
210 
211     uint8_t oneByte = 0;
212     if (!GetOneByte(oneByte)) {
213         TELEPHONY_LOGE("wap push GetOneByte fail.");
214         return false;
215     }
216     if (oneByte <= minShortOctet) {
217         sValueLength = oneByte;
218         return true;
219     }
220     return false;
221 }
222 
223 /**
224  * @brief DecodeValueLengthReturnLen
225  * value-length = short-length | (Length-quote Length)
226  * short-length = 0~30
227  * Length-quote = 31
228  * (Length-quote Length) = Length-quote + Uintvar-length
229  * @param valueLength
230  * @return true
231  * @return false
232  */
DecodeValueLengthReturnLen(uint32_t & valueLength,uint32_t & length)233 bool SmsWapPushBuffer::DecodeValueLengthReturnLen(uint32_t &valueLength, uint32_t &length)
234 {
235     const uint8_t lengthQuote = 0x1f;
236     const uint8_t maxShortLength = 30;
237 
238     length = 0;
239     valueLength = 0;
240     uint32_t uintvar = 0;
241     uint8_t oneByte = 0;
242     if (!GetOneByte(oneByte)) {
243         DecreasePointer(1);
244         TELEPHONY_LOGE("wap push GetOneByte fail.");
245         return false;
246     }
247 
248     if (oneByte <= maxShortLength) {
249         valueLength = oneByte;
250         length = 1;
251         return true;
252     } else if (oneByte == lengthQuote) {
253         /* Length-quote = 0x1F */
254         uint32_t count = 0;
255         if (!DecodeUintvar(uintvar, count)) {
256             TELEPHONY_LOGE("wap push DecodeUintvar fail.");
257             return false;
258         }
259         valueLength = uintvar;
260         length = count + 1;
261         return true;
262     }
263     return false;
264 }
265 
266 /**
267  * @brief DecodeValueLength
268  * value-length = short-length | (Length-quote Length)
269  * short-length = 0~30
270  * Length-quote = 31
271  * (Length-quote Length) = Length-quote + Uintvar-length
272  * @param valueLength
273  * @return true
274  * @return false
275  */
DecodeValueLength(uint32_t & valueLength)276 bool SmsWapPushBuffer::DecodeValueLength(uint32_t &valueLength)
277 {
278     const uint8_t lengthQuote = 0x1f;
279     const uint8_t maxShortLength = 30;
280 
281     valueLength = 0;
282     uint32_t uintvar = 0;
283     uint8_t oneByte = 0;
284     if (!GetOneByte(oneByte)) {
285         DecreasePointer(1);
286         TELEPHONY_LOGE("wap push GetOneByte fail.");
287         return false;
288     }
289 
290     if (oneByte <= maxShortLength) {
291         valueLength = oneByte;
292         return true;
293     } else if (oneByte == lengthQuote) {
294         /* Length-quote = 0x1F */
295         uint32_t count = 0;
296         if (!DecodeUintvar(uintvar, count)) {
297             TELEPHONY_LOGE("wap push DecodeUintvar fail.");
298             return false;
299         }
300         valueLength = uintvar;
301         return true;
302     }
303     return false;
304 }
305 
306 /**
307  * @brief CharIsToken
308  * RFC2616   section:2.2 Basic Rules
309  * CHAR           = <any US-ASCII character (octets 0 - 127)>
310  * CTL            = <any US-ASCII control character
311  *                   (octets 0 - 31) and DEL (127)>
312  * separators     = "(" | ")" | "<" | ">" | "@"
313  *                     | "," | ";" | ":" | "\" | <">
314  *                     | "/" | "[" | "]" | "?" | "="
315  *                     | "{" | "}" | SP | HT
316  * @param oneByte
317  * @return true
318  * @return false
319  */
CharIsToken(uint8_t oneByte)320 bool SmsWapPushBuffer::CharIsToken(uint8_t oneByte)
321 {
322     const uint8_t minToken = 33;
323     const uint8_t maxToken = 126;
324 
325     if (oneByte < minToken || oneByte > maxToken) {
326         return false;
327     }
328 
329     std::set<uint8_t> token = { '"', '(', ')', '/', ',', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
330     return !token.count(oneByte);
331 }
332 
333 /**
334  * @brief DecodeTokenText
335  * wap-230-wsp-20010705-a   section:8.4.2.2 Length
336  * Token-text = Token End-of-string
337  * End-of-string = <Octet 0>
338  * @param str
339  * @param len
340  * @return true
341  * @return false
342  */
DecodeTokenText(std::string & str,uint32_t & len)343 bool SmsWapPushBuffer::DecodeTokenText(std::string &str, uint32_t &len)
344 {
345     const uint8_t minToken = 33;
346     const uint8_t maxToken = 126;
347 
348     len = 0;
349     str.clear();
350     uint8_t oneByte = 0;
351     if (!PeekOneByte(oneByte)) {
352         TELEPHONY_LOGE("wap push PeekOneByte fail.");
353         return false;
354     }
355     if (oneByte < minToken || oneByte > maxToken) {
356         TELEPHONY_LOGE("wap push DecodeTokenText fail.");
357         return false;
358     }
359     while (GetOneByte(oneByte)) {
360         if (oneByte != 0) {
361             if (CharIsToken(oneByte)) {
362                 str += oneByte;
363                 len++;
364             }
365         } else {
366             break;
367         }
368     }
369     return (len > 0) ? true : false;
370 }
371 
372 /**
373  * @brief DecodeText
374  * wap-230-wsp-20010705-a   section:8.4.2.1 Basic rules
375  * Text-string = [Quote] *TEXT End-of-string
376  * Quote = <Octet 127>
377  * End-of-string = <Octet 0>
378  * @param str
379  * @param len
380  * @return true
381  * @return false
382  */
DecodeText(std::string & str,uint32_t & len)383 bool SmsWapPushBuffer::DecodeText(std::string &str, uint32_t &len)
384 {
385     const unsigned char quoteChar = 127;
386 
387     len = 0;
388     str.clear();
389     uint8_t oneByte = 0;
390     if (!GetOneByte(oneByte)) {
391         TELEPHONY_LOGE("wap push GetOneByte fail.");
392         return false;
393     }
394 
395     // ignore quote
396     if (oneByte != quoteChar) {
397         this->DecreasePointer(1);
398     } else {
399         len++;
400     }
401 
402     while (GetOneByte(oneByte)) {
403         if (oneByte != 0) {
404             str += oneByte;
405             len++;
406         } else {
407             break;
408         }
409     }
410     return (len > 0) ? true : false;
411 }
412 
413 /**
414  * @brief DecodeQuotedText
415  * wap-230-wsp-20010705-a   section:8.4.2.1 Basic rules
416  * Quoted-string = <Octet 34> *TEXT End-of-string
417  * The TEXT encodes an RFC2616 Quoted-string with the enclosing quotation-marks <"> removed
418  * @param str
419  * @param len
420  * @return true
421  * @return false
422  */
DecodeQuotedText(std::string & str,uint32_t & len)423 bool SmsWapPushBuffer::DecodeQuotedText(std::string &str, uint32_t &len)
424 {
425     const uint8_t quotedFlag = 0x22;
426     uint8_t oneByte = 0;
427     len = 0;
428     str.clear();
429     while (GetOneByte(oneByte)) {
430         if (oneByte != 0) {
431             if (oneByte != quotedFlag) {
432                 str += oneByte;
433             }
434             len++;
435         } else {
436             break;
437         }
438     }
439     return (len > 0) ? true : false;
440 }
441 
442 /**
443  * @brief DecodeShortInteger
444  * wap-230-wsp-20010705-a   section:8.4.2.1 Basic rules
445  * Short-integer = OCTET
446  * Integers in range 0-127 shall be encoded as a one octet value with
447  * the most significant bit set to one (1xxx xxxx) and with the value
448  * in the remaining least significant bits
449  * @param sInteger
450  * @return true
451  * @return false
452  */
DecodeShortInteger(uint8_t & sInteger)453 bool SmsWapPushBuffer::DecodeShortInteger(uint8_t &sInteger)
454 {
455     const uint8_t setHighestBitZero = 0x7f;
456     const uint8_t maxShortInteger = 0x7f;
457 
458     sInteger = 0;
459     uint8_t oneByte = 0;
460     if (!GetOneByte(oneByte)) {
461         TELEPHONY_LOGE("wap push GetOneByte fail.");
462         return false;
463     }
464     if (oneByte > maxShortInteger) {
465         sInteger = oneByte & setHighestBitZero;
466         return true;
467     }
468     return false;
469 }
470 
471 /**
472  * @brief DecodeLongInteger
473  * Long-integer = [Short-length] [Multi-octet-integer]
474  * Short-length = 1 byte
475  * Multi-octet-integer = <Short-length> bytes
476  * @param value
477  * @return true
478  * @return false
479  */
DecodeLongInteger(uint64_t & value)480 bool SmsWapPushBuffer::DecodeLongInteger(uint64_t &value)
481 {
482     unsigned char oneByte = 0;
483     uint64_t result = 0;
484     uint32_t valuelength = 0;
485     if (GetOneByte(oneByte) != true) {
486         TELEPHONY_LOGE("wap push GetOneByte fail.");
487         return false;
488     }
489     if (oneByte > LONG_VALUE_LEN_MAX) {
490         return false;
491     }
492     valuelength = oneByte;
493 
494     for (uint32_t i = 0; i < valuelength; i++) {
495         if (GetOneByte(oneByte) != true) {
496             TELEPHONY_LOGE("wap push GetOneByte fail.");
497             return false;
498         }
499         result = (result << 0x08);
500         result |= oneByte;
501     }
502     value = result;
503     return true;
504 }
505 
506 /**
507  * @brief DecodeInteger
508  * Integer-Value = Short-integer | Long-integer
509  * @param iInteger
510  * @return true
511  * @return false
512  */
DecodeInteger(uint64_t & iInteger)513 bool SmsWapPushBuffer::DecodeInteger(uint64_t &iInteger)
514 {
515     iInteger = 0;
516     if (DecodeIsShortInt()) {
517         uint8_t sInteger = 0;
518         if (DecodeShortInteger(sInteger)) {
519             iInteger = sInteger;
520             return true;
521         }
522     } else {
523         if (DecodeLongInteger(iInteger)) {
524             return true;
525         }
526     }
527     return false;
528 }
529 
530 /**
531  * @brief DecodeIsShortInt
532  * (128 - 255) It is an encoded 7-bit value; this header has no more data
533  * @return true
534  * @return false
535  */
DecodeIsShortInt()536 bool SmsWapPushBuffer::DecodeIsShortInt()
537 {
538     uint8_t oneByte = 0;
539     PeekOneByte(oneByte);
540     if (oneByte > 0x7F) {
541         return true;
542     }
543     return false;
544 }
545 
546 /**
547  * @brief DecodeIsString
548  * (32 - 127) The value is a text string, terminated by a zero octet (NUL character)
549  * @return true
550  * @return false
551  */
DecodeIsString()552 bool SmsWapPushBuffer::DecodeIsString()
553 {
554     uint8_t oneByte = 0;
555     PeekOneByte(oneByte);
556     if (0x20 <= oneByte && 0x7f >= oneByte) {
557         return true;
558     }
559     return false;
560 }
561 
562 /**
563  * @brief DecodeIsValueLength
564  * (0 - 30) This octet is followed by the indicated number (0 –30) of data octets
565  * 31 This octet is followed by a uintvar, which indicates the number of data octets after it
566  * @return true
567  * @return false
568  */
DecodeIsValueLength()569 bool SmsWapPushBuffer::DecodeIsValueLength()
570 {
571     uint8_t oneByte = 0;
572     PeekOneByte(oneByte);
573     if (oneByte <= 0x1f) {
574         return true;
575     }
576     return false;
577 }
578 
579 /**
580  * @brief DecodeExtensionMedia
581  *
582  * @return true
583  * @return false
584  */
DecodeExtensionMedia()585 bool SmsWapPushBuffer::DecodeExtensionMedia()
586 {
587     return false;
588 }
589 
590 /**
591  * @brief DecodeConstrainedEncoding
592  *
593  * @return true
594  * @return false
595  */
DecodeConstrainedEncoding()596 bool SmsWapPushBuffer::DecodeConstrainedEncoding()
597 {
598     return false;
599 }
600 
DecodeTextValue(std::string & str,bool & isNoValue)601 bool SmsWapPushBuffer::DecodeTextValue(std::string &str, bool &isNoValue)
602 {
603     const uint8_t minTextToken = 31;
604 
605     str.clear();
606     unsigned char oneByte = 0;
607     if (GetOneByte(oneByte) != true) {
608         TELEPHONY_LOGE("wap push GetOneByte fail.");
609         return false;
610     }
611     if ((oneByte & 0x80) == 0x00 && oneByte > minTextToken) {
612         std::string field = "";
613         uint32_t fieldLength = 0;
614         if (!DecodeTokenText(field, fieldLength)) {
615             TELEPHONY_LOGE("wap push DecodeTokenText fail.");
616             return false;
617         }
618     } else {
619         uint64_t fieldId = 0;
620         if (!DecodeInteger(fieldId)) {
621             TELEPHONY_LOGE("wap push DecodeInteger fail.");
622             return false;
623         }
624     }
625     bool bNoValue = false;
626     if (!DecodeNoValue(bNoValue)) {
627         TELEPHONY_LOGE("wap push DecodeNoValue fail.");
628         return false;
629     }
630     if (bNoValue) {
631         isNoValue = true;
632         return true;
633     } else {
634         if (DecreasePointer(1) != true) {
635             TELEPHONY_LOGE("wap push DecreasePointer fail.");
636             return false;
637         }
638     }
639     uint64_t fieldValue = 0;
640     if (DecodeInteger(fieldValue)) {
641         str = std::to_string(fieldValue);
642         return true;
643     }
644     uint32_t valueLength = 0;
645     if (DecodeTokenText(str, valueLength)) {
646         if (str.length() > 1 && str.at(0) == '\"') {
647             str = str.substr(1, str.length() - 1);
648         }
649         return true;
650     }
651     return false;
652 }
653 
DecodeNoValue(bool & isNoValue)654 bool SmsWapPushBuffer::DecodeNoValue(bool &isNoValue)
655 {
656     unsigned char oneByte = 0;
657     if (GetOneByte(oneByte) != true) {
658         TELEPHONY_LOGE("wap push GetOneByte fail.");
659         return false;
660     }
661     isNoValue = (oneByte == 0) ? true : false;
662     return true;
663 }
664 
MarkPosition()665 void SmsWapPushBuffer::MarkPosition()
666 {
667     savePosition_ = curPosition_;
668 }
669 
UnMarkPosition()670 void SmsWapPushBuffer::UnMarkPosition()
671 {
672     curPosition_ = savePosition_;
673 }
674 } // namespace Telephony
675 } // namespace OHOS
676