/* (c) 2002-2004 by Marcin Wiacek */ #include #include #include #include "../../gsmcomon.h" #include "../../misc/coding/coding.h" #include "../gsmcal.h" #include "../gsmpbk.h" #include "../gsmlogo.h" #include "../gsmring.h" #include "../gsmdata.h" #include "../gsmnet.h" #include "gsmsms.h" #include "gsmmulti.h" #include "gsmems.h" /* ----------------- Splitting SMS into parts ------------------------------ */ unsigned char GSM_MakeSMSIDFromTime(void) { GSM_DateTime Date; unsigned char retval; GSM_GetCurrentDateTime (&Date); retval = Date.Second; switch (Date.Minute/10) { case 2: case 7: retval = retval + 60; break; case 4: case 8: retval = retval + 120; break; case 9: case 5: case 0: retval = retval + 180; break; } retval += Date.Minute/10; return retval; } void GSM_Find_Free_Used_SMS2(GSM_Coding_Type Coding,GSM_SMSMessage SMS, int *UsedText, int *FreeText, int *FreeBytes) { int UsedBytes; switch (Coding) { case SMS_Coding_Default: FindDefaultAlphabetLen(SMS.Text,&UsedBytes,UsedText,500); UsedBytes = *UsedText * 7 / 8; if (UsedBytes * 8 / 7 != *UsedText) UsedBytes++; *FreeBytes = GSM_MAX_8BIT_SMS_LENGTH - SMS.UDH.Length - UsedBytes; *FreeText = (GSM_MAX_8BIT_SMS_LENGTH - SMS.UDH.Length) * 8 / 7 - *UsedText; break; case SMS_Coding_Unicode: *UsedText = UnicodeLength(SMS.Text); UsedBytes = *UsedText * 2; *FreeBytes = GSM_MAX_8BIT_SMS_LENGTH - SMS.UDH.Length - UsedBytes; *FreeText = *FreeBytes / 2; break; case SMS_Coding_8bit: *UsedText = UsedBytes = SMS.Length; *FreeBytes = GSM_MAX_8BIT_SMS_LENGTH - SMS.UDH.Length - UsedBytes; *FreeText = *FreeBytes; break; } dbgprintf("UDH len %i, UsedBytes %i, FreeText %i, UsedText %i, FreeBytes %i\n",SMS.UDH.Length,UsedBytes,*FreeText,*UsedText,*FreeBytes); } GSM_Error GSM_AddSMS_Text_UDH(GSM_MultiSMSMessage *SMS, GSM_Coding_Type Coding, char *Buffer, int BufferLen, bool UDH, int *UsedText, int *CopiedText, int *CopiedSMSText) { int FreeText,FreeBytes,Copy,i,j; dbgprintf("Checking used\n"); GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes); if (UDH) { dbgprintf("Adding UDH\n"); if (FreeBytes - BufferLen <= 0) { dbgprintf("Going to the new SMS\n"); SMS->Number++; GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes); } if (SMS->SMS[SMS->Number].UDH.Length == 0) { SMS->SMS[SMS->Number].UDH.Length = 1; SMS->SMS[SMS->Number].UDH.Text[0] = 0x00; } memcpy(SMS->SMS[SMS->Number].UDH.Text+SMS->SMS[SMS->Number].UDH.Length,Buffer,BufferLen); SMS->SMS[SMS->Number].UDH.Length += BufferLen; SMS->SMS[SMS->Number].UDH.Text[0] += BufferLen; SMS->SMS[SMS->Number].UDH.Type = UDH_UserUDH; dbgprintf("UDH added %i\n",BufferLen); } else { dbgprintf("Adding text\n"); if (FreeText == 0) { dbgprintf("Going to the new SMS\n"); SMS->Number++; GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes); } Copy = FreeText; dbgprintf("copy %i\n",Copy); if (BufferLen < Copy) Copy = BufferLen; dbgprintf("copy %i\n",Copy); switch (Coding) { case SMS_Coding_Default: FindDefaultAlphabetLen(Buffer,&i,&j,FreeText); dbgprintf("def length %i %i\n",i,j); SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+i*2] = 0; SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+i*2+1] = 0; memcpy(SMS->SMS[SMS->Number].Text+UnicodeLength(SMS->SMS[SMS->Number].Text)*2,Buffer,i*2); *CopiedText = i; *CopiedSMSText = j; SMS->SMS[SMS->Number].Length += i; break; case SMS_Coding_Unicode: SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+Copy*2] = 0; SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+Copy*2+1] = 0; memcpy(SMS->SMS[SMS->Number].Text+UnicodeLength(SMS->SMS[SMS->Number].Text)*2,Buffer,Copy*2); *CopiedText = *CopiedSMSText = Copy; SMS->SMS[SMS->Number].Length += Copy; break; case SMS_Coding_8bit: memcpy(SMS->SMS[SMS->Number].Text+SMS->SMS[SMS->Number].Length,Buffer,Copy); SMS->SMS[SMS->Number].Length += Copy; *CopiedText = *CopiedSMSText = Copy; break; } dbgprintf("Text added\n"); } dbgprintf("Checking on the end\n"); GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes); return ERR_NONE; } void GSM_MakeMultiPartSMS(GSM_MultiSMSMessage *SMS, unsigned char *MessageBuffer, int MessageLength, GSM_UDH UDHType, GSM_Coding_Type Coding, int Class, unsigned char ReplaceMessage) { int j,Len,UsedText,CopiedText,CopiedSMSText; unsigned char UDHID; GSM_DateTime Date; Len = 0; while(1) { GSM_SetDefaultSMSData(&SMS->SMS[SMS->Number]); SMS->SMS[SMS->Number].Class = Class; SMS->SMS[SMS->Number].Coding = Coding; SMS->SMS[SMS->Number].UDH.Type = UDHType; GSM_EncodeUDHHeader(&SMS->SMS[SMS->Number].UDH); if (Coding == SMS_Coding_8bit) { GSM_AddSMS_Text_UDH(SMS,Coding,MessageBuffer+Len,MessageLength - Len,false,&UsedText,&CopiedText,&CopiedSMSText); } else { GSM_AddSMS_Text_UDH(SMS,Coding,MessageBuffer+Len*2,MessageLength - Len,false,&UsedText,&CopiedText,&CopiedSMSText); } Len += CopiedText; dbgprintf("%i %i\n",Len,MessageLength); if (Len == MessageLength) break; if (SMS->Number == MAX_MULTI_SMS) break; SMS->Number++; } SMS->Number++; UDHID = GSM_MakeSMSIDFromTime(); GSM_GetCurrentDateTime (&Date); for (j=0;jNumber;j++) { SMS->SMS[j].UDH.Type = UDHType; SMS->SMS[j].UDH.ID8bit = UDHID; SMS->SMS[j].UDH.ID16bit = UDHID + 256 * Date.Hour; SMS->SMS[j].UDH.PartNumber = j+1; SMS->SMS[j].UDH.AllParts = SMS->Number; GSM_EncodeUDHHeader(&SMS->SMS[j].UDH); } if (SMS->Number == 1) SMS->SMS[0].ReplaceMessage = ReplaceMessage; } /* Calculates number of SMS and number of left chars in SMS */ void GSM_SMSCounter(int MessageLength, unsigned char *MessageBuffer, GSM_UDH UDHType, GSM_Coding_Type Coding, int *SMSNum, int *CharsLeft) { int UsedText,FreeBytes; GSM_MultiSMSMessage MultiSMS; MultiSMS.Number = 0; GSM_MakeMultiPartSMS(&MultiSMS,MessageBuffer,MessageLength,UDHType,Coding,-1,false); GSM_Find_Free_Used_SMS2(Coding,MultiSMS.SMS[MultiSMS.Number-1], &UsedText, CharsLeft, &FreeBytes); *SMSNum = MultiSMS.Number; } /* Nokia Smart Messaging 3.0 */ static void GSM_EncodeSMS30MultiPartSMS(GSM_MultiPartSMSInfo *Info, char *Buffer, int *Length) { int len; /*SM version. Here 3.0*/ Buffer[(*Length)++] = 0x30; if (Info->Entries[0].ID == SMS_NokiaProfileLong) { if (Info->Entries[0].Buffer != NULL) { if (Info->Entries[0].Buffer[0]!=0x00 || Info->Entries[0].Buffer[1]!=0x00) { Buffer[(*Length)++] = SM30_PROFILENAME; Buffer[(*Length)++] = 0x00; Buffer[(*Length)++] = 2*UnicodeLength(Info->Entries[0].Buffer); CopyUnicodeString(Buffer+(*Length),Info->Entries[0].Buffer); *Length = *Length + 2*UnicodeLength(Info->Entries[0].Buffer); } } if (Info->Entries[0].Ringtone != NULL) { Buffer[(*Length)++] = SM30_RINGTONE; /* Length for this part later will be changed */ Buffer[(*Length)++] = 0x01; Buffer[(*Length)++] = 0x00; /* Smart Messaging 3.0 says: 16*9=144 bytes, * but on 3310 4.02 it was possible to save about 196 chars * (without cutting) */ len = 196; Info->Entries[0].RingtoneNotes=GSM_EncodeNokiaRTTLRingtone(*Info->Entries[0].Ringtone,Buffer+(*Length),&len); Buffer[(*Length)-2] = len / 256; Buffer[(*Length)-1] = len % 256; *Length = *Length + len; } } if (Info->Entries[0].Bitmap != NULL) { if (Info->Entries[0].ID == SMS_NokiaPictureImageLong) { Buffer[(*Length)++] = SM30_OTA; } else { Buffer[(*Length)++] = SM30_SCREENSAVER; } Buffer[(*Length)++] = 0x01; Buffer[(*Length)++] = 0x00; NOKIA_CopyBitmap(GSM_NokiaPictureImage, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, Length); if (Info->Entries[0].Bitmap->Bitmap[0].Text[0]!=0 || Info->Entries[0].Bitmap->Bitmap[0].Text[1]!=0) { if (Info->UnicodeCoding) { Buffer[(*Length)++] = SM30_UNICODETEXT; /* Length for text part */ Buffer[(*Length)++] = 0x00; Buffer[(*Length)++] = UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text)*2; memcpy(Buffer+(*Length),Info->Entries[0].Bitmap->Bitmap[0].Text,UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text)*2); *Length = *Length + UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text)*2; } else { /*ID for ISO-8859-1 text*/ Buffer[(*Length)++] = SM30_ISOTEXT; Buffer[(*Length)++] = 0x00; Buffer[(*Length)++] = UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text); memcpy(Buffer+(*Length),DecodeUnicodeString(Info->Entries[0].Bitmap->Bitmap[0].Text),UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text)); *Length = *Length +UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text); } } } } /* Alcatel docs from www.alcatel.com/wap/ahead */ GSM_Error GSM_EncodeAlcatelMultiPartSMS(GSM_MultiSMSMessage *SMS, unsigned char *Data, int Len, unsigned char *Name, int Type) { unsigned char buff[100],UDHID; int p,i; GSM_UDHHeader MyUDH; for (i=0;iSMS[i]); SMS->SMS[i].UDH.Type = UDH_UserUDH; SMS->SMS[i].UDH.Text[1] = 0x80; /* Alcatel */ p = UnicodeLength(Name); EncodeDefault(buff, Name, &p, true, NULL); SMS->SMS[i].UDH.Text[2] = GSM_PackSevenBitsToEight(0, buff, SMS->SMS[i].UDH.Text+3, p) + 4; SMS->SMS[i].UDH.Text[3] = GSM_PackSevenBitsToEight(0, buff, SMS->SMS[i].UDH.Text+3, p); SMS->SMS[i].UDH.Text[4] = Type; SMS->SMS[i].UDH.Text[5] = Len / 256; SMS->SMS[i].UDH.Text[6] = Len % 256; SMS->SMS[i].UDH.Text[0] = 6 + SMS->SMS[i].UDH.Text[3]; SMS->SMS[i].UDH.Length = SMS->SMS[i].UDH.Text[0] + 1; if (Len > 140 - SMS->SMS[i].UDH.Length) { MyUDH.Type = UDH_ConcatenatedMessages; GSM_EncodeUDHHeader(&MyUDH); memcpy(SMS->SMS[i].UDH.Text+SMS->SMS[i].UDH.Length,MyUDH.Text+1,MyUDH.Length-1); SMS->SMS[i].UDH.Text[0] += MyUDH.Length-1; SMS->SMS[i].UDH.Length += MyUDH.Length-1; } SMS->SMS[i].Coding = SMS_Coding_8bit; SMS->SMS[i].Class = 1; } p = 0; while (p != Len) { i = 140-SMS->SMS[SMS->Number].UDH.Length; if (Len - p < i) i = Len - p; memcpy(SMS->SMS[SMS->Number].Text,Data+p,i); p += i; SMS->SMS[SMS->Number].Length = i; SMS->Number++; } /* Linked sms UDH */ if (SMS->Number != 1) { UDHID = GSM_MakeSMSIDFromTime(); for (i=0;iNumber;i++) { SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-3] = UDHID; SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-2] = SMS->Number; SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-1] = i+1; } } return ERR_NONE; } /* Alcatel docs from www.alcatel.com/wap/ahead and other */ GSM_Error GSM_EncodeMultiPartSMS(GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS) { unsigned char Buffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS]; unsigned char Buffer2[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS]; int Length = 0,smslen,i, Class = -1, j,p; GSM_Error error; GSM_Coding_Type Coding = SMS_Coding_8bit; GSM_UDH UDH = UDH_NoUDH; GSM_UDHHeader UDHHeader; bool EMS = false; int textnum = 0; SMS->Number = 0; if (Info->Entries[0].ID == SMS_AlcatelSMSTemplateName) { Buffer[Length++] = 0x00; //number of elements for (i=1;iEntriesNum;i++) { switch (Info->Entries[i].ID) { case SMS_EMSSound10: case SMS_EMSSound12: case SMS_EMSSonyEricssonSound: case SMS_EMSSound10Long: case SMS_EMSSound12Long: case SMS_EMSSonyEricssonSoundLong: case SMS_EMSVariableBitmap: case SMS_EMSAnimation: case SMS_EMSVariableBitmapLong: break; case SMS_EMSPredefinedSound: Buffer[0]++; Buffer[Length++] = 0x01; //type of data Buffer[Length++] = 1 % 256; //len Buffer[Length++] = 1 / 256; //len Buffer[Length++] = Info->Entries[i].Number; break; case SMS_EMSPredefinedAnimation: Buffer[0]++; Buffer[Length++] = 0x02; //type of data Buffer[Length++] = 1 % 256; //len Buffer[Length++] = 1 / 256; //len Buffer[Length++] = Info->Entries[i].Number; break; case SMS_ConcatenatedTextLong: Buffer[0]++; p = UnicodeLength(Info->Entries[i].Buffer); EncodeDefault(Buffer2, Info->Entries[i].Buffer, &p, true, NULL); Buffer[Length++] = 0x00; //type of data Length = Length + 2; smslen = GSM_PackSevenBitsToEight(0, Buffer2, Buffer+Length, p); Buffer[Length-2] = smslen % 256; //len Buffer[Length-1] = smslen / 256; //len Length = Length + smslen; break; default: return ERR_UNKNOWN; } } Buffer[0] = Buffer[0] * 2; return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Buffer,ALCATELTDD_SMSTEMPLATE); } for (i=0;iEntriesNum;i++) { switch (Info->Entries[i].ID) { case SMS_EMSPredefinedAnimation: case SMS_EMSPredefinedSound: case SMS_EMSSound10: case SMS_EMSSound12: case SMS_EMSSonyEricssonSound: case SMS_EMSSound10Long: case SMS_EMSSound12Long: case SMS_EMSSonyEricssonSoundLong: case SMS_EMSFixedBitmap: case SMS_EMSVariableBitmap: case SMS_EMSAnimation: case SMS_EMSVariableBitmapLong: EMS = true; break; case SMS_ConcatenatedTextLong: case SMS_ConcatenatedTextLong16bit: /* This covers situation, when somebody will call function * with two or more SMS_Concatenated.... entries only. * It will be still only linked sms, but functions below * will pack only first entry according to own limits. * We redirect to EMS functions, because they are more generic * here and will handle it correctly and produce linked sms * from all entries */ textnum ++; if (textnum > 1) EMS = true; if (Info->Entries[i].Left || Info->Entries[i].Right || Info->Entries[i].Center || Info->Entries[i].Large || Info->Entries[i].Small || Info->Entries[i].Bold || Info->Entries[i].Italic || Info->Entries[i].Underlined || Info->Entries[i].Strikethrough) { EMS = true; } default: break; } if (EMS) break; } if (EMS) { error=GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_NoUDH); if (error != ERR_NONE) return error; if (SMS->Number != 1) { SMS->Number = 0; for (i=0;iEntriesNum;i++) { if (Info->Entries[i].ID == SMS_ConcatenatedTextLong16bit) { return GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_ConcatenatedMessages); } } return GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_ConcatenatedMessages16bit); } return error; } if (Info->EntriesNum != 1) return ERR_UNKNOWN; switch (Info->Entries[0].ID) { case SMS_AlcatelMonoBitmapLong: Buffer[0] = Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth; Buffer[1] = Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight; PHONE_EncodeBitmap(GSM_AlcatelBMMIPicture, Buffer+2, &Info->Entries[0].Bitmap->Bitmap[0]); Length = PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight)+2; return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Bitmap->Bitmap[0].Text,ALCATELTDD_PICTURE); case SMS_AlcatelMonoAnimationLong: /* Number of sequence words */ Buffer[0] = (Info->Entries[0].Bitmap->Number+1) % 256; Buffer[1] = (Info->Entries[0].Bitmap->Number+1) / 256; /* Picture display time 1 second (1 = 100ms) */ Buffer[2] = 10 % 256; Buffer[3] = 10 / 256 + 0xF0; Length = 4; j = 0; /* Offsets to bitmaps */ for (i=0;iEntries[0].Bitmap->Number;i++) { Buffer[Length++] = (4+j+Info->Entries[0].Bitmap->Number*2) % 256; Buffer[Length++] = (4+j+Info->Entries[0].Bitmap->Number*2) / 256; j += PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight)+2; } /* Bitmaps */ for (i=0;iEntries[0].Bitmap->Number;i++) { Buffer[Length++] = Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth; Buffer[Length++] = Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight; PHONE_EncodeBitmap(GSM_AlcatelBMMIPicture, Buffer+Length, &Info->Entries[0].Bitmap->Bitmap[i]); Length += PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight); } return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Bitmap->Bitmap[0].Text,ALCATELTDD_ANIMATION); case SMS_MMSIndicatorLong: Class = 1; UDH = UDH_MMSIndicatorLong; GSM_EncodeMMSIndicatorSMSText(Buffer,&Length,*Info->Entries[0].MMSIndicator); break; case SMS_NokiaRingtoneLong: case SMS_NokiaRingtone: UDH = UDH_NokiaRingtone; Class = 1; /* 7 = length of UDH_NokiaRingtone UDH header */ Length = GSM_MAX_8BIT_SMS_LENGTH-7; Info->Entries[0].RingtoneNotes = GSM_EncodeNokiaRTTLRingtone(*Info->Entries[0].Ringtone,Buffer,&Length); if (Info->Entries[0].ID == SMS_NokiaRingtone) break; if (Info->Entries[0].RingtoneNotes != Info->Entries[0].Ringtone->NoteTone.NrCommands) { UDH = UDH_NokiaRingtoneLong; Length = (GSM_MAX_8BIT_SMS_LENGTH-12)*3; Info->Entries[0].RingtoneNotes = GSM_EncodeNokiaRTTLRingtone(*Info->Entries[0].Ringtone,Buffer,&Length); } break; case SMS_NokiaOperatorLogoLong: if (Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth > 72 || Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight > 14) { UDH = UDH_NokiaOperatorLogoLong; Class = 1; NOKIA_EncodeNetworkCode(Buffer, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode); Length = Length + 3; NOKIA_CopyBitmap(GSM_Nokia7110OperatorLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length); break; } case SMS_NokiaOperatorLogo: UDH = UDH_NokiaOperatorLogo; Class = 1; NOKIA_EncodeNetworkCode(Buffer, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode); Length = Length + 3; NOKIA_CopyBitmap(GSM_NokiaOperatorLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length); break; case SMS_NokiaCallerLogo: UDH = UDH_NokiaCallerLogo; Class = 1; NOKIA_CopyBitmap(GSM_NokiaCallerLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length); break; case SMS_NokiaProfileLong: case SMS_NokiaPictureImageLong: case SMS_NokiaScreenSaverLong: Class = 1; UDH = UDH_NokiaProfileLong; GSM_EncodeSMS30MultiPartSMS(Info,Buffer,&Length); break; case SMS_NokiaWAPBookmarkLong: Class = 1; NOKIA_EncodeWAPBookmarkSMSText(Buffer,&Length,Info->Entries[0].Bookmark); /* 7 = length of UDH_NokiaWAP UDH header */ if (Length>(GSM_MAX_8BIT_SMS_LENGTH-7)) { UDH=UDH_NokiaWAPLong; } else { UDH=UDH_NokiaWAP; } break; case SMS_NokiaWAPSettingsLong: Class = 1; UDH = UDH_NokiaWAPLong; NOKIA_EncodeWAPMMSSettingsSMSText(Buffer,&Length,Info->Entries[0].Settings,false); break; case SMS_NokiaMMSSettingsLong: Class = 1; UDH = UDH_NokiaWAPLong; NOKIA_EncodeWAPMMSSettingsSMSText(Buffer,&Length,Info->Entries[0].Settings,true); break; case SMS_NokiaVCARD10Long: GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10); /* is 1 SMS ? 8 = length of ..SCKE2 */ if (Length<=GSM_MAX_SMS_LENGTH-8) { sprintf(Buffer,"//SCKE2 "); Length = 8; GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10); } else { /* FIXME: It wasn't checked */ UDH = UDH_NokiaPhonebookLong; } Coding = SMS_Coding_Default; memcpy(Buffer2,Buffer,Length); EncodeUnicode(Buffer,Buffer2,Length); break; case SMS_NokiaVCARD21Long: GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21); /* Is 1 SMS ? 12 = length of ..SCKL23F4 */ if (Length<=GSM_MAX_SMS_LENGTH-12) { sprintf(Buffer,"//SCKL23F4%c%c",13,10); Length = 12; GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21); } else { UDH = UDH_NokiaPhonebookLong; /* Here can be also 8 bit coding */ } Coding = SMS_Coding_Default; memcpy(Buffer2,Buffer,Length); EncodeUnicode(Buffer,Buffer2,Length); break; case SMS_VCARD10Long: GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10); if (Length>GSM_MAX_SMS_LENGTH) UDH = UDH_ConcatenatedMessages; Coding = SMS_Coding_Default; memcpy(Buffer2,Buffer,Length); EncodeUnicode(Buffer,Buffer2,Length); break; case SMS_VCARD21Long: GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21); if (Length>GSM_MAX_SMS_LENGTH) UDH = UDH_ConcatenatedMessages; Coding = SMS_Coding_Default; memcpy(Buffer2,Buffer,Length); EncodeUnicode(Buffer,Buffer2,Length); break; case SMS_NokiaVCALENDAR10Long: error=GSM_EncodeVCALENDAR(Buffer,&Length,Info->Entries[0].Calendar,true,Nokia_VCalendar); if (error != ERR_NONE) return error; /* Is 1 SMS ? 8 = length of ..SCKE4 */ if (Length<=GSM_MAX_SMS_LENGTH-8) { sprintf(Buffer,"//SCKE4 "); Length = 8; GSM_EncodeVCALENDAR(Buffer,&Length,Info->Entries[0].Calendar,true,Nokia_VCalendar); } else { UDH = UDH_NokiaCalendarLong; /* can be here 8 bit coding ? */ } Coding = SMS_Coding_Default; memcpy(Buffer2,Buffer,Length); EncodeUnicode(Buffer,Buffer2,Length); break; case SMS_NokiaVTODOLong: error=GSM_EncodeVTODO(Buffer,&Length,Info->Entries[0].ToDo,true,Nokia_VToDo); if (error != ERR_NONE) return error; UDH = UDH_NokiaCalendarLong; Coding = SMS_Coding_Default; memcpy(Buffer2,Buffer,Length); EncodeUnicode(Buffer,Buffer2,Length); break; case SMS_DisableVoice: case SMS_DisableFax: case SMS_DisableEmail: case SMS_EnableVoice: case SMS_EnableFax: case SMS_EnableEmail: case SMS_VoidSMS: case SMS_Text: Class = Info->Class; switch (Info->Entries[0].ID) { case SMS_DisableVoice : UDH = UDH_DisableVoice; break; case SMS_DisableFax : UDH = UDH_DisableFax; break; case SMS_DisableEmail : UDH = UDH_DisableEmail; break; case SMS_EnableVoice : UDH = UDH_EnableVoice; break; case SMS_EnableFax : UDH = UDH_EnableFax; break; case SMS_EnableEmail : UDH = UDH_EnableEmail; break; case SMS_VoidSMS : UDH = UDH_VoidSMS; break; case SMS_Text : UDH = UDH_NoUDH; break; default : break; } UDHHeader.Type = UDH; GSM_EncodeUDHHeader(&UDHHeader); memcpy(Buffer,Info->Entries[0].Buffer,UnicodeLength(Info->Entries[0].Buffer)*2+2); if (Info->UnicodeCoding) { Coding = SMS_Coding_Unicode; Length = UnicodeLength(Info->Entries[0].Buffer); if (Length>(140-UDHHeader.Length)/2) Length = (140-UDHHeader.Length)/2; } else { Coding = SMS_Coding_Default; FindDefaultAlphabetLen(Info->Entries[0].Buffer,&Length,&smslen,(GSM_MAX_8BIT_SMS_LENGTH-UDHHeader.Length)*8/7); } break; case SMS_ConcatenatedAutoTextLong: case SMS_ConcatenatedAutoTextLong16bit: smslen = UnicodeLength(Info->Entries[0].Buffer); memcpy(Buffer,Info->Entries[0].Buffer,smslen*2); EncodeDefault(Buffer2, Buffer, &smslen, true, NULL); DecodeDefault(Buffer, Buffer2, smslen, true, NULL); #ifdef DEBUG if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) { dbgprintf("Info->Entries[0].Buffer:\n"); DumpMessage(di.df, di.dl, Info->Entries[0].Buffer, UnicodeLength(Info->Entries[0].Buffer)*2); dbgprintf("Buffer:\n"); DumpMessage(di.df, di.dl, Buffer, UnicodeLength(Buffer)*2); } #endif Info->UnicodeCoding = false; for (smslen=0;smslen<(int)(UnicodeLength(Info->Entries[0].Buffer)*2);smslen++) { if (Info->Entries[0].Buffer[smslen] != Buffer[smslen]) { Info->UnicodeCoding = true; dbgprintf("Setting to Unicode %i\n",smslen); break; } } /* No break here - we go to the SMS_ConcatenatedTextLong */ case SMS_ConcatenatedTextLong: case SMS_ConcatenatedTextLong16bit: Class = Info->Class; memcpy(Buffer,Info->Entries[0].Buffer,UnicodeLength(Info->Entries[0].Buffer)*2+2); UDH = UDH_NoUDH; if (Info->UnicodeCoding) { Coding = SMS_Coding_Unicode; Length = UnicodeLength(Info->Entries[0].Buffer); if (Info->Entries[0].ID == SMS_ConcatenatedTextLong16bit || Info->Entries[0].ID == SMS_ConcatenatedAutoTextLong16bit) { if (Length>70) UDH=UDH_ConcatenatedMessages16bit; } else { if (Length>70) UDH=UDH_ConcatenatedMessages; } } else { Coding = SMS_Coding_Default; FindDefaultAlphabetLen(Info->Entries[0].Buffer,&Length,&smslen,5000); if (Info->Entries[0].ID == SMS_ConcatenatedTextLong16bit || Info->Entries[0].ID == SMS_ConcatenatedAutoTextLong16bit) { if (smslen>GSM_MAX_SMS_LENGTH) UDH=UDH_ConcatenatedMessages16bit; } else { if (smslen>GSM_MAX_SMS_LENGTH) UDH=UDH_ConcatenatedMessages; } } default: break; } GSM_MakeMultiPartSMS(SMS,Buffer,Length,UDH,Coding,Class,Info->ReplaceMessage); return ERR_NONE; } void GSM_ClearMultiPartSMSInfo(GSM_MultiPartSMSInfo *Info) { int i; for (i=0;iEntries[i].Number = 0; Info->Entries[i].Ringtone = NULL; Info->Entries[i].Bitmap = NULL; Info->Entries[i].Bookmark = NULL; Info->Entries[i].Settings = NULL; Info->Entries[i].MMSIndicator = NULL; Info->Entries[i].Phonebook = NULL; Info->Entries[i].Calendar = NULL; Info->Entries[i].ToDo = NULL; Info->Entries[i].Protected = false; Info->Entries[i].Buffer = NULL; Info->Entries[i].Left = false; Info->Entries[i].Right = false; Info->Entries[i].Center = false; Info->Entries[i].Large = false; Info->Entries[i].Small = false; Info->Entries[i].Bold = false; Info->Entries[i].Italic = false; Info->Entries[i].Underlined = false; Info->Entries[i].Strikethrough = false; Info->Entries[i].RingtoneNotes = 0; } Info->Unknown = false; Info->EntriesNum = 0; Info->Class = -1; Info->ReplaceMessage = 0; Info->UnicodeCoding = false; } void GSM_FreeMultiPartSMSInfo(GSM_MultiPartSMSInfo *Info) { int i; for (i=0;iEntries[i].Ringtone); Info->Entries[i].Ringtone = NULL; free(Info->Entries[i].Bitmap); Info->Entries[i].Bitmap = NULL; free(Info->Entries[i].Bookmark); Info->Entries[i].Bookmark = NULL; free(Info->Entries[i].Settings); Info->Entries[i].Settings = NULL; free(Info->Entries[i].MMSIndicator); Info->Entries[i].MMSIndicator = NULL; free(Info->Entries[i].Phonebook); Info->Entries[i].Phonebook = NULL; free(Info->Entries[i].Calendar); Info->Entries[i].Calendar = NULL; free(Info->Entries[i].ToDo); Info->Entries[i].ToDo = NULL; free(Info->Entries[i].Buffer); Info->Entries[i].Buffer = NULL; } } /* ----------------- Joining SMS from parts -------------------------------- */ bool GSM_DecodeMultiPartSMS(GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS, bool ems) { int i, Length = 0; char Buffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS]; bool emsexist = false; GSM_ClearMultiPartSMSInfo(Info); if (ems) { emsexist = true; for (i=0;iNumber;i++) { if (SMS->SMS[i].UDH.Type != UDH_ConcatenatedMessages && SMS->SMS[i].UDH.Type != UDH_ConcatenatedMessages16bit && SMS->SMS[i].UDH.Type != UDH_UserUDH) { emsexist = false; break; } } } /* EMS decoding */ if (emsexist) return GSM_DecodeEMSMultiPartSMS(Info,SMS); /* Smart Messaging decoding */ if (SMS->SMS[0].UDH.Type == UDH_NokiaRingtone && SMS->Number == 1) { Info->Entries[0].Ringtone = (GSM_Ringtone *)malloc(sizeof(GSM_Ringtone)); if (Info->Entries[0].Ringtone == NULL) return false; if (GSM_DecodeNokiaRTTLRingtone(Info->Entries[0].Ringtone, SMS->SMS[0].Text, SMS->SMS[0].Length)==ERR_NONE) { Info->Entries[0].ID = SMS_NokiaRingtone; Info->EntriesNum = 1; return true; } } if (SMS->SMS[0].UDH.Type == UDH_NokiaCallerLogo && SMS->Number == 1) { Info->Entries[0].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap)); if (Info->Entries[0].Bitmap == NULL) return false; Info->Entries[0].Bitmap->Number = 1; PHONE_DecodeBitmap(GSM_NokiaCallerLogo, SMS->SMS[0].Text+4, &Info->Entries[0].Bitmap->Bitmap[0]); #ifdef DEBUG if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]); #endif Info->Entries[0].ID = SMS_NokiaCallerLogo; Info->EntriesNum = 1; return true; } if (SMS->SMS[0].UDH.Type == UDH_NokiaOperatorLogo && SMS->Number == 1) { Info->Entries[0].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap)); if (Info->Entries[0].Bitmap == NULL) return false; Info->Entries[0].Bitmap->Number = 1; PHONE_DecodeBitmap(GSM_NokiaOperatorLogo, SMS->SMS[0].Text+7, &Info->Entries[0].Bitmap->Bitmap[0]); NOKIA_DecodeNetworkCode(SMS->SMS[0].Text, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode); #ifdef DEBUG if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]); #endif Info->Entries[0].ID = SMS_NokiaOperatorLogo; Info->EntriesNum = 1; return true; } if (SMS->SMS[0].UDH.Type == UDH_NokiaProfileLong) { for (i=0;iNumber;i++) { if (SMS->SMS[i].UDH.Type != UDH_NokiaProfileLong || SMS->SMS[i].UDH.Text[11] != i+1 || SMS->SMS[i].UDH.Text[10] != SMS->Number) { return false; } memcpy(Buffer+Length,SMS->SMS[i].Text,SMS->SMS[i].Length); Length = Length + SMS->SMS[i].Length; } Info->EntriesNum = 1; Info->Entries[0].ID = SMS_NokiaPictureImageLong; Info->Entries[0].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap)); if (Info->Entries[0].Bitmap == NULL) return false; Info->Entries[0].Bitmap->Number = 1; Info->Entries[0].Bitmap->Bitmap[0].Text[0] = 0; Info->Entries[0].Bitmap->Bitmap[0].Text[1] = 0; i=1; while (i!=Length) { switch (Buffer[i]) { case SM30_ISOTEXT: dbgprintf("ISO 8859-2 text\n"); Info->Unknown = true; break; case SM30_UNICODETEXT: dbgprintf("Unicode text\n"); memcpy(Info->Entries[0].Bitmap->Bitmap[0].Text,Buffer+i+3,Buffer[i+1]*256+Buffer[i+2]); Info->Entries[0].Bitmap->Bitmap[0].Text[Buffer[i+1]*256 + Buffer[i+2]] = 0; Info->Entries[0].Bitmap->Bitmap[0].Text[Buffer[i+1]*256 + Buffer[i+2]+ 1] = 0; dbgprintf("Unicode Text \"%s\"\n",DecodeUnicodeString(Info->Entries[0].Bitmap->Bitmap[0].Text)); break; case SM30_OTA: dbgprintf("OTA bitmap as Picture Image\n"); PHONE_DecodeBitmap(GSM_NokiaPictureImage, Buffer + i + 7, &Info->Entries[0].Bitmap->Bitmap[0]); #ifdef DEBUG if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]); #endif break; case SM30_RINGTONE: dbgprintf("RTTL ringtone\n"); Info->Unknown = true; break; case SM30_PROFILENAME: dbgprintf("Profile Name\n"); Info->Entries[0].ID = SMS_NokiaProfileLong; Info->Unknown = true; break; case SM30_SCREENSAVER: dbgprintf("OTA bitmap as Screen Saver\n"); PHONE_DecodeBitmap(GSM_NokiaPictureImage, Buffer + i + 7, &Info->Entries[0].Bitmap->Bitmap[0]); #ifdef DEBUG if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]); #endif Info->Entries[0].ID = SMS_NokiaScreenSaverLong; break; } i = i + Buffer[i+1]*256 + Buffer[i+2] + 3; dbgprintf("%i %i\n",i,Length); } return true; } /* Linked sms */ if (SMS->SMS[0].UDH.Type == UDH_ConcatenatedMessages || SMS->SMS[0].UDH.Type == UDH_ConcatenatedMessages16bit) { Info->EntriesNum = 1; Info->Entries[0].ID = SMS_ConcatenatedTextLong; if (SMS->SMS[0].UDH.Type == UDH_ConcatenatedMessages16bit) { Info->Entries[0].ID = SMS_ConcatenatedTextLong16bit; } for (i=0;iNumber;i++) { switch (SMS->SMS[i].Coding) { case SMS_Coding_8bit: Info->Entries[0].Buffer = realloc(Info->Entries[0].Buffer, Length + SMS->SMS[i].Length + 2); if (Info->Entries[0].Buffer == NULL) return false; memcpy(Info->Entries[0].Buffer + Length, SMS->SMS[i].Text, SMS->SMS[i].Length); Length=Length+SMS->SMS[i].Length; break; case SMS_Coding_Unicode: if (Info->Entries[0].ID == SMS_ConcatenatedTextLong) { Info->Entries[0].ID = SMS_ConcatenatedAutoTextLong; } if (Info->Entries[0].ID == SMS_ConcatenatedTextLong16bit) { Info->Entries[0].ID = SMS_ConcatenatedAutoTextLong16bit; } case SMS_Coding_Default: Info->Entries[0].Buffer = realloc(Info->Entries[0].Buffer, Length + UnicodeLength(SMS->SMS[i].Text)*2 + 2); if (Info->Entries[0].Buffer == NULL) return false; memcpy(Info->Entries[0].Buffer+Length,SMS->SMS[i].Text,UnicodeLength(SMS->SMS[i].Text)*2); Length=Length+UnicodeLength(SMS->SMS[i].Text)*2; break; } } Info->Entries[0].Buffer[Length] = 0; Info->Entries[0].Buffer[Length+1] = 0; return true; } return false; } GSM_Error GSM_LinkSMS(GSM_MultiSMSMessage **INPUT, GSM_MultiSMSMessage **OUTPUT, bool ems) { bool *INPUTSorted, copyit; int i,OUTPUTNum,j,z,w; i = 0; while (INPUT[i] != NULL) i++; INPUTSorted = calloc(i, sizeof(bool)); if (INPUTSorted == NULL) return ERR_MOREMEMORY; OUTPUTNum = 0; OUTPUT[0] = NULL; if (ems) { i=0; while (INPUT[i] != NULL) { if (INPUT[i]->SMS[0].UDH.Type == UDH_UserUDH) { w=1; while (w < INPUT[i]->SMS[0].UDH.Length) { switch(INPUT[i]->SMS[0].UDH.Text[w]) { case 0x00: dbgprintf("Adding ID to user UDH - linked SMS with 8 bit ID\n"); INPUT[i]->SMS[0].UDH.ID8bit = INPUT[i]->SMS[0].UDH.Text[w+2]; INPUT[i]->SMS[0].UDH.AllParts = INPUT[i]->SMS[0].UDH.Text[w+3]; INPUT[i]->SMS[0].UDH.PartNumber = INPUT[i]->SMS[0].UDH.Text[w+4]; break; case 0x08: dbgprintf("Adding ID to user UDH - linked SMS with 16 bit ID\n"); INPUT[i]->SMS[0].UDH.ID16bit = INPUT[i]->SMS[0].UDH.Text[w+2]*256+INPUT[i]->SMS[0].UDH.Text[w+3]; INPUT[i]->SMS[0].UDH.AllParts = INPUT[i]->SMS[0].UDH.Text[w+4]; INPUT[i]->SMS[0].UDH.PartNumber = INPUT[i]->SMS[0].UDH.Text[w+5]; break; default: dbgprintf("Block %02x\n",INPUT[i]->SMS[0].UDH.Text[w]); } dbgprintf("%i %i %i %i\n", INPUT[i]->SMS[0].UDH.ID8bit, INPUT[i]->SMS[0].UDH.ID16bit, INPUT[i]->SMS[0].UDH.PartNumber, INPUT[i]->SMS[0].UDH.AllParts); w=w+INPUT[i]->SMS[0].UDH.Text[w+1]+2; } } i++; } } i=0; while (INPUT[i]!=NULL) { /* If this one SMS was sorted earlier, do not touch */ if (INPUTSorted[i]) { i++; continue; } copyit = false; /* If we have: * - linked sms returned by phone driver * - sms without linking * we copy it to OUTPUT */ if (INPUT[i]->Number != 1 || INPUT[i]->SMS[0].UDH.Type == UDH_NoUDH || INPUT[i]->SMS[0].UDH.PartNumber == -1) { copyit = true; } /* If we have unknown UDH, we copy it to OUTPUT */ if (INPUT[i]->SMS[0].UDH.Type == UDH_UserUDH) { if (!ems) copyit = true; if (ems && INPUT[i]->SMS[0].UDH.PartNumber == -1) copyit = true; } if (copyit) { OUTPUT[OUTPUTNum] = malloc(sizeof(GSM_MultiSMSMessage)); if (OUTPUT[OUTPUTNum] == NULL) { free(INPUTSorted); return ERR_MOREMEMORY; } OUTPUT[OUTPUTNum+1] = NULL; memcpy(OUTPUT[OUTPUTNum],INPUT[i],sizeof(GSM_MultiSMSMessage)); INPUTSorted[i]=true; OUTPUTNum++; i = 0; continue; } /* We have 1'st part of linked sms. It's single. * We will try to find other parts */ if (INPUT[i]->SMS[0].UDH.PartNumber == 1) { OUTPUT[OUTPUTNum] = malloc(sizeof(GSM_MultiSMSMessage)); if (OUTPUT[OUTPUTNum] == NULL) { free(INPUTSorted); return ERR_MOREMEMORY; } OUTPUT[OUTPUTNum+1] = NULL; memcpy(&OUTPUT[OUTPUTNum]->SMS[0],&INPUT[i]->SMS[0],sizeof(GSM_SMSMessage)); OUTPUT[OUTPUTNum]->Number = 1; INPUTSorted[i] = true; j = 1; /* We're searching for other parts in sequence */ while (j!=INPUT[i]->SMS[0].UDH.AllParts) { z=0; while(INPUT[z]!=NULL) { /* This was sorted earlier or is not single */ if (INPUTSorted[z] || INPUT[z]->Number != 1) { z++; continue; } if (ems && INPUT[i]->SMS[0].UDH.Type != UDH_ConcatenatedMessages && INPUT[i]->SMS[0].UDH.Type != UDH_ConcatenatedMessages16bit && INPUT[i]->SMS[0].UDH.Type != UDH_UserUDH && INPUT[z]->SMS[0].UDH.Type != UDH_ConcatenatedMessages && INPUT[z]->SMS[0].UDH.Type != UDH_ConcatenatedMessages16bit && INPUT[z]->SMS[0].UDH.Type != UDH_UserUDH) { if (INPUT[z]->SMS[0].UDH.Type != INPUT[i]->SMS[0].UDH.Type) { z++; continue; } } if (!ems && INPUT[z]->SMS[0].UDH.Type != INPUT[i]->SMS[0].UDH.Type) { z++; continue; } dbgprintf("compare %i %i %i %i %i", j+1, INPUT[i]->SMS[0].UDH.ID8bit, INPUT[i]->SMS[0].UDH.ID16bit, INPUT[i]->SMS[0].UDH.PartNumber, INPUT[i]->SMS[0].UDH.AllParts); dbgprintf(" %i %i %i %i\n", INPUT[z]->SMS[0].UDH.ID8bit, INPUT[z]->SMS[0].UDH.ID16bit, INPUT[z]->SMS[0].UDH.PartNumber, INPUT[z]->SMS[0].UDH.AllParts); if (INPUT[z]->SMS[0].UDH.ID8bit != INPUT[i]->SMS[0].UDH.ID8bit || INPUT[z]->SMS[0].UDH.ID16bit != INPUT[i]->SMS[0].UDH.ID16bit || INPUT[z]->SMS[0].UDH.AllParts != INPUT[i]->SMS[0].UDH.AllParts || INPUT[z]->SMS[0].UDH.PartNumber != j+1) { z++; continue; } /* For SMS_Deliver compare also SMSC and Sender number */ if (INPUT[z]->SMS[0].PDU == SMS_Deliver && (strcmp(DecodeUnicodeString(INPUT[z]->SMS[0].SMSC.Number),DecodeUnicodeString(INPUT[i]->SMS[0].SMSC.Number)) || strcmp(DecodeUnicodeString(INPUT[z]->SMS[0].Number),DecodeUnicodeString(INPUT[i]->SMS[0].Number)))) { z++; continue; } /* DCT4 Outbox: SMS Deliver. Empty number and SMSC. We compare dates */ if (INPUT[z]->SMS[0].PDU == SMS_Deliver && UnicodeLength(INPUT[z]->SMS[0].SMSC.Number)==0 && UnicodeLength(INPUT[z]->SMS[0].Number)==0 && (INPUT[z]->SMS[0].DateTime.Day != INPUT[i]->SMS[0].DateTime.Day || INPUT[z]->SMS[0].DateTime.Month != INPUT[i]->SMS[0].DateTime.Month || INPUT[z]->SMS[0].DateTime.Year != INPUT[i]->SMS[0].DateTime.Year || INPUT[z]->SMS[0].DateTime.Hour != INPUT[i]->SMS[0].DateTime.Hour || INPUT[z]->SMS[0].DateTime.Minute != INPUT[i]->SMS[0].DateTime.Minute || INPUT[z]->SMS[0].DateTime.Second != INPUT[i]->SMS[0].DateTime.Second)) { z++; continue; } /* We found correct sms. Copy it */ memcpy(&OUTPUT[OUTPUTNum]->SMS[j],&INPUT[z]->SMS[0],sizeof(GSM_SMSMessage)); OUTPUT[OUTPUTNum]->Number++; INPUTSorted[z]=true; break; } /* Incomplete sequence */ if (OUTPUT[OUTPUTNum]->Number==j) { dbgprintf("Incomplete sequence\n"); break; } j++; } OUTPUTNum++; i = 0; continue; } /* We have some next linked sms from sequence */ if (INPUT[i]->SMS[0].UDH.PartNumber > 1) { j = 0; while (INPUT[j]!=NULL) { if (INPUTSorted[j]) { j++; continue; } /* We have some not unassigned first sms from sequence. * We can't touch other sms from sequences */ if (INPUT[j]->SMS[0].UDH.PartNumber == 1) break; j++; } if (INPUT[j]==NULL) { OUTPUT[OUTPUTNum] = malloc(sizeof(GSM_MultiSMSMessage)); if (OUTPUT[OUTPUTNum] == NULL) { free(INPUTSorted); return ERR_MOREMEMORY; } OUTPUT[OUTPUTNum+1] = NULL; memcpy(OUTPUT[OUTPUTNum],INPUT[i],sizeof(GSM_MultiSMSMessage)); INPUTSorted[i]=true; OUTPUTNum++; i = 0; continue; } else i++; } } free(INPUTSorted); return ERR_NONE; } /* How should editor hadle tabs in this file? Add editor commands here. * vim: noexpandtab sw=8 ts=8 sts=8: */