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