/* * 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 #include "mms_decode_buffer.h" #include "telephony_log_wrapper.h" #include "securec.h" namespace OHOS { namespace Telephony { using namespace std; bool MmsDecodeBuffer::PeekOneByte(uint8_t &oneByte) { if (curPosition_ >= totolLength_) { TELEPHONY_LOGE("Decode buffer current position invalid."); return false; } oneByte = pduBuffer_[curPosition_]; return true; } bool MmsDecodeBuffer::GetOneByte(uint8_t &oneByte) { if (curPosition_ >= totolLength_) { TELEPHONY_LOGE("Decode buffer current position invalid."); return false; } oneByte = pduBuffer_[curPosition_]; curPosition_++; return true; } bool MmsDecodeBuffer::IncreasePointer(uint32_t offset) { if ((offset > totolLength_) || ((curPosition_ + offset) > totolLength_)) { TELEPHONY_LOGE("Decode buffer current position invalid."); return false; } curPosition_ += offset; return true; } bool MmsDecodeBuffer::DecreasePointer(uint32_t offset) { if (offset > curPosition_) { TELEPHONY_LOGE("Decode buffer 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 MmsDecodeBuffer::DecodeUintvar(uint32_t &uintVar, uint32_t &count) { const uint8_t setNotHighestBitZero = 0x80; const uint8_t setHighestBitZero = 0x7f; uint8_t oneByte = 0; count = 0; if (!GetOneByte(oneByte)) { TELEPHONY_LOGE("Decode buffer GetOneByte fail."); return false; } count++; uintVar = 0; while ((oneByte & setNotHighestBitZero) != 0) { uintVar = uintVar << 0x07; uintVar |= oneByte & setHighestBitZero; if (!GetOneByte(oneByte)) { TELEPHONY_LOGE("Decode buffer 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 MmsDecodeBuffer::DecodeShortLength(uint8_t &sValueLength) { uint8_t oneByte = 0; const unsigned char minShortOctet = 30; if (!GetOneByte(oneByte)) { TELEPHONY_LOGE("Decode buffer GetOneByte fail."); return false; } if (oneByte <= minShortOctet) { sValueLength = oneByte; return true; } return false; } /** * @brief DecodeValueLengthReturnLen * wap-230-wsp-20010705-a.pdf section:8.4.2.2 Length * value-length = short-length | (Length-quote Length) * short-length = * Length-quote = * (Length-quote Length) = Length-quote + Uintvar-length * @param valueLength * @param length * @return true * @return false */ bool MmsDecodeBuffer::DecodeValueLengthReturnLen(uint32_t &valueLength, uint32_t &length) { const uint8_t lengthQuote = 0x1f; const uint8_t maxShortLength = 30; length = 0; uint32_t uintvar = 0; uint8_t oneByte = 0; valueLength = 0; if (!GetOneByte(oneByte)) { DecreasePointer(1); TELEPHONY_LOGE("Decode buffer 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("Decode buffer DecodeUintvar fail."); return false; } valueLength = uintvar; length = count + 1; return true; } return false; } /** * @brief DecodeValueLength * wap-230-wsp-20010705-a section:8.4.2.2 Length * value-length = short-length | (Length-quote Length) * short-length = * Length-quote = * (Length-quote Length) = Length-quote + Uintvar-length * @param valueLength * @return true * @return false */ bool MmsDecodeBuffer::DecodeValueLength(uint32_t &valueLength) { const uint8_t lengthQuote = 0x1f; const uint8_t maxShortLength = 30; uint32_t uintvar = 0; uint8_t oneByte = 0; valueLength = 0; if (!GetOneByte(oneByte)) { DecreasePointer(1); TELEPHONY_LOGE("Decode buffer 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("Decode buffer 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 MmsDecodeBuffer::CharIsToken(uint8_t oneByte) { const uint8_t minToken = 33; const uint8_t maxToken = 126; if (oneByte < minToken || oneByte > maxToken) { return false; } switch (oneByte) { case '"': case '(': case ')': case ',': case '/': case ':': case ';': case '<': case '=': case '>': case '?': case '@': case '[': case '\\': case ']': case '{': case '}': return false; default: return true; } } /** * @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 MmsDecodeBuffer::DecodeTokenText(std::string &str, uint32_t &len) { len = 0; str.clear(); uint8_t oneByte = 0; const uint8_t minToken = 33; const uint8_t maxToken = 126; if (!PeekOneByte(oneByte)) { TELEPHONY_LOGE("Decode buffer PeekOneByte fail."); return false; } if (oneByte < minToken || oneByte > maxToken) { TELEPHONY_LOGE("Decode buffer DecodeTokenText fail."); return false; } while (GetOneByte(oneByte)) { if (oneByte != 0) { if (CharIsToken(oneByte)) { len++; str += oneByte; } } 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 MmsDecodeBuffer::DecodeText(std::string &str, uint32_t &len) { uint8_t oneByte = 0; const unsigned char quoteChar = 127; len = 0; str.clear(); if (!GetOneByte(oneByte)) { TELEPHONY_LOGE("Decode buffer 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 MmsDecodeBuffer::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 MmsDecodeBuffer::DecodeShortInteger(uint8_t &sInteger) { const uint8_t setHighestBitZero = 0x7f; const uint8_t maxShortInteger = 0x7f; uint8_t oneByte = 0; sInteger = 0; if (!GetOneByte(oneByte)) { TELEPHONY_LOGE("Decode buffer GetOneByte fail."); return false; } if (oneByte > maxShortInteger) { sInteger = oneByte & setHighestBitZero; return true; } return false; } /** * @brief DecodeLongInteger * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules * Long-integer = [Short-length] [Multi-octet-integer] * Short-length = 1 byte * Multi-octet-integer = bytes * @param value * @return true * @return false */ bool MmsDecodeBuffer::DecodeLongInteger(uint64_t &value) { unsigned char oneByte = 0; uint64_t result = 0; uint32_t valuelength = 0; if (GetOneByte(oneByte) != true) { TELEPHONY_LOGE("Decode buffer GetOneByte fail."); return false; } if (oneByte > LONG_VALUE_LEN_MAX) { TELEPHONY_LOGE("Decode buffer DecodeLongInteger fail."); return false; } valuelength = oneByte; for (uint32_t i = 0; i < valuelength; i++) { if (GetOneByte(oneByte) != true) { TELEPHONY_LOGE("Decode buffer GetOneByte fail."); return false; } result = (result << 0x08); result |= oneByte; } value = result; return true; } /** * @brief DecodeInteger * wap-230-wsp-20010705-a section:8.4.2.3 Parameter Values * Integer-Value = Short-integer | Long-integer * @param iInteger * @return true * @return false */ bool MmsDecodeBuffer::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 * wap-230-wsp-20010705-a section:8.4.1.2 Field values * (128 - 255) It is an encoded 7-bit value; this header has no more data * @return true * @return false */ bool MmsDecodeBuffer::DecodeIsShortInt() { const uint8_t maxShortInteger = 0x7f; uint8_t oneByte = 0; PeekOneByte(oneByte); if (oneByte > maxShortInteger) { return true; } return false; } /** * @brief DecodeIsString * wap-230-wsp-20010705-a section:8.4.1.2 Field values * (32 - 127) The value is a text string, terminated by a zero octet (NUL character) * @return true * @return false */ bool MmsDecodeBuffer::DecodeIsString() { const uint8_t minText = 0x20; const uint8_t maxText = 0x7f; uint8_t oneByte = 0; PeekOneByte(oneByte); if (minText <= oneByte && maxText >= oneByte) { return true; } return false; } /** * @brief DecodeIsValueLength * wap-230-wsp-20010705-a section:8.4.1.2 Field values * (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 MmsDecodeBuffer::DecodeIsValueLength() { const uint8_t lengthQuote = 0x1f; uint8_t oneByte = 0; PeekOneByte(oneByte); if (oneByte <= lengthQuote) { return true; } return false; } void MmsDecodeBuffer::MarkPosition() { savePosition_ = curPosition_; } void MmsDecodeBuffer::UnMarkPosition() { curPosition_ = savePosition_; } void MmsDecodeBuffer::GetPdu() { uint8_t hexOffset = 4; uint32_t maxDisplayLength = 500; char hexTable[] = "0123456789ABCDEF"; uint32_t size = GetSize(); if (size > maxDisplayLength) { TELEPHONY_LOGE("size is too long"); return; } uint32_t pos = GetCurPosition(); TELEPHONY_LOGE("The pdu size is %{public}d and current pos is %{public}d.", size, pos); uint32_t length = size - pos; length--; std::stringstream result; for (uint8_t i = 0; i <= pos; i++) { unsigned char temp = static_cast(pduBuffer_[i]) >> hexOffset; result << hexTable[temp] << hexTable[static_cast(pduBuffer_[i]) & 0xf]; } std::string resultCover = result.str(); for (uint8_t i = 0; i < length; i++) { resultCover += '*'; } TELEPHONY_LOGE("Decode fail pdu part is: %{public}s", resultCover.c_str()); } } // namespace Telephony } // namespace OHOS