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