/* * SMS.c * * Created on: Dec 4, 2020 * Author: FICOM-IT LTD */ /* * SMS.c * * Created on: Dec 4, 2020 * Author: FICOM-IT LTD */ //gitfix #include "SmsEncoderDecoderPrivate.h" #include #include #include #include static void SmsEncoderDecoder_mfree(tSmsPdu *env, void *pointer); static void *SmsEncoderDecoder_malloc(tSmsPdu *env, size_t size); // initialize PDU constants void tSmsPdu_Init(tSmsPdu *env, tMemAllocInterface *mem) { env->mCSMMR = 0; env->mRD = false; env->mSRR = false; env->mSCA = ""; env->mVP = ""; env->mCSMIEI = BIT8MIEI; env->mem = mem; } void SmsEncoderDecoder_mfree(tSmsPdu *env, void *pointer) { Mem_Free(env->mem, pointer); } void *SmsEncoderDecoder_malloc(tSmsPdu *env, size_t size) { return Mem_Alloc(env->mem, size); } char *cSub_str(tSmsPdu *env, const char *str, int start, int size) { memset(env->temp, '\0', SUB_STR_SIZE); if (size > 0) strncpy(env->temp, str + start, size); else if (size < 0) strcpy(env->temp, str + start); return env->temp; } #pragma GCC push_options #pragma GCC optimize ("O0") tSMS_Struct SmsPdu_Decode(tSmsPdu *env, const char *data, uint16_t len) { tSMS_Struct sms; int end_index; int PDUType; sms.SCA = cSCADecoding(env, data, &end_index); PDUType = strtol(cSub_str(env, data, end_index, 2), NULL, 16); end_index += 2; sms.RP = PDUType & (1 << 7) ? true : false; sms.UDHI = PDUType & (1 << 6) ? true : false; sms.SRI = PDUType & (1 << 5) ? true : false; sms.MMS = PDUType & (1 << 2) ? false : true; sms.MTI = PDUType & 3; sms.OA = cOADecoding(env, data, end_index, &end_index); sms.PID = strtol(cSub_str(env, data, end_index, 2), NULL, 16); end_index += 2; int DCSType = strtol(cSub_str(env, data, end_index, 2), NULL, 16); end_index += 2; sms.TC = DCSType & (1 << 5); sms.DCS = (tEnumDCS) ((DCSType >> 2) & 3); if (DCSType & (1 << 4)) { sms.MC = DCSType & 3; } else { sms.MC = -1; } sms.SCTS = cSCTSDecoding(env, data, end_index); end_index += 14; if (sms.UDHI) { sms.UDH = NULL; sms.UDL = end_index; // sms.UDH = tUDHDecoding(data, end_index + 2); } else { sms.UDH = NULL; } sms.UD = cUserDataDecoding(env, data, end_index, sms.UDHI, sms.DCS, &sms.UDL, len); return sms; } #pragma GCC pop_options char *cSCADecoding(tSmsPdu *env, const char *data, int *EndIndex) { int len; char *result; char *buf; len = strtol(cSub_str(env, data, 0, 2), NULL, 16); if (len == 0) { *EndIndex = 2; return NULL; } *EndIndex = (len + 1) * 2; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * len * 2); //wmemset(result, '0', sizeof(char) * (len * 2 + 1)); buf = result; len *= 2; if (strncmp(data + 2, "91", 2) == 0) { sprintf(buf++, "+"); } for (int i = 4; i < *EndIndex; i += 2) { sprintf(buf++, "%c", data[i + 1]); sprintf(buf++, "%c", data[i]); } if (result[strlen(result) - 1] == L'F') { result[strlen(result) - 1] = L'\0'; } return result; } char *cOADecoding(tSmsPdu *env, const char *data, int index, int *EndIndex) { int len; char *result, *buf; len = strtol(cSub_str(env, data, index, 2), NULL, 16); if (len == 0) { *EndIndex = index + 2; return NULL; } *EndIndex = index + 4 + len; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (len + 2)); //wmemset(result, 0, sizeof(char) * (len + 1)); buf = result; if (strncmp(data + index + 2, "91", 2) == 0) { sprintf(buf++, "+"); } for (int i = 0; i < len; i += 2) { sprintf(buf++, "%c", data[index + i + 5]); sprintf(buf++, "%c", data[index + i + 4]); } if (len % 2 != 0) { result[strlen(result) - 1] = '\0'; (*EndIndex)++; } return result; } char *cSCTSDecoding(tSmsPdu *env, const char *data, int index) { char *result; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * 32); sprintf(result, "20%02d-%02d-%02d %02d:%02d:%02d", iBCDDecoding(env, data, index, 0), iBCDDecoding(env, data, index + 2, 0), iBCDDecoding(env, data, index + 4, 0), iBCDDecoding(env, data, index + 6, 0), iBCDDecoding(env, data, index + 8, 0), iBCDDecoding(env, data, index + 10, 0) ); return result; } int iBCDDecoding(tSmsPdu *env, const char *data, int index, bool isMSB) { int n1, n10; n1 = strtol(cSub_str(env, data, index, 1), NULL, 10); n10 = strtol(cSub_str(env, data, index + 1, 1), NULL, 10); if (isMSB) { if (n10 >= 8) return -((n10 - 8) * 10 + n1); else return n10 * 10 + n1; } else { return n10 * 10 + n1; } } tUDHS *UDHDecoding(tSmsPdu *env, const char *data, int index) { int len; tUDHS *result; len = strtol(cSub_str(env, data, index, 2), NULL, 16); index += 2; int i = 0; result = (tUDHS *) SmsEncoderDecoder_malloc(env, sizeof(tUDHS)); result->UDH = (tPDUUDH *) SmsEncoderDecoder_malloc(env, sizeof(tPDUUDH) * len); result->count = 0; memset(result->UDH, 0, sizeof(tPDUUDH) * len); while (i < len) { char IEI = strtol(cSub_str(env, data, index, 2), NULL, 16); index += 2; int IEDL = strtol(cSub_str(env, data, index, 2), NULL, 16); index += 2; char *IED = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (IEDL + 1)); for (int j = 0; j < IEDL; j++) { IED[j] = strtol(cSub_str(env, data, index, 2), NULL, 16); index += 2; } result->UDH[result->count].IEI = IEI; result->UDH[result->count].IED = IED; result->count++; i += IEDL + 2; } return result; } char *cUserDataDecoding(tSmsPdu *env, const char *data, int index, bool UDHI, tEnumDCS dcs, int *UDDL, uint16_t len) { char *result; char *buf; uint16_t idWrite = 0; int UDL = strtol(cSub_str(env, data, index, 2), NULL, 16); index += 2; int UDHL = 0; if (UDHI) { UDHL = strtol(cSub_str(env, data, index, 2), NULL, 16); UDHL++; index += UDHL << 1; } if (dcs == UCS2) { int len = (UDL - UDHL) >> 1; int utf8_len; *UDDL = len; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (len * 3)); buf = result; u_int32_t code[2]; for (int i = 0; i < len; i++) { code[0] = strtol(cSub_str(env, data, (i << 2) + index, 4), NULL, 16); code[1] = 0; utf32toutf8((wchar_t *) code, (unsigned char *) buf, len * 3, &utf8_len); buf += utf8_len; } buf[0] = '\0'; return result; } else if (dcs == BIT7) { int Septets = UDL - (UDHL * 8 + 6) / 7; *UDDL = Septets; int FillBits = (UDHL * 8 + 6) / 7 * 7 - UDHL * 8; return cBIT7Decoding(env, cBIT7Unpack(env, data, index, Septets, FillBits), Septets); } else {// 8Bit UDL -= UDHL; *UDDL = UDL; uint16_t pos = UDL; pos = pos * 2; char res[pos]; pos = len - pos; uint16_t writeBits = UDL; while (idWrite < sizeof(res)) { res[idWrite] = data[pos]; idWrite++; pos++; writeBits++; } result = res; UDL -= UDHL; return result; } return 0; } char *cBIT7Unpack(tSmsPdu *env, const char *data, int index, int Septets, int FillBits) { char *result; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (Septets + 1)); // 7-Bit int PackLen = (Septets * 7 + FillBits + 7) / 8; int n = 0; int left = 0; for (int i = 0; i < PackLen; i++) { int Order = (i + (7 - FillBits)) % 7; int Value = strtol(cSub_str(env, data, (i << 1) + index, 2), NULL, 16); if (i != 0 || FillBits == 0) { result[n++] = ((Value << Order) + left) & 0x7F; } left = Value >> (7 - Order); if (Order == 6) { if (n == Septets) break; result[n++] = left; left = 0; } } return result; } char *cBIT7Decoding(tSmsPdu *env, char *BIT7Data, unsigned int size) { char *result, *buf; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (size + 1)); buf = result; for (int i = 0; i < size; i++) { u_int16_t key = BIT7Data[i]; if (isBIT7Same(env, key)) { sprintf(buf++, "%c", key); } else if (SmsCharMapGetValue(BIT7ToUCS2, SMS_DC_EC_MAP_SIZE(BIT7ToUCS2), key) >= 0) { u_int16_t value; if (key == 0x1B) { value = SmsCharMapGetValue(BIT7EToUCS2, SMS_DC_EC_MAP_SIZE(BIT7EToUCS2), BIT7Data[i + 1]); if (i < size - 1 && value > 0) { sprintf(buf++, "%c", value); i++; } else { value = SmsCharMapGetValue(BIT7ToUCS2, SMS_DC_EC_MAP_SIZE(BIT7ToUCS2), key); sprintf(buf++, "%c", value); } } else { ; value = SmsCharMapGetValue(BIT7ToUCS2, SMS_DC_EC_MAP_SIZE(BIT7ToUCS2), key); sprintf(buf++, "%c", value); } } else { sprintf(buf++, "?"); } } return result; } int isBIT7Same(tSmsPdu *env, u_int16_t UCS2) { if ((UCS2 >= 0x61 && UCS2 <= 0x7A) || (UCS2 >= 0x41 && UCS2 <= 0x5A) || (UCS2 >= 0x25 && UCS2 <= 0x3F) || (UCS2 >= 0x20 && UCS2 <= 0x23) || UCS2 == 0x0A || UCS2 == 0x0D) { return 1; } return 0; } tPDUS *SmsPdu_Encode(tSmsPdu *env, char *DA, char *UDC, tUDHS *udhs, tEnumDCS DCS) { return tPDUDoEncoding(env, "", DA, UDC, udhs, DCS); } // //////DA- DestenationAddress //tPDUS *tPDUEncodingRAWData(tSmsEncoderDecoder *env,char *DestenationAddress, uint8_t *UserData,uint16_t LengthOfData){ // sms_init(); // return tPDUDoEncodingRAWData("", DestenationAddress, UserData, LengthOfData); //} //// //// //tPDUS *tPDUDoEncodingRAWData(tSmsEncoderDecoder *env,char *SCA,char *DestenationAddress, uint8_t *UserData,uint16_t LengthOfData){ // tUDS *uds = tUDCSplitRAWData(UserData, LengthOfData); // tPDUS *pdus; // // if (uds == NULL) // return NULL; // pdus = (tPDUS *) sms_malloc(env,sizeof(tPDUS)); // pdus->count = 0; // pdus->PDU = (char **) sms_malloc(env,sizeof(char *) * uds->total); // // if (tSmsEncoderDecoder *env,uds->total > 1){ // int CSMMR = env->mCSMMR; // if (++env->mCSMMR > 0xFFFF) // env->mCSMMR = 0; // for(int i = 0; i < uds->total; i++){ // tUDHS *CSMUDH = tUpdateUDH(env,udhs, CSMMR, uds->total, i); // pdus->PDU[i] = cSoloPDUEncoding(env,SCA, DA, uds->Data[i], CSMUDH, DCS); // pdus->count++; // } // // } // else { // pdus->PDU[0] = cSoloPDUEncoding(env,SCA, DA, uds->Data[0], udhs, DCS); // pdus->count = 1; // } // // return pdus; //} tPDUS *newPdus(tSmsPdu *env, uint16_t opacity) { tPDUS *pdus = (tPDUS *) SmsEncoderDecoder_malloc(env, sizeof(tPDUS)); pdus->count = 0; pdus->opacity = opacity; pdus->PDU = (char **) SmsEncoderDecoder_malloc(env, sizeof(char *) * opacity); return pdus; } void deletePdus(tSmsPdu *env, tPDUS *pdus) { for (unsigned int i = 0; i < pdus->opacity; ++i) { SmsEncoderDecoder_mfree(env, pdus->PDU[i]); } SmsEncoderDecoder_mfree(env, pdus); } tPDUS *tPDUDoEncoding(tSmsPdu *env, char *SCA, char *DA, char *UDC, tUDHS *udhs, tEnumDCS DCS) { tUDS *uds = tUDCSplit(env, UDC, udhs, DCS); tPDUS *pdus; if (uds == NULL) { return NULL; } pdus = newPdus(env, uds->total); if (uds->total > 1) { int CSMMR = env->mCSMMR; if (++env->mCSMMR > 0xFFFF) env->mCSMMR = 0; for (int i = 0; i < uds->total; i++) { tUDHS *CSMUDH = tUpdateUDH(env, udhs, CSMMR, uds->total, i); pdus->PDU[i] = cSoloPDUEncoding(env, SCA, DA, uds->Data[i], CSMUDH, DCS); deleteUDHS(env, CSMUDH); pdus->count++; } } else { pdus->PDU[0] = cSoloPDUEncoding(env, SCA, DA, uds->Data[0], udhs, DCS); pdus->count = 1; } deleteUDS(env, uds); return pdus; } int isGSMString(tSmsPdu *env, char *Data) { if (Data == NULL || strcmp(Data, "") == 0) return 1; if (is_acsii((unsigned char *) Data) == 0) { int len; len = utf8len((unsigned char *) Data); u_int16_t *code = (u_int16_t *) SmsEncoderDecoder_malloc(env, sizeof(u_int16_t) * len); utf8toutf16((unsigned char *) Data, code, len, &len); while (*code) { if (!(isBIT7Same(env, *code) || SmsCharMapGetValue(UCS2ToBIT7, SMS_DC_EC_MAP_SIZE(UCS2ToBIT7), *code) >= 0)) return 0; code++; } return 1; } else return 1; } char *newStringCopy(tSmsPdu *env, char *orgn, uint16_t length) { char *newStr = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (length + 1)); memcpy(newStr, orgn, length); newStr[length] = 0; return newStr; } tUDS *newUDS(tSmsPdu *env) { tUDS *uds = (tUDS *) SmsEncoderDecoder_malloc(env, sizeof(tUDS)); uds->total = 0; uds->Data = (char **) SmsEncoderDecoder_malloc(env, MAX_SMS_NR * sizeof(char *)); return uds; } void deleteUDS(tSmsPdu *env, tUDS *uds) { if (uds->Data) { for (uint8_t idx = 0; idx < uds->total; ++idx) { SmsEncoderDecoder_mfree(env, uds->Data[idx]); } } SmsEncoderDecoder_mfree(env, uds->Data); SmsEncoderDecoder_mfree(env, uds); } tUDS *tUDCSplitUCS2(tSmsPdu *env, char *UDC, tUDHS *udhs, tEnumDCS DCS) { int UDHL = iGetUDHL(env, udhs); tUDS *result; uint16_t maximal_portion_length = UDHL > UCS2UDL ? 0 : UCS2UDL - UDHL; if (!maximal_portion_length) { if (!(UDC == NULL || strcmp(UDC, "") == 0)) { return NULL; } } uint16_t full_data_length = strlen((char *) UDC); if (full_data_length < maximal_portion_length) { result = newUDS(env); result->Data[result->total] = newStringCopy(env, UDC, full_data_length); ++result->total; return result; } if (UDHL == 0) UDHL++; if (env->mCSMIEI == BIT8MIEI) { UDHL += 5; // 1byte } else { UDHL += 6; // 2byte } maximal_portion_length = UDHL > UCS2UDL ? 0 : UCS2UDL - UDHL; if (!maximal_portion_length) { return NULL; } result = newUDS(env); uint16_t portion_length; uint16_t left = full_data_length; uint16_t begin_offset = 0; for (; begin_offset < full_data_length; begin_offset += portion_length, left -= portion_length) { portion_length = left > maximal_portion_length ? maximal_portion_length : left; result->Data[result->total] = newStringCopy(env, UDC + begin_offset, portion_length); ++result->total; } return result; } tUDS *tUDCSplit(tSmsPdu *env, char *UDC, tUDHS *udhs, tEnumDCS DCS) { int UDHL = iGetUDHL(env, udhs); tUDS *result; if (DCS == BIT7) { // 7-Bit int room = BIT7UDL - (UDHL * 8 + 6) / 7; if (room < 1) { if (UDC == NULL || strcmp(UDC, "") == 0) { result = (tUDS *) SmsEncoderDecoder_malloc(env, sizeof(tUDS)); result->Data = (char **) SmsEncoderDecoder_malloc(env, sizeof(char *)); result->total = 1; result->Data[0] = UDC; return result; } else return NULL; } if (iSeptetsLength(env, UDC) <= room) { result = (tUDS *) SmsEncoderDecoder_malloc(env, sizeof(tUDS)); result->Data = (char **) SmsEncoderDecoder_malloc(env, sizeof(char *)); result->total = 1; result->Data[0] = UDC; return result; } else { if (UDHL == 0) UDHL++; if (env->mCSMIEI == BIT8MIEI) UDHL += 5; else UDHL += 6; room = BIT7UDL - (UDHL * 8 + 6) / 7; if (room < 1) return NULL; int i = 0; int len = strlen(UDC); result = (tUDS *) SmsEncoderDecoder_malloc(env, sizeof(tUDS)); result->total = 0; result->Data = (char **) SmsEncoderDecoder_malloc(env, MAX_SMS_NR * sizeof(char *)); while (i < len) { int step = iSeptetsToChars(env, UDC, i, room); if (i + step < len) { result->Data[result->total] = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (step + 1)); strcpy(result->Data[result->total++], cSub_str(env, UDC, i, step)); } else { result->Data[result->total] = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (len - i + 1)); strcpy(result->Data[result->total++], cSub_str(env, UDC, i, -1)); } i += step; } return result; } } if (DCS == BIT8) { // BIT8 int room = BIT8UDL - UDHL; if (room < 1) { if (UDC == NULL || strcmp(UDC, "") == 0) { result = (tUDS *) SmsEncoderDecoder_malloc(env, sizeof(tUDS)); result->Data = (char **) SmsEncoderDecoder_malloc(env, sizeof(char *)); result->total = 1; result->Data[0] = UDC; return result; } else return NULL; } if (UDC == NULL || utf8len((unsigned char *) UDC) <= room) { result = (tUDS *) SmsEncoderDecoder_malloc(env, sizeof(tUDS)); result->Data = (char **) SmsEncoderDecoder_malloc(env, sizeof(char *)); result->total = 1; result->Data[0] = UDC; return result; } else { if (UDHL == 0) UDHL++; if (env->mCSMIEI == BIT8MIEI) UDHL += 5; // 1byte else UDHL += 6; // 2byte room = BIT8UDL - UDHL; if (room < 1) return NULL; int len = utf8len((unsigned char *) UDC); result = (tUDS *) SmsEncoderDecoder_malloc(env, sizeof(tUDS)); result->total = 0; result->Data = (char **) SmsEncoderDecoder_malloc(env, MAX_SMS_NR * sizeof(char *)); int index = 0; for (int i = 0; i < len; i += room) { int real_size; if (i + room < len) { real_size = utf8_get_size((unsigned char *) (UDC + index), room); result->Data[result->total] = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (real_size + 1)); strcpy(result->Data[result->total++], cSub_str(env, UDC, index, real_size)); } else { real_size = utf8_get_size((unsigned char *) (UDC + index), len - i); result->Data[result->total] = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (real_size + 1)); strcpy(result->Data[result->total++], cSub_str(env, UDC, index, -1)); } index += real_size; } return result; } } if (DCS == BIT8_HEX) { // BIT8 int room = BIT8UDL - UDHL; uint8_t hexRoom = room * 2; if (room < 1) { if (UDC == NULL || strcmp(UDC, "") == 0) { result = (tUDS *) SmsEncoderDecoder_malloc(env, sizeof(tUDS)); result->Data = (char **) SmsEncoderDecoder_malloc(env, sizeof(char *)); result->total = 1; result->Data[0] = UDC; return result; } else return NULL; } uint8_t dataLen = strlen(UDC) / 2; if (UDC == NULL || dataLen <= room) { result = (tUDS *) SmsEncoderDecoder_malloc(env, sizeof(tUDS)); result->Data = (char **) SmsEncoderDecoder_malloc(env, sizeof(char *)); result->total = 1; result->Data[0] = UDC; return result; } else { if (UDHL == 0) UDHL++; if (env->mCSMIEI == BIT8MIEI) UDHL += 5; // 1byte else UDHL += 6; // 2byte room = BIT8UDL - UDHL; hexRoom = room * 2; if (room < 1) return NULL; uint8_t hexDataLen = strlen(UDC) / 2; //init empty result = (tUDS *) SmsEncoderDecoder_malloc(env, sizeof(tUDS)); result->total = 0; result->Data = (char **) SmsEncoderDecoder_malloc(env, MAX_SMS_NR * sizeof(char *)); //add pdus one by one uint8_t lessThenFullRoom = 0; int real_size; for (int index = 0; index < hexDataLen; index += hexRoom) { lessThenFullRoom = index + hexRoom < hexDataLen; real_size = lessThenFullRoom ? hexDataLen - index : hexRoom; result->Data[result->total] = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (real_size + 1)); strcpy(result->Data[result->total++], cSub_str(env, UDC, index, real_size)); } return result; } } if (DCS == UCS2) { // UCS2 return tUDCSplitUCS2(env, UDC, udhs, DCS); } return NULL; } // //tUDS *tUDCSplitRAWData(tSmsEncoderDecoder *env,char *UserData, unsigned int UserDataLength){ // tUserRawDataPackages *result; // // // if (tSmsEncoderDecoder *env,BIT8UDL < 1){ // // if (tSmsEncoderDecoder *env,UserData == NULL || UserDataLength==NULL){ // result = (tUserRawDataPackages *) sms_malloc(env,sizeof(tUserRawDataPackages)); // result->Packages = (tUserRawDataSinglePackage *)sms_malloc(env,sizeof(tUserRawDataSinglePackage *)); // result->total = 1; // result->Packages[0].Data = UserData; // result->Packages[0].Length = UserDataLength; // return result; // } // else // return NULL; // } // if (tSmsEncoderDecoder *env,UserData == NULL || UserDataLength <= BIT8UDL){ // // result = (tUserRawDataPackages *) sms_malloc(env,sizeof(tUserRawDataPackages)); // result->Packages = (tUserRawDataSinglePackage **)sms_malloc(env,sizeof(tUserRawDataSinglePackage *)); // result->total = 1; // result->Packages[0].Data = UserData; // result->Packages[0].Length = UserDataLength; // // return result; // } // else // { // uint tail = UserDataLength%BIT8UDL; // // result = (tUserRawDataPackages *) sms_malloc(env,sizeof(tUserRawDataPackages)); // result->total = (UserDataLength / BIT8UDL) + tail?1:0; // result->Packages = (tUserRawDataSinglePackage **)sms_malloc(env,sizeof(tUserRawDataSinglePackage *)*result->total); // // // uint left = UserDataLength; // for(int i = 0; i < result->total; ++i){ // // result->Packages[i].Length = leftPackages[i].Data = UserData; // UserData = ((unsigned char*)UserData+result->Packages[i].Length); // // } // // return result; // } // // // // // return NULL; //} int iGetUDHL(tSmsPdu *env, tUDHS *udhs) { if (udhs == NULL) return 0; int UDHL = 1; for (int i = 0; i < udhs->count; i++) { UDHL += strlen(udhs->UDH[i].IED) + 2; } return UDHL; } int iSeptetsLength(tSmsPdu *env, char *source) { if (source == NULL || strcmp(source, "") == 0) { return 0; } int len = strlen(source); while (*source) { u_int16_t code = (u_int16_t) *source; if (SmsCharMapGetValue(UCS2ToBIT7, SMS_DC_EC_MAP_SIZE(UCS2ToBIT7), code) > 0xFF) { len++; } source++; } return len; } int iSeptetsToChars(tSmsPdu *env, char *source, int index, int septets) { if (source == NULL || strcmp(source, "") == 0) return 0; int count = 0; int i; for (i = index; i < strlen(source); i++) { u_int16_t code = (u_int16_t) source[i]; if (SmsCharMapGetValue(UCS2ToBIT7, SMS_DC_EC_MAP_SIZE(UCS2ToBIT7), code) > 0xFF) count++; if (++count >= septets) { if (count == septets) i++; break; } } return i - index; } tUDHS *newUDHS(tSmsPdu *env, int count) { tUDHS *udhs = (tUDHS *) SmsEncoderDecoder_malloc(env, sizeof(tUDHS)); udhs->UDH = (tPDUUDH *) SmsEncoderDecoder_malloc(env, sizeof(tPDUUDH) * (count)); udhs->count = count; return udhs; } void deleteUDHS(tSmsPdu *env, tUDHS *udhs) { for (uint16_t idx = 0; idx < udhs->count; ++idx) { SmsEncoderDecoder_mfree(env, udhs->UDH->IED); } SmsEncoderDecoder_mfree(env, udhs->UDH); SmsEncoderDecoder_mfree(env, udhs); } void copytPDUUDH(tSmsPdu *env, tPDUUDH *target, tPDUUDH *source) { memcpy(target, source, sizeof(tPDUUDH)); if (source->IED) { target->IED = SmsEncoderDecoder_malloc(env, sizeof(char) * target->count); memcpy(target->IED, source->IED, sizeof(target->count)); } } void copytPDUUDHS(tSmsPdu *env, tPDUUDH *target, tPDUUDH *source, uint16_t count) { for (uint16_t i = 0; i < count; ++i) { copytPDUUDH(env, target + count, source + count); } } tUDHS *tUpdateUDH(tSmsPdu *env, tUDHS *udhs, int CSMMR, int total, int index) { tUDHS *result; if (udhs == NULL || udhs->count == 0) { result = newUDHS(env, 1); } else { result = newUDHS(env, udhs->count + 1); //UDH copytPDUUDHS(env, result->UDH + 1, udhs->UDH, udhs->count); } if (env->mCSMIEI == BIT8MIEI) { result->UDH[0].IED = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * 3); result->UDH[0].count = 3; result->UDH[0].IED[0] = CSMMR & 0xFF; result->UDH[0].IED[1] = total; result->UDH[0].IED[2] = index + 1; result->UDH[0].IEI = 0; } else { result->UDH[0].IED = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * 4); result->UDH[0].count = 4; result->UDH[0].IED[0] = (CSMMR >> 8) & 0xFF; result->UDH[0].IED[1] = CSMMR & 0xFF; result->UDH[0].IED[2] = total; result->UDH[0].IED[3] = index + 1; result->UDH[0].IEI = 8; } return result; } char *cSoloPDUEncoding(tSmsPdu *env, char *SCA, char *DA, char *UC, tUDHS *udhs, tEnumDCS DCS) { char *result; char *buf, *ret; int index; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * 400); buf = result; ret = cSCAEncoding(env, SCA); index = strlen(ret); sprintf(buf, "%s", ret); buf += index; SmsEncoderDecoder_mfree(env, ret); bool hasUDH = !(udhs == NULL || udhs->count == 0); ret = cPDUTypeEncoding(env, hasUDH); sprintf(buf, "%s", ret); buf += strlen(ret); SmsEncoderDecoder_mfree(env, ret); ret = cMREncoding(env); sprintf(buf, "%s", ret); buf += strlen(ret); ret = cDAEncoding(env, DA); sprintf(buf, "%s", ret); buf += strlen(ret); SmsEncoderDecoder_mfree(env, ret); ret = cPIDEncoding(env); sprintf(buf, "%s", ret); buf += strlen(ret); ret = cDCSEncoding(env, UC, DCS); sprintf(buf, "%s", ret); buf += strlen(ret); sprintf(buf, "%s", env->mVP); buf += strlen(env->mVP); ret = cUDEncoding(env, UC, udhs, DCS); sprintf(buf, "%s", ret); SmsEncoderDecoder_mfree(env, ret); return result; } char *cSoloPDUEncodingRAWData(tSmsPdu *env, char *SCA, char *DA, char *UserData, uint UserDataLength, tUDHS *udhs) { char *result; char *buf, *ret; int index; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * 400); buf = result; ret = cSCAEncoding(env, SCA); index = strlen(ret); sprintf(buf, "%s", ret); buf += index; if (udhs == NULL || udhs->count == 0) { ret = cPDUTypeEncoding(env, false); sprintf(buf, "%s", ret); buf += strlen(ret); } else { ret = cPDUTypeEncoding(env, true); sprintf(buf, "%s", ret); buf += strlen(ret); } ret = cMREncoding(env); sprintf(buf, "%s", ret); buf += strlen(ret); ret = cDAEncoding(env, DA); sprintf(buf, "%s", ret); buf += strlen(ret); ret = cPIDEncoding(env); sprintf(buf, "%s", ret); // buf += strlen(ret); // ret = cDCSEncoding(env,UC, DCS); // sprintf(buf, "%s", ret); // // // buf += strlen(ret); // sprintf(buf, "%s", env->mVP); // // // buf += strlen(env->mVP); // ret = cUDEncoding(env,UC, udhs, DCS); // sprintf(buf, "%s", ret); return result; } char *cSCAEncoding(tSmsPdu *env, char *SCA) { char *result; if (SCA == NULL || strcmp(SCA, "") == 0) { // SMS center on SIM or set AT+CSCA command return newStringCopy(env, "00", 2); } char *buf; int len; len = strlen(SCA); result = (char *) SmsEncoderDecoder_malloc(env, (len + 5) * sizeof(char)); buf = result; int index = 0; if (SCA[0] == '+') { sprintf(buf, "%02X", len / 2 + 1); buf += 2; sprintf(buf, "91"); buf += 2; index = 1; } else { sprintf(buf, "%02X", len / 2 + 1); buf += 2; sprintf(buf, "81"); buf += 2; } // SCA for (; index < len; index += 2) { if (index == len - 1) { // “F” sprintf(buf++, "F"); sprintf(buf++, "%c", SCA[index]); } else { sprintf(buf++, "%c", SCA[index + 1]); sprintf(buf++, "%c", SCA[index]); } } return result; } char *cPDUTypeEncoding(tSmsPdu *env, bool UDH) { // Message Type Indicator // 01 SMS-SUBMIT(MS -> SMSC) int PDUType = 0x01; char *result; result = (char *) SmsEncoderDecoder_malloc(env, 3 * sizeof(char)); // User Data Header Indicator if (UDH) { PDUType |= 0x40; } // Validity Period Format if (strlen(env->mVP) == 2) { // VP PDUType |= 0x10; } else if (strlen(env->mVP) == 14) { // VP semi-octet PDUType |= 0x18; } // Status Report Request if (env->mSRR) { // 请求状态报告 PDUType |= 0x20; } // Reject Duplicate if (env->mRD) { PDUType |= 0x04; } sprintf(result, "%02X", PDUType); return result; } char *cMREncoding(tSmsPdu *env) { return "00"; } char *cDAEncoding(tSmsPdu *env, char *DA) { if (DA == NULL || strcmp(DA, "") == 0) { return newStringCopy(env, "0080", 4); } char *result, *buf; int len = strlen(DA); int index = 0; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (len + 5)); buf = result; if (DA[0] == '+') { sprintf(buf, "%02X", len - 1); buf += 2; sprintf(buf, "91"); buf += 2; index = 1; } else { sprintf(buf, "%02X", len); buf += 2; sprintf(buf, "81"); buf += 2; index = 0; } for (; index < len; index += 2) { if (index == len - 1) { sprintf(buf++, "F"); sprintf(buf++, "%c", DA[index]); } else { sprintf(buf++, "%c", DA[index + 1]); sprintf(buf++, "%c", DA[index]); } } return result; } char *cPIDEncoding(tSmsPdu *env) { return "00"; } char *cDCSEncoding(tSmsPdu *env, char *UD, tEnumDCS DCS) { if (DCS == BIT7) { // 7-Bit return "00"; } if (DCS == BIT8) { //8-bit return "04"; } if (DCS == BIT8_HEX) { //8-bit return "04"; } if (DCS == UCS2) { // UCS2 return "08"; } } char *cUDEncoding(tSmsPdu *env, char *UD, tUDHS *udhs, tEnumDCS DCS) { int UDHL; char *result; char *header = cUDHEncoding(env, udhs, &UDHL); int UDCL; char *body; body = cUDCEncoding(env, UD, &UDCL, UDHL, DCS); int UDL; if (DCS == BIT7) { // 7-Bit UDL = (UDHL * 8 + 6) / 7 + UDCL; } else { // UCS2 8-Bit UDL = UDHL + UDCL; } int len = strlen(header) + strlen(body) + 2; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (len + 1)); sprintf(result, "%02X%s%s", UDL, header, body); SmsEncoderDecoder_mfree(env, header); SmsEncoderDecoder_mfree(env, body); return result; } char *cUDHEncoding(tSmsPdu *env, tUDHS *udhs, int *UDHL) { *UDHL = 0; if (udhs == NULL || udhs->count == 0) return newStringCopy(env, "", 0); for (int i = 0; i < udhs->count; i++) { *UDHL += udhs->UDH[i].count + 2; } char *result; char *buf; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * ((*UDHL + 1) * 2 + 1)); buf = result; sprintf(buf, "%02X", *UDHL); buf += 2; for (int i = 0; i < udhs->count; i++) { sprintf(buf, "%02X", udhs->UDH[i].IEI); buf += 2; sprintf(buf, "%02X", udhs->UDH[i].count); buf += 2; for (int j = 0; j < udhs->UDH[i].count; j++) { sprintf(buf, "%02X", udhs->UDH[i].IED[j]); buf += 2; } } (*UDHL)++; return result; } char *cUDCEncoding(tSmsPdu *env, char *UDC, int *UDCL, int UDHL, tEnumDCS DCS) { if (UDC == NULL || strcmp(UDC, "") == 0) { *UDCL = 0; return ""; } if (DCS == BIT7) { // 7-Bit return cBIT7Pack(env, tBIT7Encoding(env, UDC, UDCL), UDHL); } if (DCS == BIT8) { // 8-bit int len = utf8len((unsigned char *) UDC); //int len2; // unsigned short *code; //code = (unsigned short *) sms_malloc(env,sizeof(unsigned short) * len); //utf8toutf16((unsigned char *) UDC, code, len, &len2); *UDCL = len; char *result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (*UDCL * 2 + 1)); char *buf = result; for (int i = 0; i < len; i++) { sprintf(buf, "%02X", UDC[i]); //code[i]); buf += 2; } // sms_mfree(env,code); return result; } if (DCS == BIT8_HEX) { // 8-bit hex data int len = strlen(UDC); *UDCL = len / 2; char *result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (len + 1)); memcpy(result, UDC, len); return result; } if (DCS == UCS2) { // UCS2 int len = utf8len((unsigned char *) UDC); int len2; unsigned short *code; code = (unsigned short *) SmsEncoderDecoder_malloc(env, sizeof(unsigned short) * len); utf8toutf16((unsigned char *) UDC, code, len, &len2); *UDCL = len * 2; char *result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (*UDCL * 2 + 1)); char *buf = result; for (int i = 0; i < len; i++) { sprintf(buf, "%04X", code[i]); buf += 4; } SmsEncoderDecoder_mfree(env, code); return result; } return ""; } tByteArray *tBIT7Encoding(tSmsPdu *env, char *UDC, int *Septets) { tByteArray *result; int len = strlen(UDC); result = (tByteArray *) SmsEncoderDecoder_malloc(env, sizeof(tByteArray)); result->len = 0; result->array = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (len * 2 + 1)); *Septets = 0; for (int i = 0; i < len; i++) { u_int16_t code = (u_int16_t) UDC[i]; if (isBIT7Same(env, code)) { result->array[(*Septets)++] = code; } else { u_int16_t value = SmsCharMapGetValue(UCS2ToBIT7, SMS_DC_EC_MAP_SIZE(UCS2ToBIT7), code); if (value >= 0) { if (value > 0xFF) { result->array[(*Septets)++] = value >> 8; result->array[(*Septets)++] = value & 0xFF; } else { result->array[(*Septets)++] = value; } } else { result->array[(*Septets)++] = (u_int16_t) '?'; } } } result->len = *Septets; return result; } char *cBIT7Pack(tSmsPdu *env, tByteArray *Bit7Array, int UDHL) { // 7Bit int fillBits = (UDHL * 8 + 6) / 7 * 7 - (UDHL * 8); int len = Bit7Array->len; int packLen = (len * 7 + fillBits + 7) / 8; char *result; char *buf; result = (char *) SmsEncoderDecoder_malloc(env, sizeof(char) * (packLen * 2 + 1)); buf = result; int left = 0; for (int i = 0; i < len; i++) { int32_t Value = Bit7Array->array[i]; int32_t index = (i + 8 - fillBits) % 8; if (index == 0) { left = Value; } else { int32_t n = ((Value << (8 - index)) | left) & 0xFF; sprintf(buf, "%02X", (unsigned int) n); buf += 2; left = Value >> index; } } if ((len * 7 + fillBits) % 8 != 0) { sprintf(buf, "%02X", left); buf += 2; } buf[0] = '\0'; return result; }