1e5d0e473Sopenharmony_ci/* 2e5d0e473Sopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3e5d0e473Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e5d0e473Sopenharmony_ci * you may not use this file except in compliance with the License. 5e5d0e473Sopenharmony_ci * You may obtain a copy of the License at 6e5d0e473Sopenharmony_ci * 7e5d0e473Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e5d0e473Sopenharmony_ci * 9e5d0e473Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e5d0e473Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e5d0e473Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e5d0e473Sopenharmony_ci * See the License for the specific language governing permissions and 13e5d0e473Sopenharmony_ci * limitations under the License. 14e5d0e473Sopenharmony_ci */ 15e5d0e473Sopenharmony_ci 16e5d0e473Sopenharmony_ci#include "sms_common_utils.h" 17e5d0e473Sopenharmony_ci 18e5d0e473Sopenharmony_ci#include <ctime> 19e5d0e473Sopenharmony_ci#include "securec.h" 20e5d0e473Sopenharmony_ci#include "telephony_log_wrapper.h" 21e5d0e473Sopenharmony_ci 22e5d0e473Sopenharmony_cinamespace OHOS { 23e5d0e473Sopenharmony_cinamespace Telephony { 24e5d0e473Sopenharmony_cistatic constexpr uint8_t SMS_ENCODE_GSM_BIT = 7; 25e5d0e473Sopenharmony_cistatic constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160; 26e5d0e473Sopenharmony_cistatic constexpr uint8_t SMS_BYTE_BIT = 8; 27e5d0e473Sopenharmony_cistatic constexpr uint16_t SEC_PER_HOUR = 3600; 28e5d0e473Sopenharmony_cistatic constexpr uint8_t BASE_GSM_YEAR = 100; 29e5d0e473Sopenharmony_cistatic constexpr uint8_t MAX_ABS_TIME_LEN = 32; 30e5d0e473Sopenharmony_cistatic constexpr uint8_t HEX_NUM_A = 0x0A; 31e5d0e473Sopenharmony_cistatic constexpr uint8_t HEX_NUM_B = 0x0B; 32e5d0e473Sopenharmony_cistatic constexpr uint8_t HEX_NUM_C = 0x0C; 33e5d0e473Sopenharmony_cistatic constexpr uint8_t MIN_PRINTABLE_CHAR = 32; 34e5d0e473Sopenharmony_cistatic constexpr uint8_t MAX_PRINTABLE_CHAR = 127; 35e5d0e473Sopenharmony_ci 36e5d0e473Sopenharmony_ciuint16_t SmsCommonUtils::Pack7bitChar( 37e5d0e473Sopenharmony_ci const uint8_t *userData, uint16_t dataLen, uint8_t fillBits, uint8_t *packData, uint16_t packLen) 38e5d0e473Sopenharmony_ci{ 39e5d0e473Sopenharmony_ci uint16_t dstIdx = 0; 40e5d0e473Sopenharmony_ci if (userData == nullptr || packData == nullptr || dataLen > MAX_GSM_7BIT_DATA_LEN) { 41e5d0e473Sopenharmony_ci TELEPHONY_LOGE("userData error."); 42e5d0e473Sopenharmony_ci return dstIdx; 43e5d0e473Sopenharmony_ci } 44e5d0e473Sopenharmony_ci 45e5d0e473Sopenharmony_ci auto shift = fillBits; 46e5d0e473Sopenharmony_ci if (shift > 0) { 47e5d0e473Sopenharmony_ci dstIdx = 1; 48e5d0e473Sopenharmony_ci } 49e5d0e473Sopenharmony_ci uint16_t srcIdx = 0; 50e5d0e473Sopenharmony_ci while (srcIdx < dataLen && dstIdx < packLen) { 51e5d0e473Sopenharmony_ci if (shift == 0) { 52e5d0e473Sopenharmony_ci packData[dstIdx] = userData[srcIdx]; 53e5d0e473Sopenharmony_ci shift = SMS_ENCODE_GSM_BIT; 54e5d0e473Sopenharmony_ci srcIdx++; 55e5d0e473Sopenharmony_ci dstIdx++; 56e5d0e473Sopenharmony_ci if (srcIdx >= dataLen) { 57e5d0e473Sopenharmony_ci break; 58e5d0e473Sopenharmony_ci } 59e5d0e473Sopenharmony_ci } 60e5d0e473Sopenharmony_ci if (shift > 1) { 61e5d0e473Sopenharmony_ci packData[dstIdx - 1] |= userData[srcIdx] << shift; 62e5d0e473Sopenharmony_ci packData[dstIdx] = userData[srcIdx] >> (SMS_BYTE_BIT - shift); 63e5d0e473Sopenharmony_ci srcIdx++; 64e5d0e473Sopenharmony_ci dstIdx++; 65e5d0e473Sopenharmony_ci shift--; 66e5d0e473Sopenharmony_ci } else if (shift == 1) { 67e5d0e473Sopenharmony_ci packData[dstIdx - 1] |= userData[srcIdx] << shift; 68e5d0e473Sopenharmony_ci shift--; 69e5d0e473Sopenharmony_ci srcIdx++; 70e5d0e473Sopenharmony_ci } 71e5d0e473Sopenharmony_ci } 72e5d0e473Sopenharmony_ci return dstIdx; 73e5d0e473Sopenharmony_ci} 74e5d0e473Sopenharmony_ci 75e5d0e473Sopenharmony_ciuint16_t SmsCommonUtils::Unpack7bitChar( 76e5d0e473Sopenharmony_ci const uint8_t *tpdu, uint16_t dataLen, uint8_t fillBits, uint8_t *unpackData, uint16_t unpackDataLen) 77e5d0e473Sopenharmony_ci{ 78e5d0e473Sopenharmony_ci uint16_t srcIdx = 0; 79e5d0e473Sopenharmony_ci uint16_t dstIdx = 0; 80e5d0e473Sopenharmony_ci auto shift = fillBits; 81e5d0e473Sopenharmony_ci if (unpackData == nullptr || tpdu == nullptr || dataLen == 0 || unpackDataLen == 0 || dataLen > unpackDataLen) { 82e5d0e473Sopenharmony_ci TELEPHONY_LOGE("userData error."); 83e5d0e473Sopenharmony_ci return dstIdx; 84e5d0e473Sopenharmony_ci } 85e5d0e473Sopenharmony_ci if (shift > 0) { 86e5d0e473Sopenharmony_ci srcIdx = 1; 87e5d0e473Sopenharmony_ci } 88e5d0e473Sopenharmony_ci for (; srcIdx < dataLen && dstIdx < unpackDataLen; dstIdx++) { 89e5d0e473Sopenharmony_ci if (shift == 0) { 90e5d0e473Sopenharmony_ci unpackData[dstIdx] = tpdu[srcIdx] & 0x7F; 91e5d0e473Sopenharmony_ci shift = SMS_ENCODE_GSM_BIT; 92e5d0e473Sopenharmony_ci srcIdx++; 93e5d0e473Sopenharmony_ci dstIdx++; 94e5d0e473Sopenharmony_ci if (dstIdx >= dataLen) { 95e5d0e473Sopenharmony_ci dstIdx--; 96e5d0e473Sopenharmony_ci break; 97e5d0e473Sopenharmony_ci } 98e5d0e473Sopenharmony_ci } 99e5d0e473Sopenharmony_ci if (shift > 0 && srcIdx < dataLen && dstIdx < unpackDataLen) { 100e5d0e473Sopenharmony_ci unpackData[dstIdx] = ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SMS_BYTE_BIT - shift)); 101e5d0e473Sopenharmony_ci unpackData[dstIdx] &= 0x7F; 102e5d0e473Sopenharmony_ci shift--; 103e5d0e473Sopenharmony_ci if (shift > 0) { 104e5d0e473Sopenharmony_ci srcIdx++; 105e5d0e473Sopenharmony_ci } 106e5d0e473Sopenharmony_ci } 107e5d0e473Sopenharmony_ci } 108e5d0e473Sopenharmony_ci return dstIdx; 109e5d0e473Sopenharmony_ci} 110e5d0e473Sopenharmony_ci 111e5d0e473Sopenharmony_ciuint16_t SmsCommonUtils::Unpack7bitCharForCBPdu( 112e5d0e473Sopenharmony_ci const uint8_t *tpdu, uint16_t dataLen, uint8_t fillBits, uint8_t *unpackData, uint16_t unpackDataLen) 113e5d0e473Sopenharmony_ci{ 114e5d0e473Sopenharmony_ci uint16_t srcIdx = 0; 115e5d0e473Sopenharmony_ci uint16_t dstIdx = 0; 116e5d0e473Sopenharmony_ci auto shift = fillBits; 117e5d0e473Sopenharmony_ci if (unpackData == nullptr || tpdu == nullptr || dataLen == 0 || unpackDataLen == 0 || dataLen > unpackDataLen) { 118e5d0e473Sopenharmony_ci TELEPHONY_LOGE("userData error."); 119e5d0e473Sopenharmony_ci return dstIdx; 120e5d0e473Sopenharmony_ci } 121e5d0e473Sopenharmony_ci if (shift > 0) { 122e5d0e473Sopenharmony_ci srcIdx = 1; 123e5d0e473Sopenharmony_ci } 124e5d0e473Sopenharmony_ci for (; srcIdx < dataLen && dstIdx < unpackDataLen;) { 125e5d0e473Sopenharmony_ci if (shift == 0) { 126e5d0e473Sopenharmony_ci unpackData[dstIdx] = tpdu[srcIdx] & 0x7F; 127e5d0e473Sopenharmony_ci shift = SMS_ENCODE_GSM_BIT; 128e5d0e473Sopenharmony_ci srcIdx++; 129e5d0e473Sopenharmony_ci dstIdx++; 130e5d0e473Sopenharmony_ci } 131e5d0e473Sopenharmony_ci if (shift > 0 && srcIdx < dataLen && dstIdx < unpackDataLen) { 132e5d0e473Sopenharmony_ci unpackData[dstIdx] = ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SMS_BYTE_BIT - shift)); 133e5d0e473Sopenharmony_ci unpackData[dstIdx] &= 0x7F; 134e5d0e473Sopenharmony_ci shift--; 135e5d0e473Sopenharmony_ci if (shift > 0) { 136e5d0e473Sopenharmony_ci srcIdx++; 137e5d0e473Sopenharmony_ci } 138e5d0e473Sopenharmony_ci dstIdx++; 139e5d0e473Sopenharmony_ci } 140e5d0e473Sopenharmony_ci } 141e5d0e473Sopenharmony_ci if (dstIdx >= unpackDataLen) { 142e5d0e473Sopenharmony_ci TELEPHONY_LOGE("dstIdx:%{public}d", dstIdx); 143e5d0e473Sopenharmony_ci return 0; 144e5d0e473Sopenharmony_ci } 145e5d0e473Sopenharmony_ci uint8_t value = 0; 146e5d0e473Sopenharmony_ci if (shift == 0) { 147e5d0e473Sopenharmony_ci value = tpdu[srcIdx] >> shift; 148e5d0e473Sopenharmony_ci } else if (srcIdx > 1) { 149e5d0e473Sopenharmony_ci value = tpdu[srcIdx - 1] >> shift; 150e5d0e473Sopenharmony_ci } 151e5d0e473Sopenharmony_ci if (value >= MIN_PRINTABLE_CHAR && value <= MAX_PRINTABLE_CHAR) { 152e5d0e473Sopenharmony_ci unpackData[dstIdx] = value; 153e5d0e473Sopenharmony_ci dstIdx++; 154e5d0e473Sopenharmony_ci } 155e5d0e473Sopenharmony_ci TELEPHONY_LOGI("dstIdx:%{public}d", dstIdx); 156e5d0e473Sopenharmony_ci return dstIdx; 157e5d0e473Sopenharmony_ci} 158e5d0e473Sopenharmony_ci 159e5d0e473Sopenharmony_ciuint8_t SmsCommonUtils::DigitToDtmfChar(const uint8_t c) 160e5d0e473Sopenharmony_ci{ 161e5d0e473Sopenharmony_ci if (c == '0') { 162e5d0e473Sopenharmony_ci return HEX_NUM_A; 163e5d0e473Sopenharmony_ci } else if (c == '*') { 164e5d0e473Sopenharmony_ci return HEX_NUM_B; 165e5d0e473Sopenharmony_ci } else if (c == '#') { 166e5d0e473Sopenharmony_ci return HEX_NUM_C; 167e5d0e473Sopenharmony_ci } else { 168e5d0e473Sopenharmony_ci return (c - '0'); 169e5d0e473Sopenharmony_ci } 170e5d0e473Sopenharmony_ci} 171e5d0e473Sopenharmony_ci 172e5d0e473Sopenharmony_ciuint8_t SmsCommonUtils::DtmfCharToDigit(const uint8_t c) 173e5d0e473Sopenharmony_ci{ 174e5d0e473Sopenharmony_ci switch (c) { 175e5d0e473Sopenharmony_ci case HEX_NUM_B: 176e5d0e473Sopenharmony_ci return '*'; 177e5d0e473Sopenharmony_ci case HEX_NUM_C: 178e5d0e473Sopenharmony_ci return '#'; 179e5d0e473Sopenharmony_ci case HEX_NUM_A: 180e5d0e473Sopenharmony_ci return '0'; 181e5d0e473Sopenharmony_ci default: 182e5d0e473Sopenharmony_ci return (c + '0'); 183e5d0e473Sopenharmony_ci } 184e5d0e473Sopenharmony_ci} 185e5d0e473Sopenharmony_ci 186e5d0e473Sopenharmony_ciint64_t SmsCommonUtils::ConvertTime(const struct SmsTimeAbs &timeAbs) 187e5d0e473Sopenharmony_ci{ 188e5d0e473Sopenharmony_ci time_t rawtime; 189e5d0e473Sopenharmony_ci struct tm tmObj; 190e5d0e473Sopenharmony_ci if (memset_s(&tmObj, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) { 191e5d0e473Sopenharmony_ci return time(nullptr); 192e5d0e473Sopenharmony_ci } 193e5d0e473Sopenharmony_ci tmObj.tm_year = (timeAbs.year + BASE_GSM_YEAR); 194e5d0e473Sopenharmony_ci tmObj.tm_mon = (timeAbs.month - 0x01); 195e5d0e473Sopenharmony_ci tmObj.tm_mday = timeAbs.day; 196e5d0e473Sopenharmony_ci tmObj.tm_hour = timeAbs.hour; 197e5d0e473Sopenharmony_ci tmObj.tm_min = timeAbs.minute; 198e5d0e473Sopenharmony_ci tmObj.tm_sec = timeAbs.second; 199e5d0e473Sopenharmony_ci tmObj.tm_isdst = 0; 200e5d0e473Sopenharmony_ci rawtime = mktime(&tmObj); 201e5d0e473Sopenharmony_ci GetDisplayTime(rawtime); 202e5d0e473Sopenharmony_ci rawtime -= (timeAbs.timeZone * (SEC_PER_HOUR / 0x04)); 203e5d0e473Sopenharmony_ci GetDisplayTime(rawtime); 204e5d0e473Sopenharmony_ci /* timezone value is tiemzone + daylight. So should not add daylight */ 205e5d0e473Sopenharmony_ci rawtime -= timezone; 206e5d0e473Sopenharmony_ci GetDisplayTime(rawtime); 207e5d0e473Sopenharmony_ci return rawtime; 208e5d0e473Sopenharmony_ci} 209e5d0e473Sopenharmony_ci 210e5d0e473Sopenharmony_civoid SmsCommonUtils::GetDisplayTime(const time_t &rawtime) 211e5d0e473Sopenharmony_ci{ 212e5d0e473Sopenharmony_ci struct tm tmObj; 213e5d0e473Sopenharmony_ci char displayTime[MAX_ABS_TIME_LEN]; 214e5d0e473Sopenharmony_ci if (memset_s(&tmObj, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) { 215e5d0e473Sopenharmony_ci TELEPHONY_LOGE("GetDisplayTime memset fail."); 216e5d0e473Sopenharmony_ci return; 217e5d0e473Sopenharmony_ci } 218e5d0e473Sopenharmony_ci 219e5d0e473Sopenharmony_ci if (memset_s(displayTime, sizeof(displayTime), 0x00, sizeof(displayTime)) != EOK) { 220e5d0e473Sopenharmony_ci TELEPHONY_LOGE("GetDisplayTime memset fail."); 221e5d0e473Sopenharmony_ci return; 222e5d0e473Sopenharmony_ci } 223e5d0e473Sopenharmony_ci 224e5d0e473Sopenharmony_ci localtime_r(&rawtime, &tmObj); 225e5d0e473Sopenharmony_ci if (strftime(displayTime, MAX_ABS_TIME_LEN, "%Y-%02m-%02d %T %z", &tmObj) <= 0) { 226e5d0e473Sopenharmony_ci TELEPHONY_LOGE("strftime error."); 227e5d0e473Sopenharmony_ci return; 228e5d0e473Sopenharmony_ci } 229e5d0e473Sopenharmony_ci} 230e5d0e473Sopenharmony_ci} // namespace Telephony 231e5d0e473Sopenharmony_ci} // namespace OHOS 232