/* * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "sms_wap_push_buffer.h" #include "securec.h" #include "sms_constants_utils.h" #include "string_utils.h" #include "telephony_log_wrapper.h" namespace OHOS { namespace Telephony { SmsWapPushBuffer::SmsWapPushBuffer() {} SmsWapPushBuffer::~SmsWapPushBuffer() { if (pduBuffer_ != nullptr) { pduBuffer_.reset(); } } std::unique_ptr SmsWapPushBuffer::ReadDataBuffer(uint32_t desLen) { return ReadDataBuffer(curPosition_, desLen); } std::unique_ptr SmsWapPushBuffer::ReadDataBuffer(uint32_t offset, uint32_t desLen) { if ((desLen > totolLength_) || ((offset + desLen) > totolLength_)) { return nullptr; } if (desLen > MMS_PDU_MAX_SIZE) { TELEPHONY_LOGE("desLen over size error"); return nullptr; } std::unique_ptr result = std::make_unique(desLen); if (result == nullptr) { return nullptr; } if (memcpy_s(result.get(), desLen, &pduBuffer_[offset], desLen) != EOK) { return nullptr; } return result; } bool SmsWapPushBuffer::WriteRawStringBuffer(const std::string &inSrc) { uint32_t len = inSrc.length(); if (len > MMS_PDU_MAX_SIZE) { TELEPHONY_LOGE("create wappush input source string over length error."); return false; } if (pduBuffer_) { pduBuffer_.reset(); } pduBuffer_ = std::make_unique(len); if (!pduBuffer_) { TELEPHONY_LOGE("wap push make unique fail."); return false; } if (memcpy_s(pduBuffer_.get(), len, inSrc.data(), len) != EOK) { TELEPHONY_LOGE("wap push memcpy_s fail."); return false; } totolLength_ = len; return true; } bool SmsWapPushBuffer::WriteDataBuffer(std::unique_ptr inBuff, uint32_t len) { if (inBuff == nullptr) { TELEPHONY_LOGE("wap push inBuff is null."); return false; } if (len <= 0 || len > MMS_PDU_MAX_SIZE) { TELEPHONY_LOGE("wap push len invalid ."); return false; } if (pduBuffer_) { pduBuffer_.reset(); } pduBuffer_ = std::make_unique(len); if (!pduBuffer_) { TELEPHONY_LOGE("wap push make unique fail."); return false; } if (memcpy_s(pduBuffer_.get(), len, inBuff.get(), len) != EOK) { TELEPHONY_LOGE("wap push memcpy_s fail."); return false; } totolLength_ = len; return true; } uint32_t SmsWapPushBuffer::GetCurPosition() const { return curPosition_; } uint32_t SmsWapPushBuffer::GetSize() const { return totolLength_; } bool SmsWapPushBuffer::PeekOneByte(uint8_t &oneByte) { if (curPosition_ >= totolLength_) { TELEPHONY_LOGE("wap push current position invalid."); return false; } oneByte = pduBuffer_[curPosition_]; return true; } bool SmsWapPushBuffer::GetOneByte(uint8_t &oneByte) { if (curPosition_ >= totolLength_) { TELEPHONY_LOGE("wap push current position invalid."); return false; } oneByte = pduBuffer_[curPosition_]; curPosition_++; return true; } bool SmsWapPushBuffer::IncreasePointer(uint32_t offset) { if ((offset > totolLength_) || ((curPosition_ + offset) > totolLength_)) { TELEPHONY_LOGE("wap push current position invalid."); return false; } curPosition_ += offset; return true; } bool SmsWapPushBuffer::DecreasePointer(uint32_t offset) { if (offset > curPosition_) { TELEPHONY_LOGE("wap push current position invalid."); return false; } curPosition_ -= offset; return true; } /** * @brief DecodeUintvar * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules * Uintvar-integer = 1*5 OCTET * @param uintVar * @param count * @return true * @return false */ bool SmsWapPushBuffer::DecodeUintvar(uint32_t &uintVar, uint32_t &count) { const uint8_t setNotHighestBitZero = 0x80; const uint8_t setHighestBitZero = 0x7f; count = 0; uint8_t oneByte = 0; if (!GetOneByte(oneByte)) { TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } count++; uintVar = 0; while ((oneByte & setNotHighestBitZero) != 0) { uintVar = uintVar << 0x07; uintVar |= oneByte & setHighestBitZero; if (!GetOneByte(oneByte)) { TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } count++; } uintVar = uintVar << 0x07; uintVar |= oneByte & setHighestBitZero; return true; } /** * @brief DecodeShortLength * wap-230-wsp-20010705-a.pdf section:8.4.2.2 Length * Short-length = * @param sValueLength * @return true * @return false */ bool SmsWapPushBuffer::DecodeShortLength(uint8_t &sValueLength) { const unsigned char minShortOctet = 30; uint8_t oneByte = 0; if (!GetOneByte(oneByte)) { TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } if (oneByte <= minShortOctet) { sValueLength = oneByte; return true; } return false; } /** * @brief DecodeValueLengthReturnLen * value-length = short-length | (Length-quote Length) * short-length = 0~30 * Length-quote = 31 * (Length-quote Length) = Length-quote + Uintvar-length * @param valueLength * @return true * @return false */ bool SmsWapPushBuffer::DecodeValueLengthReturnLen(uint32_t &valueLength, uint32_t &length) { const uint8_t lengthQuote = 0x1f; const uint8_t maxShortLength = 30; length = 0; valueLength = 0; uint32_t uintvar = 0; uint8_t oneByte = 0; if (!GetOneByte(oneByte)) { DecreasePointer(1); TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } if (oneByte <= maxShortLength) { valueLength = oneByte; length = 1; return true; } else if (oneByte == lengthQuote) { /* Length-quote = 0x1F */ uint32_t count = 0; if (!DecodeUintvar(uintvar, count)) { TELEPHONY_LOGE("wap push DecodeUintvar fail."); return false; } valueLength = uintvar; length = count + 1; return true; } return false; } /** * @brief DecodeValueLength * value-length = short-length | (Length-quote Length) * short-length = 0~30 * Length-quote = 31 * (Length-quote Length) = Length-quote + Uintvar-length * @param valueLength * @return true * @return false */ bool SmsWapPushBuffer::DecodeValueLength(uint32_t &valueLength) { const uint8_t lengthQuote = 0x1f; const uint8_t maxShortLength = 30; valueLength = 0; uint32_t uintvar = 0; uint8_t oneByte = 0; if (!GetOneByte(oneByte)) { DecreasePointer(1); TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } if (oneByte <= maxShortLength) { valueLength = oneByte; return true; } else if (oneByte == lengthQuote) { /* Length-quote = 0x1F */ uint32_t count = 0; if (!DecodeUintvar(uintvar, count)) { TELEPHONY_LOGE("wap push DecodeUintvar fail."); return false; } valueLength = uintvar; return true; } return false; } /** * @brief CharIsToken * RFC2616 section:2.2 Basic Rules * CHAR = * CTL = * separators = "(" | ")" | "<" | ">" | "@" * | "," | ";" | ":" | "\" | <"> * | "/" | "[" | "]" | "?" | "=" * | "{" | "}" | SP | HT * @param oneByte * @return true * @return false */ bool SmsWapPushBuffer::CharIsToken(uint8_t oneByte) { const uint8_t minToken = 33; const uint8_t maxToken = 126; if (oneByte < minToken || oneByte > maxToken) { return false; } std::set token = { '"', '(', ')', '/', ',', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' }; return !token.count(oneByte); } /** * @brief DecodeTokenText * wap-230-wsp-20010705-a section:8.4.2.2 Length * Token-text = Token End-of-string * End-of-string = * @param str * @param len * @return true * @return false */ bool SmsWapPushBuffer::DecodeTokenText(std::string &str, uint32_t &len) { const uint8_t minToken = 33; const uint8_t maxToken = 126; len = 0; str.clear(); uint8_t oneByte = 0; if (!PeekOneByte(oneByte)) { TELEPHONY_LOGE("wap push PeekOneByte fail."); return false; } if (oneByte < minToken || oneByte > maxToken) { TELEPHONY_LOGE("wap push DecodeTokenText fail."); return false; } while (GetOneByte(oneByte)) { if (oneByte != 0) { if (CharIsToken(oneByte)) { str += oneByte; len++; } } else { break; } } return (len > 0) ? true : false; } /** * @brief DecodeText * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules * Text-string = [Quote] *TEXT End-of-string * Quote = * End-of-string = * @param str * @param len * @return true * @return false */ bool SmsWapPushBuffer::DecodeText(std::string &str, uint32_t &len) { const unsigned char quoteChar = 127; len = 0; str.clear(); uint8_t oneByte = 0; if (!GetOneByte(oneByte)) { TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } // ignore quote if (oneByte != quoteChar) { this->DecreasePointer(1); } else { len++; } while (GetOneByte(oneByte)) { if (oneByte != 0) { str += oneByte; len++; } else { break; } } return (len > 0) ? true : false; } /** * @brief DecodeQuotedText * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules * Quoted-string = *TEXT End-of-string * The TEXT encodes an RFC2616 Quoted-string with the enclosing quotation-marks <"> removed * @param str * @param len * @return true * @return false */ bool SmsWapPushBuffer::DecodeQuotedText(std::string &str, uint32_t &len) { const uint8_t quotedFlag = 0x22; uint8_t oneByte = 0; len = 0; str.clear(); while (GetOneByte(oneByte)) { if (oneByte != 0) { if (oneByte != quotedFlag) { str += oneByte; } len++; } else { break; } } return (len > 0) ? true : false; } /** * @brief DecodeShortInteger * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules * Short-integer = OCTET * Integers in range 0-127 shall be encoded as a one octet value with * the most significant bit set to one (1xxx xxxx) and with the value * in the remaining least significant bits * @param sInteger * @return true * @return false */ bool SmsWapPushBuffer::DecodeShortInteger(uint8_t &sInteger) { const uint8_t setHighestBitZero = 0x7f; const uint8_t maxShortInteger = 0x7f; sInteger = 0; uint8_t oneByte = 0; if (!GetOneByte(oneByte)) { TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } if (oneByte > maxShortInteger) { sInteger = oneByte & setHighestBitZero; return true; } return false; } /** * @brief DecodeLongInteger * Long-integer = [Short-length] [Multi-octet-integer] * Short-length = 1 byte * Multi-octet-integer = bytes * @param value * @return true * @return false */ bool SmsWapPushBuffer::DecodeLongInteger(uint64_t &value) { unsigned char oneByte = 0; uint64_t result = 0; uint32_t valuelength = 0; if (GetOneByte(oneByte) != true) { TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } if (oneByte > LONG_VALUE_LEN_MAX) { return false; } valuelength = oneByte; for (uint32_t i = 0; i < valuelength; i++) { if (GetOneByte(oneByte) != true) { TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } result = (result << 0x08); result |= oneByte; } value = result; return true; } /** * @brief DecodeInteger * Integer-Value = Short-integer | Long-integer * @param iInteger * @return true * @return false */ bool SmsWapPushBuffer::DecodeInteger(uint64_t &iInteger) { iInteger = 0; if (DecodeIsShortInt()) { uint8_t sInteger = 0; if (DecodeShortInteger(sInteger)) { iInteger = sInteger; return true; } } else { if (DecodeLongInteger(iInteger)) { return true; } } return false; } /** * @brief DecodeIsShortInt * (128 - 255) It is an encoded 7-bit value; this header has no more data * @return true * @return false */ bool SmsWapPushBuffer::DecodeIsShortInt() { uint8_t oneByte = 0; PeekOneByte(oneByte); if (oneByte > 0x7F) { return true; } return false; } /** * @brief DecodeIsString * (32 - 127) The value is a text string, terminated by a zero octet (NUL character) * @return true * @return false */ bool SmsWapPushBuffer::DecodeIsString() { uint8_t oneByte = 0; PeekOneByte(oneByte); if (0x20 <= oneByte && 0x7f >= oneByte) { return true; } return false; } /** * @brief DecodeIsValueLength * (0 - 30) This octet is followed by the indicated number (0 –30) of data octets * 31 This octet is followed by a uintvar, which indicates the number of data octets after it * @return true * @return false */ bool SmsWapPushBuffer::DecodeIsValueLength() { uint8_t oneByte = 0; PeekOneByte(oneByte); if (oneByte <= 0x1f) { return true; } return false; } /** * @brief DecodeExtensionMedia * * @return true * @return false */ bool SmsWapPushBuffer::DecodeExtensionMedia() { return false; } /** * @brief DecodeConstrainedEncoding * * @return true * @return false */ bool SmsWapPushBuffer::DecodeConstrainedEncoding() { return false; } bool SmsWapPushBuffer::DecodeTextValue(std::string &str, bool &isNoValue) { const uint8_t minTextToken = 31; str.clear(); unsigned char oneByte = 0; if (GetOneByte(oneByte) != true) { TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } if ((oneByte & 0x80) == 0x00 && oneByte > minTextToken) { std::string field = ""; uint32_t fieldLength = 0; if (!DecodeTokenText(field, fieldLength)) { TELEPHONY_LOGE("wap push DecodeTokenText fail."); return false; } } else { uint64_t fieldId = 0; if (!DecodeInteger(fieldId)) { TELEPHONY_LOGE("wap push DecodeInteger fail."); return false; } } bool bNoValue = false; if (!DecodeNoValue(bNoValue)) { TELEPHONY_LOGE("wap push DecodeNoValue fail."); return false; } if (bNoValue) { isNoValue = true; return true; } else { if (DecreasePointer(1) != true) { TELEPHONY_LOGE("wap push DecreasePointer fail."); return false; } } uint64_t fieldValue = 0; if (DecodeInteger(fieldValue)) { str = std::to_string(fieldValue); return true; } uint32_t valueLength = 0; if (DecodeTokenText(str, valueLength)) { if (str.length() > 1 && str.at(0) == '\"') { str = str.substr(1, str.length() - 1); } return true; } return false; } bool SmsWapPushBuffer::DecodeNoValue(bool &isNoValue) { unsigned char oneByte = 0; if (GetOneByte(oneByte) != true) { TELEPHONY_LOGE("wap push GetOneByte fail."); return false; } isNoValue = (oneByte == 0) ? true : false; return true; } void SmsWapPushBuffer::MarkPosition() { savePosition_ = curPosition_; } void SmsWapPushBuffer::UnMarkPosition() { curPosition_ = savePosition_; } } // namespace Telephony } // namespace OHOS