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