6 #include "../../gsmcomon.h"
7 #include "../../misc/coding/coding.h"
10 #include "../gsmlogo.h"
11 #include "../gsmring.h"
12 #include "../gsmwap.h"
13 #include "../gsmnet.h"
18 /* ----------------- Splitting SMS into parts ------------------------------ */
20 unsigned char GSM_MakeSMSIDFromTime()
25 GSM_GetCurrentDateTime (&Date
);
27 switch (Date
.Minute
/10) {
28 case 2: case 7: retval
= retval
+ 60; break;
29 case 4: case 8: retval
= retval
+ 120; break;
30 case 9: case 5: case 0: retval
= retval
+ 180; break;
32 retval
+= Date
.Minute
/10;
36 void GSM_Find_Free_Used_SMS2(GSM_Coding_Type Coding
,GSM_SMSMessage SMS
, int *UsedText
, int *FreeText
, int *FreeBytes
)
41 case GSM_Coding_Default
:
42 FindDefaultAlphabetLen(SMS
.Text
,&UsedBytes
,UsedText
,500);
43 UsedBytes
= *UsedText
* 7 / 8;
44 if (UsedBytes
* 8 / 7 != *UsedText
) UsedBytes
++;
45 *FreeBytes
= GSM_MAX_8BIT_SMS_LENGTH
- SMS
.UDH
.Length
- UsedBytes
;
46 *FreeText
= (GSM_MAX_8BIT_SMS_LENGTH
- SMS
.UDH
.Length
) * 8 / 7 - *UsedText
;
48 case GSM_Coding_Unicode
:
49 *UsedText
= UnicodeLength(SMS
.Text
);
50 UsedBytes
= *UsedText
* 2;
51 *FreeBytes
= GSM_MAX_8BIT_SMS_LENGTH
- SMS
.UDH
.Length
- UsedBytes
;
52 *FreeText
= *FreeBytes
/ 2;
55 *UsedText
= UsedBytes
= SMS
.Length
;
56 *FreeBytes
= GSM_MAX_8BIT_SMS_LENGTH
- SMS
.UDH
.Length
- UsedBytes
;
57 *FreeText
= *FreeBytes
;
60 dbgprintf("UDH len %i, UsedBytes %i, FreeText %i, UsedText %i, FreeBytes %i\n",SMS
.UDH
.Length
,UsedBytes
,*FreeText
,*UsedText
,*FreeBytes
);
63 GSM_Error
GSM_AddSMS_Text_UDH(GSM_MultiSMSMessage
*SMS
,
64 GSM_Coding_Type Coding
,
72 int FreeText
,FreeBytes
,Copy
,i
,j
;
74 dbgprintf("Checking used\n");
75 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], UsedText
, &FreeText
, &FreeBytes
);
78 dbgprintf("Adding UDH\n");
79 if (FreeBytes
- BufferLen
<= 0) {
80 dbgprintf("Going to the new SMS\n");
82 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], UsedText
, &FreeText
, &FreeBytes
);
84 if (SMS
->SMS
[SMS
->Number
].UDH
.Length
== 0) {
85 SMS
->SMS
[SMS
->Number
].UDH
.Length
= 1;
86 SMS
->SMS
[SMS
->Number
].UDH
.Text
[0] = 0x00;
88 memcpy(SMS
->SMS
[SMS
->Number
].UDH
.Text
+SMS
->SMS
[SMS
->Number
].UDH
.Length
,Buffer
,BufferLen
);
89 SMS
->SMS
[SMS
->Number
].UDH
.Length
+= BufferLen
;
90 SMS
->SMS
[SMS
->Number
].UDH
.Text
[0] += BufferLen
;
91 SMS
->SMS
[SMS
->Number
].UDH
.Type
= UDH_UserUDH
;
92 dbgprintf("UDH added %i\n",BufferLen
);
94 dbgprintf("Adding text\n");
96 dbgprintf("Going to the new SMS\n");
98 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], UsedText
, &FreeText
, &FreeBytes
);
102 dbgprintf("copy %i\n",Copy
);
103 if (BufferLen
< Copy
) Copy
= BufferLen
;
104 dbgprintf("copy %i\n",Copy
);
107 case GSM_Coding_Default
:
108 FindDefaultAlphabetLen(Buffer
,&i
,&j
,FreeText
);
109 dbgprintf("def length %i %i\n",i
,j
);
110 SMS
->SMS
[SMS
->Number
].Text
[UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2+i
*2] = 0;
111 SMS
->SMS
[SMS
->Number
].Text
[UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2+i
*2+1] = 0;
112 memcpy(SMS
->SMS
[SMS
->Number
].Text
+UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2,Buffer
,i
*2);
115 SMS
->SMS
[SMS
->Number
].Length
+= i
;
117 case GSM_Coding_Unicode
:
118 SMS
->SMS
[SMS
->Number
].Text
[UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2+Copy
*2] = 0;
119 SMS
->SMS
[SMS
->Number
].Text
[UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2+Copy
*2+1] = 0;
120 memcpy(SMS
->SMS
[SMS
->Number
].Text
+UnicodeLength(SMS
->SMS
[SMS
->Number
].Text
)*2,Buffer
,Copy
*2);
121 *CopiedText
= *CopiedSMSText
= Copy
;
122 SMS
->SMS
[SMS
->Number
].Length
+= Copy
;
124 case GSM_Coding_8bit
:
125 memcpy(SMS
->SMS
[SMS
->Number
].Text
+SMS
->SMS
[SMS
->Number
].Length
,Buffer
,Copy
);
126 SMS
->SMS
[SMS
->Number
].Length
+= Copy
;
127 *CopiedText
= *CopiedSMSText
= Copy
;
130 dbgprintf("Text added\n");
133 dbgprintf("Checking on the end\n");
134 GSM_Find_Free_Used_SMS2(Coding
,SMS
->SMS
[SMS
->Number
], UsedText
, &FreeText
, &FreeBytes
);
139 void GSM_MakeMultiPartSMS(GSM_MultiSMSMessage
*SMS
,
140 unsigned char *MessageBuffer
,
143 GSM_Coding_Type Coding
,
145 unsigned char ReplaceMessage
)
147 int j
,Len
,UsedText
,CopiedText
,CopiedSMSText
;
153 GSM_SetDefaultSMSData(&SMS
->SMS
[SMS
->Number
]);
154 SMS
->SMS
[SMS
->Number
].Class
= Class
;
155 SMS
->SMS
[SMS
->Number
].Coding
= Coding
;
157 SMS
->SMS
[SMS
->Number
].UDH
.Type
= UDHType
;
158 GSM_EncodeUDHHeader(&SMS
->SMS
[SMS
->Number
].UDH
);
160 if (Coding
== GSM_Coding_8bit
) {
161 GSM_AddSMS_Text_UDH(SMS
,Coding
,MessageBuffer
+Len
,MessageLength
- Len
,false,&UsedText
,&CopiedText
,&CopiedSMSText
);
163 GSM_AddSMS_Text_UDH(SMS
,Coding
,MessageBuffer
+Len
*2,MessageLength
- Len
,false,&UsedText
,&CopiedText
,&CopiedSMSText
);
166 dbgprintf("%i %i\n",Len
,MessageLength
);
167 if (Len
== MessageLength
) break;
168 if (SMS
->Number
== MAX_MULTI_SMS
) break;
174 UDHID
= GSM_MakeSMSIDFromTime();
175 GSM_GetCurrentDateTime (&Date
);
176 for (j
=0;j
<SMS
->Number
;j
++)
178 SMS
->SMS
[j
].UDH
.Type
= UDHType
;
179 SMS
->SMS
[j
].UDH
.ID8bit
= UDHID
;
180 SMS
->SMS
[j
].UDH
.ID16bit
= UDHID
+ 256 * Date
.Hour
;
181 SMS
->SMS
[j
].UDH
.PartNumber
= j
+1;
182 SMS
->SMS
[j
].UDH
.AllParts
= SMS
->Number
;
183 GSM_EncodeUDHHeader(&SMS
->SMS
[j
].UDH
);
185 if (SMS
->Number
== 1) SMS
->SMS
[0].ReplaceMessage
= ReplaceMessage
;
188 /* Calculates number of SMS and number of left chars in SMS */
189 void GSM_SMSCounter(int MessageLength
,
190 unsigned char *MessageBuffer
,
192 GSM_Coding_Type Coding
,
196 int UsedText
,FreeBytes
;
197 GSM_MultiSMSMessage MultiSMS
;
200 GSM_MakeMultiPartSMS(&MultiSMS
,MessageBuffer
,MessageLength
,UDHType
,Coding
,-1,false);
201 GSM_Find_Free_Used_SMS2(Coding
,MultiSMS
.SMS
[MultiSMS
.Number
-1], &UsedText
, CharsLeft
, &FreeBytes
);
202 *SMSNum
= MultiSMS
.Number
;
205 /* Nokia Smart Messaging 3.0 */
206 static void GSM_EncodeSMS30MultiPartSMS(GSM_EncodeMultiPartSMSInfo
*Info
,
207 char *Buffer
, int *Length
)
211 /*SM version. Here 3.0*/
212 Buffer
[(*Length
)++] = 0x30;
214 if (Info
->Entries
[0].ID
== SMS_NokiaProfileLong
) {
215 if (Info
->Entries
[0].Buffer
!= NULL
) {
216 if (Info
->Entries
[0].Buffer
[0]!=0x00 || Info
->Entries
[0].Buffer
[1]!=0x00) {
217 Buffer
[(*Length
)++] = SM30_PROFILENAME
;
218 Buffer
[(*Length
)++] = 0x00;
219 Buffer
[(*Length
)++] = 2*UnicodeLength(Info
->Entries
[0].Buffer
);
220 CopyUnicodeString(Buffer
+(*Length
),Info
->Entries
[0].Buffer
);
221 *Length
= *Length
+ 2*UnicodeLength(Info
->Entries
[0].Buffer
);
224 if (Info
->Entries
[0].Ringtone
!= NULL
) {
225 Buffer
[(*Length
)++] = SM30_RINGTONE
;
226 /* Length for this part later will be changed */
227 Buffer
[(*Length
)++] = 0x01;
228 Buffer
[(*Length
)++] = 0x00;
229 /* Smart Messaging 3.0 says: 16*9=144 bytes,
230 * but on 3310 4.02 it was possible to save about 196 chars
231 * (without cutting) */
233 Info
->Entries
[0].RingtoneNotes
=GSM_EncodeNokiaRTTLRingtone(*Info
->Entries
[0].Ringtone
,Buffer
+(*Length
),&len
);
234 Buffer
[(*Length
)-2] = len
/ 256;
235 Buffer
[(*Length
)-1] = len
% 256;
236 *Length
= *Length
+ len
;
239 if (Info
->Entries
[0].Bitmap
!= NULL
) {
240 if (Info
->Entries
[0].ID
== SMS_NokiaPictureImageLong
) {
241 Buffer
[(*Length
)++] = SM30_OTA
;
243 Buffer
[(*Length
)++] = SM30_SCREENSAVER
;
245 Buffer
[(*Length
)++] = 0x01;
246 Buffer
[(*Length
)++] = 0x00;
247 NOKIA_CopyBitmap(GSM_NokiaPictureImage
, &Info
->Entries
[0].Bitmap
->Bitmap
[0], Buffer
, Length
);
248 if (Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[0]!=0 || Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[1]!=0) {
249 if (Info
->UnicodeCoding
) {
250 Buffer
[(*Length
)++] = SM30_UNICODETEXT
;
251 /* Length for text part */
252 Buffer
[(*Length
)++] = 0x00;
253 Buffer
[(*Length
)++] = UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
)*2;
254 memcpy(Buffer
+(*Length
),Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
,UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
)*2);
255 *Length
= *Length
+ UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
)*2;
257 /*ID for ISO-8859-1 text*/
258 Buffer
[(*Length
)++] = SM30_ISOTEXT
;
259 Buffer
[(*Length
)++] = 0x00;
260 Buffer
[(*Length
)++] = UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
);
261 memcpy(Buffer
+(*Length
),DecodeUnicodeString(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
),UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
));
262 *Length
= *Length
+UnicodeLength(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
);
268 GSM_Error
GSM_EncodeMultiPartSMS(GSM_EncodeMultiPartSMSInfo
*Info
,
269 GSM_MultiSMSMessage
*SMS
)
271 unsigned char Buffer
[GSM_MAX_SMS_LENGTH
*2*MAX_MULTI_SMS
];
272 unsigned char Buffer2
[GSM_MAX_SMS_LENGTH
*2*MAX_MULTI_SMS
];
273 int Length
= 0,smslen
,i
, Class
= -1;
275 GSM_Coding_Type Coding
= GSM_Coding_8bit
;
276 GSM_UDH UDH
= UDH_NoUDH
;
277 GSM_UDHHeader UDHHeader
;
282 for (i
=0;i
<Info
->EntriesNum
;i
++) {
283 switch (Info
->Entries
[i
].ID
) {
284 case SMS_EMSPredefinedAnimation
:
285 case SMS_EMSPredefinedSound
:
288 case SMS_EMSSonyEricssonSound
:
289 case SMS_EMSSound10Long
:
290 case SMS_EMSSound12Long
:
291 case SMS_EMSSonyEricssonSoundLong
:
292 case SMS_EMSFixedBitmap
:
293 case SMS_EMSVariableBitmap
:
294 case SMS_EMSAnimation
:
295 case SMS_EMSVariableBitmapLong
:
298 case SMS_ConcatenatedTextLong
:
299 case SMS_ConcatenatedTextLong16bit
:
300 if (Info
->Entries
[i
].Left
|| Info
->Entries
[i
].Right
||
301 Info
->Entries
[i
].Center
|| Info
->Entries
[i
].Large
||
302 Info
->Entries
[i
].Small
|| Info
->Entries
[i
].Bold
||
303 Info
->Entries
[i
].Italic
|| Info
->Entries
[i
].Underlined
||
304 Info
->Entries
[i
].Strikethrough
) {
313 error
=GSM_EncodeEMSMultiPartSMS(Info
,SMS
,UDH_NoUDH
);
314 if (error
!= GE_NONE
) return error
;
315 if (SMS
->Number
!= 1) {
317 for (i
=0;i
<Info
->EntriesNum
;i
++) {
318 if (Info
->Entries
[i
].ID
== SMS_ConcatenatedTextLong16bit
) {
319 return GSM_EncodeEMSMultiPartSMS(Info
,SMS
,UDH_ConcatenatedMessages
);
322 return GSM_EncodeEMSMultiPartSMS(Info
,SMS
,UDH_ConcatenatedMessages16bit
);
326 if (Info
->EntriesNum
!= 1) return GE_UNKNOWN
;
328 switch (Info
->Entries
[0].ID
) {
329 case SMS_MMSIndicatorLong
:
331 UDH
= UDH_MMSIndicatorLong
;
332 GSM_EncodeMMSIndicatorSMSText(Buffer
,&Length
,*Info
->Entries
[0].MMSIndicator
);
334 case SMS_NokiaRingtoneLong
:
335 case SMS_NokiaRingtone
:
336 UDH
= UDH_NokiaRingtone
;
338 /* 7 = length of UDH_NokiaRingtone UDH header */
339 Length
= GSM_MAX_8BIT_SMS_LENGTH
-7;
340 Info
->Entries
[0].RingtoneNotes
= GSM_EncodeNokiaRTTLRingtone(*Info
->Entries
[0].Ringtone
,Buffer
,&Length
);
341 if (Info
->Entries
[0].ID
== SMS_NokiaRingtone
) break;
342 if (Info
->Entries
[0].RingtoneNotes
!= Info
->Entries
[0].Ringtone
->NoteTone
.NrCommands
) {
343 UDH
= UDH_NokiaRingtoneLong
;
344 Length
= (GSM_MAX_8BIT_SMS_LENGTH
-12)*3;
345 Info
->Entries
[0].RingtoneNotes
= GSM_EncodeNokiaRTTLRingtone(*Info
->Entries
[0].Ringtone
,Buffer
,&Length
);
348 case SMS_NokiaOperatorLogoLong
:
349 if (Info
->Entries
[0].Bitmap
->Bitmap
[0].Width
> 72 || Info
->Entries
[0].Bitmap
->Bitmap
[0].Height
> 14) {
350 UDH
= UDH_NokiaOperatorLogoLong
;
352 NOKIA_EncodeNetworkCode(Buffer
, Info
->Entries
[0].Bitmap
->Bitmap
[0].NetworkCode
);
354 NOKIA_CopyBitmap(GSM_Nokia7110OperatorLogo
, &Info
->Entries
[0].Bitmap
->Bitmap
[0], Buffer
, &Length
);
357 case SMS_NokiaOperatorLogo
:
358 UDH
= UDH_NokiaOperatorLogo
;
360 NOKIA_EncodeNetworkCode(Buffer
, Info
->Entries
[0].Bitmap
->Bitmap
[0].NetworkCode
);
362 NOKIA_CopyBitmap(GSM_NokiaOperatorLogo
, &Info
->Entries
[0].Bitmap
->Bitmap
[0], Buffer
, &Length
);
364 case SMS_NokiaCallerLogo
:
365 UDH
= UDH_NokiaCallerLogo
;
367 NOKIA_CopyBitmap(GSM_NokiaCallerLogo
, &Info
->Entries
[0].Bitmap
->Bitmap
[0], Buffer
, &Length
);
369 case SMS_NokiaProfileLong
:
370 case SMS_NokiaPictureImageLong
:
371 case SMS_NokiaScreenSaverLong
:
373 UDH
= UDH_NokiaProfileLong
;
374 GSM_EncodeSMS30MultiPartSMS(Info
,Buffer
,&Length
);
376 case SMS_NokiaWAPBookmarkLong
:
378 NOKIA_EncodeWAPBookmarkSMSText(Buffer
,&Length
,Info
->Entries
[0].Bookmark
);
379 /* 7 = length of UDH_NokiaWAP UDH header */
380 if (Length
>(GSM_MAX_8BIT_SMS_LENGTH
-7)) {
381 UDH
=UDH_NokiaWAPLong
;
386 case SMS_NokiaWAPSettingsLong
:
388 UDH
= UDH_NokiaWAPLong
;
389 NOKIA_EncodeWAPMMSSettingsSMSText(Buffer
,&Length
,Info
->Entries
[0].Settings
,false);
391 case SMS_NokiaMMSSettingsLong
:
393 UDH
= UDH_NokiaWAPLong
;
394 NOKIA_EncodeWAPMMSSettingsSMSText(Buffer
,&Length
,Info
->Entries
[0].Settings
,true);
396 case SMS_NokiaVCARD10Long
:
397 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard10
);
398 /* is 1 SMS ? 8 = length of ..SCKE2 */
399 if (Length
<=GSM_MAX_SMS_LENGTH
-8) {
400 sprintf(Buffer
,"//SCKE2 ");
402 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard10
);
404 /* FIXME: It wasn't checked */
405 UDH
= UDH_NokiaPhonebookLong
;
407 Coding
= GSM_Coding_Default
;
408 memcpy(Buffer2
,Buffer
,Length
);
409 EncodeUnicode(Buffer
,Buffer2
,Length
);
411 case SMS_NokiaVCARD21Long
:
412 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard21
);
413 /* Is 1 SMS ? 12 = length of ..SCKL23F4 */
414 if (Length
<=GSM_MAX_SMS_LENGTH
-12) {
415 sprintf(Buffer
,"//SCKL23F4%c%c",13,10);
417 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard21
);
419 UDH
= UDH_NokiaPhonebookLong
;
420 /* Here can be also 8 bit coding */
422 Coding
= GSM_Coding_Default
;
423 memcpy(Buffer2
,Buffer
,Length
);
424 EncodeUnicode(Buffer
,Buffer2
,Length
);
426 case SMS_VCARD10Long
:
427 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard10
);
428 if (Length
>GSM_MAX_SMS_LENGTH
) UDH
= UDH_ConcatenatedMessages
;
429 Coding
= GSM_Coding_Default
;
430 memcpy(Buffer2
,Buffer
,Length
);
431 EncodeUnicode(Buffer
,Buffer2
,Length
);
433 case SMS_VCARD21Long
:
434 GSM_EncodeVCARD(Buffer
,&Length
,Info
->Entries
[0].Phonebook
,true,Nokia_VCard21
);
435 if (Length
>GSM_MAX_SMS_LENGTH
) UDH
= UDH_ConcatenatedMessages
;
436 Coding
= GSM_Coding_Default
;
437 memcpy(Buffer2
,Buffer
,Length
);
438 EncodeUnicode(Buffer
,Buffer2
,Length
);
440 case SMS_NokiaVCALENDAR10Long
:
441 error
=GSM_EncodeVCALENDAR(Buffer
,&Length
,Info
->Entries
[0].Calendar
,true,Nokia_VCalendar
);
442 if (error
!= GE_NONE
) return error
;
443 /* Is 1 SMS ? 8 = length of ..SCKE4 */
444 if (Length
<=GSM_MAX_SMS_LENGTH
-8) {
445 sprintf(Buffer
,"//SCKE4 ");
447 GSM_EncodeVCALENDAR(Buffer
,&Length
,Info
->Entries
[0].Calendar
,true,Nokia_VCalendar
);
449 UDH
= UDH_NokiaCalendarLong
;
450 /* can be here 8 bit coding ? */
452 Coding
= GSM_Coding_Default
;
453 memcpy(Buffer2
,Buffer
,Length
);
454 EncodeUnicode(Buffer
,Buffer2
,Length
);
456 case SMS_NokiaVTODOLong
:
457 error
=GSM_EncodeVTODO(Buffer
,&Length
,Info
->Entries
[0].ToDo
,true,Nokia_VToDo
);
458 if (error
!= GE_NONE
) return error
;
459 UDH
= UDH_NokiaCalendarLong
;
460 Coding
= GSM_Coding_Default
;
461 memcpy(Buffer2
,Buffer
,Length
);
462 EncodeUnicode(Buffer
,Buffer2
,Length
);
464 case SMS_DisableVoice
:
466 case SMS_DisableEmail
:
467 case SMS_EnableVoice
:
469 case SMS_EnableEmail
:
473 switch (Info
->Entries
[0].ID
) {
474 case SMS_DisableVoice
: UDH
= UDH_DisableVoice
; break;
475 case SMS_DisableFax
: UDH
= UDH_DisableFax
; break;
476 case SMS_DisableEmail
: UDH
= UDH_DisableEmail
; break;
477 case SMS_EnableVoice
: UDH
= UDH_EnableVoice
; break;
478 case SMS_EnableFax
: UDH
= UDH_EnableFax
; break;
479 case SMS_EnableEmail
: UDH
= UDH_EnableEmail
; break;
480 case SMS_VoidSMS
: UDH
= UDH_VoidSMS
; break;
481 case SMS_Text
: UDH
= UDH_NoUDH
; break;
484 UDHHeader
.Type
= UDH
;
485 GSM_EncodeUDHHeader(&UDHHeader
);
486 memcpy(Buffer
,Info
->Entries
[0].Buffer
,UnicodeLength(Info
->Entries
[0].Buffer
)*2+2);
487 if (Info
->UnicodeCoding
) {
488 Coding
= GSM_Coding_Unicode
;
489 Length
= UnicodeLength(Info
->Entries
[0].Buffer
);
490 if (Length
>(140-UDHHeader
.Length
)/2) Length
= (140-UDHHeader
.Length
)/2;
492 Coding
= GSM_Coding_Default
;
493 FindDefaultAlphabetLen(Info
->Entries
[0].Buffer
,&Length
,&smslen
,(GSM_MAX_8BIT_SMS_LENGTH
-UDHHeader
.Length
)*8/7);
496 case SMS_ConcatenatedAutoTextLong
:
497 case SMS_ConcatenatedAutoTextLong16bit
:
498 smslen
= UnicodeLength(Info
->Entries
[0].Buffer
);
499 memcpy(Buffer
,Info
->Entries
[0].Buffer
,smslen
*2);
500 EncodeDefault(Buffer2
, Buffer
, &smslen
, true, NULL
);
501 DecodeDefault(Buffer
, Buffer2
, smslen
, true, NULL
);
503 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) {
504 dbgprintf("Info->Entries[0].Buffer:\n");
505 DumpMessage(di
.df
, Info
->Entries
[0].Buffer
, UnicodeLength(Info
->Entries
[0].Buffer
)*2);
506 dbgprintf("Buffer:\n");
507 DumpMessage(di
.df
, Buffer
, UnicodeLength(Buffer
)*2);
510 Info
->UnicodeCoding
= false;
511 for (smslen
=0;smslen
<(int)(UnicodeLength(Info
->Entries
[0].Buffer
)*2);smslen
++) {
512 if (Info
->Entries
[0].Buffer
[smslen
] != Buffer
[smslen
]) {
513 Info
->UnicodeCoding
= true;
514 dbgprintf("Setting to Unicode %i\n",smslen
);
518 /* No break here - we go to the SMS_ConcatenatedTextLong */
519 case SMS_ConcatenatedTextLong
:
520 case SMS_ConcatenatedTextLong16bit
:
522 memcpy(Buffer
,Info
->Entries
[0].Buffer
,UnicodeLength(Info
->Entries
[0].Buffer
)*2+2);
524 if (Info
->UnicodeCoding
) {
525 Coding
= GSM_Coding_Unicode
;
526 Length
= UnicodeLength(Info
->Entries
[0].Buffer
);
527 if (Info
->Entries
[0].ID
== SMS_ConcatenatedTextLong16bit
||
528 Info
->Entries
[0].ID
== SMS_ConcatenatedAutoTextLong16bit
) {
529 if (Length
>70) UDH
=UDH_ConcatenatedMessages16bit
;
531 if (Length
>70) UDH
=UDH_ConcatenatedMessages
;
534 Coding
= GSM_Coding_Default
;
535 FindDefaultAlphabetLen(Info
->Entries
[0].Buffer
,&Length
,&smslen
,5000);
536 if (Info
->Entries
[0].ID
== SMS_ConcatenatedTextLong16bit
||
537 Info
->Entries
[0].ID
== SMS_ConcatenatedAutoTextLong16bit
) {
538 if (smslen
>GSM_MAX_SMS_LENGTH
) UDH
=UDH_ConcatenatedMessages16bit
;
540 if (smslen
>GSM_MAX_SMS_LENGTH
) UDH
=UDH_ConcatenatedMessages
;
546 GSM_MakeMultiPartSMS(SMS
,Buffer
,Length
,UDH
,Coding
,Class
,Info
->ReplaceMessage
);
550 void GSM_ClearMultiPartSMSInfo(GSM_EncodeMultiPartSMSInfo
*Info
)
554 for (i
=0;i
<MAX_MULTI_SMS
;i
++) {
555 Info
->Entries
[i
].Buffer
= NULL
;
556 Info
->Entries
[i
].Ringtone
= NULL
;
557 Info
->Entries
[i
].Bitmap
= NULL
;
558 Info
->Entries
[i
].Phonebook
= NULL
;
559 Info
->Entries
[i
].Bookmark
= NULL
;
560 Info
->Entries
[i
].Settings
= NULL
;
561 Info
->Entries
[i
].Calendar
= NULL
;
562 Info
->Entries
[i
].ToDo
= NULL
;
563 Info
->Entries
[i
].MMSIndicator
= NULL
;
564 Info
->Entries
[i
].Left
= false;
565 Info
->Entries
[i
].Right
= false;
566 Info
->Entries
[i
].Center
= false;
567 Info
->Entries
[i
].Large
= false;
568 Info
->Entries
[i
].Small
= false;
569 Info
->Entries
[i
].Bold
= false;
570 Info
->Entries
[i
].Italic
= false;
571 Info
->Entries
[i
].Underlined
= false;
572 Info
->Entries
[i
].Strikethrough
= false;
574 Info
->Entries
[i
].Protected
= false;
576 Info
->Unknown
= false;
579 /* ----------------- Joining SMS from parts -------------------------------- */
581 bool GSM_DecodeMultiPartSMS(GSM_EncodeMultiPartSMSInfo
*Info
,
582 GSM_MultiSMSMessage
*SMS
,
586 char Buffer
[GSM_MAX_SMS_LENGTH
*2*MAX_MULTI_SMS
];
587 bool emsexist
= false;
589 Info
->EntriesNum
= 0;
592 for (i
=0;i
<SMS
->Number
;i
++) {
593 if (SMS
->SMS
[i
].UDH
.Type
!= UDH_ConcatenatedMessages
&&
594 SMS
->SMS
[i
].UDH
.Type
!= UDH_ConcatenatedMessages16bit
&&
595 SMS
->SMS
[i
].UDH
.Type
!= UDH_UserUDH
) {
603 if (emsexist
) return GSM_DecodeEMSMultiPartSMS(Info
,SMS
);
605 /* Smart Messaging decoding */
606 if (SMS
->SMS
[0].UDH
.Type
== UDH_NokiaRingtone
&& SMS
->Number
== 1) {
607 if (GSM_DecodeNokiaRTTLRingtone(Info
->Entries
[0].Ringtone
, SMS
->SMS
[0].Text
, SMS
->SMS
[0].Length
)==GE_NONE
) {
608 Info
->Entries
[0].ID
= SMS_NokiaRingtone
;
609 Info
->EntriesNum
= 1;
613 if (SMS
->SMS
[0].UDH
.Type
== UDH_NokiaCallerLogo
&& SMS
->Number
== 1) {
614 PHONE_DecodeBitmap(GSM_NokiaCallerLogo
, SMS
->SMS
[0].Text
+4, &Info
->Entries
[0].Bitmap
->Bitmap
[0]);
616 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Info
->Entries
[0].Bitmap
->Bitmap
[0]);
618 Info
->Entries
[0].ID
= SMS_NokiaCallerLogo
;
619 Info
->EntriesNum
= 1;
622 if (SMS
->SMS
[0].UDH
.Type
== UDH_NokiaOperatorLogo
&& SMS
->Number
== 1) {
623 PHONE_DecodeBitmap(GSM_NokiaOperatorLogo
, SMS
->SMS
[0].Text
+7, &Info
->Entries
[0].Bitmap
->Bitmap
[0]);
624 NOKIA_DecodeNetworkCode(SMS
->SMS
[0].Text
, Info
->Entries
[0].Bitmap
->Bitmap
[0].NetworkCode
);
626 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Info
->Entries
[0].Bitmap
->Bitmap
[0]);
628 Info
->Entries
[0].ID
= SMS_NokiaOperatorLogo
;
629 Info
->EntriesNum
= 1;
632 if (SMS
->SMS
[0].UDH
.Type
== UDH_NokiaProfileLong
) {
633 for (i
=0;i
<SMS
->Number
;i
++) {
634 if (SMS
->SMS
[i
].UDH
.Type
!= UDH_NokiaProfileLong
||
635 SMS
->SMS
[i
].UDH
.Text
[11] != i
+1 ||
636 SMS
->SMS
[i
].UDH
.Text
[10] != SMS
->Number
) {
639 memcpy(Buffer
+Length
,SMS
->SMS
[i
].Text
,SMS
->SMS
[i
].Length
);
640 Length
= Length
+ SMS
->SMS
[i
].Length
;
642 Info
->EntriesNum
= 1;
643 Info
->Entries
[0].ID
= SMS_NokiaPictureImageLong
;
644 Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[0] = 0;
645 Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[1] = 0;
650 dbgprintf("ISO 8859-2 text\n");
651 Info
->Unknown
= true;
653 case SM30_UNICODETEXT
:
654 dbgprintf("Unicode text\n");
655 memcpy(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
,Buffer
+i
+3,Buffer
[i
+1]*256+Buffer
[i
+2]);
656 Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[Buffer
[i
+1]*256 + Buffer
[i
+2]] = 0;
657 Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
[Buffer
[i
+1]*256 + Buffer
[i
+2]+ 1] = 0;
658 dbgprintf("Unicode Text \"%s\"\n",DecodeUnicodeString(Info
->Entries
[0].Bitmap
->Bitmap
[0].Text
));
661 dbgprintf("OTA bitmap as Picture Image\n");
662 PHONE_DecodeBitmap(GSM_NokiaPictureImage
, Buffer
+ i
+ 7, &Info
->Entries
[0].Bitmap
->Bitmap
[0]);
664 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Info
->Entries
[0].Bitmap
->Bitmap
[0]);
668 dbgprintf("RTTL ringtone\n");
669 Info
->Unknown
= true;
671 case SM30_PROFILENAME
:
672 dbgprintf("Profile Name\n");
673 Info
->Entries
[0].ID
= SMS_NokiaProfileLong
;
674 Info
->Unknown
= true;
676 case SM30_SCREENSAVER
:
677 dbgprintf("OTA bitmap as Screen Saver\n");
678 PHONE_DecodeBitmap(GSM_NokiaPictureImage
, Buffer
+ i
+ 7, &Info
->Entries
[0].Bitmap
->Bitmap
[0]);
680 if (di
.dl
== DL_TEXTALL
|| di
.dl
== DL_TEXTALLDATE
) GSM_PrintBitmap(di
.df
,&Info
->Entries
[0].Bitmap
->Bitmap
[0]);
682 Info
->Entries
[0].ID
= SMS_NokiaScreenSaverLong
;
685 i
= i
+ Buffer
[i
+1]*256 + Buffer
[i
+2] + 3;
686 dbgprintf("%i %i\n",i
,Length
);
692 if (SMS
->SMS
[0].UDH
.Type
== UDH_ConcatenatedMessages
||
693 SMS
->SMS
[0].UDH
.Type
== UDH_ConcatenatedMessages16bit
) {
694 Info
->EntriesNum
= 1;
695 Info
->Entries
[0].ID
= SMS_ConcatenatedTextLong
;
696 if (SMS
->SMS
[0].UDH
.Type
== UDH_ConcatenatedMessages16bit
) {
697 Info
->Entries
[0].ID
= SMS_ConcatenatedTextLong16bit
;
700 for (i
=0;i
<SMS
->Number
;i
++) {
701 switch (SMS
->SMS
[i
].Coding
) {
702 case GSM_Coding_8bit
:
703 memcpy(Info
->Entries
[0].Buffer
+Length
,SMS
->SMS
[i
].Text
,SMS
->SMS
[i
].Length
);
704 Length
=Length
+SMS
->SMS
[i
].Length
;
706 case GSM_Coding_Unicode
:
707 if (Info
->Entries
[0].ID
== SMS_ConcatenatedTextLong
) {
708 Info
->Entries
[0].ID
= SMS_ConcatenatedAutoTextLong
;
710 if (Info
->Entries
[0].ID
== SMS_ConcatenatedTextLong16bit
) {
711 Info
->Entries
[0].ID
= SMS_ConcatenatedAutoTextLong16bit
;
713 case GSM_Coding_Default
:
714 memcpy(Info
->Entries
[0].Buffer
+Length
,SMS
->SMS
[i
].Text
,UnicodeLength(SMS
->SMS
[i
].Text
)*2);
715 Length
=Length
+UnicodeLength(SMS
->SMS
[i
].Text
)*2;
719 Info
->Entries
[0].Buffer
[Length
] = 0;
720 Info
->Entries
[0].Buffer
[Length
+1] = 0;
727 GSM_Error
GSM_LinkSMS(GSM_MultiSMSMessage
*INPUT
[150], GSM_MultiSMSMessage
*OUTPUT
[150], bool ems
)
729 bool INPUTSorted
[150],copyit
;
730 int i
,OUTPUTNum
,j
,z
,w
;
732 for (i
=0;i
<150;i
++) INPUTSorted
[i
] = false;
739 while (INPUT
[i
] != NULL
) {
740 if (INPUT
[i
]->SMS
[0].UDH
.Type
== UDH_UserUDH
) {
743 if (w
>= INPUT
[i
]->SMS
[0].UDH
.Length
) break;
744 switch(INPUT
[i
]->SMS
[0].UDH
.Text
[w
]) {
746 dbgprintf("Adding ID to user UDH - linked SMS with 8 bit ID\n");
747 INPUT
[i
]->SMS
[0].UDH
.ID8bit
= INPUT
[i
]->SMS
[0].UDH
.Text
[w
+2];
748 INPUT
[i
]->SMS
[0].UDH
.AllParts
= INPUT
[i
]->SMS
[0].UDH
.Text
[w
+3];
749 INPUT
[i
]->SMS
[0].UDH
.PartNumber
= INPUT
[i
]->SMS
[0].UDH
.Text
[w
+4];
752 dbgprintf("Adding ID to user UDH - linked SMS with 16 bit ID\n");
753 INPUT
[i
]->SMS
[0].UDH
.ID16bit
= INPUT
[i
]->SMS
[0].UDH
.Text
[w
+2]*256+INPUT
[i
]->SMS
[0].UDH
.Text
[w
+3];
754 INPUT
[i
]->SMS
[0].UDH
.AllParts
= INPUT
[i
]->SMS
[0].UDH
.Text
[w
+4];
755 INPUT
[i
]->SMS
[0].UDH
.PartNumber
= INPUT
[i
]->SMS
[0].UDH
.Text
[w
+5];
758 dbgprintf("Block %02x\n",INPUT
[i
]->SMS
[0].UDH
.Text
[w
]);
760 dbgprintf("%i %i %i %i\n",
761 INPUT
[i
]->SMS
[0].UDH
.ID8bit
,
762 INPUT
[i
]->SMS
[0].UDH
.ID16bit
,
763 INPUT
[i
]->SMS
[0].UDH
.PartNumber
,
764 INPUT
[i
]->SMS
[0].UDH
.AllParts
);
765 w
=w
+INPUT
[i
]->SMS
[0].UDH
.Text
[w
+1]+2;
773 while (INPUT
[i
]!=NULL
) {
774 /* If this one SMS was sorted earlier, do not touch */
775 if (INPUTSorted
[i
]) {
781 * - linked sms returned by phone driver
782 * - sms without linking
783 * we copy it to OUTPUT
785 if (INPUT
[i
]->Number
!= 1 ||
786 INPUT
[i
]->SMS
[0].UDH
.Type
== UDH_NoUDH
||
787 INPUT
[i
]->SMS
[0].UDH
.PartNumber
== -1) {
790 /* If we have unknown UDH, we copy it to OUTPUT */
791 if (INPUT
[i
]->SMS
[0].UDH
.Type
== UDH_UserUDH
) {
792 if (!ems
) copyit
= true;
793 if (ems
&& INPUT
[i
]->SMS
[0].UDH
.PartNumber
== -1) copyit
= true;
796 OUTPUT
[OUTPUTNum
] = malloc(sizeof(GSM_MultiSMSMessage
));
797 if (OUTPUT
[OUTPUTNum
] == NULL
) return GE_MOREMEMORY
;
798 OUTPUT
[OUTPUTNum
+1] = NULL
;
800 memcpy(OUTPUT
[OUTPUTNum
],INPUT
[i
],sizeof(GSM_MultiSMSMessage
));
806 /* We have 1'st part of linked sms. It's single.
807 * We will try to find other parts
809 if (INPUT
[i
]->SMS
[0].UDH
.PartNumber
== 1) {
810 OUTPUT
[OUTPUTNum
] = malloc(sizeof(GSM_MultiSMSMessage
));
811 if (OUTPUT
[OUTPUTNum
] == NULL
) return GE_MOREMEMORY
;
812 OUTPUT
[OUTPUTNum
+1] = NULL
;
814 memcpy(&OUTPUT
[OUTPUTNum
]->SMS
[0],&INPUT
[i
]->SMS
[0],sizeof(GSM_SMSMessage
));
815 OUTPUT
[OUTPUTNum
]->Number
= 1;
816 INPUTSorted
[i
] = true;
818 /* We're searching for other parts in sequence */
819 while (j
!=INPUT
[i
]->SMS
[0].UDH
.AllParts
) {
821 while(INPUT
[z
]!=NULL
) {
822 /* This was sorted earlier or is not single */
823 if (INPUTSorted
[z
] || INPUT
[z
]->Number
!= 1) {
827 if (ems
&& INPUT
[i
]->SMS
[0].UDH
.Type
!= UDH_ConcatenatedMessages
&&
828 INPUT
[i
]->SMS
[0].UDH
.Type
!= UDH_ConcatenatedMessages16bit
&&
829 INPUT
[i
]->SMS
[0].UDH
.Type
!= UDH_UserUDH
&&
830 INPUT
[z
]->SMS
[0].UDH
.Type
!= UDH_ConcatenatedMessages
&&
831 INPUT
[z
]->SMS
[0].UDH
.Type
!= UDH_ConcatenatedMessages16bit
&&
832 INPUT
[z
]->SMS
[0].UDH
.Type
!= UDH_UserUDH
) {
833 if (INPUT
[z
]->SMS
[0].UDH
.Type
!= INPUT
[i
]->SMS
[0].UDH
.Type
) {
838 if (!ems
&& INPUT
[z
]->SMS
[0].UDH
.Type
!= INPUT
[i
]->SMS
[0].UDH
.Type
) {
842 dbgprintf("compare %i %i %i %i %i",
844 INPUT
[i
]->SMS
[0].UDH
.ID8bit
,
845 INPUT
[i
]->SMS
[0].UDH
.ID16bit
,
846 INPUT
[i
]->SMS
[0].UDH
.PartNumber
,
847 INPUT
[i
]->SMS
[0].UDH
.AllParts
);
848 dbgprintf(" %i %i %i %i\n",
849 INPUT
[z
]->SMS
[0].UDH
.ID8bit
,
850 INPUT
[z
]->SMS
[0].UDH
.ID16bit
,
851 INPUT
[z
]->SMS
[0].UDH
.PartNumber
,
852 INPUT
[z
]->SMS
[0].UDH
.AllParts
);
853 if (INPUT
[z
]->SMS
[0].UDH
.ID8bit
!= INPUT
[i
]->SMS
[0].UDH
.ID8bit
||
854 INPUT
[z
]->SMS
[0].UDH
.ID16bit
!= INPUT
[i
]->SMS
[0].UDH
.ID16bit
||
855 INPUT
[z
]->SMS
[0].UDH
.AllParts
!= INPUT
[i
]->SMS
[0].UDH
.AllParts
||
856 INPUT
[z
]->SMS
[0].UDH
.PartNumber
!= j
+1) {
860 /* For SMS_Deliver compare also SMSC and Sender number */
861 if (INPUT
[z
]->SMS
[0].PDU
== SMS_Deliver
&&
862 (strcmp(DecodeUnicodeString(INPUT
[z
]->SMS
[0].SMSC
.Number
),DecodeUnicodeString(INPUT
[i
]->SMS
[0].SMSC
.Number
)) ||
863 strcmp(DecodeUnicodeString(INPUT
[z
]->SMS
[0].Number
),DecodeUnicodeString(INPUT
[i
]->SMS
[0].Number
)))) {
867 /* DCT4 Outbox: SMS Deliver. Empty number and SMSC. We compare dates */
868 if (INPUT
[z
]->SMS
[0].PDU
== SMS_Deliver
&&
869 UnicodeLength(INPUT
[z
]->SMS
[0].SMSC
.Number
)==0 &&
870 UnicodeLength(INPUT
[z
]->SMS
[0].Number
)==0 &&
871 (INPUT
[z
]->SMS
[0].DateTime
.Day
!= INPUT
[i
]->SMS
[0].DateTime
.Day
||
872 INPUT
[z
]->SMS
[0].DateTime
.Month
!= INPUT
[i
]->SMS
[0].DateTime
.Month
||
873 INPUT
[z
]->SMS
[0].DateTime
.Year
!= INPUT
[i
]->SMS
[0].DateTime
.Year
||
874 INPUT
[z
]->SMS
[0].DateTime
.Hour
!= INPUT
[i
]->SMS
[0].DateTime
.Hour
||
875 INPUT
[z
]->SMS
[0].DateTime
.Minute
!= INPUT
[i
]->SMS
[0].DateTime
.Minute
||
876 INPUT
[z
]->SMS
[0].DateTime
.Second
!= INPUT
[i
]->SMS
[0].DateTime
.Second
)) {
880 /* We found correct sms. Copy it */
881 memcpy(&OUTPUT
[OUTPUTNum
]->SMS
[j
],&INPUT
[z
]->SMS
[0],sizeof(GSM_SMSMessage
));
882 OUTPUT
[OUTPUTNum
]->Number
++;
886 /* Incomplete sequence */
887 if (OUTPUT
[OUTPUTNum
]->Number
==j
) {
888 dbgprintf("Incomplete sequence\n");
897 /* We have some next linked sms from sequence */
898 if (INPUT
[i
]->SMS
[0].UDH
.PartNumber
> 1) {
900 while (INPUT
[j
]!=NULL
) {
901 if (INPUTSorted
[j
]) {
905 /* We have some not unassigned first sms from sequence.
906 * We can't touch other sms from sequences
908 if (INPUT
[j
]->SMS
[0].UDH
.PartNumber
== 1) break;
911 if (INPUT
[j
]==NULL
) {
912 OUTPUT
[OUTPUTNum
] = malloc(sizeof(GSM_MultiSMSMessage
));
913 if (OUTPUT
[OUTPUTNum
] == NULL
) return GE_MOREMEMORY
;
914 OUTPUT
[OUTPUTNum
+1] = NULL
;
916 memcpy(OUTPUT
[OUTPUTNum
],INPUT
[i
],sizeof(GSM_MultiSMSMessage
));
927 /* How should editor hadle tabs in this file? Add editor commands here.
928 * vim: noexpandtab sw=8 ts=8 sts=8: