/* * Copyright (C) 2023 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_common_utils.h" #include #include "securec.h" #include "telephony_log_wrapper.h" namespace OHOS { namespace Telephony { static constexpr uint8_t SMS_ENCODE_GSM_BIT = 7; static constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160; static constexpr uint8_t SMS_BYTE_BIT = 8; static constexpr uint16_t SEC_PER_HOUR = 3600; static constexpr uint8_t BASE_GSM_YEAR = 100; static constexpr uint8_t MAX_ABS_TIME_LEN = 32; static constexpr uint8_t HEX_NUM_A = 0x0A; static constexpr uint8_t HEX_NUM_B = 0x0B; static constexpr uint8_t HEX_NUM_C = 0x0C; static constexpr uint8_t MIN_PRINTABLE_CHAR = 32; static constexpr uint8_t MAX_PRINTABLE_CHAR = 127; uint16_t SmsCommonUtils::Pack7bitChar( const uint8_t *userData, uint16_t dataLen, uint8_t fillBits, uint8_t *packData, uint16_t packLen) { uint16_t dstIdx = 0; if (userData == nullptr || packData == nullptr || dataLen > MAX_GSM_7BIT_DATA_LEN) { TELEPHONY_LOGE("userData error."); return dstIdx; } auto shift = fillBits; if (shift > 0) { dstIdx = 1; } uint16_t srcIdx = 0; while (srcIdx < dataLen && dstIdx < packLen) { if (shift == 0) { packData[dstIdx] = userData[srcIdx]; shift = SMS_ENCODE_GSM_BIT; srcIdx++; dstIdx++; if (srcIdx >= dataLen) { break; } } if (shift > 1) { packData[dstIdx - 1] |= userData[srcIdx] << shift; packData[dstIdx] = userData[srcIdx] >> (SMS_BYTE_BIT - shift); srcIdx++; dstIdx++; shift--; } else if (shift == 1) { packData[dstIdx - 1] |= userData[srcIdx] << shift; shift--; srcIdx++; } } return dstIdx; } uint16_t SmsCommonUtils::Unpack7bitChar( const uint8_t *tpdu, uint16_t dataLen, uint8_t fillBits, uint8_t *unpackData, uint16_t unpackDataLen) { uint16_t srcIdx = 0; uint16_t dstIdx = 0; auto shift = fillBits; if (unpackData == nullptr || tpdu == nullptr || dataLen == 0 || unpackDataLen == 0 || dataLen > unpackDataLen) { TELEPHONY_LOGE("userData error."); return dstIdx; } if (shift > 0) { srcIdx = 1; } for (; srcIdx < dataLen && dstIdx < unpackDataLen; dstIdx++) { if (shift == 0) { unpackData[dstIdx] = tpdu[srcIdx] & 0x7F; shift = SMS_ENCODE_GSM_BIT; srcIdx++; dstIdx++; if (dstIdx >= dataLen) { dstIdx--; break; } } if (shift > 0 && srcIdx < dataLen && dstIdx < unpackDataLen) { unpackData[dstIdx] = ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SMS_BYTE_BIT - shift)); unpackData[dstIdx] &= 0x7F; shift--; if (shift > 0) { srcIdx++; } } } return dstIdx; } uint16_t SmsCommonUtils::Unpack7bitCharForCBPdu( const uint8_t *tpdu, uint16_t dataLen, uint8_t fillBits, uint8_t *unpackData, uint16_t unpackDataLen) { uint16_t srcIdx = 0; uint16_t dstIdx = 0; auto shift = fillBits; if (unpackData == nullptr || tpdu == nullptr || dataLen == 0 || unpackDataLen == 0 || dataLen > unpackDataLen) { TELEPHONY_LOGE("userData error."); return dstIdx; } if (shift > 0) { srcIdx = 1; } for (; srcIdx < dataLen && dstIdx < unpackDataLen;) { if (shift == 0) { unpackData[dstIdx] = tpdu[srcIdx] & 0x7F; shift = SMS_ENCODE_GSM_BIT; srcIdx++; dstIdx++; } if (shift > 0 && srcIdx < dataLen && dstIdx < unpackDataLen) { unpackData[dstIdx] = ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SMS_BYTE_BIT - shift)); unpackData[dstIdx] &= 0x7F; shift--; if (shift > 0) { srcIdx++; } dstIdx++; } } if (dstIdx >= unpackDataLen) { TELEPHONY_LOGE("dstIdx:%{public}d", dstIdx); return 0; } uint8_t value = 0; if (shift == 0) { value = tpdu[srcIdx] >> shift; } else if (srcIdx > 1) { value = tpdu[srcIdx - 1] >> shift; } if (value >= MIN_PRINTABLE_CHAR && value <= MAX_PRINTABLE_CHAR) { unpackData[dstIdx] = value; dstIdx++; } TELEPHONY_LOGI("dstIdx:%{public}d", dstIdx); return dstIdx; } uint8_t SmsCommonUtils::DigitToDtmfChar(const uint8_t c) { if (c == '0') { return HEX_NUM_A; } else if (c == '*') { return HEX_NUM_B; } else if (c == '#') { return HEX_NUM_C; } else { return (c - '0'); } } uint8_t SmsCommonUtils::DtmfCharToDigit(const uint8_t c) { switch (c) { case HEX_NUM_B: return '*'; case HEX_NUM_C: return '#'; case HEX_NUM_A: return '0'; default: return (c + '0'); } } int64_t SmsCommonUtils::ConvertTime(const struct SmsTimeAbs &timeAbs) { time_t rawtime; struct tm tmObj; if (memset_s(&tmObj, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) { return time(nullptr); } tmObj.tm_year = (timeAbs.year + BASE_GSM_YEAR); tmObj.tm_mon = (timeAbs.month - 0x01); tmObj.tm_mday = timeAbs.day; tmObj.tm_hour = timeAbs.hour; tmObj.tm_min = timeAbs.minute; tmObj.tm_sec = timeAbs.second; tmObj.tm_isdst = 0; rawtime = mktime(&tmObj); GetDisplayTime(rawtime); rawtime -= (timeAbs.timeZone * (SEC_PER_HOUR / 0x04)); GetDisplayTime(rawtime); /* timezone value is tiemzone + daylight. So should not add daylight */ rawtime -= timezone; GetDisplayTime(rawtime); return rawtime; } void SmsCommonUtils::GetDisplayTime(const time_t &rawtime) { struct tm tmObj; char displayTime[MAX_ABS_TIME_LEN]; if (memset_s(&tmObj, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) { TELEPHONY_LOGE("GetDisplayTime memset fail."); return; } if (memset_s(displayTime, sizeof(displayTime), 0x00, sizeof(displayTime)) != EOK) { TELEPHONY_LOGE("GetDisplayTime memset fail."); return; } localtime_r(&rawtime, &tmObj); if (strftime(displayTime, MAX_ABS_TIME_LEN, "%Y-%02m-%02d %T %z", &tmObj) <= 0) { TELEPHONY_LOGE("strftime error."); return; } } } // namespace Telephony } // namespace OHOS