Gammu internals  1.38.0
gsmmulti.c File Reference
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <gammu-unicode.h>
#include <gammu-debug.h>
#include "gsmmulti.h"
#include "../gsmring.h"
#include "../gsmlogo.h"
#include "../../misc/coding/coding.h"
#include "../../debug.h"
#include "gsmems.h"
#include "../gsmdata.h"
#include "../gsmnet.h"
Include dependency graph for gsmmulti.c:

Go to the source code of this file.

Functions

unsigned char GSM_MakeSMSIDFromTime (void)
 
void GSM_Find_Free_Used_SMS2 (GSM_Debug_Info *di, GSM_Coding_Type Coding, GSM_SMSMessage *SMS, size_t *UsedText, size_t *FreeText, size_t *FreeBytes)
 
unsigned int ReassembleCharacter (char *Buffer, size_t character_index)
 
int AlignIfSurrogatePair (GSM_Debug_Info *di, size_t *Copy, char *Buffer, size_t BufferLen)
 
int AlignIfCombinedCharacter (GSM_Debug_Info *di, size_t *Copy, char *Buffer, size_t BufferLen)
 
int AlignIfCombinedSurrogate (GSM_Debug_Info *di, size_t *Copy, char *Buffer, size_t BufferLen)
 
int AlignSegmentForContent (GSM_Debug_Info *di, size_t *Copy, char *Buffer, size_t BufferLen)
 
GSM_Error GSM_AddSMS_Text_UDH (GSM_Debug_Info *di, GSM_MultiSMSMessage *SMS, GSM_Coding_Type Coding, char *Buffer, size_t BufferLen, gboolean UDH, size_t *UsedText, size_t *CopiedText, size_t *CopiedSMSText)
 
void GSM_MakeMultiPartSMS (GSM_Debug_Info *di, GSM_MultiSMSMessage *SMS, unsigned char *MessageBuffer, size_t MessageLength, GSM_UDH UDHType, GSM_Coding_Type Coding, int Class, unsigned char ReplaceMessage)
 
void GSM_SMSCounter (GSM_Debug_Info *di, unsigned char *MessageBuffer, GSM_UDH UDHType, GSM_Coding_Type Coding, int *SMSNum, size_t *CharsLeft)
 
static void GSM_EncodeSMS30MultiPartSMS (GSM_MultiPartSMSInfo *Info, char *Buffer, size_t *Length)
 
GSM_Error GSM_EncodeAlcatelMultiPartSMS (GSM_Debug_Info *di, GSM_MultiSMSMessage *SMS, unsigned char *Data, size_t Len, unsigned char *Name, size_t Type)
 
GSM_Error GSM_EncodeMultiPartSMS (GSM_Debug_Info *di, GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS)
 
void GSM_ClearMultiPartSMSInfo (GSM_MultiPartSMSInfo *Info)
 
void GSM_FreeMultiPartSMSInfo (GSM_MultiPartSMSInfo *Info)
 
gboolean GSM_DecodeMMSIndication (GSM_Debug_Info *di, GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS)
 
gboolean GSM_DecodeNokiaProfile (GSM_Debug_Info *di, GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS)
 
gboolean GSM_DecodeLinkedText (GSM_Debug_Info *di, GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS)
 
gboolean GSM_DecodeMultiPartSMS (GSM_Debug_Info *di, GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS, gboolean ems)
 
GSM_Error GSM_LinkSMS (GSM_Debug_Info *di, GSM_MultiSMSMessage **InputMessages, GSM_MultiSMSMessage **OutputMessages, gboolean ems)
 

Function Documentation

§ AlignIfCombinedCharacter()

int AlignIfCombinedCharacter ( GSM_Debug_Info di,
size_t *  Copy,
char *  Buffer,
size_t  BufferLen 
)

Definition at line 115 of file gsmmulti.c.

References ReassembleCharacter().

Referenced by AlignSegmentForContent().

119 {
120  int rv = 0;
121  unsigned int n;
122 
123  /* Precondition:
124  * If we only have one character to copy, or if there isn't any
125  * code unit following our copy window, don't change anything. */
126 
127  if (*Copy <= 1 || *Copy >= BufferLen) {
128  return rv;
129  }
130 
131  /* Don't split up a combining sequence:
132  * Peek at the next message segment to see if it begins with
133  * a combining character (e.g. a discritical mark). If it does,
134  * push the final character of this message segment in to the
135  * next message segment. This ensures that the recipient can
136  * visually combine the sequence, even if reassembly fails. */
137 
138  n = ReassembleCharacter(Buffer, *Copy);
139 
140  /* Unicode combining characters:
141  * Combining Half Marks (U+FE20 - U+FE2F)
142  * Combining Diacritical Marks (U+300 - U+36F)
143  * Combining Diacritical Marks Extended (U+1AB0 - U+1AFF)
144  * Combining Diacritical Marks Supplement (U+1DC0 - U+1DFF)
145  * Combining Diacritical Marks for Symbols (U+20D0 - U+20FF) */
146 
147  if ((n >= 0xfe20 && n <= 0xfe2f) ||
148  (n >= 0x300 && n <= 0x36f) || (n >= 0x1ab0 && n <= 0x1aff) ||
149  (n >= 0x1dc0 && n <= 0x1dff) || (n >= 0x20d0 && n <= 0x20ff)) {
150  *Copy -= 1;
151  ++rv;
152  }
153 
154  return rv;
155 }
unsigned int ReassembleCharacter(char *Buffer, size_t character_index)
Definition: gsmmulti.c:71

§ AlignIfCombinedSurrogate()

int AlignIfCombinedSurrogate ( GSM_Debug_Info di,
size_t *  Copy,
char *  Buffer,
size_t  BufferLen 
)

Definition at line 157 of file gsmmulti.c.

References ReassembleCharacter().

Referenced by AlignSegmentForContent().

161 {
162  int rv = 0;
163  unsigned int l1, l2, r1, r2;
164 
165  /* Precondition:
166  * If we have two or fewer characters to copy, omitting two
167  * of them would cause us to send empty message segments. If
168  * there aren't at least two characters remaining *after* the
169  * copy boundary, then there can't possibly be space for a
170  * second surrogate pair there. In either case, send as-is. */
171 
172  if (*Copy <= 2 || (*Copy + 2) >= BufferLen) {
173  return rv;
174  }
175 
176  /* Fetch characters:
177  * We retrieve two UTF-16 characters directly preceeding the
178  * copy boundary, and two directly following the copy boundary. */
179 
180  l1 = ReassembleCharacter(Buffer, *Copy - 2);
181  l2 = ReassembleCharacter(Buffer, *Copy - 1);
182  r1 = ReassembleCharacter(Buffer, *Copy);
183  r2 = ReassembleCharacter(Buffer, *Copy + 1);
184 
185  /* Regional Indicator Symbol (U+1F1E6 - U+1F1FF)
186  * UTF-16 surrogate pairs: 0xd83c 0xdde6 - 0xd83c 0xddff */
187 
188  if (l1 == 0xd83c && r1 == 0xd83c &&
189  l2 >= 0xdde6 && l2 <= 0xddff && r2 >= 0xdde6 && r2 <= 0xddff) {
190  *Copy -= 2;
191  rv += 2;
192  }
193 
194  return rv;
195 }
unsigned int ReassembleCharacter(char *Buffer, size_t character_index)
Definition: gsmmulti.c:71

§ AlignIfSurrogatePair()

int AlignIfSurrogatePair ( GSM_Debug_Info di,
size_t *  Copy,
char *  Buffer,
size_t  BufferLen 
)

Definition at line 81 of file gsmmulti.c.

References ReassembleCharacter().

Referenced by AlignSegmentForContent().

85 {
86  int rv = 0;
87  unsigned int n;
88 
89  /* Precondition:
90  * Resulting copy must always be non-zero. */
91 
92  if (*Copy <= 1) {
93  return rv;
94  }
95 
96  /* Don't split a UTF-16 surrogate pair:
97  * If the final code unit to be copied is a lead surrogate, save
98  * it for the next message segment. This allows recipients to view
99  * the proper four-byte UTF-16 character even if they're unable to
100  * reassemble the message (e.g. if a telecom strips off the UDH). */
101 
102  n = ReassembleCharacter(Buffer, *Copy - 1);
103 
104  /* UTF-16 leading surrogate:
105  * First character in pair is always between U+D800 and U+DBFF */
106 
107  if (n >= 0xd800 && n <= 0xdbff) {
108  *Copy -= 1;
109  ++rv;
110  }
111 
112  return rv;
113 }
unsigned int ReassembleCharacter(char *Buffer, size_t character_index)
Definition: gsmmulti.c:71

§ AlignSegmentForContent()

int AlignSegmentForContent ( GSM_Debug_Info di,
size_t *  Copy,
char *  Buffer,
size_t  BufferLen 
)

Definition at line 197 of file gsmmulti.c.

References AlignIfCombinedCharacter(), AlignIfCombinedSurrogate(), and AlignIfSurrogatePair().

Referenced by GSM_AddSMS_Text_UDH().

201 {
202  int rv = 0;
203 
204  if (!(rv += AlignIfSurrogatePair(di, Copy, Buffer, BufferLen))) {
205  rv += AlignIfCombinedCharacter(di, Copy, Buffer, BufferLen);
206  }
207 
208  rv += AlignIfCombinedSurrogate(di, Copy, Buffer, BufferLen);
209  return rv;
210 }
int AlignIfCombinedSurrogate(GSM_Debug_Info *di, size_t *Copy, char *Buffer, size_t BufferLen)
Definition: gsmmulti.c:157
int AlignIfCombinedCharacter(GSM_Debug_Info *di, size_t *Copy, char *Buffer, size_t BufferLen)
Definition: gsmmulti.c:115
int AlignIfSurrogatePair(GSM_Debug_Info *di, size_t *Copy, char *Buffer, size_t BufferLen)
Definition: gsmmulti.c:81

§ GSM_AddSMS_Text_UDH()

GSM_Error GSM_AddSMS_Text_UDH ( GSM_Debug_Info di,
GSM_MultiSMSMessage SMS,
GSM_Coding_Type  Coding,
char *  Buffer,
size_t  BufferLen,
gboolean  UDH,
size_t *  UsedText,
size_t *  CopiedText,
size_t *  CopiedSMSText 
)

Definition at line 212 of file gsmmulti.c.

References AlignSegmentForContent(), ERR_NONE, FindDefaultAlphabetLen(), GSM_Find_Free_Used_SMS2(), GSM_UDHHeader::Length, GSM_SMSMessage::Length, GSM_MultiSMSMessage::Number, smfprintf(), GSM_MultiSMSMessage::SMS, SMS_Coding_8bit, SMS_Coding_Default_No_Compression, SMS_Coding_Unicode_No_Compression, GSM_UDHHeader::Text, GSM_SMSMessage::Text, GSM_UDHHeader::Type, GSM_SMSMessage::UDH, UDH_UserUDH, and UnicodeLength().

Referenced by GSM_EncodeEMSMultiPartSMS(), and GSM_MakeMultiPartSMS().

221 {
222  size_t FreeText=0,FreeBytes=0,Copy,i,j;
223 
224  smfprintf(di, "Checking used: ");
226  di, Coding, &(SMS->SMS[SMS->Number]),
227  UsedText, &FreeText, &FreeBytes
228  );
229 
230  if (UDH) {
231  smfprintf(di, "Adding UDH\n");
232  if (FreeBytes - BufferLen <= 0) {
233  smfprintf(di, "Going to the new SMS\n");
234  SMS->Number++;
236  di, Coding, &(SMS->SMS[SMS->Number]),
237  UsedText, &FreeText, &FreeBytes
238  );
239  }
240  if (SMS->SMS[SMS->Number].UDH.Length == 0) {
241  SMS->SMS[SMS->Number].UDH.Length = 1;
242  SMS->SMS[SMS->Number].UDH.Text[0] = 0x00;
243  }
244  memcpy(SMS->SMS[SMS->Number].UDH.Text+SMS->SMS[SMS->Number].UDH.Length,Buffer,BufferLen);
245  SMS->SMS[SMS->Number].UDH.Length += BufferLen;
246  SMS->SMS[SMS->Number].UDH.Text[0] += BufferLen;
247  SMS->SMS[SMS->Number].UDH.Type = UDH_UserUDH;
248  smfprintf(di, "UDH added %ld\n", (long)BufferLen);
249  } else {
250  smfprintf(di, "Adding text\n");
251  if (FreeText == 0) {
252  smfprintf(di, "Going to the new SMS\n");
253  SMS->Number++;
255  di, Coding, &(SMS->SMS[SMS->Number]),
256  UsedText, &FreeText, &FreeBytes
257  );
258  }
259 
260  Copy = FreeText;
261  smfprintf(di, "Copy %ld (max %ld)\n", (long)Copy, (long)BufferLen);
262  if (BufferLen < Copy) {
263  Copy = BufferLen;
264  }
265 
266  switch (Coding) {
268  FindDefaultAlphabetLen(Buffer,&i,&j,FreeText);
269  smfprintf(di, "Defalt text, length %ld %ld\n", (long)i, (long)j);
270  SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+i*2] = 0;
271  SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+i*2+1] = 0;
272  memcpy(SMS->SMS[SMS->Number].Text+UnicodeLength(SMS->SMS[SMS->Number].Text)*2,Buffer,i*2);
273  *CopiedText = i;
274  *CopiedSMSText = j;
275  SMS->SMS[SMS->Number].Length += i;
276  break;
278  AlignSegmentForContent(di, &Copy, Buffer, BufferLen);
279  SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+Copy*2] = 0;
280  SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+Copy*2+1] = 0;
281  memcpy(SMS->SMS[SMS->Number].Text+UnicodeLength(SMS->SMS[SMS->Number].Text)*2,Buffer,Copy*2);
282  *CopiedText = *CopiedSMSText = Copy;
283  SMS->SMS[SMS->Number].Length += Copy;
284  break;
285  case SMS_Coding_8bit:
286  memcpy(SMS->SMS[SMS->Number].Text+SMS->SMS[SMS->Number].Length,Buffer,Copy);
287  SMS->SMS[SMS->Number].Length += Copy;
288  *CopiedText = *CopiedSMSText = Copy;
289  break;
290  default:
291  break;
292  }
293  smfprintf(di, "Text added\n");
294  }
295 
296  smfprintf(di, "Checking at the end: ");
298  di, Coding, &(SMS->SMS[SMS->Number]),
299  UsedText, &FreeText, &FreeBytes
300  );
301 
302  return ERR_NONE;
303 }
unsigned char Text[(GSM_MAX_SMS_LENGTH+1) *2]
void FindDefaultAlphabetLen(const unsigned char *src, size_t *srclen, size_t *smslen, size_t maxlen)
Definition: coding.c:914
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
GSM_UDHHeader UDH
int AlignSegmentForContent(GSM_Debug_Info *di, size_t *Copy, char *Buffer, size_t BufferLen)
Definition: gsmmulti.c:197
void GSM_Find_Free_Used_SMS2(GSM_Debug_Info *di, GSM_Coding_Type Coding, GSM_SMSMessage *SMS, size_t *UsedText, size_t *FreeText, size_t *FreeBytes)
Definition: gsmmulti.c:37
unsigned char Text[GSM_MAX_UDH_LENGTH]
GSM_SMSMessage SMS[GSM_MAX_MULTI_SMS]
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240

§ GSM_DecodeLinkedText()

gboolean GSM_DecodeLinkedText ( GSM_Debug_Info di,
GSM_MultiPartSMSInfo Info,
GSM_MultiSMSMessage SMS 
)

Decodes long linked text SMS.

Definition at line 1229 of file gsmmulti.c.

References GSM_MultiPartSMSEntry::Buffer, GSM_SMSMessage::Coding, GSM_MultiPartSMSInfo::Entries, GSM_MultiPartSMSInfo::EntriesNum, FALSE, GSM_MultiPartSMSEntry::ID, GSM_SMSMessage::Length, GSM_MultiSMSMessage::Number, GSM_MultiSMSMessage::SMS, SMS_Coding_8bit, SMS_Coding_Default_No_Compression, SMS_Coding_Unicode_No_Compression, SMS_ConcatenatedAutoTextLong, SMS_ConcatenatedAutoTextLong16bit, SMS_ConcatenatedTextLong, SMS_ConcatenatedTextLong16bit, GSM_SMSMessage::Text, TRUE, GSM_UDHHeader::Type, GSM_SMSMessage::UDH, UDH_ConcatenatedMessages16bit, and UnicodeLength().

Referenced by GSM_DecodeMultiPartSMS().

1232 {
1233  int i, Length = 0;
1234 
1235  Info->EntriesNum = 1;
1236  Info->Entries[0].ID = SMS_ConcatenatedTextLong;
1237  if (SMS->SMS[0].UDH.Type == UDH_ConcatenatedMessages16bit) {
1239  }
1240 
1241  for (i=0;i<SMS->Number;i++) {
1242  switch (SMS->SMS[i].Coding) {
1243  case SMS_Coding_8bit:
1244  Info->Entries[0].Buffer = (unsigned char *)realloc(Info->Entries[0].Buffer, Length + SMS->SMS[i].Length + 2);
1245  if (Info->Entries[0].Buffer == NULL) return FALSE;
1246 
1247  memcpy(Info->Entries[0].Buffer + Length, SMS->SMS[i].Text, SMS->SMS[i].Length);
1248  Length=Length+SMS->SMS[i].Length;
1249  break;
1251  if (Info->Entries[0].ID == SMS_ConcatenatedTextLong) {
1253  }
1254  if (Info->Entries[0].ID == SMS_ConcatenatedTextLong16bit) {
1256  }
1258  Info->Entries[0].Buffer = (unsigned char *)realloc(Info->Entries[0].Buffer, Length + UnicodeLength(SMS->SMS[i].Text)*2 + 2);
1259  if (Info->Entries[0].Buffer == NULL) return FALSE;
1260 
1261  memcpy(Info->Entries[0].Buffer+Length,SMS->SMS[i].Text,UnicodeLength(SMS->SMS[i].Text)*2);
1262  Length=Length+UnicodeLength(SMS->SMS[i].Text)*2;
1263  break;
1264  default:
1265  break;
1266  }
1267  }
1268  Info->Entries[0].Buffer[Length] = 0;
1269  Info->Entries[0].Buffer[Length+1] = 0;
1270  return TRUE;
1271 }
unsigned char Text[(GSM_MAX_SMS_LENGTH+1) *2]
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
GSM_UDHHeader UDH
GSM_MultiPartSMSEntry Entries[GSM_MAX_MULTI_SMS]
GSM_Coding_Type Coding
#define FALSE
Definition: gammu-types.h:25
GSM_SMSMessage SMS[GSM_MAX_MULTI_SMS]
EncodeMultiPartSMSID ID
unsigned char * Buffer
#define TRUE
Definition: gammu-types.h:28

§ GSM_DecodeMMSIndication()

gboolean GSM_DecodeMMSIndication ( GSM_Debug_Info di,
GSM_MultiPartSMSInfo Info,
GSM_MultiSMSMessage SMS 
)

Decodes long MMS notification SMS.

Definition at line 981 of file gsmmulti.c.

References GSM_MMSIndicator::Address, GSM_MMSIndicator::Class, dbgprintf, DumpMessage(), GSM_MultiPartSMSInfo::Entries, GSM_MultiPartSMSInfo::EntriesNum, FALSE, GSM_MAX_MULTI_SMS, GSM_MAX_SMS_LENGTH, GSM_MMS_Advertisement, GSM_MMS_Auto, GSM_MMS_Info, GSM_MMS_None, GSM_MMS_Personal, GSM_MultiPartSMSEntry::ID, GSM_SMSMessage::Length, GSM_MMSIndicator::MessageSize, GSM_MultiPartSMSEntry::MMSIndicator, GSM_MultiSMSMessage::Number, GSM_MMSIndicator::Sender, GSM_MultiSMSMessage::SMS, SMS_MMSIndicatorLong, GSM_UDHHeader::Text, GSM_SMSMessage::Text, GSM_MMSIndicator::Title, TRUE, GSM_UDHHeader::Type, GSM_SMSMessage::UDH, UDH_MMSIndicatorLong, and UDH_UserUDH.

Referenced by GSM_DecodeEMSMultiPartSMS(), and GSM_DecodeMultiPartSMS().

984 {
985  int i, Length = 0, j;
986  unsigned char Buffer[GSM_MAX_SMS_LENGTH*2*GSM_MAX_MULTI_SMS];
987 
988  /* Concatenate data */
989  for (i = 0; i < SMS->Number; i++) {
990  if (SMS->SMS[i].UDH.Type == UDH_MMSIndicatorLong) {
991  if (SMS->SMS[i].UDH.Text[11] != i+1 ||
992  SMS->SMS[i].UDH.Text[10] != SMS->Number) {
993  return FALSE;
994  }
995  } else if (SMS->SMS[i].UDH.Type != UDH_UserUDH) {
996  return FALSE;
997  }
998  memcpy(Buffer + Length, SMS->SMS[i].Text, SMS->SMS[i].Length);
999  Length = Length + SMS->SMS[i].Length;
1000  }
1001 
1002  dbgprintf(di, "MMS data of length %d:\n", Length);
1003  DumpMessage(di, Buffer, Length);
1004  Info->Entries[0].MMSIndicator = (GSM_MMSIndicator *)malloc(sizeof(GSM_MMSIndicator));
1005  if (Info->Entries[0].MMSIndicator == NULL) {
1006  return FALSE;
1007  }
1008  Info->EntriesNum = 1;
1009  Info->Entries[0].ID = SMS_MMSIndicatorLong;
1010  Info->Entries[0].MMSIndicator->Class = GSM_MMS_None;
1011  Info->Entries[0].MMSIndicator->MessageSize = 0;
1012  Info->Entries[0].MMSIndicator->Title[0] = 0;
1013  Info->Entries[0].MMSIndicator->Sender[0] = 0;
1014  Info->Entries[0].MMSIndicator->Address[0] = 0;
1015 
1016  /* First byte is transaction ID */
1017  /* PUSH */
1018  if (Buffer[1] != 0x06) {
1019  dbgprintf(di, "Unsupported transaction id: 0x%02x\n", Buffer[1]);
1020  return FALSE;
1021  }
1022  /* Process payload */
1023  for (i = 3 + Buffer[2]; i < Length; i++) {
1024  switch(Buffer[i]) {
1025  case 0x8c:
1026  /* Transaction type */
1027  i++;
1028  if (Buffer[i] != 0x82) {
1029  dbgprintf(di, "Unsupported transaction type: 0x%02x\n", Buffer[i]);
1030  return FALSE;
1031  }
1032  break;
1033  case 0x98:
1034  /* Message ID */
1035  while (Buffer[i] != 0 && i < Length) i++;
1036  break;
1037  case 0x8d:
1038  /* MMS version */
1039  i++;
1040  if (Buffer[i] < 0x90 || Buffer[i] > 0x92) {
1041  dbgprintf(di, "Unsupported MMS version: 0x%02x\n", Buffer[i]);
1042  return FALSE;
1043  }
1044  break;
1045  case 0x89:
1046  /* Sender */
1047  i++;
1048  if (Buffer[i] == 0) continue;
1049  if (Buffer[i + 1] == 0x80) {
1050  if (Buffer[i + 2] < 32) {
1051  /* String with length + encoding, we just ignore it for now */
1052  strcpy(Info->Entries[0].MMSIndicator->Sender, Buffer + i + 4);
1053  } else {
1054  strcpy(Info->Entries[0].MMSIndicator->Sender, Buffer + i + 2);
1055  }
1056  }
1057  i += Buffer[i];
1058  break;
1059  case 0x96:
1060  /* Title */
1061  if (Buffer[i + 1] == 0x0a && Buffer[i + 2] == 0xea) {
1062  /* UTF-8 */
1063  strcpy(Info->Entries[0].MMSIndicator->Title, Buffer + i + 3);
1064  i += strlen(Info->Entries[0].MMSIndicator->Title) + 3;
1065  } else {
1066  strcpy(Info->Entries[0].MMSIndicator->Title, Buffer + i + 1);
1067  i += strlen(Info->Entries[0].MMSIndicator->Title) + 1;
1068  }
1069  break;
1070  case 0x8a:
1071  /* Class */
1072  i++;
1073  switch (Buffer[i]) {
1074  case 0x80:
1076  break;
1077  case 0x81:
1079  break;
1080  case 0x82:
1081  Info->Entries[0].MMSIndicator->Class = GSM_MMS_Info;
1082  break;
1083  case 0x83:
1084  Info->Entries[0].MMSIndicator->Class = GSM_MMS_Auto;
1085  break;
1086  default:
1087  dbgprintf(di, "Unsupported MMS class: 0x%02x\n", Buffer[i]);
1088  break;
1089  }
1090  break;
1091  case 0x8e:
1092  /* Message size */
1093  i++;
1094  for (j = i + 1; j < i + 1 + Buffer[i]; j++) {
1095  Info->Entries[0].MMSIndicator->MessageSize = (Info->Entries[0].MMSIndicator->MessageSize << 8) + Buffer[j];
1096  }
1097  i += Buffer[i];
1098  break;
1099  case 0x88:
1100  /* Don't know */
1101  i++;
1102  break;
1103  case 0x81:
1104  /* Don't know */
1105  i++;
1106  i += Buffer[i];
1107  break;
1108  case 0x83:
1109  /* URL */
1110  strcpy(Info->Entries[0].MMSIndicator->Address, Buffer + i + 1);
1111  i += strlen(Info->Entries[0].MMSIndicator->Address) + 1;
1112  break;
1113  case 0x87:
1114  default:
1115  dbgprintf(di, "Unknown MMS tag: 0x%02x\n", Buffer[i]);
1116  break;
1117  }
1118  }
1119 
1120  return TRUE;
1121 }
unsigned char Text[(GSM_MAX_SMS_LENGTH+1) *2]
void DumpMessage(GSM_Debug_Info *d, const unsigned char *message, const size_t messagesize)
Definition: debug.c:314
char Address[500]
Definition: gammu-message.h:90
GSM_MMSIndicator * MMSIndicator
GSM_UDHHeader UDH
GSM_MMS_Class Class
GSM_MultiPartSMSEntry Entries[GSM_MAX_MULTI_SMS]
#define GSM_MAX_SMS_LENGTH
Definition: gammu-limits.h:176
unsigned char Text[GSM_MAX_UDH_LENGTH]
#define FALSE
Definition: gammu-types.h:25
GSM_SMSMessage SMS[GSM_MAX_MULTI_SMS]
char Sender[200]
Definition: gammu-message.h:98
EncodeMultiPartSMSID ID
#define GSM_MAX_MULTI_SMS
Definition: gammu-limits.h:162
#define dbgprintf
Definition: debug.h:72
#define TRUE
Definition: gammu-types.h:28

§ GSM_DecodeNokiaProfile()

gboolean GSM_DecodeNokiaProfile ( GSM_Debug_Info di,
GSM_MultiPartSMSInfo Info,
GSM_MultiSMSMessage SMS 
)

Decodes long Nokia profile SMS.

Definition at line 1126 of file gsmmulti.c.

References GSM_MultiBitmap::Bitmap, GSM_MultiPartSMSEntry::Bitmap, DecodeUnicodeString(), _GSM_Debug_Info::df, _GSM_Debug_Info::dl, DL_TEXTALL, DL_TEXTALLDATE, EncodeUnicode(), GSM_MultiPartSMSInfo::Entries, GSM_MultiPartSMSInfo::EntriesNum, FALSE, GSM_MAX_MULTI_SMS, GSM_MAX_SMS_LENGTH, GSM_NokiaPictureImage, GSM_PrintBitmap(), GSM_MultiPartSMSEntry::ID, GSM_SMSMessage::Length, GSM_MultiBitmap::Number, GSM_MultiSMSMessage::Number, PHONE_DecodeBitmap(), SM30_ISOTEXT, SM30_OTA, SM30_PROFILENAME, SM30_RINGTONE, SM30_SCREENSAVER, SM30_UNICODETEXT, smfprintf(), GSM_MultiSMSMessage::SMS, SMS_NokiaPictureImageLong, SMS_NokiaProfileLong, SMS_NokiaScreenSaverLong, GSM_Bitmap::Text, GSM_UDHHeader::Text, GSM_SMSMessage::Text, TRUE, GSM_UDHHeader::Type, GSM_SMSMessage::UDH, UDH_NokiaProfileLong, and GSM_MultiPartSMSInfo::Unknown.

Referenced by GSM_DecodeMultiPartSMS().

1129 {
1130  int i, Length = 0;
1131  char Buffer[GSM_MAX_SMS_LENGTH*2*GSM_MAX_MULTI_SMS];
1132 
1133  for (i=0;i<SMS->Number;i++) {
1134  if (SMS->SMS[i].UDH.Type != UDH_NokiaProfileLong ||
1135  SMS->SMS[i].UDH.Text[11] != i+1 ||
1136  SMS->SMS[i].UDH.Text[10] != SMS->Number) {
1137  return FALSE;
1138  }
1139  memcpy(Buffer+Length,SMS->SMS[i].Text,SMS->SMS[i].Length);
1140  Length = Length + SMS->SMS[i].Length;
1141  }
1142  Info->EntriesNum = 1;
1144  Info->Entries[0].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
1145  if (Info->Entries[0].Bitmap == NULL) return FALSE;
1146  Info->Entries[0].Bitmap->Number = 0;
1147  Info->Entries[0].Bitmap->Bitmap[0].Text[0] = 0;
1148  Info->Entries[0].Bitmap->Bitmap[0].Text[1] = 0;
1149  i=1;
1150  while (i < Length) {
1151  switch (Buffer[i]) {
1152  case SM30_ISOTEXT:
1153  smfprintf(di, "ISO 8859-2 text\n");
1154  break;
1155  case SM30_UNICODETEXT:
1156  smfprintf(di, "Unicode text\n");
1157  break;
1158  case SM30_OTA:
1159  smfprintf(di, "OTA bitmap as Picture Image\n");
1160  PHONE_DecodeBitmap(GSM_NokiaPictureImage, Buffer + i + 7, &Info->Entries[0].Bitmap->Bitmap[Info->Entries[0].Bitmap->Number]);
1161  Info->Entries[0].Bitmap->Number += 1;
1162 #ifdef DEBUG
1163  if (di->dl == DL_TEXTALL || di->dl == DL_TEXTALLDATE) {
1164  GSM_PrintBitmap(di->df, &Info->Entries[0].Bitmap->Bitmap[0]);
1165  }
1166 #endif
1167  break;
1168  case SM30_RINGTONE:
1169  smfprintf(di, "RTTL ringtone\n");
1170  Info->Unknown = TRUE;
1171  break;
1172  case SM30_PROFILENAME:
1173  smfprintf(di, "Profile Name\n");
1174  Info->Entries[0].ID = SMS_NokiaProfileLong;
1175  Info->Unknown = TRUE;
1176  break;
1177  case SM30_SCREENSAVER:
1178  smfprintf(di, "OTA bitmap as Screen Saver\n");
1179  PHONE_DecodeBitmap(GSM_NokiaPictureImage, Buffer + i + 7, &Info->Entries[0].Bitmap->Bitmap[Info->Entries[0].Bitmap->Number]);
1180  Info->Entries[0].Bitmap->Number += 1;
1181 #ifdef DEBUG
1182  if (di->dl == DL_TEXTALL || di->dl == DL_TEXTALLDATE) {
1183  GSM_PrintBitmap(di->df, &Info->Entries[0].Bitmap->Bitmap[0]);
1184  }
1185 #endif
1186  Info->Entries[0].ID = SMS_NokiaScreenSaverLong;
1187  break;
1188  }
1189  i = i + Buffer[i+1]*256 + Buffer[i+2] + 3;
1190  smfprintf(di, "Profile: pos=%i length=%i\n", i, Length);
1191  }
1192  i=1;
1193  while (i < Length) {
1194  switch (Buffer[i]) {
1195  case SM30_ISOTEXT:
1196  smfprintf(di, "ISO 8859-2 text\n");
1197  EncodeUnicode (Info->Entries[0].Bitmap->Bitmap[0].Text, Buffer+i+3, Buffer[i+2]);
1198  smfprintf(di, "ISO Text \"%s\"\n",DecodeUnicodeString(Info->Entries[0].Bitmap->Bitmap[0].Text));
1199  break;
1200  case SM30_UNICODETEXT:
1201  smfprintf(di, "Unicode text\n");
1202  memcpy(Info->Entries[0].Bitmap->Bitmap[0].Text,Buffer+i+3,Buffer[i+1]*256+Buffer[i+2]);
1203  Info->Entries[0].Bitmap->Bitmap[0].Text[Buffer[i+1]*256 + Buffer[i+2]] = 0;
1204  Info->Entries[0].Bitmap->Bitmap[0].Text[Buffer[i+1]*256 + Buffer[i+2]+ 1] = 0;
1205  smfprintf(di, "Unicode Text \"%s\"\n",DecodeUnicodeString(Info->Entries[0].Bitmap->Bitmap[0].Text));
1206  break;
1207  case SM30_OTA:
1208  smfprintf(di, "OTA bitmap as Picture Image\n");
1209  break;
1210  case SM30_RINGTONE:
1211  smfprintf(di, "RTTL ringtone\n");
1212  break;
1213  case SM30_PROFILENAME:
1214  smfprintf(di, "Profile Name\n");
1215  break;
1216  case SM30_SCREENSAVER:
1217  smfprintf(di, "OTA bitmap as Screen Saver\n");
1218  break;
1219  }
1220  i = i + Buffer[i+1]*256 + Buffer[i+2] + 3;
1221  smfprintf(di, "Profile: pos=%i length=%i\n", i, Length);
1222  }
1223  return TRUE;
1224 }
#define SM30_PROFILENAME
Definition: gsmmulti.h:20
unsigned char Text[(GSM_MAX_SMS_LENGTH+1) *2]
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
GSM_MultiBitmap * Bitmap
#define SM30_RINGTONE
Definition: gsmmulti.h:19
FILE * df
Definition: debug.h:36
GSM_UDHHeader UDH
void PHONE_DecodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
Definition: gsmlogo.c:141
GSM_MultiPartSMSEntry Entries[GSM_MAX_MULTI_SMS]
#define GSM_MAX_SMS_LENGTH
Definition: gammu-limits.h:176
unsigned char Text[GSM_MAX_UDH_LENGTH]
void GSM_PrintBitmap(FILE *file, GSM_Bitmap *bitmap)
Definition: gsmlogo.c:257
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
#define FALSE
Definition: gammu-types.h:25
#define SM30_UNICODETEXT
Definition: gsmmulti.h:17
#define SM30_ISOTEXT
Definition: gsmmulti.h:16
GSM_SMSMessage SMS[GSM_MAX_MULTI_SMS]
EncodeMultiPartSMSID ID
GSM_Bitmap Bitmap[GSM_MAX_MULTI_BITMAP]
Definition: gammu-bitmap.h:192
#define GSM_MAX_MULTI_SMS
Definition: gammu-limits.h:162
unsigned char Number
Definition: gammu-bitmap.h:188
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240
unsigned char Text[2 *(GSM_BITMAP_TEXT_LENGTH+1)]
Definition: gammu-bitmap.h:118
#define TRUE
Definition: gammu-types.h:28
#define SM30_SCREENSAVER
Definition: gsmmulti.h:22
Debug_Level dl
Definition: debug.h:35
#define SM30_OTA
Definition: gsmmulti.h:18

§ GSM_EncodeAlcatelMultiPartSMS()

GSM_Error GSM_EncodeAlcatelMultiPartSMS ( GSM_Debug_Info di,
GSM_MultiSMSMessage SMS,
unsigned char *  Data,
size_t  Len,
unsigned char *  Name,
size_t  Type 
)

Definition at line 438 of file gsmmulti.c.

References GSM_SMSMessage::Class, GSM_SMSMessage::Coding, EncodeDefault(), ERR_NONE, GSM_EncodeUDHHeader(), GSM_MakeSMSIDFromTime(), GSM_MAX_MULTI_SMS, GSM_PackSevenBitsToEight(), GSM_SetDefaultSMSData(), GSM_UDHHeader::Length, GSM_SMSMessage::Length, GSM_MultiSMSMessage::Number, GSM_MultiSMSMessage::SMS, SMS_Coding_8bit, GSM_UDHHeader::Text, GSM_SMSMessage::Text, TRUE, GSM_UDHHeader::Type, GSM_SMSMessage::UDH, UDH_ConcatenatedMessages, UDH_UserUDH, and UnicodeLength().

Referenced by GSM_EncodeMultiPartSMS().

443 {
444  unsigned char buff[100],UDHID;
445  size_t i, p;
446  GSM_UDHHeader MyUDH;
447 
448  for (i=0;i<GSM_MAX_MULTI_SMS;i++) {
449  GSM_SetDefaultSMSData(&SMS->SMS[i]);
450  SMS->SMS[i].UDH.Type = UDH_UserUDH;
451  SMS->SMS[i].UDH.Text[1] = 0x80; /* Alcatel */
452  p = UnicodeLength(Name);
453  EncodeDefault(buff, Name, &p, TRUE, NULL);
454  SMS->SMS[i].UDH.Text[2] = GSM_PackSevenBitsToEight(0, buff, SMS->SMS[i].UDH.Text+3, p) + 4;
455  SMS->SMS[i].UDH.Text[3] = GSM_PackSevenBitsToEight(0, buff, SMS->SMS[i].UDH.Text+3, p);
456  SMS->SMS[i].UDH.Text[4] = Type;
457  SMS->SMS[i].UDH.Text[5] = Len / 256;
458  SMS->SMS[i].UDH.Text[6] = Len % 256;
459  SMS->SMS[i].UDH.Text[0] = 6 + SMS->SMS[i].UDH.Text[3];
460  SMS->SMS[i].UDH.Length = SMS->SMS[i].UDH.Text[0] + 1;
461 
462  if (Len > (size_t)(140 - SMS->SMS[i].UDH.Length)) {
464  GSM_EncodeUDHHeader(di, &MyUDH);
465 
466  memcpy(SMS->SMS[i].UDH.Text+SMS->SMS[i].UDH.Length,MyUDH.Text+1,MyUDH.Length-1);
467  SMS->SMS[i].UDH.Text[0] += MyUDH.Length-1;
468  SMS->SMS[i].UDH.Length += MyUDH.Length-1;
469  }
470 
471  SMS->SMS[i].Coding = SMS_Coding_8bit;
472  SMS->SMS[i].Class = 1;
473  }
474 
475  p = 0;
476  while (p != Len) {
477  i = 140-SMS->SMS[SMS->Number].UDH.Length;
478  if (Len - p < i) i = Len - p;
479  memcpy(SMS->SMS[SMS->Number].Text,Data+p,i);
480  p += i;
481  SMS->SMS[SMS->Number].Length = i;
482  SMS->Number++;
483 
484  }
485 
486  /* Linked sms UDH */
487  if (SMS->Number != 1) {
488  UDHID = GSM_MakeSMSIDFromTime();
489  for (i = 0; i < (size_t)SMS->Number; i++) {
490  SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-3] = UDHID;
491  SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-2] = SMS->Number;
492  SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-1] = i+1;
493  }
494  }
495 
496  return ERR_NONE;
497 }
unsigned char Text[(GSM_MAX_SMS_LENGTH+1) *2]
int GSM_PackSevenBitsToEight(size_t offset, const unsigned char *input, unsigned char *output, size_t length)
Definition: coding.c:993
signed char Class
void GSM_SetDefaultSMSData(GSM_SMSMessage *SMS)
Definition: gsmsms.c:1129
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
GSM_UDHHeader UDH
GSM_Coding_Type Coding
unsigned char Text[GSM_MAX_UDH_LENGTH]
GSM_SMSMessage SMS[GSM_MAX_MULTI_SMS]
#define GSM_MAX_MULTI_SMS
Definition: gammu-limits.h:162
void GSM_EncodeUDHHeader(GSM_Debug_Info *di, GSM_UDHHeader *UDH)
Definition: gsmsms.c:1151
unsigned char GSM_MakeSMSIDFromTime(void)
Definition: gsmmulti.c:21
#define TRUE
Definition: gammu-types.h:28
void EncodeDefault(unsigned char *dest, const unsigned char *src, size_t *len, gboolean UseExtensions, unsigned char *ExtraAlphabet)
Definition: coding.c:831

§ GSM_EncodeSMS30MultiPartSMS()

static void GSM_EncodeSMS30MultiPartSMS ( GSM_MultiPartSMSInfo Info,
char *  Buffer,
size_t *  Length 
)
static

Definition at line 375 of file gsmmulti.c.

References GSM_MultiBitmap::Bitmap, GSM_MultiPartSMSEntry::Bitmap, GSM_MultiPartSMSEntry::Buffer, CopyUnicodeString(), DecodeUnicodeString(), GSM_MultiPartSMSInfo::Entries, GSM_EncodeNokiaRTTLRingtone(), GSM_NokiaPictureImage, GSM_MultiPartSMSEntry::ID, NOKIA_CopyBitmap(), GSM_MultiPartSMSEntry::Ringtone, GSM_MultiPartSMSEntry::RingtoneNotes, SM30_ISOTEXT, SM30_OTA, SM30_PROFILENAME, SM30_RINGTONE, SM30_SCREENSAVER, SM30_UNICODETEXT, SMS_NokiaPictureImageLong, SMS_NokiaProfileLong, GSM_Bitmap::Text, GSM_MultiPartSMSInfo::UnicodeCoding, and UnicodeLength().

Referenced by GSM_EncodeMultiPartSMS().

377 {
378  size_t len;
379 
380  /*SM version. Here 3.0*/
381  Buffer[(*Length)++] = 0x30;
382 
383  if (Info->Entries[0].ID == SMS_NokiaProfileLong) {
384  if (Info->Entries[0].Buffer != NULL) {
385  if (Info->Entries[0].Buffer[0]!=0x00 || Info->Entries[0].Buffer[1]!=0x00) {
386  Buffer[(*Length)++] = SM30_PROFILENAME;
387  Buffer[(*Length)++] = 0x00;
388  Buffer[(*Length)++] = 2*UnicodeLength(Info->Entries[0].Buffer);
389  CopyUnicodeString(Buffer+(*Length),Info->Entries[0].Buffer);
390  *Length = *Length + 2*UnicodeLength(Info->Entries[0].Buffer);
391  }
392  }
393  if (Info->Entries[0].Ringtone != NULL) {
394  Buffer[(*Length)++] = SM30_RINGTONE;
395  /* Length for this part later will be changed */
396  Buffer[(*Length)++] = 0x01;
397  Buffer[(*Length)++] = 0x00;
398  /* Smart Messaging 3.0 says: 16*9=144 bytes,
399  * but on 3310 4.02 it was possible to save about 196 chars
400  * (without cutting) */
401  len = 196;
402  Info->Entries[0].RingtoneNotes=GSM_EncodeNokiaRTTLRingtone(Info->Entries[0].Ringtone,Buffer+(*Length),&len);
403  Buffer[(*Length)-2] = len / 256;
404  Buffer[(*Length)-1] = len % 256;
405  *Length = *Length + len;
406  }
407  }
408  if (Info->Entries[0].Bitmap != NULL) {
409  if (Info->Entries[0].ID == SMS_NokiaPictureImageLong) {
410  Buffer[(*Length)++] = SM30_OTA;
411  } else {
412  Buffer[(*Length)++] = SM30_SCREENSAVER;
413  }
414  Buffer[(*Length)++] = 0x01;
415  Buffer[(*Length)++] = 0x00;
416  NOKIA_CopyBitmap(GSM_NokiaPictureImage, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, Length);
417  if (Info->Entries[0].Bitmap->Bitmap[0].Text[0]!=0 || Info->Entries[0].Bitmap->Bitmap[0].Text[1]!=0) {
418  if (Info->UnicodeCoding) {
419  Buffer[(*Length)++] = SM30_UNICODETEXT;
420  /* Length for text part */
421  Buffer[(*Length)++] = 0x00;
422  Buffer[(*Length)++] = UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text)*2;
423  memcpy(Buffer+(*Length),Info->Entries[0].Bitmap->Bitmap[0].Text,UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text)*2);
424  *Length = *Length + UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text)*2;
425  } else {
426  /*ID for ISO-8859-1 text*/
427  Buffer[(*Length)++] = SM30_ISOTEXT;
428  Buffer[(*Length)++] = 0x00;
429  Buffer[(*Length)++] = UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text);
430  memcpy(Buffer+(*Length),DecodeUnicodeString(Info->Entries[0].Bitmap->Bitmap[0].Text),UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text));
431  *Length = *Length +UnicodeLength(Info->Entries[0].Bitmap->Bitmap[0].Text);
432  }
433  }
434  }
435 }
#define SM30_PROFILENAME
Definition: gsmmulti.h:20
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
void CopyUnicodeString(unsigned char *Dest, const unsigned char *Source)
Definition: coding.c:1192
GSM_MultiBitmap * Bitmap
#define SM30_RINGTONE
Definition: gsmmulti.h:19
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
GSM_Ringtone * Ringtone
GSM_MultiPartSMSEntry Entries[GSM_MAX_MULTI_SMS]
unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, size_t *maxlength)
Definition: gsmring.c:992
void NOKIA_CopyBitmap(GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, size_t *Length)
Definition: gsmlogo.c:1132
#define SM30_UNICODETEXT
Definition: gsmmulti.h:17
#define SM30_ISOTEXT
Definition: gsmmulti.h:16
EncodeMultiPartSMSID ID
GSM_Bitmap Bitmap[GSM_MAX_MULTI_BITMAP]
Definition: gammu-bitmap.h:192
unsigned char * Buffer
unsigned char Text[2 *(GSM_BITMAP_TEXT_LENGTH+1)]
Definition: gammu-bitmap.h:118
#define SM30_SCREENSAVER
Definition: gsmmulti.h:22
#define SM30_OTA
Definition: gsmmulti.h:18

§ GSM_Find_Free_Used_SMS2()

void GSM_Find_Free_Used_SMS2 ( GSM_Debug_Info di,
GSM_Coding_Type  Coding,
GSM_SMSMessage SMS,
size_t *  UsedText,
size_t *  FreeText,
size_t *  FreeBytes 
)

Definition at line 37 of file gsmmulti.c.

References FindDefaultAlphabetLen(), GSM_MAX_8BIT_SMS_LENGTH, GSM_UDHHeader::Length, GSM_SMSMessage::Length, smfprintf(), SMS_Coding_8bit, SMS_Coding_Default_No_Compression, SMS_Coding_Unicode_No_Compression, GSM_SMSMessage::Text, GSM_SMSMessage::UDH, and UnicodeLength().

Referenced by GSM_AddSMS_Text_UDH(), GSM_EncodeEMSMultiPartSMS(), and GSM_SMSCounter().

38 {
39  size_t UsedBytes = 0;
40 
41  switch (Coding) {
43  FindDefaultAlphabetLen(SMS->Text,&UsedBytes,UsedText,500);
44  UsedBytes = *UsedText * 7 / 8;
45  if (UsedBytes * 8 / 7 != *UsedText) UsedBytes++;
46  *FreeBytes = GSM_MAX_8BIT_SMS_LENGTH - SMS->UDH.Length - UsedBytes;
47  *FreeText = (GSM_MAX_8BIT_SMS_LENGTH - SMS->UDH.Length) * 8 / 7 - *UsedText;
48  break;
50  *UsedText = UnicodeLength(SMS->Text);
51  UsedBytes = *UsedText * 2;
52  *FreeBytes = GSM_MAX_8BIT_SMS_LENGTH - SMS->UDH.Length - UsedBytes;
53  *FreeText = *FreeBytes / 2;
54  break;
55  case SMS_Coding_8bit:
56  *UsedText = UsedBytes = SMS->Length;
57  *FreeBytes = GSM_MAX_8BIT_SMS_LENGTH - SMS->UDH.Length - UsedBytes;
58  *FreeText = *FreeBytes;
59  break;
60  default:
61  break;
62  }
63  smfprintf(di, "UDH len %i, UsedBytes %ld, FreeText %ld, UsedText %ld, FreeBytes %ld\n",
64  SMS->UDH.Length,
65  (long)UsedBytes,
66  (long)*FreeText,
67  (long)*UsedText,
68  (long)*FreeBytes);
69 }
unsigned char Text[(GSM_MAX_SMS_LENGTH+1) *2]
void FindDefaultAlphabetLen(const unsigned char *src, size_t *srclen, size_t *smslen, size_t maxlen)
Definition: coding.c:914
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
GSM_UDHHeader UDH
#define GSM_MAX_8BIT_SMS_LENGTH
Definition: gammu-limits.h:190
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240

§ GSM_MakeMultiPartSMS()

void GSM_MakeMultiPartSMS ( GSM_Debug_Info di,
GSM_MultiSMSMessage SMS,
unsigned char *  MessageBuffer,
size_t  MessageLength,
GSM_UDH  UDHType,
GSM_Coding_Type  Coding,
int  Class,
unsigned char  ReplaceMessage 
)

Definition at line 305 of file gsmmulti.c.

References GSM_UDHHeader::AllParts, GSM_SMSMessage::Class, GSM_SMSMessage::Coding, FALSE, GSM_AddSMS_Text_UDH(), GSM_EncodeUDHHeader(), GSM_GetCurrentDateTime(), GSM_MakeSMSIDFromTime(), GSM_MAX_MULTI_SMS, GSM_SetDefaultSMSData(), GSM_DateTime::Hour, GSM_UDHHeader::ID16bit, GSM_UDHHeader::ID8bit, GSM_MultiSMSMessage::Number, GSM_UDHHeader::PartNumber, GSM_SMSMessage::ReplaceMessage, smfprintf(), GSM_MultiSMSMessage::SMS, SMS_Coding_8bit, GSM_UDHHeader::Type, and GSM_SMSMessage::UDH.

Referenced by GSM_EncodeMultiPartSMS(), and GSM_SMSCounter().

312 {
313  size_t Len,UsedText = 0,CopiedText = 0,CopiedSMSText = 0;
314  int j;
315  unsigned char UDHID;
316  GSM_DateTime Date;
317 
318  Len = 0;
319  while(1) {
320  if (SMS->Number >= GSM_MAX_MULTI_SMS) {
321  break;
322  }
323  GSM_SetDefaultSMSData(&SMS->SMS[SMS->Number]);
324  SMS->SMS[SMS->Number].Class = Class;
325  SMS->SMS[SMS->Number].Coding = Coding;
326 
327  SMS->SMS[SMS->Number].UDH.Type = UDHType;
328  GSM_EncodeUDHHeader(di, &SMS->SMS[SMS->Number].UDH);
329 
330  if (Coding == SMS_Coding_8bit) {
331  GSM_AddSMS_Text_UDH(di, SMS,Coding,MessageBuffer+Len,MessageLength - Len,FALSE,&UsedText,&CopiedText,&CopiedSMSText);
332  } else {
333  GSM_AddSMS_Text_UDH(di, SMS,Coding,MessageBuffer+Len*2,MessageLength - Len,FALSE,&UsedText,&CopiedText,&CopiedSMSText);
334  }
335  Len += CopiedText;
336  smfprintf(di, "%ld %ld\n", (long)Len, (long)MessageLength);
337  SMS->Number++;
338  if (Len == MessageLength) break;
339  }
340 
341  UDHID = GSM_MakeSMSIDFromTime();
342  GSM_GetCurrentDateTime (&Date);
343  for (j=0;j<SMS->Number;j++) {
344  SMS->SMS[j].UDH.Type = UDHType;
345  SMS->SMS[j].UDH.ID8bit = UDHID;
346  SMS->SMS[j].UDH.ID16bit = UDHID + 256 * Date.Hour;
347  SMS->SMS[j].UDH.PartNumber = j+1;
348  SMS->SMS[j].UDH.AllParts = SMS->Number;
349  GSM_EncodeUDHHeader(di, &SMS->SMS[j].UDH);
350  }
351  if (SMS->Number == 1) SMS->SMS[0].ReplaceMessage = ReplaceMessage;
352 }
GSM_Error GSM_AddSMS_Text_UDH(GSM_Debug_Info *di, GSM_MultiSMSMessage *SMS, GSM_Coding_Type Coding, char *Buffer, size_t BufferLen, gboolean UDH, size_t *UsedText, size_t *CopiedText, size_t *CopiedSMSText)
Definition: gsmmulti.c:212
unsigned char ReplaceMessage
signed char Class
void GSM_SetDefaultSMSData(GSM_SMSMessage *SMS)
Definition: gsmsms.c:1129
GSM_UDHHeader UDH
GSM_Coding_Type Coding
#define FALSE
Definition: gammu-types.h:25
GSM_SMSMessage SMS[GSM_MAX_MULTI_SMS]
#define GSM_MAX_MULTI_SMS
Definition: gammu-limits.h:162
void GSM_GetCurrentDateTime(GSM_DateTime *Date)
Definition: misc.c:184
int smfprintf(GSM_Debug_Info *d, const char *format,...)
Definition: debug.c:240
void GSM_EncodeUDHHeader(GSM_Debug_Info *di, GSM_UDHHeader *UDH)
Definition: gsmsms.c:1151
unsigned char GSM_MakeSMSIDFromTime(void)
Definition: gsmmulti.c:21

§ GSM_MakeSMSIDFromTime()

unsigned char GSM_MakeSMSIDFromTime ( void  )

Definition at line 21 of file gsmmulti.c.

References GSM_GetCurrentDateTime(), GSM_DateTime::Minute, and GSM_DateTime::Second.

Referenced by GSM_EncodeAlcatelMultiPartSMS(), GSM_EncodeEMSMultiPartSMS(), and GSM_MakeMultiPartSMS().

22 {
23  GSM_DateTime Date;
24  unsigned char retval;
25 
26  GSM_GetCurrentDateTime (&Date);
27  retval = Date.Second;
28  switch (Date.Minute/10) {
29  case 2: case 7: retval = retval + 60; break;
30  case 4: case 8: retval = retval + 120; break;
31  case 9: case 5: case 0: retval = retval + 180; break;
32  }
33  retval += Date.Minute/10;
34  return retval;
35 }
void GSM_GetCurrentDateTime(GSM_DateTime *Date)
Definition: misc.c:184

§ ReassembleCharacter()

unsigned int ReassembleCharacter ( char *  Buffer,
size_t  character_index 
)

Definition at line 71 of file gsmmulti.c.

Referenced by AlignIfCombinedCharacter(), AlignIfCombinedSurrogate(), and AlignIfSurrogatePair().

72 {
73  size_t offset = character_index * 2;
74 
75  return (
76  (unsigned int) ((unsigned char) Buffer[offset] << 8)
77  + (unsigned char) Buffer[offset + 1]
78  );
79 }