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