summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/service
authorzautrix <zautrix>2004-08-07 17:24:40 (UTC)
committer zautrix <zautrix>2004-08-07 17:24:40 (UTC)
commit88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22 (patch) (unidiff)
tree6331418973714243beb674abc87692277b83869d /gammu/emb/common/service
parentef8a09ce74ad3f0a51484d03fdf009bd5b3677bf (diff)
downloadkdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.zip
kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.tar.gz
kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.tar.bz2
Initial revision
Diffstat (limited to 'gammu/emb/common/service') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/service/backup/backgen.h69
-rw-r--r--gammu/emb/common/service/backup/backics.c42
-rw-r--r--gammu/emb/common/service/backup/backics.h17
-rw-r--r--gammu/emb/common/service/backup/backldif.c297
-rw-r--r--gammu/emb/common/service/backup/backldif.h17
-rw-r--r--gammu/emb/common/service/backup/backlmb.c413
-rw-r--r--gammu/emb/common/service/backup/backlmb.h17
-rw-r--r--gammu/emb/common/service/backup/backtext.c2908
-rw-r--r--gammu/emb/common/service/backup/backtext.h17
-rw-r--r--gammu/emb/common/service/backup/backvcf.c75
-rw-r--r--gammu/emb/common/service/backup/backvcf.h17
-rw-r--r--gammu/emb/common/service/backup/backvcs.c106
-rw-r--r--gammu/emb/common/service/backup/backvcs.h17
-rw-r--r--gammu/emb/common/service/backup/gsmback.c280
-rw-r--r--gammu/emb/common/service/backup/gsmback.h48
-rw-r--r--gammu/emb/common/service/gsmcal.c509
-rw-r--r--gammu/emb/common/service/gsmcal.h445
-rw-r--r--gammu/emb/common/service/gsmcall.h185
-rw-r--r--gammu/emb/common/service/gsmdata.c366
-rw-r--r--gammu/emb/common/service/gsmdata.h152
-rw-r--r--gammu/emb/common/service/gsmlogo.c1003
-rw-r--r--gammu/emb/common/service/gsmlogo.h180
-rw-r--r--gammu/emb/common/service/gsmmisc.c262
-rw-r--r--gammu/emb/common/service/gsmmisc.h316
-rw-r--r--gammu/emb/common/service/gsmnet.c444
-rw-r--r--gammu/emb/common/service/gsmnet.h98
-rw-r--r--gammu/emb/common/service/gsmpbk.c370
-rw-r--r--gammu/emb/common/service/gsmpbk.h270
-rw-r--r--gammu/emb/common/service/gsmprof.h104
-rw-r--r--gammu/emb/common/service/gsmring.c1600
-rw-r--r--gammu/emb/common/service/gsmring.h202
-rw-r--r--gammu/emb/common/service/sms/gsmems.c765
-rw-r--r--gammu/emb/common/service/sms/gsmems.h20
-rw-r--r--gammu/emb/common/service/sms/gsmmulti.c1148
-rw-r--r--gammu/emb/common/service/sms/gsmmulti.h271
-rw-r--r--gammu/emb/common/service/sms/gsmsms.c663
-rw-r--r--gammu/emb/common/service/sms/gsmsms.h492
37 files changed, 14205 insertions, 0 deletions
diff --git a/gammu/emb/common/service/backup/backgen.h b/gammu/emb/common/service/backup/backgen.h
new file mode 100644
index 0000000..9d7d973
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backgen.h
@@ -0,0 +1,69 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef __gsm_backgen_h
4#define __gsm_backgen_h
5
6#include "../../config.h"
7#include "../../misc/misc.h"
8#include "../gsmpbk.h"
9#include "../gsmcal.h"
10#include "../gsmlogo.h"
11#include "../gsmring.h"
12#include "../gsmdata.h"
13#include "../gsmprof.h"
14#include "../gsmmisc.h"
15#include "../sms/gsmsms.h"
16
17 #define GSM_BACKUP_MAX_PHONEPHONEBOOK 501
18 #define GSM_BACKUP_MAX_SIMPHONEBOOK 251
19 #define GSM_BACKUP_MAX_CALLER 6
20 #define GSM_BACKUP_MAX_SMSC 10
21 #define GSM_BACKUP_MAX_WAPBOOKMARK40
22 #define GSM_BACKUP_MAX_WAPSETTINGS30
23 #define GSM_BACKUP_MAX_MMSSETTINGS30
24 #define GSM_BACKUP_MAX_RINGTONES30
25 #define GSM_BACKUP_MAX_PROFILES 10
26 #define GSM_BACKUP_MAX_FMSTATIONS20
27 #define GSM_BACKUP_MAX_GPRSPOINT10
28 #define GSM_BACKUP_MAX_NOTE 10/* FIXME */
29
30typedef struct {
31 char IMEI [MAX_IMEI_LENGTH];
32 char Model [MAX_MODEL_LENGTH+MAX_VERSION_LENGTH];
33 char Creator [80];
34 GSM_DateTime DateTime;
35 bool DateTimeAvailable;
36 char MD5Original[100];
37 char MD5Calculated[100];
38 GSM_MemoryEntry *PhonePhonebook[GSM_BACKUP_MAX_PHONEPHONEBOOK + 1];
39 GSM_MemoryEntry *SIMPhonebook[GSM_BACKUP_MAX_SIMPHONEBOOK + 1];
40 GSM_CalendarEntry *Calendar[GSM_MAXCALENDARTODONOTES + 1];
41 GSM_Bitmap *CallerLogos[GSM_BACKUP_MAX_CALLER + 1];
42 GSM_SMSC *SMSC [GSM_BACKUP_MAX_SMSC + 1];
43 GSM_WAPBookmark *WAPBookmark[GSM_BACKUP_MAX_WAPBOOKMARK + 1];
44 GSM_MultiWAPSettings *WAPSettings[GSM_BACKUP_MAX_WAPSETTINGS + 1];
45 GSM_MultiWAPSettings *MMSSettings[GSM_BACKUP_MAX_MMSSETTINGS + 1];
46 GSM_Ringtone *Ringtone[GSM_BACKUP_MAX_RINGTONES + 1];
47 GSM_ToDoEntry *ToDo [GSM_MAXCALENDARTODONOTES + 1];
48 GSM_Profile *Profiles[GSM_BACKUP_MAX_PROFILES + 1];
49 GSM_FMStation *FMStation[GSM_BACKUP_MAX_FMSTATIONS +1];
50 GSM_GPRSAccessPoint *GPRSPoint[GSM_BACKUP_MAX_GPRSPOINT + 1];
51 GSM_NoteEntry *Note [GSM_BACKUP_MAX_NOTE + 1];
52 GSM_Bitmap *StartupLogo;
53 GSM_Bitmap *OperatorLogo;
54} GSM_Backup;
55
56 #define GSM_BACKUP_MAX_SMS500
57
58typedef struct {
59 GSM_SMSMessage *SMS[GSM_BACKUP_MAX_SMS];
60} GSM_SMS_Backup;
61
62extern GSM_Error GSM_ReadSMSBackupFile(char *FileName, GSM_SMS_Backup *backup);
63extern GSM_Error GSM_SaveSMSBackupFile(char *FileName, GSM_SMS_Backup *backup);
64
65#endif
66
67/* How should editor hadle tabs in this file? Add editor commands here.
68 * vim: noexpandtab sw=8 ts=8 sts=8:
69 */
diff --git a/gammu/emb/common/service/backup/backics.c b/gammu/emb/common/service/backup/backics.c
new file mode 100644
index 0000000..3e6b083
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backics.c
@@ -0,0 +1,42 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmlogo.h"
10#include "../gsmmisc.h"
11#include "backics.h"
12
13#ifdef GSM_ENABLE_BACKUP
14
15GSM_Error SaveICS(char *FileName, GSM_Backup *backup)
16{
17 FILE *file;
18
19 file = fopen(FileName, "wb");
20 if (file == NULL) return ERR_CANTOPENFILE;
21
22 fclose(file);
23 return ERR_NONE;
24}
25
26GSM_Error LoadICS(char *FileName, GSM_Backup *backup)
27{
28 GSM_File File;
29 GSM_Error error;
30
31 File.Buffer = NULL;
32 error = GSM_ReadFile(FileName, &File);
33 if (error != ERR_NONE) return error;
34
35 return ERR_NONE;
36}
37
38#endif
39
40/* How should editor hadle tabs in this file? Add editor commands here.
41 * vim: noexpandtab sw=8 ts=8 sts=8:
42 */
diff --git a/gammu/emb/common/service/backup/backics.h b/gammu/emb/common/service/backup/backics.h
new file mode 100644
index 0000000..80e2b15
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backics.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backics_h
4#define __gsm_backics_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error SaveICS(char *FileName, GSM_Backup *backup);
10GSM_Error LoadICS(char *FileName, GSM_Backup *backup);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/backldif.c b/gammu/emb/common/service/backup/backldif.c
new file mode 100644
index 0000000..ab16160
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backldif.c
@@ -0,0 +1,297 @@
1/* (c) 2003-2004 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmlogo.h"
10#include "../gsmmisc.h"
11#include "backldif.h"
12
13#ifdef GSM_ENABLE_BACKUP
14
15static void SaveLDIFText(FILE *file, unsigned char *Name, unsigned char *Value)
16{
17 unsigned char Buffer[1000],Buffer2[1000];
18
19 if (EncodeUTF8(Buffer, Value)) {
20 // dbgprintf("%s\n",Buffer);
21 EncodeBASE64(Buffer, Buffer2, strlen(Buffer));
22 fprintf(file,"%s:: %s%c%c",Name,Buffer2,13,10);
23 } else {
24 fprintf(file,"%s: %s%c%c",Name,DecodeUnicodeString(Value),13,10);
25 }
26}
27
28GSM_Error SaveLDIF(char *FileName, GSM_Backup *backup)
29{
30 int i, j;
31 FILE *file;
32
33 file = fopen(FileName, "wb");
34 if (file == NULL) return ERR_CANTOPENFILE;
35
36 i=0;
37 while (backup->PhonePhonebook[i]!=NULL) {
38 for (j=0;j<backup->PhonePhonebook[i]->EntriesNum;j++) {
39 switch (backup->PhonePhonebook[i]->Entries[j].EntryType) {
40 case PBK_Text_Name:
41 SaveLDIFText(file, "dn", backup->PhonePhonebook[i]->Entries[j].Text);
42 break;
43 default:
44 break;
45 }
46 }
47 fprintf(file, "objectclass: top%c%c",13,10);
48 fprintf(file, "objectclass: person%c%c",13,10);
49 fprintf(file, "objectclass: organizationalPerson%c%c",13,10);
50 fprintf(file, "objectclass: inetOrgPerson%c%c",13,10);
51 fprintf(file, "objectclass: mozillaAbPersonObsolete%c%c",13,10);
52 for (j=0;j<backup->PhonePhonebook[i]->EntriesNum;j++) {
53 switch (backup->PhonePhonebook[i]->Entries[j].EntryType) {
54 case PBK_Text_Postal:
55 SaveLDIFText(file, "HomePostalAddress", backup->PhonePhonebook[i]->Entries[j].Text);
56 break;
57 case PBK_Text_URL:
58 SaveLDIFText(file, "homeurl", backup->PhonePhonebook[i]->Entries[j].Text);
59 break;
60 case PBK_Text_Name:
61 SaveLDIFText(file, "givenName", backup->PhonePhonebook[i]->Entries[j].Text);
62 SaveLDIFText(file, "cn", backup->PhonePhonebook[i]->Entries[j].Text);
63 break;
64 case PBK_Text_Note:
65 SaveLDIFText(file, "Description", backup->PhonePhonebook[i]->Entries[j].Text);
66 break;
67 case PBK_Number_Work:
68 SaveLDIFText(file, "workPhone", backup->PhonePhonebook[i]->Entries[j].Text);//not exist in Mozilla 1.4 win32
69 break;
70 case PBK_Number_Mobile:
71 SaveLDIFText(file, "mobile", backup->PhonePhonebook[i]->Entries[j].Text);
72 break;
73 case PBK_Number_Pager:
74 SaveLDIFText(file, "pager", backup->PhonePhonebook[i]->Entries[j].Text);
75 break;
76 case PBK_Number_Fax:
77 SaveLDIFText(file, "fax", backup->PhonePhonebook[i]->Entries[j].Text);//facsimileTelephoneNumber
78 break;
79 case PBK_Number_Home:
80 SaveLDIFText(file, "homePhone", backup->PhonePhonebook[i]->Entries[j].Text);
81 break;
82 case PBK_Number_General:
83 SaveLDIFText(file, "telephoneNumber", backup->PhonePhonebook[i]->Entries[j].Text);//work in Mozilla 1.4 win32
84 break;
85 case PBK_Text_Email:
86 SaveLDIFText(file, "mail", backup->PhonePhonebook[i]->Entries[j].Text);
87 break;
88 case PBK_Text_Email2:
89 SaveLDIFText(file, "mozillaSecondEmail", backup->PhonePhonebook[i]->Entries[j].Text);
90 break;
91 case PBK_Text_Custom1:
92 SaveLDIFText(file, "custom1", backup->PhonePhonebook[i]->Entries[j].Text);
93 break;
94 case PBK_Text_Custom2:
95 SaveLDIFText(file, "custom2", backup->PhonePhonebook[i]->Entries[j].Text);
96 break;
97 case PBK_Text_Custom3:
98 SaveLDIFText(file, "custom3", backup->PhonePhonebook[i]->Entries[j].Text);
99 break;
100 case PBK_Text_Custom4:
101 SaveLDIFText(file, "custom4", backup->PhonePhonebook[i]->Entries[j].Text);
102 break;
103 case PBK_Text_Company:
104 SaveLDIFText(file, "o", backup->PhonePhonebook[i]->Entries[j].Text);
105 break;
106 case PBK_Text_JobTitle:
107 SaveLDIFText(file, "title", backup->PhonePhonebook[i]->Entries[j].Text);
108 break;
109 case PBK_Text_StreetAddress:
110 SaveLDIFText(file, "homePostalAddress", backup->PhonePhonebook[i]->Entries[j].Text);
111 break;
112 case PBK_Text_City:
113 SaveLDIFText(file, "mozillaHomeLocalityName", backup->PhonePhonebook[i]->Entries[j].Text);
114 break;
115 case PBK_Text_State:
116 SaveLDIFText(file, "mozillaHomeState", backup->PhonePhonebook[i]->Entries[j].Text);
117 break;
118 case PBK_Text_Zip:
119 SaveLDIFText(file, "mozillaHomePostalCode", backup->PhonePhonebook[i]->Entries[j].Text);
120 break;
121 case PBK_Text_Country:
122 SaveLDIFText(file, "mozillaHomeCountryName", backup->PhonePhonebook[i]->Entries[j].Text);
123 break;
124 case PBK_Number_Other:
125 case PBK_Caller_Group:
126 case PBK_RingtoneID:
127 case PBK_PictureID:
128 case PBK_Date:
129 case PBK_RingtoneFileSystemID:
130 case PBK_Text_UserID:
131 case PBK_SMSListID:
132 case PBK_Category:
133 case PBK_Private:
134 case PBK_Text_LastName:
135 case PBK_Text_FirstName:
136 dbgprintf("Feature missed\n");
137 break;
138 }
139 }
140 fprintf(file, "%c%c",13,10);
141 i++;
142 }
143 fclose(file);
144 return ERR_NONE;
145}
146
147static bool ReadLDIFText(char *Buffer, char *Start, char *Value)
148{
149 unsigned char Buffer2[1000],buff[200];
150 int i;
151
152 Value[0] = 0x00;
153
154 strcpy(buff,Start);
155 strcat(buff,":: ");
156 if (!strncmp(Buffer,buff,strlen(buff))) {
157 i = DecodeBASE64(Buffer+strlen(Start)+3, Buffer2, strlen(Buffer)-(strlen(Start)+3));
158 dbgprintf("Text after DecodeBASE64 is \"%s\"\n",Buffer2);
159 DecodeUTF8(Value, Buffer2, i);
160 dbgprintf("Text after DecodeUTF8 is \"%s\"\n",DecodeUnicodeString(Value));
161 return true;
162 }
163 strcpy(buff,Start);
164 strcat(buff,": ");
165 if (!strncmp(Buffer,buff,strlen(buff))) {
166 EncodeUnicode(Value,Buffer+strlen(Start)+2,strlen(Buffer)-(strlen(Start)+2));
167 dbgprintf("Text after EncodeUnicode is \"%s\"\n",DecodeUnicodeString(Value));
168 return true;
169 }
170 return false;
171}
172
173static GSM_Error GSM_DecodeLDIFEntry(unsigned char *Buffer, int *Pos, GSM_MemoryEntry *Pbk)
174{
175 unsigned char Line[2000],Buff[2000],Buff2[2000];
176 int Level = 0;
177
178 Buff[0] = 0;
179 Pbk->EntriesNum = 0;
180
181 while (1) {
182 MyGetLine(Buffer, Pos, Line, strlen(Buffer));
183 if (strlen(Line) == 0) break;
184 switch (Level) {
185 case 0:
186 if (ReadLDIFText(Line, "objectclass", Buff)) {
187 sprintf(Buff2,"%s",DecodeUnicodeString(Buff));
188 if (!strcmp("mozillaAbPersonObsolete",Buff2)) {
189 dbgprintf("level1\n");
190 Level = 1;
191 }
192 }
193 break;
194 case 1:
195 if (ReadLDIFText(Line, "dn", Buff)) {
196 dbgprintf("entries num is %i\n",Pbk->EntriesNum);
197 if (Pbk->EntriesNum == 0) return ERR_EMPTY;
198 return ERR_NONE;
199 }
200 if (ReadLDIFText(Line, "givenName", Buff)) {
201 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
202 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Name;
203 Pbk->EntriesNum++;
204 }
205 if (ReadLDIFText(Line, "telephoneNumber", Buff)) {
206 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
207 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_General;
208 Pbk->EntriesNum++;
209 }
210 if (ReadLDIFText(Line, "mobile", Buff)) {
211 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
212 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Mobile;
213 Pbk->EntriesNum++;
214 }
215 if (ReadLDIFText(Line, "workPhone", Buff)) {
216 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
217 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Work;
218 Pbk->EntriesNum++;
219 }
220 if (ReadLDIFText(Line, "fax", Buff)) {
221 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
222 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Fax;
223 Pbk->EntriesNum++;
224 }
225 if (ReadLDIFText(Line, "homePhone",Buff)) {
226 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
227 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Home;
228 Pbk->EntriesNum++;
229 }
230 if (ReadLDIFText(Line, "Description", Buff)) {
231 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
232 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Note;
233 Pbk->EntriesNum++;
234 }
235 if (ReadLDIFText(Line, "HomePostalAddress", Buff)) {
236 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
237 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Postal;
238 Pbk->EntriesNum++;
239 }
240 if (ReadLDIFText(Line, "mail", Buff)) {
241 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
242 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email;
243 Pbk->EntriesNum++;
244 }
245 if (ReadLDIFText(Line, "homeurl", Buff)) {
246 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
247 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_URL;
248 Pbk->EntriesNum++;
249 }
250 /* FIXME: add rest */
251 break;
252 }
253 }
254
255 dbgprintf("entries num is %i\n",Pbk->EntriesNum);
256 if (Pbk->EntriesNum == 0) return ERR_EMPTY;
257 return ERR_NONE;
258}
259
260GSM_Error LoadLDIF(char *FileName, GSM_Backup *backup)
261{
262 GSM_File File;
263 GSM_Error error;
264 GSM_MemoryEntryPbk;
265 int numPbk = 0, Pos;
266
267 File.Buffer = NULL;
268 error = GSM_ReadFile(FileName, &File);
269 if (error != ERR_NONE) return error;
270
271 Pos = 0;
272 while (1) {
273 error = GSM_DecodeLDIFEntry(File.Buffer, &Pos, &Pbk);
274 if (error == ERR_EMPTY) break;
275 if (error != ERR_NONE) return error;
276 if (numPbk < GSM_BACKUP_MAX_PHONEPHONEBOOK) {
277 backup->PhonePhonebook[numPbk] = malloc(sizeof(GSM_MemoryEntry));
278 if (backup->PhonePhonebook[numPbk] == NULL) return ERR_MOREMEMORY;
279 backup->PhonePhonebook[numPbk + 1] = NULL;
280 } else {
281 dbgprintf("Increase GSM_BACKUP_MAX_PHONEPHONEBOOK\n");
282 return ERR_MOREMEMORY;
283 }
284 memcpy(backup->PhonePhonebook[numPbk],&Pbk,sizeof(GSM_MemoryEntry));
285 backup->PhonePhonebook[numPbk]->Location = numPbk + 1;
286 backup->PhonePhonebook[numPbk]->MemoryType = MEM_ME;
287 numPbk++;
288 }
289
290 return ERR_NONE;
291}
292
293#endif
294
295/* How should editor hadle tabs in this file? Add editor commands here.
296 * vim: noexpandtab sw=8 ts=8 sts=8:
297 */
diff --git a/gammu/emb/common/service/backup/backldif.h b/gammu/emb/common/service/backup/backldif.h
new file mode 100644
index 0000000..212c048
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backldif.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backldif_h
4#define __gsm_backldif_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error SaveLDIF(char *FileName, GSM_Backup *backup);
10GSM_Error LoadLDIF(char *FileName, GSM_Backup *backup);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/backlmb.c b/gammu/emb/common/service/backup/backlmb.c
new file mode 100644
index 0000000..d7f845a
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backlmb.c
@@ -0,0 +1,413 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmlogo.h"
10#include "../gsmmisc.h"
11#include "backlmb.h"
12
13#ifdef GSM_ENABLE_BACKUP
14
15static void SaveLMBStartupEntry(FILE *file, GSM_Bitmap bitmap)
16{
17 int count=13;
18 GSM_Phone_Bitmap_Types Type;
19 /* Welcome note and logo header block */
20 char req[1000] = {
21 'W','E','L',' ', /*block identifier*/
22 00,00, /*block data size*/
23 0x02,00,00,00,00,00,
24 0x00}; /*number of blocks (like in 6110 frame)*/
25
26 if (bitmap.Type == GSM_StartupLogo) {
27 req[count++] = 0x01;
28 req[count++] = bitmap.BitmapHeight;
29 req[count++] = bitmap.BitmapWidth;
30 Type = GSM_NokiaStartupLogo;
31 switch (bitmap.BitmapHeight) {
32 case 65: Type = GSM_Nokia7110StartupLogo; break;
33 case 60: Type = GSM_Nokia6210StartupLogo; break;
34 }
35 PHONE_EncodeBitmap(Type, req+count, &bitmap);
36 count = count + PHONE_GetBitmapSize(Type, 0, 0);
37
38 req[12]++;
39 }
40 if (bitmap.Type == GSM_WelcomeNote_Text) {
41 req[count++]=0x02;
42 req[count++]=UnicodeLength(bitmap.Text);
43 memcpy(req+count,DecodeUnicodeString(bitmap.Text),UnicodeLength(bitmap.Text));
44 count=count+UnicodeLength(bitmap.Text);
45
46 req[12]++;
47 }
48
49 req[4]=(count-12)%256;
50 req[5]=(count-12)/256;
51
52 fwrite(req, 1, count, file);
53 }
54
55static void SaveLMBCallerEntry(FILE *file, GSM_Bitmap bitmap)
56{
57 int count=12, textlen;
58 char req[500] = {
59 'C','G','R',' ', /*block identifier*/
60 00,00, /*block data size*/
61 02,00,
62 00, /*group number=0,1,etc.*/
63 00,00,00};
64
65 req[count++] = bitmap.Location - 1;
66 if (bitmap.DefaultName) {
67 req[count++] = 0;
68 } else {
69 textlen = UnicodeLength(bitmap.Text);
70 req[count++] = textlen;
71 memcpy(req+count,DecodeUnicodeString(bitmap.Text),textlen);
72 count += textlen;
73 }
74 if (bitmap.DefaultRingtone) {
75 req[count++] = 0x16;
76 } else {
77 req[count++] = bitmap.RingtoneID;
78 }
79 if (bitmap.BitmapEnabled) req[count++] = 0x01; else req[count++] = 0x00;
80 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 4) >> 8;
81 req[count++] = (PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 4) % 0xff;
82 if (bitmap.DefaultBitmap) {
83 bitmap.BitmapWidth = 72;
84 bitmap.BitmapHeight = 14;
85 GSM_ClearBitmap(&bitmap);
86 }
87 NOKIA_CopyBitmap(GSM_NokiaCallerLogo, &bitmap, req, &count);
88 req[count++]=0;
89
90 req[4]=(count-12)%256;
91 req[5]=(count-12)/256;
92 req[8]=bitmap.Location;
93
94 fwrite(req, 1, count, file);
95 }
96
97void SaveLMBPBKEntry(FILE *file, GSM_MemoryEntry *entry)
98{
99 int count = 16, blocks;
100 char req[500] = {
101 'P','B','E','2', /*block identifier*/
102 00,00, /*block data size*/
103 00,00,
104 00,00, /*position of phonebook entry*/
105 03, /*memory type. ME=02;SM=03*/
106 00,
107 00,00, /*position of phonebook entry*/
108 03, /*memory type. ME=02;SM=03*/
109 00};
110
111 count=count+N71_65_EncodePhonebookFrame(NULL, req+16, *entry, &blocks, true, true);
112
113 req[4]=(count-12)%256;
114 req[5]=(count-12)/256;
115 req[8]=req[12] = entry->Location & 0xff;
116 req[9]=req[13] = (entry->Location >> 8);
117 if (entry->MemoryType==MEM_ME) req[10]=req[14]=2;
118
119 fwrite(req, 1, count, file);
120}
121
122GSM_Error SaveLMB(char *FileName, GSM_Backup *backup)
123{
124 FILE *file;
125 int i;
126 char LMBHeader[] = {'L','M','B',' '}; /*file identifier*/
127 char PBKHeader[] = { /*Phonebook header block */
128 'P','B','K',' ', /*block identifier*/
129 0x08,00, /*block data size*/
130 0x02,00,
131 03, /*memory type. ME=02;SM=03*/
132 00,00,00,
133 00,00, /*size of phonebook*/
134 14, /*max length of each position*/
135 00,00,00,00,00};
136
137
138 file = fopen(FileName, "wb");
139 if (file == NULL) return ERR_CANTOPENFILE;
140
141 /* Write the header of the file. */
142 fwrite(LMBHeader, 1, sizeof(LMBHeader), file);
143
144 if (backup->PhonePhonebook[0]!=NULL) {
145 PBKHeader[8] = 2; /* memory type=MEM_ME */
146 PBKHeader[12] = (unsigned char)(500 % 256);
147 PBKHeader[13] = 500 / 256;
148 fwrite(PBKHeader, 1, sizeof(PBKHeader), file);
149 i=0;
150 while (backup->PhonePhonebook[i]!=NULL) {
151 SaveLMBPBKEntry(file, backup->PhonePhonebook[i]);
152 i++;
153 }
154 }
155 if (backup->SIMPhonebook[0]!=NULL) {
156 PBKHeader[8] = 3; /* memory type=MEM_SM */
157 PBKHeader[12] = (unsigned char)(250 % 256);
158 PBKHeader[13] = 250 / 256;
159 PBKHeader[14] = 0x16; /* max size of one entry */
160 fwrite(PBKHeader, 1, sizeof(PBKHeader), file);
161 i=0;
162 while (backup->SIMPhonebook[i]!=NULL) {
163 SaveLMBPBKEntry(file, backup->SIMPhonebook[i]);
164 i++;
165 }
166 }
167 i=0;
168 while (backup->CallerLogos[i]!=NULL) {
169 SaveLMBCallerEntry(file, *backup->CallerLogos[i]);
170 i++;
171 }
172 if (backup->StartupLogo!=NULL) {
173 SaveLMBStartupEntry(file, *backup->StartupLogo);
174 }
175
176 fclose(file);
177 return ERR_NONE;
178}
179
180static GSM_Error LoadLMBCallerEntry(unsigned char *buffer, unsigned char *buffer2, GSM_Backup *backup)
181{
182 GSM_Bitmap bitmap;
183 int num;
184
185#ifdef DEBUG
186 dbgprintf("Number %i, name \"", buffer2[0]+1);
187 for (num=0;num<buffer2[1];num++) dbgprintf("%c", buffer2[num+2]);
188 dbgprintf("\"\n");
189 dbgprintf("Ringtone ID=%i\n", buffer2[num+2]);
190 if (buffer2[num+3]==1) {
191 dbgprintf("Logo enabled\n");
192 } else {
193 dbgprintf("Logo disabled\n");
194 }
195#endif
196
197 bitmap.Location = buffer2[0] + 1;
198 bitmap.Type = GSM_CallerGroupLogo;
199 bitmap.DefaultRingtone = false;
200 bitmap.RingtoneID = buffer2[buffer2[1]+2];
201
202 EncodeUnicode(bitmap.Text,buffer2+2,buffer2[1]);
203 if (bitmap.Text[0] == 0x00 && bitmap.Text[1] == 0x00) {
204 bitmap.DefaultName = true;
205 } else {
206 bitmap.DefaultName = false;
207 }
208
209 bitmap.BitmapEnabled = false;
210 if (buffer2[buffer2[1]+3]==1) bitmap.BitmapEnabled=true;
211
212 bitmap.DefaultBitmap = false;
213 PHONE_DecodeBitmap(GSM_NokiaCallerLogo, buffer2+(buffer2[1]+10), &bitmap);
214
215#ifdef DEBUG
216 dbgprintf("Caller logo\n");
217 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&bitmap);
218#endif
219
220 num = 0;
221 while (backup->CallerLogos[num] != NULL) num++;
222 if (num < GSM_BACKUP_MAX_CALLER) {
223 backup->CallerLogos[num] = malloc(sizeof(GSM_Bitmap));
224 if (backup->CallerLogos[num] == NULL) return ERR_MOREMEMORY;
225 backup->CallerLogos[num + 1] = NULL;
226 } else {
227 dbgprintf("Increase GSM_BACKUP_MAX_CALLER\n");
228 return ERR_MOREMEMORY;
229 }
230 *backup->CallerLogos[num] = bitmap;
231
232 return ERR_NONE;
233 }
234
235static GSM_Error LoadLMBStartupEntry(unsigned char *buffer, unsigned char *buffer2, GSM_Backup *backup)
236{
237 int i,j;
238#ifdef DEBUG
239 int z;
240#endif
241 GSM_Phone_Bitmap_Types Type;
242
243 j=1;
244 for (i=0;i<buffer2[0];i++) {
245 switch (buffer2[j++]) {
246 case 1:
247 dbgprintf("Block 1 - startup logo\n");
248 backup->StartupLogo = malloc(sizeof(GSM_Bitmap));
249 if (backup->StartupLogo == NULL) return ERR_MOREMEMORY;
250 backup->StartupLogo->Location= 1;
251 backup->StartupLogo->BitmapHeight= buffer2[j++];
252 backup->StartupLogo->BitmapWidth= buffer2[j++];
253 Type = GSM_NokiaStartupLogo;
254 switch (backup->StartupLogo->BitmapHeight) {
255 case 65: Type = GSM_Nokia7110StartupLogo; break;
256 case 60: Type = GSM_Nokia6210StartupLogo; break;
257 }
258 PHONE_DecodeBitmap(Type, buffer2+j, backup->StartupLogo);
259#ifdef DEBUG
260 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,backup->StartupLogo);
261#endif
262 j = j + PHONE_GetBitmapSize(Type,0,0);
263 break;
264 case 2:
265#ifdef DEBUG
266 dbgprintf("Block 2 - welcome note \"");
267 for (z=0;z<buffer2[j];z++) dbgprintf("%c",buffer2[j+z+1]);
268 dbgprintf("\"\n");
269#endif
270 if (backup->StartupLogo == NULL) {
271 backup->StartupLogo = malloc(sizeof(GSM_Bitmap));
272 if (backup->StartupLogo == NULL) return ERR_MOREMEMORY;
273 backup->StartupLogo->Type = GSM_WelcomeNote_Text;
274 EncodeUnicode(backup->StartupLogo->Text,buffer2+j,buffer2[j]);
275 }
276 j = j + buffer2[j];
277 break;
278 default:
279 dbgprintf("Unknown block %02x\n",buffer2[j]);
280 break;
281 }
282 }
283 return ERR_NONE;
284}
285
286static GSM_Error LoadLMBPbkEntry(unsigned char *buffer, unsigned char *buffer2, GSM_Backup *backup)
287{
288 GSM_MemoryEntry pbk;
289 int num;
290
291#ifdef DEBUG
292 dbgprintf("Memory : ");
293 switch(buffer[10]) {
294 case 2 : dbgprintf("(internal)\n"); break;
295 case 3 : dbgprintf("(sim)\n"); break;
296 default: dbgprintf("(unknown)\n"); break;
297 }
298 dbgprintf("Location : %i\n",buffer2[0]+buffer2[1]*256);
299#endif
300
301 N71_65_DecodePhonebook(NULL, &pbk, NULL,NULL,buffer2+4,(buffer[4]+buffer[5]*256)-4,false);
302
303 pbk.MemoryType=MEM_SM;
304 if (buffer[10]==2) pbk.MemoryType=MEM_ME;
305
306 pbk.Location=buffer2[0]+256*buffer2[1];
307
308 num = 0;
309 if (buffer[10]==2) {
310 while (backup->PhonePhonebook[num] != NULL) num++;
311 if (num < GSM_BACKUP_MAX_PHONEPHONEBOOK) {
312 backup->PhonePhonebook[num] = malloc(sizeof(GSM_MemoryEntry));
313 if (backup->PhonePhonebook[num] == NULL) return ERR_MOREMEMORY;
314 backup->PhonePhonebook[num + 1] = NULL;
315 } else {
316 dbgprintf("Increase GSM_BACKUP_MAX_PHONEPHONEBOOK\n");
317 return ERR_MOREMEMORY;
318 }
319 *backup->PhonePhonebook[num] = pbk;
320 } else {
321 while (backup->SIMPhonebook[num] != NULL) num++;
322 if (num < GSM_BACKUP_MAX_SIMPHONEBOOK) {
323 backup->SIMPhonebook[num] = malloc(sizeof(GSM_MemoryEntry));
324 if (backup->SIMPhonebook[num] == NULL) return ERR_MOREMEMORY;
325 backup->SIMPhonebook[num + 1] = NULL;
326 } else {
327 dbgprintf("Increase GSM_BACKUP_MAX_SIMPHONEBOOK\n");
328 return ERR_MOREMEMORY;
329 }
330 *backup->SIMPhonebook[num] = pbk;
331 }
332 return ERR_NONE;
333}
334
335GSM_Error LoadLMB(char *FileName, GSM_Backup *backup)
336{
337#ifdef DEBUG
338 int i;
339#endif
340 unsigned char buffer[12], buffer2[1000];
341 FILE *file;
342 GSM_Errorerror;
343
344 file = fopen(FileName, "rb");
345 if (file == NULL) return(ERR_CANTOPENFILE);
346
347 /* Read the header of the file. */
348 fread(buffer, 1, 4, file);
349
350 /* while we have something to read */
351 while (fread(buffer, 1, 12, file)==12) {
352#ifdef DEBUG
353 /* Info about block in the file */
354 dbgprintf("Block \"");
355 for (i=0;i<4;i++) {dbgprintf("%c",buffer[i]);}
356 dbgprintf("\" (");
357 if (memcmp(buffer, "PBK ",4)==0) { dbgprintf("Phonebook");
358 } else if (memcmp(buffer, "PBE2",4)==0) { dbgprintf("Phonebook entry");
359 } else if (memcmp(buffer, "CGR ",4)==0) { dbgprintf("Caller group");
360 } else if (memcmp(buffer, "SPD ",4)==0) { dbgprintf("Speed dial");
361 } else if (memcmp(buffer, "OLG ",4)==0) { dbgprintf("Operator logo");
362 } else if (memcmp(buffer, "WEL ",4)==0) { dbgprintf("Startup logo and welcome text");
363 } else { dbgprintf("unknown - ignored");
364 }
365 dbgprintf(") - length %i\n", buffer[4]+buffer[5]*256);
366#endif
367 /* reading block data */
368 fread(buffer2, 1, buffer[4]+buffer[5]*256, file);
369
370#ifdef DEBUG
371 if (memcmp(buffer, "PBK ",4)==0) {
372 dbgprintf("Size of phonebook %i, type %i ",(buffer2[0]+buffer2[1]*256),buffer[8]);
373 switch(buffer[8]) {
374 case 2 : dbgprintf("(internal)");break;
375 case 3 : dbgprintf("(sim)") ;break;
376 default: dbgprintf("(unknown)") ;break;
377 }
378 dbgprintf(", length of each position - %i\n",buffer2[2]);
379 }
380#endif
381 if (memcmp(buffer, "PBE2",4)==0) {
382 error = LoadLMBPbkEntry(buffer,buffer2,backup);
383 if (error != ERR_NONE) {
384 fclose(file);
385 return error;
386 }
387 }
388 if (memcmp(buffer, "CGR ",4)==0) {
389 error = LoadLMBCallerEntry(buffer, buffer2, backup);
390 if (error != ERR_NONE) {
391 fclose(file);
392 return error;
393 }
394 }
395 if (memcmp(buffer, "WEL ",4)==0) {
396 error = LoadLMBStartupEntry(buffer, buffer2, backup);
397 if (error != ERR_NONE) {
398 fclose(file);
399 return error;
400 }
401 }
402 }
403
404 fclose(file);
405
406 return ERR_NONE;
407}
408
409#endif
410
411/* How should editor hadle tabs in this file? Add editor commands here.
412 * vim: noexpandtab sw=8 ts=8 sts=8:
413 */
diff --git a/gammu/emb/common/service/backup/backlmb.h b/gammu/emb/common/service/backup/backlmb.h
new file mode 100644
index 0000000..18bba66
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backlmb.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backlmb_h
4#define __gsm_backlmb_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error SaveLMB(char *FileName, GSM_Backup *backup);
10GSM_Error LoadLMB(char *FileName, GSM_Backup *backup);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/backtext.c b/gammu/emb/common/service/backup/backtext.c
new file mode 100644
index 0000000..fee0f73
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backtext.c
@@ -0,0 +1,2908 @@
1/* (c) 2002-2004 by Marcin Wiacek, Walek and Michal Cihar */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/cfg.h"
9#include "../../misc/coding/coding.h"
10#include "../../misc/coding/md5.h"
11#include "../gsmlogo.h"
12#include "../gsmmisc.h"
13#include "backtext.h"
14
15#ifdef GSM_ENABLE_BACKUP
16
17GSM_Error FindBackupChecksum(char *FileName, bool UseUnicode, char *checksum)
18{
19 INI_Section *file_info, *h;
20 INI_Entry *e;
21 char *buffer = NULL,buff[100];
22 int len=0;
23
24 //int i;
25
26 file_info = INI_ReadFile(FileName, UseUnicode);
27
28 if (UseUnicode) {
29 for (h = file_info; h != NULL; h = h->Next) {
30 EncodeUnicode(buff,"Checksum",8);
31 if (mywstrncasecmp(buff, h->SectionName, 8)) continue;
32
33 buffer = (unsigned char *)realloc(buffer,len+UnicodeLength(h->SectionName)*2+2);
34 CopyUnicodeString(buffer+len,h->SectionName);
35 len+=UnicodeLength(h->SectionName)*2;
36 // dbgprintf("[%s]\n",DecodeUnicodeConsole(h->SectionName));
37
38 for (e = h->SubEntries; e != NULL; e = e->Next) {
39 buffer = (unsigned char *)realloc(buffer,len+UnicodeLength(e->EntryName)*2+2);
40 CopyUnicodeString(buffer+len,e->EntryName);
41 len+=UnicodeLength(e->EntryName)*2;
42 buffer = (unsigned char *)realloc(buffer,len+UnicodeLength(e->EntryValue)*2+2);
43 CopyUnicodeString(buffer+len,e->EntryValue);
44 len+=UnicodeLength(e->EntryValue)*2;
45 // dbgprintf("\"%s\"",DecodeUnicodeConsole(e->EntryName));
46 // dbgprintf("=\"%s\"\n",DecodeUnicodeConsole(e->EntryValue));
47 }
48 }
49 } else {
50 for (h = file_info; h != NULL; h = h->Next) {
51 if (mystrncasecmp("Checksum", h->SectionName, 8)) continue;
52
53 buffer = (unsigned char *)realloc(buffer,len+strlen(h->SectionName)+1);
54 strcpy(buffer+len,h->SectionName);
55 len+=strlen(h->SectionName);
56
57 for (e = h->SubEntries; e != NULL; e = e->Next) {
58 // dbgprintf("%s=%s\n",e->EntryName,e->EntryValue);
59 buffer = (unsigned char *)realloc(buffer,len+strlen(e->EntryName)+1);
60 strcpy(buffer+len,e->EntryName);
61 len+=strlen(e->EntryName);
62 buffer = (unsigned char *)realloc(buffer,len+strlen(e->EntryValue)+1);
63 strcpy(buffer+len,e->EntryValue);
64 len+=strlen(e->EntryValue);
65 }
66 }
67 }
68
69 //for (i=0;i<len;i++) printf("%02x",buffer[i]);
70 CalculateMD5(buffer, len, checksum);
71 free(buffer);
72
73 return ERR_NONE;
74}
75
76static unsigned char *ReadCFGText(INI_Section *cfg, unsigned char *section, unsigned char *key, bool Unicode)
77{
78 unsigned char Buffer[500],Buffer2[500],*retval;
79
80 if (Unicode) {
81 EncodeUnicode(Buffer2,key,strlen(key));
82 retval = INI_GetValue(cfg,section,Buffer2,Unicode);
83 if (retval != NULL) return DecodeUnicodeString(retval);
84 return NULL;
85 } else {
86 strcpy(Buffer,section);
87 strcpy(Buffer2,key);
88 return INI_GetValue(cfg,section,key,Unicode);
89 }
90}
91
92static void SaveLinkedBackupText(FILE *file, char *myname, char *myvalue, bool UseUnicode)
93{
94 int w,current;
95 unsigned char buffer2[1000],buffer3[1000];
96
97 current = strlen(myvalue); w = 0;
98 while (true) {
99 if (current > 200) {
100 memcpy(buffer2,myvalue+(strlen(myvalue)-current),200);
101 buffer2[200] = 0;
102 current = current - 200;
103 } else {
104 memcpy(buffer2,myvalue+(strlen(myvalue)-current),current);
105 buffer2[current] = 0;
106 current = 0;
107 }
108 if (UseUnicode) {
109 sprintf(buffer3,"%s%02i = %s%c%c",myname,w,buffer2,13,10);
110 EncodeUnicode(buffer2,buffer3,strlen(buffer3));
111 fwrite(buffer2,1,strlen(buffer3)*2,file);
112 } else {
113 fprintf(file,"%s%02i = %s%c%c",myname,w,buffer2,13,10);
114 }
115 if (current == 0) break;
116 w++;
117 }
118}
119
120static void ReadLinkedBackupText(INI_Section *file_info, char *section, char *myname, char *myvalue, bool UseUnicode)
121{
122 unsigned char buffer2[300];
123 char *readvalue;
124 int i;
125
126 i=0;
127 myvalue[0] = 0;
128 while (true) {
129 sprintf(buffer2,"%s%02i",myname,i);
130 readvalue = ReadCFGText(file_info, section, buffer2, UseUnicode);
131 if (readvalue!=NULL) {
132 myvalue[strlen(myvalue)+strlen(readvalue)]=0;
133 memcpy(myvalue+strlen(myvalue),readvalue,strlen(readvalue));
134 } else break;
135 i++;
136 }
137}
138
139static void SaveBackupText(FILE *file, char *myname, char *myvalue, bool UseUnicode)
140{
141 unsigned char buffer[10000], buffer2[10000];
142
143 if (myname[0] == 0x00) {
144 if (UseUnicode) {
145 EncodeUnicode(buffer,myvalue,strlen(myvalue));
146 fwrite(buffer,1,strlen(myvalue)*2,file);
147 } else fprintf(file,"%s",myvalue);
148 } else {
149 if (UseUnicode) {
150 sprintf(buffer,"%s = \"",myname);
151 EncodeUnicode(buffer2,buffer,strlen(buffer));
152 fwrite(buffer2,1,strlen(buffer)*2,file);
153
154 fwrite(myvalue,1,UnicodeLength(myvalue)*2,file);
155
156 sprintf(buffer,"\"%c%c",13,10);
157 EncodeUnicode(buffer2,buffer,strlen(buffer));
158 fwrite(buffer2,1,strlen(buffer)*2,file);
159 } else {
160 sprintf(buffer,"%s = \"%s\"%c%c",myname,DecodeUnicodeString(myvalue),13,10);
161 fprintf(file,"%s",buffer);
162
163 EncodeHexBin(buffer,myvalue,UnicodeLength(myvalue)*2);
164 fprintf(file,"%sUnicode = %s%c%c",myname,buffer,13,10);
165 }
166 }
167}
168
169static bool ReadBackupText(INI_Section *file_info, char *section, char *myname, char *myvalue, bool UseUnicode)
170{
171 unsigned char paramname[10000],*readvalue;
172
173 if (UseUnicode) {
174 EncodeUnicode(paramname,myname,strlen(myname));
175 readvalue = INI_GetValue(file_info, section, paramname, UseUnicode);
176 if (readvalue!=NULL) {
177 CopyUnicodeString(myvalue,readvalue+2);
178 myvalue[UnicodeLength(readvalue)*2-4]=0;
179 myvalue[UnicodeLength(readvalue)*2-3]=0;
180 dbgprintf("%s\n",DecodeUnicodeString(readvalue));
181 } else {
182 myvalue[0]=0;
183 myvalue[1]=0;
184 return false;
185 }
186 } else {
187 strcpy(paramname,myname);
188 strcat(paramname,"Unicode");
189 readvalue = ReadCFGText(file_info, section, paramname, UseUnicode);
190 if (readvalue!=NULL) {
191 dbgprintf("%s %i\n",readvalue,strlen(readvalue));
192 DecodeHexBin (myvalue, readvalue, strlen(readvalue));
193 myvalue[strlen(readvalue)/2]=0;
194 myvalue[strlen(readvalue)/2+1]=0;
195 dbgprintf("%s\n",DecodeUnicodeString(myvalue));
196 } else {
197 strcpy(paramname,myname);
198 readvalue = ReadCFGText(file_info, section, paramname, UseUnicode);
199 if (readvalue!=NULL) {
200 EncodeUnicode(myvalue,readvalue+1,strlen(readvalue)-2);
201 } else {
202 myvalue[0]=0;
203 myvalue[1]=0;
204 return false;
205 }
206 }
207 }
208 return true;
209}
210
211static void SaveVCalDateTime(FILE *file, GSM_DateTime *dt, bool UseUnicode)
212{
213 unsigned char buffer[100];
214 int Length = 3;
215
216 sprintf(buffer, " = ");
217 SaveVCALDateTime(buffer, &Length, dt, NULL);
218 SaveBackupText(file, "", buffer, UseUnicode);
219}
220
221static void SaveVCalDate(FILE *file, GSM_DateTime *dt, bool UseUnicode)
222{
223 unsigned char buffer[100];
224
225 sprintf(buffer, " = %04d%02d%02d%c%c", dt->Year, dt->Month, dt->Day,13,10);
226 SaveBackupText(file, "", buffer, UseUnicode);
227}
228
229/* ---------------------- backup files ------------------------------------- */
230
231static void SavePbkEntry(FILE *file, GSM_MemoryEntry *Pbk, bool UseUnicode)
232{
233 booltext;
234 charbuffer[1000];
235 intj, i;
236
237 sprintf(buffer,"Location = %03i%c%c",Pbk->Location,13,10);
238 SaveBackupText(file, "", buffer, UseUnicode);
239 for (j=0;j<Pbk->EntriesNum;j++) {
240 text = true;
241 switch (Pbk->Entries[j].EntryType) {
242 case PBK_Number_General:
243 sprintf(buffer,"Entry%02iType = NumberGeneral%c%c",j,13,10);
244 SaveBackupText(file, "", buffer, UseUnicode);
245 break;
246 case PBK_Number_Mobile:
247 sprintf(buffer,"Entry%02iType = NumberMobile%c%c",j,13,10);
248 SaveBackupText(file, "", buffer, UseUnicode);
249 break;
250 case PBK_Number_Work:
251 sprintf(buffer,"Entry%02iType = NumberWork%c%c",j,13,10);
252 SaveBackupText(file, "", buffer, UseUnicode);
253 break;
254 case PBK_Number_Fax:
255 sprintf(buffer,"Entry%02iType = NumberFax%c%c",j,13,10);
256 SaveBackupText(file, "", buffer, UseUnicode);
257 break;
258 case PBK_Number_Home:
259 sprintf(buffer,"Entry%02iType = NumberHome%c%c",j,13,10);
260 SaveBackupText(file, "", buffer, UseUnicode);
261 break;
262 case PBK_Number_Pager:
263 sprintf(buffer,"Entry%02iType = NumberPager%c%c",j,13,10);
264 SaveBackupText(file, "", buffer, UseUnicode);
265 break;
266 case PBK_Number_Other:
267 sprintf(buffer,"Entry%02iType = NumberOther%c%c",j,13,10);
268 SaveBackupText(file, "", buffer, UseUnicode);
269 break;
270 case PBK_Text_Note:
271 sprintf(buffer,"Entry%02iType = Note%c%c",j,13,10);
272 SaveBackupText(file, "", buffer, UseUnicode);
273 break;
274 case PBK_Text_Postal:
275 sprintf(buffer,"Entry%02iType = Postal%c%c",j,13,10);
276 SaveBackupText(file, "", buffer, UseUnicode);
277 break;
278 case PBK_Text_Email:
279 sprintf(buffer,"Entry%02iType = Email%c%c",j,13,10);
280 SaveBackupText(file, "", buffer, UseUnicode);
281 break;
282 case PBK_Text_Email2:
283 sprintf(buffer,"Entry%02iType = Email2%c%c",j,13,10);
284 SaveBackupText(file, "", buffer, UseUnicode);
285 break;
286 case PBK_Text_URL:
287 sprintf(buffer,"Entry%02iType = URL%c%c",j,13,10);
288 SaveBackupText(file, "", buffer, UseUnicode);
289 break;
290 case PBK_Text_Name:
291 sprintf(buffer,"Entry%02iType = Name%c%c",j,13,10);
292 SaveBackupText(file, "", buffer, UseUnicode);
293 break;
294 case PBK_Caller_Group:
295 sprintf(buffer,"Entry%02iType = CallerGroup%c%c",j,13,10);
296 SaveBackupText(file, "", buffer, UseUnicode);
297 sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
298 SaveBackupText(file, "", buffer, UseUnicode);
299 text = false;
300 break;
301 case PBK_RingtoneID:
302 sprintf(buffer,"Entry%02iType = RingtoneID%c%c",j,13,10);
303 SaveBackupText(file, "", buffer, UseUnicode);
304 sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
305 SaveBackupText(file, "", buffer, UseUnicode);
306 text = false;
307 break;
308 case PBK_PictureID:
309 sprintf(buffer,"Entry%02iType = PictureID%c%c",j,13,10);
310 SaveBackupText(file, "", buffer, UseUnicode);
311 sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
312 SaveBackupText(file, "", buffer, UseUnicode);
313 text = false;
314 break;
315 case PBK_Text_UserID:
316 sprintf(buffer,"Entry%02iType = UserID%c%c",j,13,10);
317 SaveBackupText(file, "", buffer, UseUnicode);
318 break;
319 case PBK_Category:
320 sprintf(buffer,"Entry%02iType = Category%c%c",j,13,10);
321 SaveBackupText(file, "", buffer, UseUnicode);
322 sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
323 SaveBackupText(file, "", buffer, UseUnicode);
324 text = false;
325 break;
326 case PBK_Private:
327 sprintf(buffer,"Entry%02iType = Private%c%c",j,13,10);
328 SaveBackupText(file, "", buffer, UseUnicode);
329 sprintf(buffer,"Entry%02iNumber = %i%c%c",j,Pbk->Entries[j].Number,13,10);
330 SaveBackupText(file, "", buffer, UseUnicode);
331 text = false;
332 break;
333 case PBK_Text_LastName:
334 sprintf(buffer,"Entry%02iType = LastName%c%c",j,13,10);
335 SaveBackupText(file, "", buffer, UseUnicode);
336 break;
337 case PBK_Text_FirstName:
338 sprintf(buffer,"Entry%02iType = FirstName%c%c",j,13,10);
339 SaveBackupText(file, "", buffer, UseUnicode);
340 break;
341 case PBK_Text_Company:
342 sprintf(buffer,"Entry%02iType = Company%c%c",j,13,10);
343 SaveBackupText(file, "", buffer, UseUnicode);
344 break;
345 case PBK_Text_JobTitle:
346 sprintf(buffer,"Entry%02iType = JobTitle%c%c",j,13,10);
347 SaveBackupText(file, "", buffer, UseUnicode);
348 break;
349 case PBK_Text_StreetAddress:
350 sprintf(buffer,"Entry%02iType = Address%c%c",j,13,10);
351 SaveBackupText(file, "", buffer, UseUnicode);
352 break;
353 case PBK_Text_City:
354 sprintf(buffer,"Entry%02iType = City%c%c",j,13,10);
355 SaveBackupText(file, "", buffer, UseUnicode);
356 break;
357 case PBK_Text_State:
358 sprintf(buffer,"Entry%02iType = State%c%c",j,13,10);
359 SaveBackupText(file, "", buffer, UseUnicode);
360 break;
361 case PBK_Text_Zip:
362 sprintf(buffer,"Entry%02iType = Zip%c%c",j,13,10);
363 SaveBackupText(file, "", buffer, UseUnicode);
364 break;
365 case PBK_Text_Country:
366 sprintf(buffer,"Entry%02iType = Country%c%c",j,13,10);
367 SaveBackupText(file, "", buffer, UseUnicode);
368 break;
369 case PBK_Text_Custom1:
370 sprintf(buffer,"Entry%02iType = Custom1%c%c",j,13,10);
371 SaveBackupText(file, "", buffer, UseUnicode);
372 break;
373 case PBK_Text_Custom2:
374 sprintf(buffer,"Entry%02iType = Custom2%c%c",j,13,10);
375 SaveBackupText(file, "", buffer, UseUnicode);
376 break;
377 case PBK_Text_Custom3:
378 sprintf(buffer,"Entry%02iType = Custom3%c%c",j,13,10);
379 SaveBackupText(file, "", buffer, UseUnicode);
380 break;
381 case PBK_Text_Custom4:
382 sprintf(buffer,"Entry%02iType = Custom4%c%c",j,13,10);
383 SaveBackupText(file, "", buffer, UseUnicode);
384 break;
385 case PBK_SMSListID:
386 case PBK_RingtoneFileSystemID:
387 case PBK_Date:
388 break;
389 }
390 if (text) {
391 sprintf(buffer,"Entry%02iText",j);
392 SaveBackupText(file,buffer,Pbk->Entries[j].Text, UseUnicode);
393 }
394 switch (Pbk->Entries[j].EntryType) {
395 case PBK_Number_General:
396 case PBK_Number_Mobile:
397 case PBK_Number_Work:
398 case PBK_Number_Fax:
399 case PBK_Number_Home:
400 case PBK_Number_Other:
401 case PBK_Number_Pager:
402 if (Pbk->Entries[j].VoiceTag!=0) {
403 sprintf(buffer,"Entry%02iVoiceTag = %i%c%c",j,Pbk->Entries[j].VoiceTag,13,10);
404 SaveBackupText(file, "", buffer, UseUnicode);
405 }
406 i = 0;
407 while (Pbk->Entries[j].SMSList[i]!=0) {
408 sprintf(buffer,"Entry%02iSMSList%02i = %i%c%c",j,i,Pbk->Entries[j].SMSList[i],13,10);
409 SaveBackupText(file, "", buffer, UseUnicode);
410 i++;
411 }
412 break;
413 default:
414 break;
415 }
416 }
417 sprintf(buffer,"%c%c",13,10);
418 SaveBackupText(file, "", buffer, UseUnicode);
419}
420
421static void SaveCalendarEntry(FILE *file, GSM_CalendarEntry *Note, bool UseUnicode)
422{
423 int i;
424 charbuffer[1000];
425
426 sprintf(buffer,"Location = %d%c%c", Note->Location,13,10);
427 SaveBackupText(file, "", buffer, UseUnicode);
428 SaveBackupText(file, "", "Type = ", UseUnicode);
429 switch (Note->Type) {
430 case GSM_CAL_REMINDER : sprintf(buffer,"Reminder%c%c", 13,10); break;
431 case GSM_CAL_CALL : sprintf(buffer,"Call%c%c", 13,10); break;
432 case GSM_CAL_MEETING : sprintf(buffer,"Meeting%c%c", 13,10); break;
433 case GSM_CAL_BIRTHDAY : sprintf(buffer,"Birthday%c%c", 13,10); break;
434 case GSM_CAL_TRAVEL : sprintf(buffer,"Travel%c%c", 13,10); break;
435 case GSM_CAL_VACATION : sprintf(buffer,"Vacation%c%c", 13,10); break;
436 case GSM_CAL_MEMO : sprintf(buffer,"Memo%c%c", 13,10); break;
437 case GSM_CAL_ALARM : sprintf(buffer,"Alarm%c%c", 13,10); break;
438 case GSM_CAL_DAILY_ALARM : sprintf(buffer,"DailyAlarm%c%c", 13,10); break;
439 case GSM_CAL_T_ATHL : sprintf(buffer,"Training/Athletism%c%c", 13,10); break;
440 case GSM_CAL_T_BALL : sprintf(buffer,"Training/BallGames%c%c", 13,10); break;
441 case GSM_CAL_T_CYCL : sprintf(buffer,"Training/Cycling%c%c", 13,10); break;
442 case GSM_CAL_T_BUDO : sprintf(buffer,"Training/Budo%c%c", 13,10); break;
443 case GSM_CAL_T_DANC : sprintf(buffer,"Training/Dance%c%c", 13,10); break;
444 case GSM_CAL_T_EXTR : sprintf(buffer,"Training/ExtremeSports%c%c", 13,10); break;
445 case GSM_CAL_T_FOOT : sprintf(buffer,"Training/Football%c%c", 13,10); break;
446 case GSM_CAL_T_GOLF : sprintf(buffer,"Training/Golf%c%c", 13,10); break;
447 case GSM_CAL_T_GYM : sprintf(buffer,"Training/Gym%c%c", 13,10); break;
448 case GSM_CAL_T_HORS : sprintf(buffer,"Training/HorseRaces%c%c", 13,10); break;
449 case GSM_CAL_T_HOCK : sprintf(buffer,"Training/Hockey%c%c", 13,10); break;
450 case GSM_CAL_T_RACE : sprintf(buffer,"Training/Races%c%c", 13,10); break;
451 case GSM_CAL_T_RUGB : sprintf(buffer,"Training/Rugby%c%c", 13,10); break;
452 case GSM_CAL_T_SAIL : sprintf(buffer,"Training/Sailing%c%c", 13,10); break;
453 case GSM_CAL_T_STRE : sprintf(buffer,"Training/StreetGames%c%c",13,10); break;
454 case GSM_CAL_T_SWIM : sprintf(buffer,"Training/Swimming%c%c", 13,10); break;
455 case GSM_CAL_T_TENN : sprintf(buffer,"Training/Tennis%c%c", 13,10); break;
456 case GSM_CAL_T_TRAV : sprintf(buffer,"Training/Travels%c%c", 13,10); break;
457 case GSM_CAL_T_WINT : sprintf(buffer,"Training/WinterGames%c%c", 13,10); break;
458 }
459 SaveBackupText(file, "", buffer, UseUnicode);
460 for (i=0;i<Note->EntriesNum;i++) {
461 switch (Note->Entries[i].EntryType) {
462 case CAL_START_DATETIME:
463 SaveBackupText(file, "", "StartTime", UseUnicode);
464 SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
465 break;
466 case CAL_END_DATETIME:
467 SaveBackupText(file, "", "StopTime", UseUnicode);
468 SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
469 break;
470 case CAL_ALARM_DATETIME:
471 SaveBackupText(file, "", "Alarm", UseUnicode);
472 SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
473 sprintf(buffer,"AlarmType = Tone%c%c",13,10);
474 SaveBackupText(file, "", buffer, UseUnicode);
475 break;
476 case CAL_SILENT_ALARM_DATETIME:
477 SaveBackupText(file, "", "Alarm", UseUnicode);
478 SaveVCalDateTime(file, &Note->Entries[i].Date, UseUnicode);
479 sprintf(buffer,"AlarmType = Silent%c%c",13,10);
480 SaveBackupText(file, "", buffer, UseUnicode);
481 break;
482 case CAL_PRIVATE:
483 sprintf(buffer, "Private = %d%c%c",Note->Entries[i].Number,13,10);
484 SaveBackupText(file, "", buffer, UseUnicode);
485 break;
486 case CAL_LOCATION:
487 SaveBackupText(file, "EventLocation", Note->Entries[i].Text, UseUnicode);
488 break;
489 case CAL_CONTACTID:
490 sprintf(buffer, "ContactID = %d%c%c",Note->Entries[i].Number,13,10);
491 SaveBackupText(file, "", buffer, UseUnicode);
492 break;
493 case CAL_RECURRANCE:
494 sprintf(buffer, "Recurrance = %d%c%c",Note->Entries[i].Number/24,13,10);
495 SaveBackupText(file, "", buffer, UseUnicode);
496 break;
497 case CAL_TEXT:
498 SaveBackupText(file, "Text", Note->Entries[i].Text, UseUnicode);
499 break;
500 case CAL_PHONE:
501 SaveBackupText(file, "Phone", Note->Entries[i].Text, UseUnicode);
502 break;
503 case CAL_REPEAT_STOPDATE:
504 SaveBackupText(file, "", "RepeatStopDate", UseUnicode);
505 SaveVCalDate(file, &Note->Entries[i].Date, UseUnicode);
506 break;
507 case CAL_REPEAT_STARTDATE:
508 SaveBackupText(file, "", "RepeatStartDate", UseUnicode);
509 SaveVCalDate(file, &Note->Entries[i].Date, UseUnicode);
510 break;
511 case CAL_REPEAT_DAYOFWEEK:
512 sprintf(buffer, "RepeatDayOfWeek = %d%c%c",Note->Entries[i].Number,13,10);
513 SaveBackupText(file, "", buffer, UseUnicode);
514 break;
515 case CAL_REPEAT_DAY:
516 sprintf(buffer, "RepeatDay = %d%c%c",Note->Entries[i].Number,13,10);
517 SaveBackupText(file, "", buffer, UseUnicode);
518 break;
519 case CAL_REPEAT_WEEKOFMONTH:
520 sprintf(buffer, "RepeatWeekOfMonth = %d%c%c",Note->Entries[i].Number,13,10);
521 SaveBackupText(file, "", buffer, UseUnicode);
522 break;
523 case CAL_REPEAT_MONTH:
524 sprintf(buffer, "RepeatMonth = %d%c%c",Note->Entries[i].Number,13,10);
525 SaveBackupText(file, "", buffer, UseUnicode);
526 break;
527 case CAL_REPEAT_FREQUENCY:
528 sprintf(buffer, "RepeatFrequency = %d%c%c",Note->Entries[i].Number,13,10);
529 SaveBackupText(file, "", buffer, UseUnicode);
530 break;
531 }
532 }
533 sprintf(buffer, "%c%c",13,10);
534 SaveBackupText(file, "", buffer, UseUnicode);
535}
536
537static void SaveWAPSettingsEntry(FILE *file, GSM_MultiWAPSettings *settings, bool UseUnicode)
538{
539 int i;
540 char buffer[10000];
541
542 if (settings->Active) {
543 sprintf(buffer,"Active = Yes%c%c",13,10);
544 SaveBackupText(file, "", buffer, UseUnicode);
545 }
546 switch (settings->ActiveBearer) {
547 case WAPSETTINGS_BEARER_SMS : sprintf(buffer,"Bearer = SMS%c%c",13,10); break;
548 case WAPSETTINGS_BEARER_GPRS: sprintf(buffer,"Bearer = GPRS%c%c",13,10); break;
549 case WAPSETTINGS_BEARER_DATA: sprintf(buffer,"Bearer = Data%c%c",13,10); break;
550 case WAPSETTINGS_BEARER_USSD: sprintf(buffer,"Bearer = USSD%c%c",13,10);
551 }
552 SaveBackupText(file, "", buffer, UseUnicode);
553 if (settings->ReadOnly) {
554 sprintf(buffer,"ReadOnly = Yes%c%c",13,10);
555 SaveBackupText(file, "", buffer, UseUnicode);
556 }
557 sprintf(buffer,"Proxy");
558 SaveBackupText(file, buffer, settings->Proxy, UseUnicode);
559 sprintf(buffer,"ProxyPort = %i%c%c",settings->ProxyPort,13,10);
560 SaveBackupText(file, "", buffer, UseUnicode);
561 sprintf(buffer,"Proxy2");
562 SaveBackupText(file, buffer, settings->Proxy2, UseUnicode);
563 sprintf(buffer,"Proxy2Port = %i%c%c",settings->Proxy2Port,13,10);
564 SaveBackupText(file, "", buffer, UseUnicode);
565 sprintf(buffer,"%c%c",13,10);
566 SaveBackupText(file, "", buffer, UseUnicode);
567 for (i=0;i<settings->Number;i++) {
568 sprintf(buffer,"Title%02i",i);
569 SaveBackupText(file, buffer, settings->Settings[i].Title, UseUnicode);
570 sprintf(buffer,"HomePage%02i",i);
571 SaveBackupText(file, buffer, settings->Settings[i].HomePage, UseUnicode);
572 if (settings->Settings[i].IsContinuous) {
573 sprintf(buffer,"Type%02i = Continuous%c%c",i,13,10);
574 } else {
575 sprintf(buffer,"Type%02i = Temporary%c%c",i,13,10);
576 }
577 SaveBackupText(file, "", buffer, UseUnicode);
578 if (settings->Settings[i].IsSecurity) {
579 sprintf(buffer,"Security%02i = On%c%c",i,13,10);
580 } else {
581 sprintf(buffer,"Security%02i = Off%c%c",i,13,10);
582 }
583 SaveBackupText(file, "", buffer, UseUnicode);
584 switch (settings->Settings[i].Bearer) {
585 case WAPSETTINGS_BEARER_SMS:
586 sprintf(buffer,"Bearer%02i = SMS%c%c",i,13,10);
587 SaveBackupText(file, "", buffer, UseUnicode);
588 sprintf(buffer,"Server%02i",i);
589 SaveBackupText(file, buffer, settings->Settings[i].Server, UseUnicode);
590 sprintf(buffer,"Service%02i",i);
591 SaveBackupText(file, buffer, settings->Settings[i].Service, UseUnicode);
592 break;
593 case WAPSETTINGS_BEARER_GPRS:
594 sprintf(buffer,"Bearer%02i = GPRS%c%c",i,13,10);
595 SaveBackupText(file, "", buffer, UseUnicode);
596 sprintf(buffer,"IP%02i",i);
597 SaveBackupText(file, buffer, settings->Settings[i].IPAddress, UseUnicode);
598 case WAPSETTINGS_BEARER_DATA:
599 if (settings->Settings[i].Bearer == WAPSETTINGS_BEARER_DATA) {
600 sprintf(buffer,"Bearer%02i = Data%c%c",i,13,10);
601 SaveBackupText(file, "", buffer, UseUnicode);
602 if (settings->Settings[i].IsISDNCall) {
603 sprintf(buffer,"CallType%02i = ISDN%c%c",i,13,10);
604 } else {
605 sprintf(buffer,"CallType%02i = Analogue%c%c",i,13,10);
606 }
607 SaveBackupText(file, "", buffer, UseUnicode);
608 sprintf(buffer,"IP%02i",i);
609 SaveBackupText(file, buffer, settings->Settings[i].IPAddress, UseUnicode);
610 }
611 sprintf(buffer,"Number%02i",i);
612 SaveBackupText(file, buffer, settings->Settings[i].DialUp, UseUnicode);
613 if (settings->Settings[i].ManualLogin) {
614 sprintf(buffer,"Login%02i = Manual%c%c",i,13,10);
615 } else {
616 sprintf(buffer,"Login%02i = Automatic%c%c",i,13,10);
617 }
618 SaveBackupText(file, "", buffer, UseUnicode);
619 if (settings->Settings[i].IsNormalAuthentication) {
620 sprintf(buffer,"Authentication%02i = Normal%c%c",i,13,10);
621 } else {
622 sprintf(buffer,"Authentication%02i = Secure%c%c",i,13,10);
623 }
624 SaveBackupText(file, "", buffer, UseUnicode);
625 switch (settings->Settings[i].Speed) {
626 case WAPSETTINGS_SPEED_9600 : sprintf(buffer,"CallSpeed%02i = 9600%c%c" ,i,13,10); break;
627 case WAPSETTINGS_SPEED_14400: sprintf(buffer,"CallSpeed%02i = 14400%c%c",i,13,10); break;
628 case WAPSETTINGS_SPEED_AUTO : sprintf(buffer,"CallSpeed%02i = auto%c%c" ,i,13,10); break;
629 }
630 switch (settings->Settings[i].Speed) {
631 case WAPSETTINGS_SPEED_9600 :
632 case WAPSETTINGS_SPEED_14400:
633 case WAPSETTINGS_SPEED_AUTO :
634 SaveBackupText(file, "", buffer, UseUnicode);
635 default:
636 break;
637 }
638 sprintf(buffer,"User%02i",i);
639 SaveBackupText(file, buffer, settings->Settings[i].User, UseUnicode);
640 sprintf(buffer,"Password%02i",i);
641 SaveBackupText(file, buffer, settings->Settings[i].Password, UseUnicode);
642 break;
643 case WAPSETTINGS_BEARER_USSD:
644 sprintf(buffer,"Bearer%02i = USSD%c%c",i,13,10);
645 SaveBackupText(file, "", buffer, UseUnicode);
646 sprintf(buffer,"ServiceCode%02i",i);
647 SaveBackupText(file, buffer, settings->Settings[i].Code, UseUnicode);
648 if (settings->Settings[i].IsIP) {
649 sprintf(buffer,"IP%02i",i);
650 } else {
651 sprintf(buffer,"Number%02i",i);
652 }
653 SaveBackupText(file, buffer, settings->Settings[i].Service, UseUnicode);
654 }
655 sprintf(buffer,"%c%c",13,10);
656 SaveBackupText(file, "", buffer, UseUnicode);
657 }
658}
659
660static void SaveBitmapEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
661{
662 unsigned char buffer[10000],buffer2[10000];
663 int x,y;
664
665 sprintf(buffer,"Width = %i%c%c",bitmap->BitmapWidth,13,10);
666 SaveBackupText(file, "", buffer, UseUnicode);
667 sprintf(buffer,"Height = %i%c%c",bitmap->BitmapHeight,13,10);
668 SaveBackupText(file, "", buffer, UseUnicode);
669 for (y=0;y<bitmap->BitmapHeight;y++) {
670 for (x=0;x<bitmap->BitmapWidth;x++) {
671 buffer[x] = ' ';
672 if (GSM_IsPointBitmap(bitmap,x,y)) buffer[x]='#';
673 }
674 buffer[bitmap->BitmapWidth] = 0;
675 sprintf(buffer2,"Bitmap%02i = \"%s\"%c%c",y,buffer,13,10);
676 SaveBackupText(file, "", buffer2, UseUnicode);
677 }
678}
679
680static void SaveCallerEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
681{
682 unsigned char buffer[1000];
683
684 sprintf(buffer,"Location = %03i%c%c",bitmap->Location,13,10);
685 SaveBackupText(file, "", buffer, UseUnicode);
686 if (!bitmap->DefaultName) SaveBackupText(file, "Name", bitmap->Text, UseUnicode);
687 if (!bitmap->DefaultRingtone) {
688 if (bitmap->FileSystemRingtone) {
689 sprintf(buffer,"FileRingtone = %02x%c%c",bitmap->RingtoneID,13,10);
690 } else {
691 sprintf(buffer,"Ringtone = %02x%c%c",bitmap->RingtoneID,13,10);
692 }
693 SaveBackupText(file, "", buffer, UseUnicode);
694 }
695 if (bitmap->BitmapEnabled) {
696 sprintf(buffer,"Enabled = True%c%c",13,10);
697 } else {
698 sprintf(buffer,"Enabled = False%c%c",13,10);
699 }
700 SaveBackupText(file, "", buffer, UseUnicode);
701 if (!bitmap->DefaultBitmap) SaveBitmapEntry(file, bitmap, UseUnicode);
702 sprintf(buffer,"%c%c",13,10);
703 SaveBackupText(file, "", buffer, UseUnicode);
704}
705
706static void SaveWAPBookmarkEntry(FILE *file, GSM_WAPBookmark *bookmark, bool UseUnicode)
707{
708 unsigned char buffer[1000];
709
710 SaveBackupText(file, "URL", bookmark->Address, UseUnicode);
711 SaveBackupText(file, "Title", bookmark->Title, UseUnicode);
712 sprintf(buffer,"%c%c",13,10);
713 SaveBackupText(file, "", buffer, UseUnicode);
714}
715
716static void SaveStartupEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
717{
718 unsigned char buffer[1000];
719
720 sprintf(buffer,"[Startup]%c%c",13,10);
721 SaveBackupText(file, "", buffer, UseUnicode);
722 if (bitmap->Type == GSM_WelcomeNote_Text) {
723 SaveBackupText(file, "Text", bitmap->Text, UseUnicode);
724 }
725 if (bitmap->Type == GSM_StartupLogo) {
726 SaveBitmapEntry(file, bitmap, UseUnicode);
727 }
728 sprintf(buffer,"%c%c",13,10);
729 SaveBackupText(file, "", buffer, UseUnicode);
730}
731
732static void SaveSMSCEntry(FILE *file, GSM_SMSC *SMSC, bool UseUnicode)
733{
734 unsigned char buffer[1000];
735
736 sprintf(buffer,"Location = %03i%c%c",SMSC->Location,13,10);
737 SaveBackupText(file, "", buffer, UseUnicode);
738 SaveBackupText(file, "Name", SMSC->Name, UseUnicode);
739 SaveBackupText(file, "Number", SMSC->Number, UseUnicode);
740 SaveBackupText(file, "DefaultNumber", SMSC->DefaultNumber, UseUnicode);
741 SaveBackupText(file, "", "Format = ", UseUnicode);
742 switch (SMSC->Format) {
743 case SMS_FORMAT_Text: sprintf(buffer,"Text"); break;
744 case SMS_FORMAT_Fax: sprintf(buffer,"Fax"); break;
745 case SMS_FORMAT_Email: sprintf(buffer,"Email"); break;
746 case SMS_FORMAT_Pager: sprintf(buffer,"Pager"); break;
747 }
748 SaveBackupText(file, "", buffer, UseUnicode);
749 sprintf(buffer,"%c%cValidity = ",13,10);
750 SaveBackupText(file, "", buffer, UseUnicode);
751 switch (SMSC->Validity.Relative) {
752 case SMS_VALID_1_Hour : sprintf(buffer, "1hour"); break;
753 case SMS_VALID_6_Hours : sprintf(buffer, "6hours"); break;
754 case SMS_VALID_1_Day : sprintf(buffer, "24hours"); break;
755 case SMS_VALID_3_Days : sprintf(buffer, "72hours"); break;
756 case SMS_VALID_1_Week : sprintf(buffer, "1week"); break;
757 case SMS_VALID_Max_Time:
758 default : sprintf(buffer,"MaximumTime"); break;
759 }
760 SaveBackupText(file, "", buffer, UseUnicode);
761 sprintf(buffer,"%c%c%c%c",13,10,13,10);
762 SaveBackupText(file, "", buffer, UseUnicode);
763}
764
765static void SaveRingtoneEntry(FILE *file, GSM_Ringtone *ringtone, bool UseUnicode)
766{
767 unsigned char buffer[45000];
768 int i,j;
769
770 sprintf(buffer,"Location = %i%c%c",ringtone->Location,13,10);
771 SaveBackupText(file, "", buffer, UseUnicode);
772 SaveBackupText(file, "Name", ringtone->Name, UseUnicode);
773 switch (ringtone->Format) {
774 case RING_NOKIABINARY:
775 j = 0; i = 0;
776 EncodeHexBin(buffer,ringtone->NokiaBinary.Frame,ringtone->NokiaBinary.Length);
777 SaveLinkedBackupText(file, "NokiaBinary", buffer, UseUnicode);
778 break;
779 case RING_MIDI:
780 j = 0; i = 0;
781 EncodeHexBin(buffer,ringtone->NokiaBinary.Frame,ringtone->NokiaBinary.Length);
782 SaveLinkedBackupText(file, "Pure Midi", buffer, UseUnicode);
783 break;
784 case RING_NOTETONE:
785 break;
786 }
787 sprintf(buffer,"%c%c",13,10);
788 SaveBackupText(file, "", buffer, UseUnicode);
789}
790
791static void SaveOperatorEntry(FILE *file, GSM_Bitmap *bitmap, bool UseUnicode)
792{
793 unsigned char buffer[1000];
794
795 sprintf(buffer,"[Operator]%c%c",13,10);
796 SaveBackupText(file, "", buffer, UseUnicode);
797 sprintf(buffer,"Network = \"%s\"%c%c", bitmap->NetworkCode,13,10);
798 SaveBackupText(file, "", buffer, UseUnicode);
799 SaveBitmapEntry(file, bitmap, UseUnicode);
800 sprintf(buffer,"%c%c",13,10);
801 SaveBackupText(file, "", buffer, UseUnicode);
802}
803
804static void SaveToDoEntry(FILE *file, GSM_ToDoEntry *ToDo, bool UseUnicode)
805{
806 unsigned char buffer[1000];
807 int j;
808
809 sprintf(buffer,"Location = %i%c%c",ToDo->Location,13,10);
810 SaveBackupText(file, "", buffer, UseUnicode);
811 switch (ToDo->Priority) {
812 case GSM_Priority_High:
813 sprintf(buffer,"Priority = High%c%c",13,10);
814 break;
815 case GSM_Priority_Medium:
816 sprintf(buffer,"Priority = Medium%c%c",13,10);
817 break;
818 case GSM_Priority_Low:
819 sprintf(buffer,"Priority = Low%c%c",13,10);
820 break;
821 }
822 SaveBackupText(file, "", buffer, UseUnicode);
823
824 for (j=0;j<ToDo->EntriesNum;j++) {
825 switch (ToDo->Entries[j].EntryType) {
826 case TODO_END_DATETIME:
827 SaveBackupText(file, "", "DueTime", UseUnicode);
828 SaveVCalDateTime(file, &ToDo->Entries[j].Date, UseUnicode);
829 break;
830 case TODO_COMPLETED:
831 sprintf(buffer,"Completed = %s%c%c",ToDo->Entries[j].Number == 1 ? "yes" : "no" ,13,10);
832 SaveBackupText(file, "", buffer, UseUnicode);
833 break;
834 case TODO_ALARM_DATETIME:
835 SaveBackupText(file, "", "Alarm", UseUnicode);
836 SaveVCalDateTime(file, &ToDo->Entries[j].Date, UseUnicode);
837 break;
838 case TODO_SILENT_ALARM_DATETIME:
839 SaveBackupText(file, "", "SilentAlarm", UseUnicode);
840 SaveVCalDateTime(file, &ToDo->Entries[j].Date, UseUnicode);
841 break;
842 case TODO_TEXT:
843 SaveBackupText(file, "Text", ToDo->Entries[j].Text, UseUnicode);
844 break;
845 case TODO_PRIVATE:
846 sprintf(buffer,"Private = %i%c%c",ToDo->Entries[j].Number,13,10);
847 SaveBackupText(file, "", buffer, UseUnicode);
848 break;
849 case TODO_CATEGORY:
850 sprintf(buffer,"Category = %i%c%c",ToDo->Entries[j].Number,13,10);
851 SaveBackupText(file, "", buffer, UseUnicode);
852 break;
853 case TODO_CONTACTID:
854 sprintf(buffer,"ContactID = %i%c%c",ToDo->Entries[j].Number,13,10);
855 SaveBackupText(file, "", buffer, UseUnicode);
856 break;
857 case TODO_PHONE:
858 SaveBackupText(file, "Phone", ToDo->Entries[j].Text, UseUnicode);
859 break;
860 }
861 }
862 sprintf(buffer,"%c%c",13,10);
863 SaveBackupText(file, "", buffer, UseUnicode);
864}
865
866static void SaveProfileEntry(FILE *file, GSM_Profile *Profile, bool UseUnicode)
867{
868 int j,k;
869 bool special;
870 unsigned char buffer[1000];
871
872 sprintf(buffer,"Location = %i%c%c",Profile->Location,13,10);
873 SaveBackupText(file, "", buffer, UseUnicode);
874 SaveBackupText(file, "Name",Profile->Name, UseUnicode);
875
876 if (Profile->DefaultName) {
877 sprintf(buffer,"DefaultName = true%c%c",13,10);
878 SaveBackupText(file, "", buffer, UseUnicode);
879 }
880 if (Profile->HeadSetProfile) {
881 sprintf(buffer,"HeadSetProfile = true%c%c",13,10);
882 SaveBackupText(file, "", buffer, UseUnicode);
883 }
884 if (Profile->CarKitProfile) {
885 sprintf(buffer,"CarKitProfile = true%c%c",13,10);
886 SaveBackupText(file, "", buffer, UseUnicode);
887 }
888
889 for (j=0;j<Profile->FeaturesNumber;j++) {
890 sprintf(buffer,"Feature%02i = ",j);
891 SaveBackupText(file, "", buffer, UseUnicode);
892 special = false;
893 switch (Profile->FeatureID[j]) {
894 case Profile_MessageToneID:
895 case Profile_RingtoneID:
896 special = true;
897 if (Profile->FeatureID[j] == Profile_RingtoneID) {
898 sprintf(buffer,"RingtoneID%c%c",13,10);
899 } else {
900 sprintf(buffer,"MessageToneID%c%c",13,10);
901 }
902 SaveBackupText(file, "", buffer, UseUnicode);
903 sprintf(buffer,"Value%02i = %i%c%c",j,Profile->FeatureValue[j],13,10);
904 SaveBackupText(file, "", buffer, UseUnicode);
905 break;
906 case Profile_CallerGroups:
907 special = true;
908 sprintf(buffer,"CallerGroups%c%c",13,10);
909 SaveBackupText(file, "", buffer, UseUnicode);
910 sprintf(buffer,"Value%02i = ",j);
911 SaveBackupText(file, "", buffer, UseUnicode);
912 for (k=0;k<5;k++) {
913 if (Profile->CallerGroups[k]) {
914 sprintf(buffer,"%i",k);
915 SaveBackupText(file, "", buffer, UseUnicode);
916 }
917 }
918 sprintf(buffer,"%c%c",13,10);
919 SaveBackupText(file, "", buffer, UseUnicode);
920 break;
921 case Profile_ScreenSaverNumber:
922 special = true;
923 sprintf(buffer,"ScreenSaverNumber%c%c",13,10);
924 SaveBackupText(file, "", buffer, UseUnicode);
925 sprintf(buffer,"Value%02i = %i%c%c",j,Profile->FeatureValue[j],13,10);
926 SaveBackupText(file, "", buffer, UseUnicode);
927 break;
928 case Profile_CallAlert : sprintf(buffer,"IncomingCallAlert%c%c",13,10); break;
929 case Profile_RingtoneVolume : sprintf(buffer,"RingtoneVolume%c%c",13,10); break;
930 case Profile_Vibration : sprintf(buffer,"Vibrating%c%c",13,10); break;
931 case Profile_MessageTone : sprintf(buffer,"MessageTone%c%c",13,10); break;
932 case Profile_KeypadTone : sprintf(buffer,"KeypadTones%c%c",13,10); break;
933 case Profile_WarningTone : sprintf(buffer,"WarningTones%c%c",13,10); break;
934 case Profile_ScreenSaver : sprintf(buffer,"ScreenSaver%c%c",13,10); break;
935 case Profile_ScreenSaverTime : sprintf(buffer,"ScreenSaverTimeout%c%c",13,10); break;
936 case Profile_AutoAnswer : sprintf(buffer,"AutomaticAnswer%c%c",13,10); break;
937 case Profile_Lights : sprintf(buffer,"Lights%c%c",13,10); break;
938 default : special = true;
939 }
940 if (!special) {
941 SaveBackupText(file, "", buffer, UseUnicode);
942 sprintf(buffer,"Value%02i = ",j);
943 SaveBackupText(file, "", buffer, UseUnicode);
944 switch (Profile->FeatureValue[j]) {
945 case PROFILE_VOLUME_LEVEL1 :
946 case PROFILE_KEYPAD_LEVEL1 : sprintf(buffer,"Level1%c%c",13,10); break;
947 case PROFILE_VOLUME_LEVEL2 :
948 case PROFILE_KEYPAD_LEVEL2 : sprintf(buffer,"Level2%c%c",13,10); break;
949 case PROFILE_VOLUME_LEVEL3 :
950 case PROFILE_KEYPAD_LEVEL3 : sprintf(buffer,"Level3%c%c",13,10); break;
951 case PROFILE_VOLUME_LEVEL4 : sprintf(buffer,"Level4%c%c",13,10); break;
952 case PROFILE_VOLUME_LEVEL5 : sprintf(buffer,"Level5%c%c",13,10); break;
953 case PROFILE_MESSAGE_NOTONE :
954 case PROFILE_AUTOANSWER_OFF :
955 case PROFILE_LIGHTS_OFF :
956 case PROFILE_SAVER_OFF :
957 case PROFILE_WARNING_OFF :
958 case PROFILE_CALLALERT_OFF :
959 case PROFILE_VIBRATION_OFF :
960 case PROFILE_KEYPAD_OFF : sprintf(buffer,"Off%c%c",13,10); break;
961 case PROFILE_CALLALERT_RINGING : sprintf(buffer,"Ringing%c%c",13,10); break;
962 case PROFILE_CALLALERT_RINGONCE : sprintf(buffer,"RingOnce%c%c",13,10); break;
963 case PROFILE_CALLALERT_ASCENDING : sprintf(buffer,"Ascending%c%c",13,10); break;
964 case PROFILE_CALLALERT_CALLERGROUPS : sprintf(buffer,"CallerGroups%c%c",13,10);break;
965 case PROFILE_MESSAGE_STANDARD : sprintf(buffer,"Standard%c%c",13,10); break;
966 case PROFILE_MESSAGE_SPECIAL : sprintf(buffer,"Special%c%c",13,10); break;
967 case PROFILE_MESSAGE_BEEPONCE :
968 case PROFILE_CALLALERT_BEEPONCE : sprintf(buffer,"BeepOnce%c%c",13,10); break;
969 case PROFILE_MESSAGE_ASCENDING : sprintf(buffer,"Ascending%c%c",13,10); break;
970 case PROFILE_MESSAGE_PERSONAL : sprintf(buffer,"Personal%c%c",13,10); break;
971 case PROFILE_AUTOANSWER_ON :
972 case PROFILE_WARNING_ON :
973 case PROFILE_SAVER_ON :
974 case PROFILE_VIBRATION_ON : sprintf(buffer,"On%c%c",13,10); break;
975 case PROFILE_VIBRATION_FIRST : sprintf(buffer,"VibrateFirst%c%c",13,10);break;
976 case PROFILE_LIGHTS_AUTO : sprintf(buffer,"Auto%c%c",13,10); break;
977 case PROFILE_SAVER_TIMEOUT_5SEC : sprintf(buffer,"5Seconds%c%c",13,10); break;
978 case PROFILE_SAVER_TIMEOUT_20SEC : sprintf(buffer,"20Seconds%c%c",13,10); break;
979 case PROFILE_SAVER_TIMEOUT_1MIN : sprintf(buffer,"1Minute%c%c",13,10); break;
980 case PROFILE_SAVER_TIMEOUT_2MIN : sprintf(buffer,"2Minutes%c%c",13,10); break;
981 case PROFILE_SAVER_TIMEOUT_5MIN : sprintf(buffer,"5Minutes%c%c",13,10); break;
982 case PROFILE_SAVER_TIMEOUT_10MIN : sprintf(buffer,"10Minutes%c%c",13,10);break;
983 default : sprintf(buffer,"UNKNOWN%c%c",13,10);
984 }
985 SaveBackupText(file, "", buffer, UseUnicode);
986 }
987 }
988 sprintf(buffer,"%c%c",13,10);
989 SaveBackupText(file, "", buffer, UseUnicode);
990}
991
992static void SaveFMStationEntry(FILE *file, GSM_FMStation *FMStation, bool UseUnicode)
993{
994 unsigned char buffer[1000];
995
996 sprintf(buffer,"Location = %i%c%c",FMStation->Location,13,10);
997 SaveBackupText(file, "", buffer, UseUnicode);
998 SaveBackupText(file, "StationName", FMStation->StationName, UseUnicode);
999 sprintf(buffer,"Frequency = %f%c%c",FMStation->Frequency,13,10);
1000 SaveBackupText(file, "", buffer, UseUnicode);
1001 sprintf(buffer,"%c%c",13,10);
1002 SaveBackupText(file, "", buffer, UseUnicode);
1003}
1004
1005static void SaveGPRSPointEntry(FILE *file, GSM_GPRSAccessPoint *GPRSPoint, bool UseUnicode)
1006{
1007 unsigned char buffer[1000];
1008
1009 sprintf(buffer,"Location = %i%c%c",GPRSPoint->Location,13,10);
1010 SaveBackupText(file, "", buffer, UseUnicode);
1011 SaveBackupText(file, "Name", GPRSPoint->Name, UseUnicode);
1012 SaveBackupText(file, "URL", GPRSPoint->URL, UseUnicode);
1013 if (GPRSPoint->Active) {
1014 sprintf(buffer,"Active = Yes%c%c",13,10);
1015 SaveBackupText(file, "", buffer, UseUnicode);
1016 }
1017 sprintf(buffer,"%c%c",13,10);
1018 SaveBackupText(file, "", buffer, UseUnicode);
1019}
1020
1021GSM_Error SaveBackup(char *FileName, GSM_Backup *backup, bool UseUnicode)
1022{
1023 int i;
1024 unsigned char buffer[1000],checksum[200];
1025 FILE *file;
1026
1027 file = fopen(FileName, "wb");
1028 if (file == NULL) return ERR_CANTOPENFILE;
1029
1030 if (UseUnicode) {
1031 sprintf(buffer,"%c%c", 0xFE, 0xFF);
1032 SaveBackupText(file, "", buffer, false);
1033 }
1034
1035 sprintf(buffer,"# Format of this file was designed for Gammu (see www.mwiacek.com)%c%c%c%c",13,10,13,10);
1036 SaveBackupText(file, "", buffer, UseUnicode);
1037 sprintf(buffer,"[Backup]%c%c",13,10);
1038 SaveBackupText(file, "", buffer, UseUnicode);
1039 sprintf(buffer,"IMEI = \"%s\"%c%c",backup->IMEI,13,10);
1040 SaveBackupText(file, "", buffer, UseUnicode);
1041 sprintf(buffer,"Phone = \"%s\"%c%c",backup->Model,13,10);
1042 SaveBackupText(file, "", buffer, UseUnicode);
1043 if (backup->Creator[0] != 0) {
1044 sprintf(buffer,"Creator = \"%s\"%c%c",backup->Creator,13,10);
1045 SaveBackupText(file, "", buffer, UseUnicode);
1046 }
1047 if (backup->DateTimeAvailable) {
1048 SaveBackupText(file, "", "DateTime", UseUnicode);
1049 SaveVCalDateTime(file, &backup->DateTime, UseUnicode);
1050 }
1051 sprintf(buffer,"Format = 1.03%c%c",13,10);
1052 SaveBackupText(file, "", buffer, UseUnicode);
1053 sprintf(buffer,"%c%c",13,10);
1054 SaveBackupText(file, "", buffer, UseUnicode);
1055
1056 i=0;
1057 while (backup->PhonePhonebook[i]!=NULL) {
1058 sprintf(buffer,"[PhonePBK%03i]%c%c",i+1,13,10);
1059 SaveBackupText(file, "", buffer, UseUnicode);
1060 SavePbkEntry(file, backup->PhonePhonebook[i], UseUnicode);
1061 i++;
1062 }
1063 i=0;
1064 while (backup->SIMPhonebook[i]!=NULL) {
1065 sprintf(buffer,"[SIMPBK%03i]%c%c",i+1,13,10);
1066 SaveBackupText(file, "", buffer, UseUnicode);
1067 SavePbkEntry(file, backup->SIMPhonebook[i], UseUnicode);
1068 i++;
1069 }
1070 i=0;
1071 while (backup->Calendar[i]!=NULL) {
1072 sprintf(buffer,"[Calendar%03i]%c%c",i+1,13,10);
1073 SaveBackupText(file, "", buffer, UseUnicode);
1074 SaveCalendarEntry(file, backup->Calendar[i], UseUnicode);
1075 i++;
1076 }
1077 i=0;
1078 while (backup->CallerLogos[i]!=NULL) {
1079 sprintf(buffer,"[Caller%03i]%c%c",i+1,13,10);
1080 SaveBackupText(file, "", buffer, UseUnicode);
1081 SaveCallerEntry(file, backup->CallerLogos[i], UseUnicode);
1082 i++;
1083 }
1084 i=0;
1085 while (backup->SMSC[i]!=NULL) {
1086 sprintf(buffer,"[SMSC%03i]%c%c",i+1,13,10);
1087 SaveBackupText(file, "", buffer, UseUnicode);
1088 SaveSMSCEntry(file, backup->SMSC[i], UseUnicode);
1089 i++;
1090 }
1091 i=0;
1092 while (backup->WAPBookmark[i]!=NULL) {
1093 sprintf(buffer,"[WAPBookmark%03i]%c%c",i+1,13,10);
1094 SaveBackupText(file, "", buffer, UseUnicode);
1095 SaveWAPBookmarkEntry(file, backup->WAPBookmark[i], UseUnicode);
1096 i++;
1097 }
1098 i=0;
1099 while (backup->WAPSettings[i]!=NULL) {
1100 sprintf(buffer,"[WAPSettings%03i]%c%c",i+1,13,10);
1101 SaveBackupText(file, "", buffer, UseUnicode);
1102 SaveWAPSettingsEntry(file, backup->WAPSettings[i], UseUnicode);
1103 i++;
1104 }
1105 i=0;
1106 while (backup->MMSSettings[i]!=NULL) {
1107 sprintf(buffer,"[MMSSettings%03i]%c%c",i+1,13,10);
1108 SaveBackupText(file, "", buffer, UseUnicode);
1109 SaveWAPSettingsEntry(file, backup->MMSSettings[i], UseUnicode);
1110 i++;
1111 }
1112 i=0;
1113 while (backup->Ringtone[i]!=NULL) {
1114 sprintf(buffer,"[Ringtone%03i]%c%c",i+1,13,10);
1115 SaveBackupText(file, "", buffer, UseUnicode);
1116 SaveRingtoneEntry(file, backup->Ringtone[i], UseUnicode);
1117 i++;
1118 }
1119 i=0;
1120 while (backup->ToDo[i]!=NULL) {
1121 sprintf(buffer,"[TODO%03i]%c%c",i+1,13,10);
1122 SaveBackupText(file, "", buffer, UseUnicode);
1123 SaveToDoEntry(file, backup->ToDo[i], UseUnicode);
1124 i++;
1125 }
1126 i=0;
1127 while (backup->Profiles[i]!=NULL) {
1128 sprintf(buffer,"[Profile%03i]%c%c",i+1,13,10);
1129 SaveBackupText(file, "", buffer, UseUnicode);
1130 SaveProfileEntry(file, backup->Profiles[i], UseUnicode);
1131 i++;
1132 }
1133 i=0;
1134 while (backup->FMStation[i]!=NULL) {
1135 sprintf(buffer,"[FMStation%03i]%c%c",i+1,13,10);
1136 SaveBackupText(file, "", buffer, UseUnicode);
1137 SaveFMStationEntry(file, backup->FMStation[i], UseUnicode);
1138 i++;
1139 }
1140 i=0;
1141 while (backup->GPRSPoint[i]!=NULL) {
1142 sprintf(buffer,"[GPRSPoint%03i]%c%c",i+1,13,10);
1143 SaveBackupText(file, "", buffer, UseUnicode);
1144 SaveGPRSPointEntry(file, backup->GPRSPoint[i], UseUnicode);
1145 i++;
1146 }
1147
1148 if (backup->StartupLogo!=NULL) {
1149 SaveStartupEntry(file, backup->StartupLogo, UseUnicode);
1150 }
1151 if (backup->OperatorLogo!=NULL) {
1152 SaveOperatorEntry(file, backup->OperatorLogo, UseUnicode);
1153 }
1154
1155 fclose(file);
1156
1157 FindBackupChecksum(FileName, UseUnicode, checksum);
1158
1159 file = fopen(FileName, "ab");
1160 if (file == NULL) return ERR_CANTOPENFILE;
1161 sprintf(buffer,"[Checksum]%c%c",13,10);
1162 SaveBackupText(file, "", buffer, UseUnicode);
1163 sprintf(buffer,"MD5=%s%c%c",checksum,13,10);
1164 SaveBackupText(file, "", buffer, UseUnicode);
1165 fclose(file);
1166
1167 return ERR_NONE;
1168}
1169
1170static void ReadPbkEntry(INI_Section *file_info, char *section, GSM_MemoryEntry *Pbk, bool UseUnicode)
1171{
1172 unsigned char buffer[10000];
1173 char *readvalue;
1174 int num,i;
1175 INI_Entry *e;
1176
1177 Pbk->EntriesNum = 0;
1178 e = INI_FindLastSectionEntry(file_info, section, UseUnicode);
1179
1180 while (e != NULL) {
1181 num = -1;
1182 if (UseUnicode) {
1183 sprintf(buffer,"%s",DecodeUnicodeString(e->EntryName));
1184 } else {
1185 sprintf(buffer,"%s",e->EntryName);
1186 }
1187 if (strlen(buffer) == 11) {
1188 if (mystrncasecmp("Entry", buffer, 5) &&
1189 mystrncasecmp("Type", buffer+7, 4)) {
1190 num = atoi(buffer+5);
1191 }
1192 }
1193 e = e->Prev;
1194 if (num != -1) {
1195 sprintf(buffer,"Entry%02iType",num);
1196 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1197 if (mystrncasecmp(readvalue,"NumberGeneral",0)) {
1198 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_General;
1199 } else if (mystrncasecmp(readvalue,"NumberMobile",0)) {
1200 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Mobile;
1201 } else if (mystrncasecmp(readvalue,"NumberWork",0)) {
1202 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Work;
1203 } else if (mystrncasecmp(readvalue,"NumberFax",0)) {
1204 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Fax;
1205 } else if (mystrncasecmp(readvalue,"NumberHome",0)) {
1206 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Home;
1207 } else if (mystrncasecmp(readvalue,"NumberOther",0)) {
1208 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Other;
1209 } else if (mystrncasecmp(readvalue,"NumberPager",0)) {
1210 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Pager;
1211 } else if (mystrncasecmp(readvalue,"Note",0)) {
1212 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Note;
1213 } else if (mystrncasecmp(readvalue,"Postal",0)) {
1214 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Postal;
1215 } else if (mystrncasecmp(readvalue,"Email",0)) {
1216 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email;
1217 } else if (mystrncasecmp(readvalue,"Email2",0)) {
1218 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email2;
1219 } else if (mystrncasecmp(readvalue,"URL",0)) {
1220 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_URL;
1221 } else if (mystrncasecmp(readvalue,"FirstName",0)) {
1222 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_FirstName;
1223 } else if (mystrncasecmp(readvalue,"LastName",0)) {
1224 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_LastName;
1225 } else if (mystrncasecmp(readvalue,"Company",0)) {
1226 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Company;
1227 } else if (mystrncasecmp(readvalue,"JobTitle",0)) {
1228 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_JobTitle;
1229 } else if (mystrncasecmp(readvalue,"Address",0)) {
1230 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_StreetAddress;
1231 } else if (mystrncasecmp(readvalue,"City",0)) {
1232 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_City;
1233 } else if (mystrncasecmp(readvalue,"State",0)) {
1234 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_State;
1235 } else if (mystrncasecmp(readvalue,"Zip",0)) {
1236 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Zip;
1237 } else if (mystrncasecmp(readvalue,"Country",0)) {
1238 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Country;
1239 } else if (mystrncasecmp(readvalue,"Custom1",0)) {
1240 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom1;
1241 } else if (mystrncasecmp(readvalue,"Custom2",0)) {
1242 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom2;
1243 } else if (mystrncasecmp(readvalue,"Custom3",0)) {
1244 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom3;
1245 } else if (mystrncasecmp(readvalue,"Custom4",0)) {
1246 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Custom4;
1247 } else if (mystrncasecmp(readvalue,"Name",0)) {
1248 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Name;
1249 } else if (mystrncasecmp(readvalue,"Category",0)) {
1250 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Category;
1251 Pbk->Entries[Pbk->EntriesNum].Number = 0;
1252 sprintf(buffer,"Entry%02iNumber",num);
1253 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1254 if (readvalue!=NULL) {
1255 Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
1256 }
1257 Pbk->EntriesNum ++;
1258 continue;
1259 } else if (mystrncasecmp(readvalue,"Private",0)) {
1260 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Private;
1261 Pbk->Entries[Pbk->EntriesNum].Number = 0;
1262 sprintf(buffer,"Entry%02iNumber",num);
1263 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1264 if (readvalue!=NULL) {
1265 Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
1266 }
1267 Pbk->EntriesNum ++;
1268 continue;
1269 } else if (mystrncasecmp(readvalue,"CallerGroup",0)) {
1270 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Caller_Group;
1271 Pbk->Entries[Pbk->EntriesNum].Number = 0;
1272 sprintf(buffer,"Entry%02iNumber",num);
1273 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1274 if (readvalue!=NULL) {
1275 Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
1276 }
1277 Pbk->EntriesNum ++;
1278 continue;
1279 } else if (mystrncasecmp(readvalue,"RingtoneID",0)) {
1280 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_RingtoneID;
1281 Pbk->Entries[Pbk->EntriesNum].Number = 0;
1282 sprintf(buffer,"Entry%02iNumber",num);
1283 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1284 if (readvalue!=NULL) {
1285 Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
1286 }
1287 Pbk->EntriesNum ++;
1288 continue;
1289 } else if (mystrncasecmp(readvalue,"PictureID",0)) {
1290 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_PictureID;
1291 Pbk->Entries[Pbk->EntriesNum].Number = 0;
1292 sprintf(buffer,"Entry%02iNumber",num);
1293 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1294 if (readvalue!=NULL) {
1295 Pbk->Entries[Pbk->EntriesNum].Number = atoi(readvalue);
1296 }
1297 Pbk->EntriesNum ++;
1298 continue;
1299 } else if (mystrncasecmp(readvalue,"UserID",0)) {
1300 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_UserID;
1301 }
1302 sprintf(buffer,"Entry%02iText",num);
1303 ReadBackupText(file_info, section, buffer, Pbk->Entries[Pbk->EntriesNum].Text,UseUnicode);
1304 dbgprintf("text \"%s\", type %i\n",DecodeUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text),Pbk->Entries[Pbk->EntriesNum].EntryType);
1305 Pbk->Entries[Pbk->EntriesNum].VoiceTag = 0;
1306 sprintf(buffer,"Entry%02iVoiceTag",num);
1307 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1308 if (readvalue!=NULL) {
1309 Pbk->Entries[Pbk->EntriesNum].VoiceTag = atoi(readvalue);
1310 }
1311 i = 0;
1312 while (1) {
1313 Pbk->Entries[Pbk->EntriesNum].SMSList[i] = 0;
1314 sprintf(buffer,"Entry%02iSMSList%02i",num,i);
1315 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1316 if (readvalue==NULL) break;
1317 Pbk->Entries[Pbk->EntriesNum].SMSList[i] = atoi(readvalue);
1318 i++;
1319 }
1320 Pbk->EntriesNum ++;
1321 }
1322 }
1323}
1324
1325static void ReadCalendarEntry(INI_Section *file_info, char *section, GSM_CalendarEntry *note, bool UseUnicode)
1326{
1327 unsigned char buffer[10000];
1328 char *readvalue;
1329
1330 sprintf(buffer,"Location");
1331 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1332 if (readvalue!=NULL) note->Location = atoi(readvalue);
1333
1334 sprintf(buffer,"Type");
1335 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1336 note->Type = GSM_CAL_REMINDER;
1337 if (readvalue!=NULL)
1338 {
1339 if (mystrncasecmp(readvalue,"Call",0)) {
1340 note->Type = GSM_CAL_CALL;
1341 } else if (mystrncasecmp(readvalue,"Meeting",0)) {
1342 note->Type = GSM_CAL_MEETING;
1343 } else if (mystrncasecmp(readvalue,"Birthday",0)) {
1344 note->Type = GSM_CAL_BIRTHDAY;
1345 } else if (mystrncasecmp(readvalue,"Memo",0)) {
1346 note->Type = GSM_CAL_MEMO;
1347 } else if (mystrncasecmp(readvalue,"Travel",0)) {
1348 note->Type = GSM_CAL_TRAVEL;
1349 } else if (mystrncasecmp(readvalue,"Vacation",0)) {
1350 note->Type = GSM_CAL_VACATION;
1351 } else if (mystrncasecmp(readvalue,"DailyAlarm",0)) {
1352 note->Type = GSM_CAL_DAILY_ALARM;
1353 } else if (mystrncasecmp(readvalue,"Alarm",0)) {
1354 note->Type = GSM_CAL_ALARM;
1355 } else if (mystrncasecmp(readvalue,"Training/Athletism",0)) {
1356 note->Type = GSM_CAL_T_ATHL;
1357 } else if (mystrncasecmp(readvalue,"Training/BallGames",0)) {
1358 note->Type = GSM_CAL_T_BALL;
1359 } else if (mystrncasecmp(readvalue,"Training/Cycling",0)) {
1360 note->Type = GSM_CAL_T_CYCL;
1361 } else if (mystrncasecmp(readvalue,"Training/Budo",0)) {
1362 note->Type = GSM_CAL_T_BUDO;
1363 } else if (mystrncasecmp(readvalue,"Training/Dance",0)) {
1364 note->Type = GSM_CAL_T_DANC;
1365 } else if (mystrncasecmp(readvalue,"Training/ExtremeSports",0)) {
1366 note->Type = GSM_CAL_T_EXTR;
1367 } else if (mystrncasecmp(readvalue,"Training/Football",0)) {
1368 note->Type = GSM_CAL_T_FOOT;
1369 } else if (mystrncasecmp(readvalue,"Training/Golf",0)) {
1370 note->Type = GSM_CAL_T_GOLF;
1371 } else if (mystrncasecmp(readvalue,"Training/Gym",0)) {
1372 note->Type = GSM_CAL_T_GYM;
1373 } else if (mystrncasecmp(readvalue,"Training/HorseRaces",0)) {
1374 note->Type = GSM_CAL_T_HORS;
1375 } else if (mystrncasecmp(readvalue,"Training/Hockey",0)) {
1376 note->Type = GSM_CAL_T_HOCK;
1377 } else if (mystrncasecmp(readvalue,"Training/Races",0)) {
1378 note->Type = GSM_CAL_T_RACE;
1379 } else if (mystrncasecmp(readvalue,"Training/Rugby",0)) {
1380 note->Type = GSM_CAL_T_RUGB;
1381 } else if (mystrncasecmp(readvalue,"Training/Sailing",0)) {
1382 note->Type = GSM_CAL_T_SAIL;
1383 } else if (mystrncasecmp(readvalue,"Training/StreetGames",0)) {
1384 note->Type = GSM_CAL_T_STRE;
1385 } else if (mystrncasecmp(readvalue,"Training/Swimming",0)) {
1386 note->Type = GSM_CAL_T_SWIM;
1387 } else if (mystrncasecmp(readvalue,"Training/Tennis",0)) {
1388 note->Type = GSM_CAL_T_TENN;
1389 } else if (mystrncasecmp(readvalue,"Training/Travels",0)) {
1390 note->Type = GSM_CAL_T_TRAV;
1391 } else if (mystrncasecmp(readvalue,"Training/WinterGames",0)) {
1392 note->Type = GSM_CAL_T_WINT;
1393 }
1394 }
1395 note->EntriesNum = 0;
1396 sprintf(buffer,"Text");
1397 if (ReadBackupText(file_info, section, buffer, note->Entries[note->EntriesNum].Text,UseUnicode)) {
1398 note->Entries[note->EntriesNum].EntryType = CAL_TEXT;
1399 note->EntriesNum++;
1400 }
1401 sprintf(buffer,"Phone");
1402 if (ReadBackupText(file_info, section, buffer, note->Entries[note->EntriesNum].Text,UseUnicode)) {
1403 note->Entries[note->EntriesNum].EntryType = CAL_PHONE;
1404 note->EntriesNum++;
1405 }
1406 sprintf(buffer,"Private");
1407 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1408 if (readvalue!=NULL) {
1409 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1410 note->Entries[note->EntriesNum].EntryType = CAL_PRIVATE;
1411 note->EntriesNum++;
1412 }
1413 sprintf(buffer,"EventLocation");
1414 if (ReadBackupText(file_info, section, buffer, note->Entries[note->EntriesNum].Text,UseUnicode)) {
1415 note->Entries[note->EntriesNum].EntryType = CAL_LOCATION;
1416 note->EntriesNum++;
1417 }
1418 sprintf(buffer,"ContactID");
1419 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1420 if (readvalue!=NULL) {
1421 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1422 note->Entries[note->EntriesNum].EntryType = CAL_CONTACTID;
1423 note->EntriesNum++;
1424 }
1425 sprintf(buffer,"Recurrance");
1426 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1427 if (readvalue!=NULL) {
1428 note->Entries[note->EntriesNum].Number = atoi(readvalue) * 24;
1429 note->Entries[note->EntriesNum].EntryType = CAL_RECURRANCE;
1430 note->EntriesNum++;
1431 }
1432 sprintf(buffer,"StartTime");
1433 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1434 if (readvalue!=NULL) {
1435 ReadVCALDateTime(readvalue, &note->Entries[note->EntriesNum].Date);
1436 note->Entries[note->EntriesNum].EntryType = CAL_START_DATETIME;
1437 note->EntriesNum++;
1438 }
1439 sprintf(buffer,"StopTime");
1440 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1441 if (readvalue!=NULL) {
1442 ReadVCALDateTime(readvalue, &note->Entries[note->EntriesNum].Date);
1443 note->Entries[note->EntriesNum].EntryType = CAL_END_DATETIME;
1444 note->EntriesNum++;
1445 }
1446 sprintf(buffer,"Alarm");
1447 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1448 if (readvalue!=NULL)
1449 {
1450 ReadVCALDateTime(readvalue, &note->Entries[note->EntriesNum].Date);
1451 note->Entries[note->EntriesNum].EntryType = CAL_ALARM_DATETIME;
1452 sprintf(buffer,"AlarmType");
1453 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1454 if (readvalue!=NULL)
1455 {
1456 if (mystrncasecmp(readvalue,"Silent",0)) {
1457 note->Entries[note->EntriesNum].EntryType = CAL_SILENT_ALARM_DATETIME;
1458 }
1459 }
1460 note->EntriesNum++;
1461 }
1462 sprintf(buffer,"RepeatStartDate");
1463 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1464 if (readvalue!=NULL) {
1465 ReadVCALDateTime(readvalue, &note->Entries[note->EntriesNum].Date);
1466 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_STARTDATE;
1467 note->EntriesNum++;
1468 }
1469 sprintf(buffer,"RepeatStopDate");
1470 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1471 if (readvalue!=NULL) {
1472 ReadVCALDateTime(readvalue, &note->Entries[note->EntriesNum].Date);
1473 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_STOPDATE;
1474 note->EntriesNum++;
1475 }
1476 sprintf(buffer,"RepeatDayOfWeek");
1477 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1478 if (readvalue!=NULL) {
1479 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1480 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_DAYOFWEEK;
1481 note->EntriesNum++;
1482 }
1483 sprintf(buffer,"RepeatDay");
1484 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1485 if (readvalue!=NULL) {
1486 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1487 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_DAY;
1488 note->EntriesNum++;
1489 }
1490 sprintf(buffer,"RepeatWeekOfMonth");
1491 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1492 if (readvalue!=NULL) {
1493 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1494 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_WEEKOFMONTH;
1495 note->EntriesNum++;
1496 }
1497 sprintf(buffer,"RepeatMonth");
1498 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1499 if (readvalue!=NULL) {
1500 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1501 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_MONTH;
1502 note->EntriesNum++;
1503 }
1504 sprintf(buffer,"RepeatFrequency");
1505 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1506 if (readvalue!=NULL) {
1507 note->Entries[note->EntriesNum].Number = atoi(readvalue);
1508 note->Entries[note->EntriesNum].EntryType = CAL_REPEAT_FREQUENCY;
1509 note->EntriesNum++;
1510 }
1511}
1512
1513static void ReadToDoEntry(INI_Section *file_info, char *section, GSM_ToDoEntry *ToDo, bool UseUnicode)
1514{
1515 unsigned char buffer[10000];
1516 char *readvalue;
1517
1518 ToDo->EntriesNum = 0;
1519
1520 sprintf(buffer,"Location");
1521 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1522 if (readvalue!=NULL) ToDo->Location = atoi(readvalue);
1523
1524 ToDo->Priority = GSM_Priority_High;
1525 sprintf(buffer,"Priority");
1526 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1527 if (readvalue!=NULL) {
1528 if (!strcmp(readvalue,"3") || !strcmp(readvalue,"Low")) {
1529 ToDo->Priority = GSM_Priority_Low;
1530 }
1531 if (!strcmp(readvalue,"2") || !strcmp(readvalue,"Medium")) {
1532 ToDo->Priority = GSM_Priority_Medium;
1533 }
1534 }
1535
1536 sprintf(buffer,"Text");
1537 if (ReadBackupText(file_info, section, buffer, ToDo->Entries[ToDo->EntriesNum].Text,UseUnicode)) {
1538 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_TEXT;
1539 ToDo->EntriesNum++;
1540 }
1541
1542 sprintf(buffer,"Phone");
1543 if (ReadBackupText(file_info, section, buffer, ToDo->Entries[ToDo->EntriesNum].Text,UseUnicode)) {
1544 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_PHONE;
1545 ToDo->EntriesNum++;
1546 }
1547
1548 sprintf(buffer,"Private");
1549 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1550 if (readvalue!=NULL) {
1551 ToDo->Entries[ToDo->EntriesNum].Number = atoi(readvalue);
1552 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_PRIVATE;
1553 ToDo->EntriesNum++;
1554 }
1555
1556 sprintf(buffer,"Completed");
1557 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1558 if (readvalue!=NULL) {
1559 if (strncmp(readvalue, "yes", 3) == 0) {
1560 ToDo->Entries[ToDo->EntriesNum].Number = 1;
1561 } else {
1562 ToDo->Entries[ToDo->EntriesNum].Number = 0;
1563 }
1564 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_COMPLETED;
1565 ToDo->EntriesNum++;
1566 }
1567
1568 sprintf(buffer,"Category");
1569 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1570 if (readvalue!=NULL) {
1571 ToDo->Entries[ToDo->EntriesNum].Number = atoi(readvalue);
1572 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_CATEGORY;
1573 ToDo->EntriesNum++;
1574 }
1575
1576 sprintf(buffer,"ContactID");
1577 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1578 if (readvalue!=NULL) {
1579 ToDo->Entries[ToDo->EntriesNum].Number = atoi(readvalue);
1580 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_CONTACTID;
1581 ToDo->EntriesNum++;
1582 }
1583
1584 sprintf(buffer,"DueTime");
1585 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1586 if (readvalue!=NULL) {
1587 ReadVCALDateTime(readvalue, &ToDo->Entries[ToDo->EntriesNum].Date);
1588 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_END_DATETIME;
1589 ToDo->EntriesNum++;
1590 }
1591
1592 sprintf(buffer,"Alarm");
1593 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1594 if (readvalue!=NULL) {
1595 ReadVCALDateTime(readvalue, &ToDo->Entries[ToDo->EntriesNum].Date);
1596 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_ALARM_DATETIME;
1597 ToDo->EntriesNum++;
1598 }
1599
1600 sprintf(buffer,"SilentAlarm");
1601 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1602 if (readvalue!=NULL) {
1603 ReadVCALDateTime(readvalue, &ToDo->Entries[ToDo->EntriesNum].Date);
1604 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_SILENT_ALARM_DATETIME;
1605 ToDo->EntriesNum++;
1606 }
1607}
1608
1609static bool ReadBitmapEntry(INI_Section *file_info, char *section, GSM_Bitmap *bitmap, bool UseUnicode)
1610{
1611 char *readvalue;
1612 unsigned charbuffer[10000];
1613 unsigned char Width, Height;
1614 int x, y;
1615
1616 GSM_GetMaxBitmapWidthHeight(bitmap->Type, &Width, &Height);
1617 sprintf(buffer,"Width");
1618 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1619 if (readvalue==NULL) bitmap->BitmapWidth = Width; else bitmap->BitmapWidth = atoi(readvalue);
1620 sprintf(buffer,"Height");
1621 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1622 if (readvalue==NULL) bitmap->BitmapHeight = Height; else bitmap->BitmapHeight = atoi(readvalue);
1623 GSM_ClearBitmap(bitmap);
1624 for (y=0;y<bitmap->BitmapHeight;y++) {
1625 sprintf(buffer,"Bitmap%02i",y);
1626 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1627 if (readvalue!=NULL) {
1628 for (x=0;x<bitmap->BitmapWidth;x++) {
1629 if (readvalue[x+1]=='#') GSM_SetPointBitmap(bitmap,x,y);
1630 }
1631 } else return false;
1632 }
1633 return true;
1634}
1635
1636static void ReadCallerEntry(INI_Section *file_info, char *section, GSM_Bitmap *bitmap, bool UseUnicode)
1637{
1638 unsigned char buffer[10000];
1639 char *readvalue;
1640
1641 bitmap->Type = GSM_CallerGroupLogo;
1642 bitmap->DefaultBitmap = !ReadBitmapEntry(file_info, section, bitmap, UseUnicode);
1643 if (bitmap->DefaultBitmap) {
1644 bitmap->BitmapWidth = 72;
1645 bitmap->BitmapHeight = 14;
1646 GSM_ClearBitmap(bitmap);
1647 }
1648 sprintf(buffer,"Name");
1649 ReadBackupText(file_info, section, buffer, bitmap->Text,UseUnicode);
1650 if (bitmap->Text[0] == 0x00 && bitmap->Text[1] == 0x00) {
1651 bitmap->DefaultName = true;
1652 } else {
1653 bitmap->DefaultName = false;
1654 }
1655 sprintf(buffer,"Ringtone");
1656 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1657 if (readvalue==NULL) {
1658 sprintf(buffer,"FileRingtone");
1659 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1660 if (readvalue==NULL) {
1661 bitmap->DefaultRingtone = true;
1662 } else {
1663 DecodeHexBin (&bitmap->RingtoneID, readvalue, 2);
1664 bitmap->DefaultRingtone = false;
1665 bitmap->FileSystemRingtone = true;
1666 }
1667 } else {
1668 DecodeHexBin (&bitmap->RingtoneID, readvalue, 2);
1669 bitmap->DefaultRingtone = false;
1670 bitmap->FileSystemRingtone = false;
1671 }
1672 sprintf(buffer,"Enabled");
1673 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1674 bitmap->BitmapEnabled = true;
1675 if (readvalue!=NULL) {
1676 if (mystrncasecmp(readvalue,"False",0)) bitmap->BitmapEnabled = false;
1677 }
1678}
1679
1680static void ReadStartupEntry(INI_Section *file_info, char *section, GSM_Bitmap *bitmap, bool UseUnicode)
1681{
1682 unsigned char buffer[10000];
1683
1684 sprintf(buffer,"Text");
1685 ReadBackupText(file_info, section, buffer, bitmap->Text,UseUnicode);
1686 if (bitmap->Text[0]!=0 || bitmap->Text[1]!=0) {
1687 bitmap->Type = GSM_WelcomeNote_Text;
1688 } else {
1689 bitmap->Type = GSM_StartupLogo;
1690 bitmap->Location = 1;
1691 ReadBitmapEntry(file_info, section, bitmap, UseUnicode);
1692#ifdef DEBUG
1693 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,bitmap);
1694#endif
1695 }
1696}
1697
1698static void ReadWAPBookmarkEntry(INI_Section *file_info, char *section, GSM_WAPBookmark *bookmark, bool UseUnicode)
1699{
1700 unsigned char buffer[10000];
1701
1702 sprintf(buffer,"URL");
1703 ReadBackupText(file_info, section, buffer, bookmark->Address,UseUnicode);
1704 sprintf(buffer,"Title");
1705 ReadBackupText(file_info, section, buffer, bookmark->Title,UseUnicode);
1706}
1707
1708static void ReadOperatorEntry(INI_Section *file_info, char *section, GSM_Bitmap *bitmap, bool UseUnicode)
1709{
1710 unsigned char buffer[10000];
1711 char *readvalue;
1712
1713 sprintf(buffer,"Network");
1714 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1715 memcpy(bitmap->NetworkCode, readvalue + 1, 6);
1716 bitmap->NetworkCode[6] = 0;
1717 bitmap->Type = GSM_OperatorLogo;
1718 ReadBitmapEntry(file_info, section, bitmap, UseUnicode);
1719}
1720
1721static void ReadSMSCEntry(INI_Section *file_info, char *section, GSM_SMSC *SMSC, bool UseUnicode)
1722{
1723 unsigned char buffer[10000];
1724 char *readvalue;
1725
1726 sprintf(buffer,"Name");
1727 ReadBackupText(file_info, section, buffer, SMSC->Name,UseUnicode);
1728 sprintf(buffer,"Number");
1729 ReadBackupText(file_info, section, buffer, SMSC->Number,UseUnicode);
1730 sprintf(buffer,"DefaultNumber");
1731 ReadBackupText(file_info, section, buffer, SMSC->DefaultNumber,UseUnicode);
1732 sprintf(buffer,"Format");
1733 SMSC->Format = SMS_FORMAT_Text;
1734 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1735 if (readvalue!=NULL) {
1736 if (mystrncasecmp(readvalue,"Fax",0)) {
1737 SMSC->Format = SMS_FORMAT_Fax;
1738 } else if (mystrncasecmp(readvalue,"Email",0)) {
1739 SMSC->Format = SMS_FORMAT_Email;
1740 } else if (mystrncasecmp(readvalue,"Pager",0)) {
1741 SMSC->Format = SMS_FORMAT_Pager;
1742 }
1743 }
1744 sprintf(buffer,"Validity");
1745 SMSC->Validity.Relative = SMS_VALID_Max_Time;
1746 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1747 if (readvalue!=NULL) {
1748 if (mystrncasecmp(readvalue,"1hour",0)) {
1749 SMSC->Validity.Relative = SMS_VALID_1_Hour;
1750 } else if (mystrncasecmp(readvalue,"6hours",0)) {
1751 SMSC->Validity.Relative = SMS_VALID_6_Hours;
1752 } else if (mystrncasecmp(readvalue,"24hours",0)) {
1753 SMSC->Validity.Relative = SMS_VALID_1_Day;
1754 } else if (mystrncasecmp(readvalue,"72hours",0)) {
1755 SMSC->Validity.Relative = SMS_VALID_3_Days;
1756 } else if (mystrncasecmp(readvalue,"1week",0)) {
1757 SMSC->Validity.Relative = SMS_VALID_1_Week;
1758 }
1759 }
1760}
1761
1762static void ReadWAPSettingsEntry(INI_Section *file_info, char *section, GSM_MultiWAPSettings *settings, bool UseUnicode)
1763{
1764 unsigned char buffer[10000], *readvalue;
1765 int num;
1766 INI_Entry *e;
1767
1768 settings->ActiveBearer = WAPSETTINGS_BEARER_DATA;
1769 sprintf(buffer,"Bearer");
1770 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1771 if (readvalue!=NULL) {
1772 if (mystrncasecmp(readvalue,"SMS",0)) {
1773 settings->ActiveBearer = WAPSETTINGS_BEARER_SMS;
1774 } else if (mystrncasecmp(readvalue,"GPRS",0)) {
1775 settings->ActiveBearer = WAPSETTINGS_BEARER_GPRS;
1776 } else if (mystrncasecmp(readvalue,"USSD",0)) {
1777 settings->ActiveBearer = WAPSETTINGS_BEARER_USSD;
1778 }
1779 }
1780
1781 settings->Active = false;
1782 sprintf(buffer,"Active");
1783 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1784 if (readvalue!=NULL) {
1785 if (mystrncasecmp(readvalue,"Yes",0)) settings->Active = true;
1786 }
1787
1788 settings->ReadOnly = false;
1789 sprintf(buffer,"ReadOnly");
1790 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1791 if (readvalue!=NULL) {
1792 if (mystrncasecmp(readvalue,"Yes",0)) settings->ReadOnly = true;
1793 }
1794
1795 sprintf(buffer,"Proxy");
1796 ReadBackupText(file_info, section, buffer, settings->Proxy,UseUnicode);
1797 sprintf(buffer,"ProxyPort");
1798 settings->ProxyPort = 8080;
1799 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1800 if (readvalue!=NULL) settings->ProxyPort = atoi(readvalue);
1801 sprintf(buffer,"Proxy2");
1802 ReadBackupText(file_info, section, buffer, settings->Proxy2,UseUnicode);
1803 sprintf(buffer,"Proxy2Port");
1804 settings->Proxy2Port = 8080;
1805 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1806 if (readvalue!=NULL) settings->Proxy2Port = atoi(readvalue);
1807
1808 settings->Number = 0;
1809 e = INI_FindLastSectionEntry(file_info, section, UseUnicode);
1810 while (e != NULL) {
1811 num = -1;
1812 if (UseUnicode) {
1813 sprintf(buffer,"%s",DecodeUnicodeString(e->EntryName));
1814 } else {
1815 sprintf(buffer,"%s",e->EntryName);
1816 }
1817 if (strlen(buffer) == 7) {
1818 if (mystrncasecmp("Title", buffer,5)) num = atoi(buffer+5);
1819 }
1820 e = e->Prev;
1821 if (num != -1) {
1822 sprintf(buffer,"Title%02i",num);
1823 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Title,UseUnicode);
1824 sprintf(buffer,"HomePage%02i",num);
1825 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].HomePage,UseUnicode);
1826 sprintf(buffer,"Type%02i",num);
1827 settings->Settings[settings->Number].IsContinuous = true;
1828 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1829 if (readvalue!=NULL) {
1830 if (mystrncasecmp(readvalue,"Temporary",0)) settings->Settings[settings->Number].IsContinuous = false;
1831 }
1832 sprintf(buffer,"Security%02i",num);
1833 settings->Settings[settings->Number].IsSecurity = true;
1834 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1835 if (readvalue!=NULL)
1836 {
1837 if (mystrncasecmp(readvalue,"Off",0)) settings->Settings[settings->Number].IsSecurity = false;
1838 }
1839 sprintf(buffer,"Bearer%02i",num);
1840 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1841 if (readvalue!=NULL)
1842 {
1843 if (mystrncasecmp(readvalue,"SMS",0)) {
1844 settings->Settings[settings->Number].Bearer = WAPSETTINGS_BEARER_SMS;
1845 sprintf(buffer,"Server%02i",num);
1846 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Server,UseUnicode);
1847 sprintf(buffer,"Service%02i",num);
1848 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Service,UseUnicode);
1849 } else if ((mystrncasecmp(readvalue,"Data",0) || mystrncasecmp(readvalue,"GPRS",0))) {
1850 settings->Settings[settings->Number].Bearer = WAPSETTINGS_BEARER_DATA;
1851 if (mystrncasecmp(readvalue,"GPRS",0)) settings->Settings[settings->Number].Bearer = WAPSETTINGS_BEARER_GPRS;
1852 sprintf(buffer,"Number%02i",num);
1853 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].DialUp,UseUnicode);
1854 sprintf(buffer,"IP%02i",num);
1855 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].IPAddress,UseUnicode);
1856 sprintf(buffer,"User%02i",num);
1857 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].User,UseUnicode);
1858 sprintf(buffer,"Password%02i",num);
1859 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Password,UseUnicode);
1860 sprintf(buffer,"Authentication%02i",num);
1861 settings->Settings[settings->Number].IsNormalAuthentication = true;
1862 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1863 if (readvalue!=NULL)
1864 {
1865 if (mystrncasecmp(readvalue,"Secure",0)) settings->Settings[settings->Number].IsNormalAuthentication = false;
1866 }
1867 sprintf(buffer,"CallSpeed%02i",num);
1868 settings->Settings[settings->Number].Speed = WAPSETTINGS_SPEED_14400;
1869 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1870 if (readvalue!=NULL)
1871 {
1872 if (mystrncasecmp(readvalue,"9600",0)) settings->Settings[settings->Number].Speed = WAPSETTINGS_SPEED_9600;
1873 if (mystrncasecmp(readvalue,"auto",0)) settings->Settings[settings->Number].Speed = WAPSETTINGS_SPEED_AUTO;
1874 }
1875 sprintf(buffer,"Login%02i",num);
1876 settings->Settings[settings->Number].ManualLogin = false;
1877 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1878 if (readvalue!=NULL)
1879 {
1880 if (mystrncasecmp(readvalue,"Manual",0)) settings->Settings[settings->Number].ManualLogin = true;
1881 }
1882 sprintf(buffer,"CallType%02i",num);
1883 settings->Settings[settings->Number].IsISDNCall = true;
1884 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1885 if (readvalue!=NULL)
1886 {
1887 if (mystrncasecmp(readvalue,"Analogue",0)) settings->Settings[settings->Number].IsISDNCall = false;
1888 }
1889 } else if (mystrncasecmp(readvalue,"USSD",0)) {
1890 settings->Settings[settings->Number].Bearer = WAPSETTINGS_BEARER_USSD;
1891 sprintf(buffer,"ServiceCode%02i",num);
1892 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Code,UseUnicode);
1893 sprintf(buffer,"IP%02i",num);
1894 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1895 if (readvalue!=NULL) {
1896 settings->Settings[settings->Number].IsIP = true;
1897 sprintf(buffer,"IP%02i",num);
1898 } else {
1899 settings->Settings[settings->Number].IsIP = false;
1900 sprintf(buffer,"Number%02i",num);
1901 }
1902 ReadBackupText(file_info, section, buffer, settings->Settings[settings->Number].Service,UseUnicode);
1903 }
1904 }
1905 settings->Number++;
1906 }
1907 }
1908}
1909
1910static void ReadRingtoneEntry(INI_Section *file_info, char *section, GSM_Ringtone *ringtone, bool UseUnicode)
1911{
1912 unsigned char buffer[10000], buffer2[10000], *readvalue;
1913
1914 sprintf(buffer,"Name");
1915 ReadBackupText(file_info, section, buffer, ringtone->Name,UseUnicode);
1916 ringtone->Location = 0;
1917 sprintf(buffer,"Location");
1918 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1919 if (readvalue!=NULL) ringtone->Location = atoi(readvalue);
1920 sprintf(buffer,"NokiaBinary00");
1921 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1922 if (readvalue!=NULL) {
1923 ringtone->Format = RING_NOKIABINARY;
1924 ReadLinkedBackupText(file_info, section, "NokiaBinary", buffer2, UseUnicode);
1925 DecodeHexBin (ringtone->NokiaBinary.Frame, buffer2, strlen(buffer2));
1926 ringtone->NokiaBinary.Length = strlen(buffer2)/2;
1927 }
1928 sprintf(buffer,"Pure Midi00");
1929 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1930 if (readvalue!=NULL) {
1931 ringtone->Format = RING_MIDI;
1932 ReadLinkedBackupText(file_info, section, "Pure Midi", buffer2, UseUnicode);
1933 DecodeHexBin (ringtone->NokiaBinary.Frame, buffer2, strlen(buffer2));
1934 ringtone->NokiaBinary.Length = strlen(buffer2)/2;
1935 }
1936
1937}
1938
1939static void ReadProfileEntry(INI_Section *file_info, char *section, GSM_Profile *Profile, bool UseUnicode)
1940{
1941 unsigned char buffer[10000];
1942 char *readvalue;
1943 bool unknown;
1944 int num,j;
1945 INI_Entry *e;
1946
1947 sprintf(buffer,"Name");
1948 ReadBackupText(file_info, section, buffer, Profile->Name,UseUnicode);
1949
1950 sprintf(buffer,"Location");
1951 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1952 Profile->Location = atoi(readvalue);
1953
1954 Profile->DefaultName = false;
1955 sprintf(buffer,"DefaultName");
1956 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1957 if (readvalue!=NULL && mystrncasecmp(buffer,"true",0)) Profile->DefaultName = true;
1958
1959 Profile->HeadSetProfile = false;
1960 sprintf(buffer,"HeadSetProfile");
1961 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1962 if (readvalue!=NULL && mystrncasecmp(buffer,"true",0)) Profile->HeadSetProfile = true;
1963
1964 Profile->CarKitProfile = false;
1965 sprintf(buffer,"CarKitProfile");
1966 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1967 if (readvalue!=NULL && mystrncasecmp(buffer,"true",0)) Profile->CarKitProfile = true;
1968
1969 Profile->FeaturesNumber = 0;
1970 e = INI_FindLastSectionEntry(file_info, section, UseUnicode);
1971 while (e != NULL) {
1972 num = -1;
1973 if (UseUnicode) {
1974 sprintf(buffer,"%s",DecodeUnicodeString(e->EntryName));
1975 } else {
1976 sprintf(buffer,"%s",e->EntryName);
1977 }
1978 if (strlen(buffer) == 9) {
1979 if (mystrncasecmp("Feature", buffer, 7)) num = atoi(buffer+7);
1980 }
1981 e = e->Prev;
1982 if (num != -1) {
1983 sprintf(buffer,"Feature%02i",num);
1984 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1985 if (readvalue==NULL) break;
1986 unknown = true;
1987 if (mystrncasecmp(readvalue,"RingtoneID",0)) {
1988 Profile->FeatureID[Profile->FeaturesNumber]=Profile_RingtoneID;
1989 sprintf(buffer,"Value%02i",num);
1990 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1991 Profile->FeatureValue[Profile->FeaturesNumber]=atoi(readvalue);
1992 Profile->FeaturesNumber++;
1993 } else if (mystrncasecmp(readvalue,"MessageToneID",0)) {
1994 Profile->FeatureID[Profile->FeaturesNumber]=Profile_MessageToneID;
1995 sprintf(buffer,"Value%02i",num);
1996 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
1997 Profile->FeatureValue[Profile->FeaturesNumber]=atoi(readvalue);
1998 Profile->FeaturesNumber++;
1999 } else if (mystrncasecmp(readvalue,"ScreenSaverNumber",0)) {
2000 Profile->FeatureID[Profile->FeaturesNumber]=Profile_ScreenSaverNumber;
2001 sprintf(buffer,"Value%02i",num);
2002 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2003 Profile->FeatureValue[Profile->FeaturesNumber]=atoi(readvalue);
2004 Profile->FeaturesNumber++;
2005 } else if (mystrncasecmp(readvalue,"CallerGroups",0)) {
2006 Profile->FeatureID[Profile->FeaturesNumber]=Profile_CallerGroups;
2007 sprintf(buffer,"Value%02i",num);
2008 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2009 for (j=0;j<5;j++) {
2010 Profile->CallerGroups[j]=false;
2011 if (strstr(readvalue,"1"+j)!=NULL) Profile->CallerGroups[j]=true;
2012 }
2013 Profile->FeaturesNumber++;
2014 } else if (mystrncasecmp(readvalue,"IncomingCallAlert",0)) {
2015 Profile->FeatureID[Profile->FeaturesNumber]=Profile_CallAlert;
2016 unknown = false;
2017 } else if (mystrncasecmp(readvalue,"RingtoneVolume",0)) {
2018 Profile->FeatureID[Profile->FeaturesNumber]=Profile_RingtoneVolume;
2019 unknown = false;
2020 } else if (mystrncasecmp(readvalue,"Vibrating",0)) {
2021 Profile->FeatureID[Profile->FeaturesNumber]=Profile_Vibration;
2022 unknown = false;
2023 } else if (mystrncasecmp(readvalue,"MessageTone",0)) {
2024 Profile->FeatureID[Profile->FeaturesNumber]=Profile_MessageTone;
2025 unknown = false;
2026 } else if (mystrncasecmp(readvalue,"KeypadTones",0)) {
2027 Profile->FeatureID[Profile->FeaturesNumber]=Profile_KeypadTone;
2028 unknown = false;
2029 } else if (mystrncasecmp(readvalue,"WarningTones",0)) {
2030 Profile->FeatureID[Profile->FeaturesNumber]=Profile_WarningTone;
2031 unknown = false;
2032 } else if (mystrncasecmp(readvalue,"ScreenSaver",0)) {
2033 Profile->FeatureID[Profile->FeaturesNumber]=Profile_ScreenSaver;
2034 unknown = false;
2035 } else if (mystrncasecmp(readvalue,"ScreenSaverTimeout",0)) {
2036 Profile->FeatureID[Profile->FeaturesNumber]=Profile_ScreenSaverTime;
2037 unknown = false;
2038 } else if (mystrncasecmp(readvalue,"AutomaticAnswer",0)) {
2039 Profile->FeatureID[Profile->FeaturesNumber]=Profile_AutoAnswer;
2040 unknown = false;
2041 } else if (mystrncasecmp(readvalue,"Lights",0)) {
2042 Profile->FeatureID[Profile->FeaturesNumber]=Profile_Lights;
2043 unknown = false;
2044 }
2045 if (!unknown) {
2046 sprintf(buffer,"Value%02i",num);
2047 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2048 if (mystrncasecmp(readvalue,"Level1",0)) {
2049 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VOLUME_LEVEL1;
2050 if (Profile->FeatureID[Profile->FeaturesNumber]==Profile_KeypadTone) {
2051 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_KEYPAD_LEVEL1;
2052 }
2053 } else if (mystrncasecmp(readvalue,"Level2",0)) {
2054 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VOLUME_LEVEL2;
2055 if (Profile->FeatureID[Profile->FeaturesNumber]==Profile_KeypadTone) {
2056 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_KEYPAD_LEVEL2;
2057 }
2058 } else if (mystrncasecmp(readvalue,"Level3",0)) {
2059 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VOLUME_LEVEL3;
2060 if (Profile->FeatureID[Profile->FeaturesNumber]==Profile_KeypadTone) {
2061 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_KEYPAD_LEVEL3;
2062 }
2063 } else if (mystrncasecmp(readvalue,"Level4",0)) {
2064 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VOLUME_LEVEL4;
2065 } else if (mystrncasecmp(readvalue,"Level5",0)) {
2066 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VOLUME_LEVEL5;
2067 } else if (mystrncasecmp(readvalue,"Off",0)) {
2068 switch (Profile->FeatureID[Profile->FeaturesNumber]) {
2069 case Profile_MessageTone:
2070 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_NOTONE;
2071 break;
2072 case Profile_AutoAnswer:
2073 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_AUTOANSWER_OFF;
2074 break;
2075 case Profile_Lights:
2076 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_LIGHTS_OFF;
2077 break;
2078 case Profile_ScreenSaver:
2079 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_OFF;
2080 break;
2081 case Profile_WarningTone:
2082 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_WARNING_OFF;
2083 break;
2084 case Profile_CallAlert:
2085 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_OFF;
2086 break;
2087 case Profile_Vibration:
2088 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VIBRATION_OFF;
2089 break;
2090 default:
2091 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_KEYPAD_OFF;
2092 break;
2093 }
2094 } else if (mystrncasecmp(readvalue,"Ringing",0)) {
2095 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_RINGING;
2096 } else if (mystrncasecmp(readvalue,"BeepOnce",0)) {
2097 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_BEEPONCE;
2098 if (Profile->FeatureID[Profile->FeaturesNumber]==Profile_MessageTone) {
2099 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_BEEPONCE;
2100 }
2101 } else if (mystrncasecmp(readvalue,"RingOnce",0)) {
2102 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_RINGONCE;
2103 } else if (mystrncasecmp(readvalue,"Ascending",0)) {
2104 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_ASCENDING;
2105 } else if (mystrncasecmp(readvalue,"CallerGroups",0)) {
2106 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_CALLALERT_CALLERGROUPS;
2107 } else if (mystrncasecmp(readvalue,"Standard",0)) {
2108 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_STANDARD;
2109 } else if (mystrncasecmp(readvalue,"Special",0)) {
2110 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_SPECIAL;
2111 } else if (mystrncasecmp(readvalue,"Ascending",0)) {
2112 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_ASCENDING;
2113 } else if (mystrncasecmp(readvalue,"Personal",0)) {
2114 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_MESSAGE_PERSONAL;
2115 } else if (mystrncasecmp(readvalue,"VibrateFirst",0)) {
2116 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VIBRATION_FIRST;
2117 } else if (mystrncasecmp(readvalue,"Auto",0)) {
2118 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_LIGHTS_AUTO;
2119 } else if (mystrncasecmp(readvalue,"5Seconds",0)) {
2120 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_5SEC;
2121 } else if (mystrncasecmp(readvalue,"20Seconds",0)) {
2122 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_20SEC;
2123 } else if (mystrncasecmp(readvalue,"1Minute",0)) {
2124 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_1MIN;
2125 } else if (mystrncasecmp(readvalue,"2Minutes",0)) {
2126 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_2MIN;
2127 } else if (mystrncasecmp(readvalue,"5Minutes",0)) {
2128 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_5MIN;
2129 } else if (mystrncasecmp(readvalue,"10Minutes",0)) {
2130 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_TIMEOUT_10MIN;
2131 } else if (mystrncasecmp(readvalue,"On",0)) {
2132 switch (Profile->FeatureID[Profile->FeaturesNumber]) {
2133 case Profile_AutoAnswer:
2134 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_AUTOANSWER_ON;
2135 break;
2136 case Profile_WarningTone:
2137 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_WARNING_ON;
2138 break;
2139 case Profile_ScreenSaver:
2140 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_SAVER_ON;
2141 break;
2142 default:
2143 Profile->FeatureValue[Profile->FeaturesNumber]=PROFILE_VIBRATION_ON;
2144 break;
2145 }
2146 } else unknown = true;
2147 }
2148 if (!unknown) Profile->FeaturesNumber++;
2149 }
2150 }
2151}
2152
2153static void ReadFMStationEntry(INI_Section *file_info, char *section, GSM_FMStation *FMStation, bool UseUnicode)
2154{
2155 unsigned char buffer[10000], *readvalue;
2156
2157 FMStation->Location = 0;
2158 FMStation->Frequency = 0;
2159
2160 sprintf(buffer,"Location");
2161 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2162 if (readvalue!=NULL) FMStation->Location = atoi(readvalue);
2163
2164 sprintf(buffer,"StationName");
2165 ReadBackupText(file_info, section, buffer, FMStation->StationName,UseUnicode);
2166
2167 sprintf(buffer,"Frequency");
2168 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2169 if (readvalue!=NULL) StringToDouble(readvalue, &FMStation->Frequency);
2170}
2171
2172static void ReadGPRSPointEntry(INI_Section *file_info, char *section, GSM_GPRSAccessPoint *GPRSPoint, bool UseUnicode)
2173{
2174 unsigned char buffer[10000], *readvalue;
2175
2176 GPRSPoint->Name[0] = 0;
2177 GPRSPoint->Name[1] = 0;
2178 GPRSPoint->URL[0] = 0;
2179 GPRSPoint->URL[1] = 0;
2180 GPRSPoint->Location = 0;
2181
2182 GPRSPoint->Active = false;
2183 sprintf(buffer,"Active");
2184 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2185 if (readvalue!=NULL) {
2186 if (mystrncasecmp(readvalue,"Yes",0)) GPRSPoint->Active = true;
2187 }
2188
2189 sprintf(buffer,"Location");
2190 readvalue = ReadCFGText(file_info, section, buffer, UseUnicode);
2191 if (readvalue!=NULL) GPRSPoint->Location = atoi(readvalue);
2192
2193 sprintf(buffer,"Name");
2194 ReadBackupText(file_info, section, buffer, GPRSPoint->Name,UseUnicode);
2195
2196 sprintf(buffer,"URL");
2197 ReadBackupText(file_info, section, buffer, GPRSPoint->URL,UseUnicode);
2198}
2199
2200static void ReadNoteEntry(INI_Section *file_info, char *section, GSM_NoteEntry *Note, bool UseUnicode)
2201{
2202 unsigned char buffer[100];
2203
2204 sprintf(buffer,"Text");
2205 ReadBackupText(file_info, section, buffer, Note->Text,UseUnicode);
2206}
2207
2208GSM_Error LoadBackup(char *FileName, GSM_Backup *backup, bool UseUnicode)
2209{
2210 INI_Section *file_info, *h;
2211 char buffer[100], *readvalue;
2212 int num;
2213 GSM_MemoryEntry PBK;
2214 bool found;
2215
2216 file_info = INI_ReadFile(FileName, UseUnicode);
2217
2218 sprintf(buffer,"Backup");
2219 if (UseUnicode) EncodeUnicode(buffer,"Backup",6);
2220
2221 readvalue = ReadCFGText(file_info, buffer, "Format", UseUnicode);
2222 /* Did we read anything? */
2223 if (readvalue == NULL) return ERR_FILENOTSUPPORTED;
2224 /* Is this format version supported ? */
2225 if (strcmp(readvalue,"1.01")!=0 && strcmp(readvalue,"1.02")!=0 &&
2226 strcmp(readvalue,"1.03")!=0) return ERR_FILENOTSUPPORTED;
2227
2228 readvalue = ReadCFGText(file_info, buffer, "IMEI", UseUnicode);
2229 if (readvalue!=NULL) strcpy(backup->IMEI,readvalue);
2230 readvalue = ReadCFGText(file_info, buffer, "Phone", UseUnicode);
2231 if (readvalue!=NULL) strcpy(backup->Model,readvalue);
2232 readvalue = ReadCFGText(file_info, buffer, "Creator", UseUnicode);
2233 if (readvalue!=NULL) strcpy(backup->Creator,readvalue);
2234 readvalue = ReadCFGText(file_info, buffer, "DateTime", UseUnicode);
2235 if (readvalue!=NULL) {
2236 ReadVCALDateTime(readvalue, &backup->DateTime);
2237 backup->DateTimeAvailable = true;
2238 }
2239
2240 sprintf(buffer,"Checksum");
2241 if (UseUnicode) EncodeUnicode(buffer,"Checksum",8);
2242 readvalue = ReadCFGText(file_info, buffer, "MD5", UseUnicode);
2243 if (readvalue!=NULL) strcpy(backup->MD5Original,readvalue);
2244
2245 num = 0;
2246 for (h = file_info; h != NULL; h = h->Next) {
2247 found = false;
2248 if (UseUnicode) {
2249 EncodeUnicode(buffer,"Profile",7);
2250 if (mywstrncasecmp(buffer, h->SectionName, 7)) found = true;
2251 } else {
2252 if (mystrncasecmp("Profile", h->SectionName, 7)) found = true;
2253 }
2254 if (found) {
2255 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2256 if (readvalue==NULL) break;
2257 if (num < GSM_BACKUP_MAX_PROFILES) {
2258 backup->Profiles[num] = malloc(sizeof(GSM_Profile));
2259 if (backup->Profiles[num] == NULL) return ERR_MOREMEMORY;
2260 backup->Profiles[num + 1] = NULL;
2261 } else {
2262 dbgprintf("Increase GSM_BACKUP_MAX_PROFILES\n");
2263 return ERR_MOREMEMORY;
2264 }
2265 ReadProfileEntry(file_info, h->SectionName, backup->Profiles[num], UseUnicode);
2266 num++;
2267 }
2268 }
2269 num = 0;
2270 for (h = file_info; h != NULL; h = h->Next) {
2271 found = false;
2272 if (UseUnicode) {
2273 EncodeUnicode(buffer,"PhonePBK",8);
2274 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2275 } else {
2276 if (mystrncasecmp("PhonePBK", h->SectionName, 8)) found = true;
2277 }
2278 if (found) {
2279 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2280 if (readvalue==NULL) break;
2281 if (num < GSM_BACKUP_MAX_PHONEPHONEBOOK) {
2282 backup->PhonePhonebook[num] = malloc(sizeof(GSM_MemoryEntry));
2283 if (backup->PhonePhonebook[num] == NULL) return ERR_MOREMEMORY;
2284 backup->PhonePhonebook[num + 1] = NULL;
2285 } else {
2286 dbgprintf("Increase GSM_BACKUP_MAX_PHONEPHONEBOOK\n");
2287 return ERR_MOREMEMORY;
2288 }
2289 backup->PhonePhonebook[num]->Location= atoi (readvalue);
2290 backup->PhonePhonebook[num]->MemoryType= MEM_ME;
2291 ReadPbkEntry(file_info, h->SectionName, backup->PhonePhonebook[num],UseUnicode);
2292 dbgprintf("number of entries = %i\n",backup->PhonePhonebook[num]->EntriesNum);
2293 num++;
2294 }
2295 }
2296 num = 0;
2297 while (0) {
2298 if (backup->PhonePhonebook[num] == NULL) break;
2299 if (backup->PhonePhonebook[num+1] != NULL) {
2300 if (backup->PhonePhonebook[num+1]->Location < backup->PhonePhonebook[num]->Location) {
2301 memcpy(&PBK,backup->PhonePhonebook[num+1],sizeof(GSM_MemoryEntry));
2302 memcpy(backup->PhonePhonebook[num+1],backup->PhonePhonebook[num],sizeof(GSM_MemoryEntry));
2303 memcpy(backup->PhonePhonebook[num],&PBK,sizeof(GSM_MemoryEntry));
2304 num = 0;
2305 continue;
2306 }
2307 }
2308 num++;
2309 }
2310 num = 0;
2311 for (h = file_info; h != NULL; h = h->Next) {
2312 found = false;
2313 if (UseUnicode) {
2314 EncodeUnicode(buffer,"SIMPBK",6);
2315 if (mywstrncasecmp(buffer, h->SectionName, 6)) found = true;
2316 } else {
2317 if (mystrncasecmp("SIMPBK", h->SectionName, 6)) found = true;
2318 }
2319 if (found) {
2320 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2321 if (readvalue==NULL) break;
2322 if (num < GSM_BACKUP_MAX_SIMPHONEBOOK) {
2323 backup->SIMPhonebook[num] = malloc(sizeof(GSM_MemoryEntry));
2324 if (backup->SIMPhonebook[num] == NULL) return ERR_MOREMEMORY;
2325 backup->SIMPhonebook[num + 1] = NULL;
2326 } else {
2327 dbgprintf("Increase GSM_BACKUP_MAX_SIMPHONEBOOK\n");
2328 return ERR_MOREMEMORY;
2329 }
2330 backup->SIMPhonebook[num]->Location= atoi (readvalue);
2331 backup->SIMPhonebook[num]->MemoryType= MEM_SM;
2332 ReadPbkEntry(file_info, h->SectionName, backup->SIMPhonebook[num],UseUnicode);
2333 num++;
2334 }
2335 }
2336 num = 0;
2337 while (0) {
2338 if (backup->SIMPhonebook[num] == NULL) break;
2339 if (backup->SIMPhonebook[num+1] != NULL) {
2340 if (backup->SIMPhonebook[num+1]->Location < backup->SIMPhonebook[num]->Location) {
2341 memcpy(&PBK,backup->SIMPhonebook[num+1],sizeof(GSM_MemoryEntry));
2342 memcpy(backup->SIMPhonebook[num+1],backup->SIMPhonebook[num],sizeof(GSM_MemoryEntry));
2343 memcpy(backup->SIMPhonebook[num],&PBK,sizeof(GSM_MemoryEntry));
2344 num = 0;
2345 continue;
2346 }
2347 }
2348 num++;
2349 }
2350 num = 0;
2351 for (h = file_info; h != NULL; h = h->Next) {
2352 found = false;
2353 if (UseUnicode) {
2354 EncodeUnicode(buffer,"Calendar",8);
2355 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2356 } else {
2357 if (mystrncasecmp("Calendar", h->SectionName, 8)) found = true;
2358 }
2359 if (found) {
2360 readvalue = ReadCFGText(file_info, h->SectionName, "Type", UseUnicode);
2361 if (readvalue==NULL) break;
2362 if (num < GSM_MAXCALENDARTODONOTES) {
2363 backup->Calendar[num] = malloc(sizeof(GSM_CalendarEntry));
2364 if (backup->Calendar[num] == NULL) return ERR_MOREMEMORY;
2365 backup->Calendar[num + 1] = NULL;
2366 } else {
2367 dbgprintf("Increase GSM_MAXCALENDARTODONOTES\n");
2368 return ERR_MOREMEMORY;
2369 }
2370 backup->Calendar[num]->Location = num + 1;
2371 ReadCalendarEntry(file_info, h->SectionName, backup->Calendar[num],UseUnicode);
2372 num++;
2373 }
2374 }
2375 num = 0;
2376 for (h = file_info; h != NULL; h = h->Next) {
2377 found = false;
2378 if (UseUnicode) {
2379 EncodeUnicode(buffer,"Caller",6);
2380 if (mywstrncasecmp(buffer, h->SectionName, 6)) found = true;
2381 } else {
2382 if (mystrncasecmp("Caller", h->SectionName, 6)) found = true;
2383 }
2384 if (found) {
2385 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2386 if (readvalue==NULL) break;
2387 if (num < GSM_BACKUP_MAX_CALLER) {
2388 backup->CallerLogos[num] = malloc(sizeof(GSM_Bitmap));
2389 if (backup->CallerLogos[num] == NULL) return ERR_MOREMEMORY;
2390 backup->CallerLogos[num + 1] = NULL;
2391 } else {
2392 dbgprintf("Increase GSM_BACKUP_MAX_CALLER\n");
2393 return ERR_MOREMEMORY;
2394 }
2395 backup->CallerLogos[num]->Location = atoi (readvalue);
2396 ReadCallerEntry(file_info, h->SectionName, backup->CallerLogos[num],UseUnicode);
2397 num++;
2398 }
2399 }
2400 num = 0;
2401 for (h = file_info; h != NULL; h = h->Next) {
2402 found = false;
2403 if (UseUnicode) {
2404 EncodeUnicode(buffer,"SMSC",4);
2405 if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
2406 } else {
2407 if (mystrncasecmp("SMSC", h->SectionName, 4)) found = true;
2408 }
2409 if (found) {
2410 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2411 if (readvalue==NULL) break;
2412 if (num < GSM_BACKUP_MAX_SMSC) {
2413 backup->SMSC[num] = malloc(sizeof(GSM_SMSC));
2414 if (backup->SMSC[num] == NULL) return ERR_MOREMEMORY;
2415 backup->SMSC[num + 1] = NULL;
2416 } else {
2417 dbgprintf("Increase GSM_BACKUP_MAX_SMSC\n");
2418 return ERR_MOREMEMORY;
2419 }
2420 backup->SMSC[num]->Location = atoi (readvalue);
2421 ReadSMSCEntry(file_info, h->SectionName, backup->SMSC[num],UseUnicode);
2422 num++;
2423 }
2424 }
2425 num = 0;
2426 for (h = file_info; h != NULL; h = h->Next) {
2427 found = false;
2428 if (UseUnicode) {
2429 EncodeUnicode(buffer,"WAPBookmark",11);
2430 if (mywstrncasecmp(buffer, h->SectionName, 11)) found = true;
2431 if (!found) {
2432 EncodeUnicode(buffer,"Bookmark",8);
2433 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2434 }
2435 } else {
2436 if (mystrncasecmp("WAPBookmark", h->SectionName, 11)) found = true;
2437 if (!found) {
2438 if (mystrncasecmp("Bookmark", h->SectionName, 8)) found = true;
2439 }
2440 }
2441 if (found) {
2442 readvalue = ReadCFGText(file_info, h->SectionName, "URL", UseUnicode);
2443 if (readvalue==NULL) break;
2444 if (num < GSM_BACKUP_MAX_WAPBOOKMARK) {
2445 backup->WAPBookmark[num] = malloc(sizeof(GSM_WAPBookmark));
2446 if (backup->WAPBookmark[num] == NULL) return ERR_MOREMEMORY;
2447 backup->WAPBookmark[num + 1] = NULL;
2448 } else {
2449 dbgprintf("Increase GSM_BACKUP_MAX_WAPBOOKMARK\n");
2450 return ERR_MOREMEMORY;
2451 }
2452 backup->WAPBookmark[num]->Location = num + 1;
2453 ReadWAPBookmarkEntry(file_info, h->SectionName, backup->WAPBookmark[num],UseUnicode);
2454 num++;
2455 }
2456 }
2457 num = 0;
2458 for (h = file_info; h != NULL; h = h->Next) {
2459 found = false;
2460 if (UseUnicode) {
2461 EncodeUnicode(buffer,"WAPSettings",11);
2462 if (mywstrncasecmp(buffer, h->SectionName, 11)) found = true;
2463 if (!found) {
2464 EncodeUnicode(buffer,"Settings",8);
2465 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2466 }
2467 } else {
2468 if (mystrncasecmp("WAPSettings", h->SectionName, 11)) found = true;
2469 if (!found) {
2470 if (mystrncasecmp("Settings", h->SectionName, 8)) found = true;
2471 }
2472 }
2473 if (found) {
2474 readvalue = ReadCFGText(file_info, h->SectionName, "Title00", UseUnicode);
2475 if (readvalue==NULL) break;
2476 if (num < GSM_BACKUP_MAX_WAPSETTINGS) {
2477 backup->WAPSettings[num] = malloc(sizeof(GSM_MultiWAPSettings));
2478 if (backup->WAPSettings[num] == NULL) return ERR_MOREMEMORY;
2479 backup->WAPSettings[num + 1] = NULL;
2480 } else {
2481 dbgprintf("Increase GSM_BACKUP_MAX_WAPSETTINGS\n");
2482 return ERR_MOREMEMORY;
2483 }
2484 backup->WAPSettings[num]->Location = num + 1;
2485 dbgprintf("reading wap settings\n");
2486 ReadWAPSettingsEntry(file_info, h->SectionName, backup->WAPSettings[num],UseUnicode);
2487 num++;
2488 }
2489 }
2490 num = 0;
2491 for (h = file_info; h != NULL; h = h->Next) {
2492 found = false;
2493 if (UseUnicode) {
2494 EncodeUnicode(buffer,"MMSSettings",8);
2495 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2496 } else {
2497 if (mystrncasecmp("MMSSettings", h->SectionName, 8)) found = true;
2498 }
2499 if (found) {
2500 readvalue = ReadCFGText(file_info, h->SectionName, "Title00", UseUnicode);
2501 if (readvalue==NULL) break;
2502 if (num < GSM_BACKUP_MAX_MMSSETTINGS) {
2503 backup->MMSSettings[num] = malloc(sizeof(GSM_MultiWAPSettings));
2504 if (backup->MMSSettings[num] == NULL) return ERR_MOREMEMORY;
2505 backup->MMSSettings[num + 1] = NULL;
2506 } else {
2507 dbgprintf("Increase GSM_BACKUP_MAX_MMSSETTINGS\n");
2508 return ERR_MOREMEMORY;
2509 }
2510 backup->MMSSettings[num]->Location = num + 1;
2511 dbgprintf("reading mms settings\n");
2512 ReadWAPSettingsEntry(file_info, h->SectionName, backup->MMSSettings[num],UseUnicode);
2513 num++;
2514 }
2515 }
2516 num = 0;
2517 for (h = file_info; h != NULL; h = h->Next) {
2518 found = false;
2519 if (UseUnicode) {
2520 EncodeUnicode(buffer,"Ringtone",8);
2521 if (mywstrncasecmp(buffer, h->SectionName, 8)) found = true;
2522 } else {
2523 if (mystrncasecmp("Ringtone", h->SectionName, 8)) found = true;
2524 }
2525 if (found) {
2526 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2527 if (readvalue==NULL) break;
2528 if (num < GSM_BACKUP_MAX_RINGTONES) {
2529 backup->Ringtone[num] = malloc(sizeof(GSM_Ringtone));
2530 if (backup->Ringtone[num] == NULL) return ERR_MOREMEMORY;
2531 backup->Ringtone[num + 1] = NULL;
2532 } else {
2533 dbgprintf("Increase GSM_BACKUP_MAX_RINGTONES\n");
2534 return ERR_MOREMEMORY;
2535 }
2536 ReadRingtoneEntry(file_info, h->SectionName, backup->Ringtone[num],UseUnicode);
2537 num++;
2538 }
2539 }
2540 num = 0;
2541 for (h = file_info; h != NULL; h = h->Next) {
2542 found = false;
2543 if (UseUnicode) {
2544 EncodeUnicode(buffer,"TODO",4);
2545 if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
2546 } else {
2547 if (mystrncasecmp("TODO", h->SectionName, 4)) found = true;
2548 }
2549 if (found) {
2550 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2551 if (readvalue==NULL) break;
2552 if (num < GSM_MAXCALENDARTODONOTES) {
2553 backup->ToDo[num] = malloc(sizeof(GSM_ToDoEntry));
2554 if (backup->ToDo[num] == NULL) return ERR_MOREMEMORY;
2555 backup->ToDo[num + 1] = NULL;
2556 } else {
2557 dbgprintf("Increase GSM_MAXCALENDARTODONOTES\n");
2558 return ERR_MOREMEMORY;
2559 }
2560 backup->ToDo[num]->Location = num + 1;
2561 ReadToDoEntry(file_info, h->SectionName, backup->ToDo[num],UseUnicode);
2562 num++;
2563 }
2564 }
2565 sprintf(buffer,"Startup");
2566 readvalue = ReadCFGText(file_info, buffer, "Text", UseUnicode);
2567 if (readvalue==NULL) {
2568 readvalue = ReadCFGText(file_info, buffer, "Width", UseUnicode);
2569 }
2570 if (readvalue!=NULL) {
2571 backup->StartupLogo = malloc(sizeof(GSM_Bitmap));
2572 if (backup->StartupLogo == NULL) return ERR_MOREMEMORY;
2573 ReadStartupEntry(file_info, buffer, backup->StartupLogo,UseUnicode);
2574 }
2575 sprintf(buffer,"Operator");
2576 readvalue = ReadCFGText(file_info, buffer, "Network", UseUnicode);
2577 if (readvalue!=NULL) {
2578 backup->OperatorLogo = malloc(sizeof(GSM_Bitmap));
2579 if (backup->OperatorLogo == NULL) return ERR_MOREMEMORY;
2580 ReadOperatorEntry(file_info, buffer, backup->OperatorLogo,UseUnicode);
2581 }
2582 num = 0;
2583 for (h = file_info; h != NULL; h = h->Next) {
2584 found = false;
2585 if (UseUnicode) {
2586 EncodeUnicode(buffer,"FMStation",9);
2587 if (mywstrncasecmp(buffer, h->SectionName, 9)) found = true;
2588 } else {
2589 if (mystrncasecmp("FMStation", h->SectionName, 9)) found = true;
2590 }
2591 if (found) {
2592 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2593 if (readvalue==NULL) break;
2594 if (num < GSM_BACKUP_MAX_FMSTATIONS) {
2595 backup->FMStation[num] = malloc(sizeof(GSM_FMStation));
2596 if (backup->FMStation[num] == NULL) return ERR_MOREMEMORY;
2597 backup->FMStation[num + 1] = NULL;
2598 } else {
2599 dbgprintf("Increase GSM_BACKUP_MAX_FMSTATIONS\n");
2600 return ERR_MOREMEMORY;
2601 }
2602 backup->FMStation[num]->Location = num + 1;
2603 ReadFMStationEntry(file_info, h->SectionName, backup->FMStation[num],UseUnicode);
2604 num++;
2605 }
2606 }
2607 num = 0;
2608 for (h = file_info; h != NULL; h = h->Next) {
2609 found = false;
2610 if (UseUnicode) {
2611 EncodeUnicode(buffer,"GPRSPoint",9);
2612 if (mywstrncasecmp(buffer, h->SectionName, 9)) found = true;
2613 } else {
2614 if (mystrncasecmp("GPRSPoint", h->SectionName, 9)) found = true;
2615 }
2616 if (found) {
2617 readvalue = ReadCFGText(file_info, h->SectionName, "Location", UseUnicode);
2618 if (readvalue==NULL) break;
2619 if (num < GSM_BACKUP_MAX_GPRSPOINT) {
2620 backup->GPRSPoint[num] = malloc(sizeof(GSM_GPRSAccessPoint));
2621 if (backup->GPRSPoint[num] == NULL) return ERR_MOREMEMORY;
2622 backup->GPRSPoint[num + 1] = NULL;
2623 } else {
2624 dbgprintf("Increase GSM_BACKUP_MAX_GPRSPOINT\n");
2625 return ERR_MOREMEMORY;
2626 }
2627 backup->GPRSPoint[num]->Location = num + 1;
2628 ReadGPRSPointEntry(file_info, h->SectionName, backup->GPRSPoint[num],UseUnicode);
2629 num++;
2630 }
2631 }
2632 num = 0;
2633 for (h = file_info; h != NULL; h = h->Next) {
2634 found = false;
2635 if (UseUnicode) {
2636 EncodeUnicode(buffer,"Note",4);
2637 if (mywstrncasecmp(buffer, h->SectionName, 4)) found = true;
2638 } else {
2639 if (mystrncasecmp("Note", h->SectionName, 4)) found = true;
2640 }
2641 if (found) {
2642 readvalue = ReadCFGText(file_info, h->SectionName, "Text", UseUnicode);
2643 if (readvalue==NULL) break;
2644 if (num < GSM_BACKUP_MAX_NOTE) {
2645 backup->Note[num] = malloc(sizeof(GSM_NoteEntry));
2646 if (backup->Note[num] == NULL) return ERR_MOREMEMORY;
2647 backup->Note[num + 1] = NULL;
2648 } else {
2649 dbgprintf("Increase GSM_BACKUP_MAX_NOTE\n");
2650 return ERR_MOREMEMORY;
2651 }
2652 ReadNoteEntry(file_info, h->SectionName, backup->Note[num],UseUnicode);
2653 num++;
2654 }
2655 }
2656 if (backup->MD5Original[0]!=0) {
2657 FindBackupChecksum(FileName, UseUnicode, backup->MD5Calculated);
2658 }
2659
2660 return ERR_NONE;
2661}
2662
2663/* ---------------------- backup files for SMS ----------------------------- */
2664
2665static void ReadSMSBackupEntry(INI_Section *file_info, char *section, GSM_SMSMessage *SMS)
2666{
2667 unsigned char buffer[10000], *readvalue;
2668
2669 GSM_SetDefaultSMSData(SMS);
2670
2671 SMS->PDU = SMS_Submit;
2672 SMS->SMSC.Location = 0;
2673 sprintf(buffer,"SMSC");
2674 ReadBackupText(file_info, section, buffer, SMS->SMSC.Number, false);
2675 sprintf(buffer,"ReplySMSC");
2676 SMS->ReplyViaSameSMSC = false;
2677 readvalue = ReadCFGText(file_info, section, buffer, false);
2678 if (readvalue!=NULL) {
2679 if (mystrncasecmp(readvalue,"True",0)) SMS->ReplyViaSameSMSC = true;
2680 }
2681 sprintf(buffer,"Class");
2682 SMS->Class = -1;
2683 readvalue = ReadCFGText(file_info, section, buffer, false);
2684 if (readvalue!=NULL) SMS->Class = atoi(readvalue);
2685 sprintf(buffer,"Sent");
2686 readvalue = ReadCFGText(file_info, section, buffer, false);
2687 if (readvalue!=NULL) {
2688 ReadVCALDateTime(readvalue, &SMS->DateTime);
2689 SMS->PDU = SMS_Deliver;
2690 }
2691 sprintf(buffer,"RejectDuplicates");
2692 SMS->RejectDuplicates = false;
2693 readvalue = ReadCFGText(file_info, section, buffer, false);
2694 if (readvalue!=NULL) {
2695 if (mystrncasecmp(readvalue,"True",0)) SMS->RejectDuplicates = true;
2696 }
2697 sprintf(buffer,"ReplaceMessage");
2698 SMS->ReplaceMessage = 0;
2699 readvalue = ReadCFGText(file_info, section, buffer, false);
2700 if (readvalue!=NULL) SMS->ReplaceMessage = atoi(readvalue);
2701 sprintf(buffer,"MessageReference");
2702 SMS->MessageReference = 0;
2703 readvalue = ReadCFGText(file_info, section, buffer, false);
2704 if (readvalue!=NULL) SMS->MessageReference = atoi(readvalue);
2705 sprintf(buffer,"State");
2706 SMS->State = SMS_UnRead;
2707 readvalue = ReadCFGText(file_info, section, buffer, false);
2708 if (readvalue!=NULL) {
2709 if (mystrncasecmp(readvalue,"Read",0)) SMS->State = SMS_Read;
2710 else if (mystrncasecmp(readvalue,"Sent",0))SMS->State = SMS_Sent;
2711 else if (mystrncasecmp(readvalue,"UnSent",0))SMS->State = SMS_UnSent;
2712 }
2713 sprintf(buffer,"Number");
2714 ReadBackupText(file_info, section, buffer, SMS->Number, false);
2715 sprintf(buffer,"Name");
2716 ReadBackupText(file_info, section, buffer, SMS->Name, false);
2717 sprintf(buffer,"Length");
2718 SMS->Length = 0;
2719 readvalue = ReadCFGText(file_info, section, buffer, false);
2720 if (readvalue!=NULL) SMS->Length = atoi(readvalue);
2721 sprintf(buffer,"Coding");
2722 SMS->Coding = SMS_Coding_Default;
2723 readvalue = ReadCFGText(file_info, section, buffer, false);
2724 if (readvalue!=NULL) {
2725 if (mystrncasecmp(readvalue,"Unicode",0)) {
2726 SMS->Coding = SMS_Coding_Unicode;
2727 } else if (mystrncasecmp(readvalue,"8bit",0)) {
2728 SMS->Coding = SMS_Coding_8bit;
2729 }
2730 }
2731 ReadLinkedBackupText(file_info, section, "Text", buffer, false);
2732 DecodeHexBin (SMS->Text, buffer, strlen(buffer));
2733 SMS->Text[strlen(buffer)/2]= 0;
2734 SMS->Text[strlen(buffer)/2+1] = 0;
2735 sprintf(buffer,"Folder");
2736 readvalue = ReadCFGText(file_info, section, buffer, false);
2737 if (readvalue!=NULL) SMS->Folder = atoi(readvalue);
2738 SMS->UDH.Type = UDH_NoUDH;
2739 SMS->UDH.Length = 0;
2740 SMS->UDH.ID8bit = -1;
2741 SMS->UDH.ID16bit= -1;
2742 SMS->UDH.PartNumber= -1;
2743 SMS->UDH.AllParts= -1;
2744 sprintf(buffer,"UDH");
2745 readvalue = ReadCFGText(file_info, section, buffer, false);
2746 if (readvalue!=NULL) {
2747 DecodeHexBin (SMS->UDH.Text, readvalue, strlen(readvalue));
2748 SMS->UDH.Length = strlen(readvalue)/2;
2749 GSM_DecodeUDHHeader(&SMS->UDH);
2750 }
2751}
2752
2753static GSM_Error GSM_ReadSMSBackupTextFile(char *FileName, GSM_SMS_Backup *backup)
2754{
2755 INI_Section*file_info, *h;
2756 char *readvalue;
2757 int num;
2758
2759 backup->SMS[0] = NULL;
2760
2761 file_info = INI_ReadFile(FileName, false);
2762
2763 num = 0;
2764 for (h = file_info; h != NULL; h = h->Next) {
2765 if (mystrncasecmp("SMSBackup", h->SectionName, 9)) {
2766 readvalue = ReadCFGText(file_info, h->SectionName, "Number", false);
2767 if (readvalue==NULL) break;
2768 if (num < GSM_BACKUP_MAX_SMS) {
2769 backup->SMS[num] = malloc(sizeof(GSM_SMSMessage));
2770 if (backup->SMS[num] == NULL) return ERR_MOREMEMORY;
2771 backup->SMS[num + 1] = NULL;
2772 } else {
2773 dbgprintf("Increase GSM_BACKUP_MAX_SMS\n");
2774 return ERR_MOREMEMORY;
2775 }
2776 backup->SMS[num]->Location = num + 1;
2777 ReadSMSBackupEntry(file_info, h->SectionName, backup->SMS[num]);
2778 num++;
2779 }
2780 }
2781 return ERR_NONE;
2782}
2783
2784GSM_Error GSM_ReadSMSBackupFile(char *FileName, GSM_SMS_Backup *backup)
2785{
2786 FILE *file;
2787
2788 backup->SMS[0] = NULL;
2789
2790 file = fopen(FileName, "rb");
2791 if (file == NULL) return(ERR_CANTOPENFILE);
2792
2793 fclose(file);
2794
2795 return GSM_ReadSMSBackupTextFile(FileName, backup);
2796}
2797
2798GSM_Error SaveSMSBackupTextFile(FILE *file, GSM_SMS_Backup *backup)
2799{
2800 int i,w,current;
2801 unsigned char buffer[10000];
2802 GSM_DateTimeDT;
2803
2804 fprintf(file,"\n# File created by Gammu (www.mwiacek.com) version %s\n",VERSION);
2805 GSM_GetCurrentDateTime (&DT);
2806 fprintf(file,"# Saved %s\n\n",OSDateTime(DT,false));
2807
2808 i=0;
2809 while (backup->SMS[i]!=NULL) {
2810 fprintf(file,"[SMSBackup%03i]\n",i);
2811 switch (backup->SMS[i]->Coding) {
2812 case SMS_Coding_Unicode:
2813 case SMS_Coding_Default:
2814 sprintf(buffer,"%s",DecodeUnicodeString(backup->SMS[i]->Text));
2815 fprintf(file,"#");
2816 current = 0;
2817 for (w=0;w<(int)(strlen(buffer));w++) {
2818 switch (buffer[w]) {
2819 case 10:
2820 fprintf(file,"\n#");
2821 current = 0;
2822 break;
2823 case 13:
2824 break;
2825 default:
2826 if (isprint(buffer[w])) {
2827 fprintf(file,"%c",buffer[w]);
2828 current ++;
2829 }
2830 if (current == 75) {
2831 fprintf(file,"\n#");
2832 current = 0;
2833 }
2834 }
2835 }
2836 fprintf(file,"\n");
2837 break;
2838 default:
2839 break;
2840 }
2841 if (backup->SMS[i]->PDU == SMS_Deliver) {
2842 SaveBackupText(file, "SMSC", backup->SMS[i]->SMSC.Number, false);
2843 if (backup->SMS[i]->ReplyViaSameSMSC) fprintf(file,"SMSCReply = true\n");
2844 fprintf(file,"Sent");
2845 SaveVCalDateTime(file,&backup->SMS[i]->DateTime, false);
2846 }
2847 fprintf(file,"State = ");
2848 switch (backup->SMS[i]->State) {
2849 case SMS_UnRead : fprintf(file,"UnRead\n");break;
2850 case SMS_Read : fprintf(file,"Read\n");break;
2851 case SMS_Sent : fprintf(file,"Sent\n");break;
2852 case SMS_UnSent : fprintf(file,"UnSent\n");break;
2853 }
2854 SaveBackupText(file, "Number", backup->SMS[i]->Number, false);
2855 SaveBackupText(file, "Name", backup->SMS[i]->Name, false);
2856 if (backup->SMS[i]->UDH.Type != UDH_NoUDH) {
2857 EncodeHexBin(buffer,backup->SMS[i]->UDH.Text,backup->SMS[i]->UDH.Length);
2858 fprintf(file,"UDH = %s\n",buffer);
2859 }
2860 switch (backup->SMS[i]->Coding) {
2861 case SMS_Coding_Unicode:
2862 case SMS_Coding_Default:
2863 EncodeHexBin(buffer,backup->SMS[i]->Text,backup->SMS[i]->Length*2);
2864 break;
2865 default:
2866 EncodeHexBin(buffer,backup->SMS[i]->Text,backup->SMS[i]->Length);
2867 break;
2868 }
2869 SaveLinkedBackupText(file, "Text", buffer, false);
2870 switch (backup->SMS[i]->Coding) {
2871 case SMS_Coding_Unicode : fprintf(file,"Coding = Unicode\n"); break;
2872 case SMS_Coding_Default : fprintf(file,"Coding = Default\n"); break;
2873 case SMS_Coding_8bit : fprintf(file,"Coding = 8bit\n"); break;
2874 }
2875 fprintf(file,"Folder = %i\n",backup->SMS[i]->Folder);
2876 fprintf(file,"Length = %i\n",backup->SMS[i]->Length);
2877 fprintf(file,"Class = %i\n",backup->SMS[i]->Class);
2878 fprintf(file,"ReplySMSC = ");
2879 if (backup->SMS[i]->ReplyViaSameSMSC) fprintf(file,"True\n"); else fprintf(file,"False\n");
2880 fprintf(file,"RejectDuplicates = ");
2881 if (backup->SMS[i]->RejectDuplicates) fprintf(file,"True\n"); else fprintf(file,"False\n");
2882 fprintf(file,"ReplaceMessage = %i\n",backup->SMS[i]->ReplaceMessage);
2883 fprintf(file,"MessageReference = %i\n",backup->SMS[i]->MessageReference);
2884 fprintf(file,"\n");
2885 i++;
2886 }
2887 return ERR_NONE;
2888}
2889
2890GSM_Error GSM_SaveSMSBackupFile(char *FileName, GSM_SMS_Backup *backup)
2891{
2892 FILE *file;
2893
2894 file = fopen(FileName, "wb");
2895 if (file == NULL) return(ERR_CANTOPENFILE);
2896
2897 SaveSMSBackupTextFile(file,backup);
2898
2899 fclose(file);
2900
2901 return ERR_NONE;
2902}
2903
2904#endif
2905
2906/* How should editor hadle tabs in this file? Add editor commands here.
2907 * vim: noexpandtab sw=8 ts=8 sts=8:
2908 */
diff --git a/gammu/emb/common/service/backup/backtext.h b/gammu/emb/common/service/backup/backtext.h
new file mode 100644
index 0000000..a95bd89
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backtext.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backtext_h
4#define __gsm_backtext_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error LoadBackup(char *FileName, GSM_Backup *backup, bool UseUnicode);
10GSM_Error SaveBackup(char *FileName, GSM_Backup *backup, bool UseUnicode);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/backvcf.c b/gammu/emb/common/service/backup/backvcf.c
new file mode 100644
index 0000000..761a81b
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backvcf.c
@@ -0,0 +1,75 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmlogo.h"
10#include "../gsmmisc.h"
11#include "backvcf.h"
12
13#ifdef GSM_ENABLE_BACKUP
14
15GSM_Error SaveVCard(char *FileName, GSM_Backup *backup)
16{
17 int i, Length = 0;
18 unsigned char Buffer[1000];
19 FILE *file;
20
21 file = fopen(FileName, "wb");
22 if (file == NULL) return ERR_CANTOPENFILE;
23
24 i=0;
25 while (backup->PhonePhonebook[i]!=NULL) {
26 sprintf(Buffer, "%c%c",13,10);
27 fwrite(Buffer,1,2,file);
28 Length = 0;
29 GSM_EncodeVCARD(Buffer,&Length,backup->PhonePhonebook[i],true,Nokia_VCard21);
30 fwrite(Buffer,1,Length,file);
31 i++;
32 }
33
34 fclose(file);
35 return ERR_NONE;
36}
37
38GSM_Error LoadVCard(char *FileName, GSM_Backup *backup)
39{
40 GSM_File File;
41 GSM_Error error;
42 GSM_MemoryEntry Pbk;
43 int numPbk = 0, Pos;
44
45 File.Buffer = NULL;
46 error = GSM_ReadFile(FileName, &File);
47 if (error != ERR_NONE) return error;
48
49 Pos = 0;
50 while (1) {
51 error = GSM_DecodeVCARD(File.Buffer, &Pos, &Pbk, Nokia_VCard21);
52 if (error == ERR_EMPTY) break;
53 if (error != ERR_NONE) return error;
54 if (numPbk < GSM_BACKUP_MAX_PHONEPHONEBOOK) {
55 backup->PhonePhonebook[numPbk] = malloc(sizeof(GSM_MemoryEntry));
56 if (backup->PhonePhonebook[numPbk] == NULL) return ERR_MOREMEMORY;
57 backup->PhonePhonebook[numPbk + 1] = NULL;
58 } else {
59 dbgprintf("Increase GSM_BACKUP_MAX_PHONEPHONEBOOK\n");
60 return ERR_MOREMEMORY;
61 }
62 memcpy(backup->PhonePhonebook[numPbk],&Pbk,sizeof(GSM_MemoryEntry));
63 backup->PhonePhonebook[numPbk]->Location = numPbk + 1;
64 backup->PhonePhonebook[numPbk]->MemoryType = MEM_ME;
65 numPbk++;
66 }
67
68 return ERR_NONE;
69}
70
71#endif
72
73/* How should editor hadle tabs in this file? Add editor commands here.
74 * vim: noexpandtab sw=8 ts=8 sts=8:
75 */
diff --git a/gammu/emb/common/service/backup/backvcf.h b/gammu/emb/common/service/backup/backvcf.h
new file mode 100644
index 0000000..8cbb6cf
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backvcf.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backvcf_h
4#define __gsm_backvcf_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error SaveVCard(char *FileName, GSM_Backup *backup);
10GSM_Error LoadVCard(char *FileName, GSM_Backup *backup);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/backvcs.c b/gammu/emb/common/service/backup/backvcs.c
new file mode 100644
index 0000000..332e718
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backvcs.c
@@ -0,0 +1,106 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmlogo.h"
10#include "../gsmmisc.h"
11#include "backvcs.h"
12
13#ifdef GSM_ENABLE_BACKUP
14
15GSM_Error SaveVCalendar(char *FileName, GSM_Backup *backup)
16{
17 int i, Length = 0;
18 unsigned char Buffer[1000];
19 FILE *file;
20
21 file = fopen(FileName, "wb");
22 if (file == NULL) return ERR_CANTOPENFILE;
23
24 Length=sprintf(Buffer, "BEGIN:VCALENDAR%c%c",13,10);
25 Length+=sprintf(Buffer+Length, "VERSION:1.0%c%c",13,10);
26 fwrite(Buffer,1,Length,file);
27
28 i=0;
29 while (backup->Calendar[i]!=NULL) {
30 sprintf(Buffer, "%c%c",13,10);
31 fwrite(Buffer,1,2,file);
32 Length = 0;
33 GSM_EncodeVCALENDAR(Buffer,&Length,backup->Calendar[i],false,Nokia_VCalendar);
34 fwrite(Buffer,1,Length,file);
35 i++;
36 }
37 i=0;
38 while (backup->ToDo[i]!=NULL) {
39 sprintf(Buffer, "%c%c",13,10);
40 fwrite(Buffer,1,2,file);
41 Length = 0;
42 GSM_EncodeVTODO(Buffer,&Length,backup->ToDo[i],false,Nokia_VToDo);
43 fwrite(Buffer,1,Length,file);
44 i++;
45 }
46
47 Length=sprintf(Buffer, "%c%cEND:VCALENDAR%c%c",13,10,13,10);
48 fwrite(Buffer,1,Length,file);
49
50 fclose(file);
51 return ERR_NONE;
52}
53
54GSM_Error LoadVCalendar(char *FileName, GSM_Backup *backup)
55{
56 GSM_File File;
57 GSM_Error error;
58 GSM_CalendarEntryCalendar;
59 GSM_ToDoEntry ToDo;
60 int numCal = 0, numToDo = 0, Pos;
61
62 File.Buffer = NULL;
63 error = GSM_ReadFile(FileName, &File);
64 if (error != ERR_NONE) return error;
65
66 Pos = 0;
67 while (1) {
68 error = GSM_DecodeVCALENDAR_VTODO(File.Buffer, &Pos, &Calendar, &ToDo, Nokia_VCalendar, Nokia_VToDo);
69 if (error == ERR_EMPTY) break;
70 if (error != ERR_NONE) return error;
71 if (Calendar.EntriesNum != 0) {
72 if (numCal < GSM_MAXCALENDARTODONOTES) {
73 backup->Calendar[numCal] = malloc(sizeof(GSM_CalendarEntry));
74 if (backup->Calendar[numCal] == NULL) return ERR_MOREMEMORY;
75 backup->Calendar[numCal + 1] = NULL;
76 } else {
77 dbgprintf("Increase GSM_MAXCALENDARTODONOTES\n");
78 return ERR_MOREMEMORY;
79 }
80 memcpy(backup->Calendar[numCal],&Calendar,sizeof(GSM_CalendarEntry));
81 backup->Calendar[numCal]->Location = numCal + 1;
82 numCal++;
83 }
84 if (ToDo.EntriesNum != 0) {
85 if (numToDo < GSM_MAXCALENDARTODONOTES) {
86 backup->ToDo[numToDo] = malloc(sizeof(GSM_ToDoEntry));
87 if (backup->ToDo[numToDo] == NULL) return ERR_MOREMEMORY;
88 backup->ToDo[numToDo + 1] = NULL;
89 } else {
90 dbgprintf("Increase GSM_MAXCALENDARTODONOTES\n");
91 return ERR_MOREMEMORY;
92 }
93 memcpy(backup->ToDo[numToDo],&ToDo,sizeof(GSM_ToDoEntry));
94 backup->ToDo[numToDo]->Location = numToDo + 1;
95 numToDo++;
96 }
97 }
98
99 return ERR_NONE;
100}
101
102#endif
103
104/* How should editor hadle tabs in this file? Add editor commands here.
105 * vim: noexpandtab sw=8 ts=8 sts=8:
106 */
diff --git a/gammu/emb/common/service/backup/backvcs.h b/gammu/emb/common/service/backup/backvcs.h
new file mode 100644
index 0000000..f3331b5
--- a/dev/null
+++ b/gammu/emb/common/service/backup/backvcs.h
@@ -0,0 +1,17 @@
1/* (c) 2003 by Marcin Wiacek */
2
3#ifndef __gsm_backvcs_h
4#define __gsm_backvcs_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9GSM_Error SaveVCalendar(char *FileName, GSM_Backup *backup);
10GSM_Error LoadVCalendar(char *FileName, GSM_Backup *backup);
11#endif
12
13#endif
14
15/* How should editor hadle tabs in this file? Add editor commands here.
16 * vim: noexpandtab sw=8 ts=8 sts=8:
17 */
diff --git a/gammu/emb/common/service/backup/gsmback.c b/gammu/emb/common/service/backup/gsmback.c
new file mode 100644
index 0000000..91ac745
--- a/dev/null
+++ b/gammu/emb/common/service/backup/gsmback.c
@@ -0,0 +1,280 @@
1/* (c) 2002-2004 by Marcin Wiacek & Michal Cihar */
2
3#include <string.h>
4#include <ctype.h>
5
6#include "../../phone/nokia/nfunc.h"
7#include "../../phone/nokia/dct3/n7110.h"
8#include "../../misc/coding/coding.h"
9#include "../../misc/cfg.h"
10#include "../gsmlogo.h"
11#include "../gsmmisc.h"
12#include "../gsmcal.h"
13#include "gsmback.h"
14#include "backtext.h"
15#include "backldif.h"
16#include "backlmb.h"
17#include "backvcs.h"
18#include "backvcf.h"
19#include "backics.h"
20
21#ifdef GSM_ENABLE_BACKUP
22
23void GSM_FreeBackup(GSM_Backup *backup)
24{
25 int i;
26
27 i=0;
28 while (backup->PhonePhonebook[i]!=NULL) {
29 free(backup->PhonePhonebook[i]);
30 backup->PhonePhonebook[i] = NULL;
31 i++;
32 }
33 i=0;
34 while (backup->SIMPhonebook[i]!=NULL) {
35 free(backup->SIMPhonebook[i]);
36 backup->SIMPhonebook[i] = NULL;
37 i++;
38 }
39 i=0;
40 while (backup->Calendar[i]!=NULL) {
41 free(backup->Calendar[i]);
42 backup->Calendar[i] = NULL;
43 i++;
44 }
45 i=0;
46 while (backup->CallerLogos[i]!=NULL) {
47 free(backup->CallerLogos[i]);
48 backup->CallerLogos[i] = NULL;
49 i++;
50 }
51 i=0;
52 while (backup->SMSC[i]!=NULL) {
53 free(backup->SMSC[i]);
54 backup->SMSC[i] = NULL;
55 i++;
56 }
57 i=0;
58 while (backup->WAPBookmark[i]!=NULL) {
59 free(backup->WAPBookmark[i]);
60 backup->WAPBookmark[i] = NULL;
61 i++;
62 }
63 i=0;
64 while (backup->WAPSettings[i]!=NULL) {
65 free(backup->WAPSettings[i]);
66 backup->WAPSettings[i] = NULL;
67 i++;
68 }
69 i=0;
70 while (backup->MMSSettings[i]!=NULL) {
71 free(backup->MMSSettings[i]);
72 backup->MMSSettings[i] = NULL;
73 i++;
74 }
75 i=0;
76 while (backup->Ringtone[i]!=NULL) {
77 free(backup->Ringtone[i]);
78 backup->Ringtone[i] = NULL;
79 i++;
80 }
81 i=0;
82 while (backup->ToDo[i]!=NULL) {
83 free(backup->ToDo[i]);
84 backup->ToDo[i] = NULL;
85 i++;
86 }
87 i=0;
88 while (backup->Profiles[i]!=NULL) {
89 free(backup->Profiles[i]);
90 backup->Profiles[i] = NULL;
91 i++;
92 }
93 i=0;
94 while (backup->FMStation[i]!=NULL) {
95 free(backup->FMStation[i]);
96 backup->FMStation[i] = NULL;
97 i++;
98 }
99 if (backup->StartupLogo!=NULL) {
100 free(backup->StartupLogo);
101 backup->StartupLogo = NULL;
102 }
103 if (backup->OperatorLogo!=NULL) {
104 free(backup->OperatorLogo);
105 backup->OperatorLogo = NULL;
106 }
107 i=0;
108 while (backup->GPRSPoint[i]!=NULL) {
109 free(backup->GPRSPoint[i]);
110 backup->GPRSPoint[i] = NULL;
111 i++;
112 }
113 i=0;
114 while (backup->Note[i]!=NULL) {
115 free(backup->Note[i]);
116 backup->Note[i] = NULL;
117 i++;
118 }
119}
120
121GSM_Error GSM_SaveBackupFile(char *FileName, GSM_Backup *backup, bool UseUnicode)
122{
123 if (strstr(FileName,".lmb")) {
124 return SaveLMB(FileName,backup);
125 } else if (strstr(FileName,".vcs")) {
126 return SaveVCalendar(FileName,backup);
127 } else if (strstr(FileName,".vcf")) {
128 return SaveVCard(FileName,backup);
129 } else if (strstr(FileName,".ldif")) {
130 return SaveLDIF(FileName,backup);
131 } else if (strstr(FileName,".ics")) {
132 return SaveICS(FileName,backup);
133 } else {
134 return SaveBackup(FileName,backup, UseUnicode);
135 }
136}
137
138GSM_Error GSM_ReadBackupFile(char *FileName, GSM_Backup *backup)
139{
140 FILE *file;
141 unsigned charbuffer[300];
142
143 file = fopen(FileName, "rb");
144 if (file == NULL) return ERR_CANTOPENFILE;
145 fread(buffer, 1, 9, file); /* Read the header of the file. */
146 fclose(file);
147
148 GSM_ClearBackup(backup);
149
150 /* Attempt to identify filetype */
151 if (strstr(FileName,".vcs")) {
152 return LoadVCalendar(FileName,backup);
153 } else if (strstr(FileName,".vcf")) {
154 return LoadVCard(FileName,backup);
155 } else if (strstr(FileName,".ldif")) {
156 return LoadLDIF(FileName,backup);
157 } else if (strstr(FileName,".ics")) {
158 return LoadICS(FileName,backup);
159 } else if (memcmp(buffer, "LMB ",4)==0) {
160 return LoadLMB(FileName,backup);
161 } else if (buffer[0] == 0xFE && buffer[1] == 0xFF) {
162 return LoadBackup(FileName,backup,true);
163 } else if (buffer[0] == 0xFF && buffer[1] == 0xFE) {
164 return LoadBackup(FileName,backup,true);
165 } else {
166 return LoadBackup(FileName,backup,false);
167 }
168}
169
170void GSM_ClearBackup(GSM_Backup *backup)
171{
172 backup->PhonePhonebook[0] = NULL;
173 backup->SIMPhonebook[0] = NULL;
174 backup->Calendar[0] = NULL;
175 backup->CallerLogos[0] = NULL;
176 backup->SMSC [0] = NULL;
177 backup->WAPBookmark[0] = NULL;
178 backup->WAPSettings[0] = NULL;
179 backup->MMSSettings[0] = NULL;
180 backup->Ringtone[0] = NULL;
181 backup->Profiles[0] = NULL;
182 backup->ToDo [0] = NULL;
183 backup->GPRSPoint[0] = NULL;
184 backup->FMStation[0] = NULL;
185 backup->Note [0] = NULL;
186 backup->StartupLogo = NULL;
187 backup->OperatorLogo = NULL;
188
189 backup->Creator [0] = 0;
190 backup->IMEI [0] = 0;
191 backup->Model [0] = 0;
192 backup->DateTimeAvailable = false;
193 backup->MD5Original[0] = 0;
194 backup->MD5Calculated[0] = 0;
195}
196
197void GSM_GetBackupFormatFeatures(char *FileName, GSM_Backup_Info *info)
198{
199 info->UseUnicode= false;
200 info->IMEI = false;
201 info->Model = false;
202 info->DateTime = false;
203 info->PhonePhonebook = false;
204 info->SIMPhonebook = false;
205 info->ToDo = false;
206 info->Calendar = false;
207 info->CallerLogos = false;
208 info->SMSC = false;
209 info->WAPBookmark = false;
210 info->WAPSettings = false;
211 info->MMSSettings = false;
212 info->Ringtone = false;
213 info->StartupLogo = false;
214 info->OperatorLogo = false;
215 info->Profiles = false;
216 info->FMStation = false;
217 info->GPRSPoint = false;
218 info->Note = false;
219
220 if (strstr(FileName,".lmb")) {
221 info->PhonePhonebook = true;
222 info->SIMPhonebook = true;
223 info->CallerLogos = true;
224 info->StartupLogo = true;
225 } else if (strstr(FileName,".vcs")) {
226 info->ToDo = true;
227 info->Calendar = true;
228 } else if (strstr(FileName,".vcf")) {
229 info->PhonePhonebook= true;
230 } else if (strstr(FileName,".ics")) {
231 info->ToDo = true;
232 info->Calendar = true;
233 } else if (strstr(FileName,".ldif")) {
234 info->PhonePhonebook= true;
235 } else {
236 info->UseUnicode= true;
237 info->IMEI = true;
238 info->Model = true;
239 info->DateTime = true;
240 info->PhonePhonebook = true;
241 info->SIMPhonebook = true;
242 info->ToDo = true;
243 info->Calendar = true;
244 info->CallerLogos = true;
245 info->SMSC = true;
246 info->WAPBookmark = true;
247 info->WAPSettings = true;
248 info->MMSSettings = true;
249 info->Ringtone = true;
250 info->StartupLogo = true;
251 info->OperatorLogo = true;
252 info->Profiles = true;
253 info->FMStation = true;
254 info->GPRSPoint = true;
255 info->Note = true;
256 }
257}
258
259void GSM_GetBackupFileFeatures(char *FileName, GSM_Backup_Info *info, GSM_Backup *backup)
260{
261 GSM_GetBackupFormatFeatures(FileName, info);
262
263 if (info->PhonePhonebook && backup->PhonePhonebook[0] == NULL) info->PhonePhonebook = false;
264 if (info->SIMPhonebook && backup->SIMPhonebook[0] == NULL) info->SIMPhonebook = false;
265 if (info->Calendar && backup->Calendar[0] == NULL) info->Calendar = false;
266 if (info->ToDo && backup->ToDo[0] == NULL) info->ToDo = false;
267 if (info->WAPBookmark && backup->WAPBookmark[0] == NULL) info->WAPBookmark = false;
268 if (info->WAPSettings && backup->WAPSettings[0] == NULL) info->WAPSettings = false;
269 if (info->MMSSettings && backup->MMSSettings[0] == NULL) info->MMSSettings = false;
270 if (info->FMStation && backup->FMStation[0] == NULL) info->FMStation = false;
271 if (info->GPRSPoint && backup->GPRSPoint[0] == NULL) info->GPRSPoint = false;
272 if (info->Profiles && backup->Profiles[0] == NULL) info->Profiles = false;
273 /* .... */
274}
275
276#endif
277
278/* How should editor hadle tabs in this file? Add editor commands here.
279 * vim: noexpandtab sw=8 ts=8 sts=8:
280 */
diff --git a/gammu/emb/common/service/backup/gsmback.h b/gammu/emb/common/service/backup/gsmback.h
new file mode 100644
index 0000000..1fd99b0
--- a/dev/null
+++ b/gammu/emb/common/service/backup/gsmback.h
@@ -0,0 +1,48 @@
1/* (c) 2003-2004 by Marcin Wiacek */
2
3#ifndef __gsm_back_h
4#define __gsm_back_h
5
6#include "backgen.h"
7
8#ifdef GSM_ENABLE_BACKUP
9
10GSM_Error GSM_SaveBackupFile(char *FileName, GSM_Backup *backup, bool UseUnicode);
11GSM_Error GSM_ReadBackupFile(char *FileName, GSM_Backup *backup);
12
13void GSM_ClearBackup (GSM_Backup *backup);
14void GSM_FreeBackup (GSM_Backup *backup);
15
16typedef struct {
17 bool UseUnicode;
18
19 bool IMEI;
20 bool Model;
21 bool DateTime;
22 bool ToDo;
23 bool PhonePhonebook;
24 bool SIMPhonebook;
25 bool Calendar;
26 bool CallerLogos;
27 bool SMSC;
28 bool WAPBookmark;
29 bool Profiles;
30 bool WAPSettings;
31 bool MMSSettings;
32 bool Ringtone;
33 bool StartupLogo;
34 bool OperatorLogo;
35 bool FMStation;
36 bool GPRSPoint;
37 bool Note;
38} GSM_Backup_Info;
39
40void GSM_GetBackupFormatFeatures(char *FileName, GSM_Backup_Info *info);
41void GSM_GetBackupFileFeatures (char *FileName, GSM_Backup_Info *info, GSM_Backup *backup);
42
43#endif
44#endif
45
46/* How should editor hadle tabs in this file? Add editor commands here.
47 * vim: noexpandtab sw=8 ts=8 sts=8:
48 */
diff --git a/gammu/emb/common/service/gsmcal.c b/gammu/emb/common/service/gsmcal.c
new file mode 100644
index 0000000..950e35e
--- a/dev/null
+++ b/gammu/emb/common/service/gsmcal.c
@@ -0,0 +1,509 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#include <string.h>
4
5#include "gsmcal.h"
6#include "gsmmisc.h"
7#include "../misc/coding/coding.h"
8
9bool IsCalendarNoteFromThePast(GSM_CalendarEntry *note)
10{
11 bool Past = true;
12 int i;
13 GSM_DateTimeDT;
14
15 GSM_GetCurrentDateTime (&DT);
16 for (i = 0; i < note->EntriesNum; i++) {
17 switch (note->Entries[i].EntryType) {
18 case CAL_RECURRANCE:
19 Past = false;
20 break;
21 case CAL_START_DATETIME :
22 if (note->Entries[i].Date.Year > DT.Year) Past = false;
23 if (note->Entries[i].Date.Year == DT.Year &&
24 note->Entries[i].Date.Month > DT.Month) Past = false;
25 if (note->Entries[i].Date.Year == DT.Year &&
26 note->Entries[i].Date.Month == DT.Month &&
27 note->Entries[i].Date.Day > DT.Day) Past = false;
28 break;
29 default:
30 break;
31 }
32 if (!Past) break;
33 }
34 switch (note->Type) {
35 case GSM_CAL_BIRTHDAY:
36 Past = false;
37 break;
38 default:
39 break;
40 }
41 return Past;
42}
43
44void GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(GSM_CalendarEntry *entry, int *Text, int *Time, int *Alarm, int *Phone, int *Recurrance, int *EndTime, int *Location)
45{
46 int i;
47
48 *Text = -1;
49 *Time = -1;
50 *Alarm = -1;
51 *Phone = -1;
52 *Recurrance= -1;
53 *EndTime= -1;
54 *Location= -1;
55 for (i = 0; i < entry->EntriesNum; i++) {
56 switch (entry->Entries[i].EntryType) {
57 case CAL_START_DATETIME :
58 if (*Time == -1) *Time = i;
59 break;
60 case CAL_END_DATETIME :
61 if (*EndTime == -1) *EndTime = i;
62 break;
63 case CAL_ALARM_DATETIME :
64 case CAL_SILENT_ALARM_DATETIME:
65 if (*Alarm == -1) *Alarm = i;
66 break;
67 case CAL_RECURRANCE:
68 if (*Recurrance == -1) *Recurrance = i;
69 break;
70 case CAL_TEXT:
71 if (*Text == -1) *Text = i;
72 break;
73 case CAL_PHONE:
74 if (*Phone == -1) *Phone = i;
75 break;
76 case CAL_LOCATION:
77 if (*Location == -1) *Location = i;
78 break;
79 default:
80 break;
81 }
82 }
83}
84
85GSM_Error GSM_EncodeVCALENDAR(char *Buffer, int *Length, GSM_CalendarEntry *note, bool header, GSM_VCalendarVersion Version)
86{
87 int Text, Time, Alarm, Phone, Recurrance, EndTime, Location;
88 char buffer[2000];
89
90 GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(note, &Text, &Time, &Alarm, &Phone, &Recurrance, &EndTime, &Location);
91
92 if (header) {
93 *Length+=sprintf(Buffer, "BEGIN:VCALENDAR%c%c",13,10);
94 *Length+=sprintf(Buffer+(*Length), "VERSION:1.0%c%c",13,10);
95 }
96 *Length+=sprintf(Buffer+(*Length), "BEGIN:VEVENT%c%c",13,10);
97
98 if (Version == Nokia_VCalendar) {
99 *Length+=sprintf(Buffer+(*Length), "CATEGORIES:");
100 switch (note->Type) {
101 case GSM_CAL_REMINDER:
102 *Length+=sprintf(Buffer+(*Length), "REMINDER%c%c",13,10);
103 break;
104 case GSM_CAL_MEMO:
105 *Length+=sprintf(Buffer+(*Length), "MISCELLANEOUS%c%c",13,10);
106 break;
107 case GSM_CAL_CALL:
108 *Length+=sprintf(Buffer+(*Length), "PHONE CALL%c%c",13,10);
109 break;
110 case GSM_CAL_BIRTHDAY:
111 *Length+=sprintf(Buffer+(*Length), "SPECIAL OCCASION%c%c",13,10);
112 break;
113 case GSM_CAL_MEETING:
114 default:
115 *Length+=sprintf(Buffer+(*Length), "MEETING%c%c",13,10);
116 break;
117 }
118 if (note->Type == GSM_CAL_CALL) {
119 buffer[0] = 0;
120 buffer[1] = 0;
121 if (Phone != -1) CopyUnicodeString(buffer,note->Entries[Phone].Text);
122 if (Text != -1) {
123 if (Phone != -1) EncodeUnicode(buffer+UnicodeLength(buffer)*2," ",1);
124 CopyUnicodeString(buffer+UnicodeLength(buffer)*2,note->Entries[Text].Text);
125 }
126 SaveVCALText(Buffer, Length, buffer, "SUMMARY");
127 } else {
128 SaveVCALText(Buffer, Length, note->Entries[Text].Text, "SUMMARY");
129 }
130 if (note->Type == GSM_CAL_MEETING && Location != -1) {
131 SaveVCALText(Buffer, Length, note->Entries[Location].Text, "LOCATION");
132 }
133
134 if (Time == -1) return ERR_UNKNOWN;
135 SaveVCALDateTime(Buffer, Length, &note->Entries[Time].Date, "DTSTART");
136
137 if (EndTime != -1) {
138 SaveVCALDateTime(Buffer, Length, &note->Entries[EndTime].Date, "DTEND");
139 }
140
141 if (Alarm != -1) {
142 if (note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) {
143 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "DALARM");
144 } else {
145 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "AALARM");
146 }
147 }
148
149 /* Birthday is known to be recurranced */
150 if (Recurrance != -1 && note->Type != GSM_CAL_BIRTHDAY) {
151 switch(note->Entries[Recurrance].Number/24) {
152 case 1 : *Length+=sprintf(Buffer+(*Length), "RRULE:D1 #0%c%c",13,10); break;
153 case 7 : *Length+=sprintf(Buffer+(*Length), "RRULE:W1 #0%c%c",13,10); break;
154 case 14 : *Length+=sprintf(Buffer+(*Length), "RRULE:W2 #0%c%c",13,10); break;
155 case 365 : *Length+=sprintf(Buffer+(*Length), "RRULE:YD1 #0%c%c",13,10); break;
156 }
157 }
158 } else if (Version == Siemens_VCalendar) {
159 *Length+=sprintf(Buffer+(*Length), "CATEGORIES:");
160 switch (note->Type) {
161 case GSM_CAL_MEETING:
162 *Length+=sprintf(Buffer+(*Length), "MEETING%c%c",13,10);
163 break;
164 case GSM_CAL_CALL:
165 *Length+=sprintf(Buffer+(*Length), "PHONE CALL%c%c",13,10);
166 break;
167 case GSM_CAL_BIRTHDAY:
168 *Length+=sprintf(Buffer+(*Length), "ANNIVERSARY%c%c",13,10);
169 break;
170 case GSM_CAL_MEMO:
171 default:
172 *Length+=sprintf(Buffer+(*Length), "MISCELLANEOUS%c%c",13,10);
173 break;
174 }
175
176 if (Time == -1) return ERR_UNKNOWN;
177 SaveVCALDateTime(Buffer, Length, &note->Entries[Time].Date, "DTSTART");
178
179 if (Alarm != -1) {
180 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "DALARM");
181 }
182
183 if (Recurrance != -1) {
184 switch(note->Entries[Recurrance].Number/24) {
185 case 1 : *Length+=sprintf(Buffer+(*Length), "RRULE:D1%c%c",13,10);break;
186 case 7 : *Length+=sprintf(Buffer+(*Length), "RRULE:D7%c%c",13,10);break;
187 case 30 : *Length+=sprintf(Buffer+(*Length), "RRULE:MD1%c%c",13,10);break;
188 case 365 : *Length+=sprintf(Buffer+(*Length), "RRULE:YD1%c%c",13,10);break;
189 }
190 }
191
192 if (note->Type == GSM_CAL_CALL) {
193 buffer[0] = 0;
194 buffer[1] = 0;
195 if (Phone != -1) CopyUnicodeString(buffer,note->Entries[Phone].Text);
196 if (Text != -1) {
197 if (Phone != -1) EncodeUnicode(buffer+UnicodeLength(buffer)*2," ",1);
198 CopyUnicodeString(buffer+UnicodeLength(buffer)*2,note->Entries[Text].Text);
199 }
200 SaveVCALText(Buffer, Length, buffer, "DESCRIPTION");
201 } else {
202 SaveVCALText(Buffer, Length, note->Entries[Text].Text, "DESCRIPTION");
203 }
204 } else if (Version == SonyEricsson_VCalendar) {
205 *Length+=sprintf(Buffer+(*Length), "CATEGORIES:");
206 switch (note->Type) {
207 case GSM_CAL_MEETING:
208 *Length+=sprintf(Buffer+(*Length), "MEETING%c%c",13,10);
209 break;
210 case GSM_CAL_REMINDER:
211 *Length+=sprintf(Buffer+(*Length), "DATE%c%c",13,10);
212 break;
213 case GSM_CAL_TRAVEL:
214 *Length+=sprintf(Buffer+(*Length), "TRAVEL%c%c",13,10);
215 break;
216 case GSM_CAL_VACATION:
217 *Length+=sprintf(Buffer+(*Length), "VACATION%c%c",13,10);
218 break;
219 case GSM_CAL_BIRTHDAY:
220 *Length+=sprintf(Buffer+(*Length), "ANNIVERSARY%c%c",13,10);
221 break;
222 case GSM_CAL_MEMO:
223 default:
224 *Length+=sprintf(Buffer+(*Length), "MISCELLANEOUS%c%c",13,10);
225 break;
226 }
227
228 if (Time == -1) return ERR_UNKNOWN;
229 SaveVCALDateTime(Buffer, Length, &note->Entries[Time].Date, "DTSTART");
230
231 if (EndTime != -1) {
232 SaveVCALDateTime(Buffer, Length, &note->Entries[EndTime].Date, "DTEND");
233 }
234
235 if (Alarm != -1) {
236 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "AALARM");
237 }
238
239 SaveVCALText(Buffer, Length, note->Entries[Text].Text, "SUMMARY");
240
241 if (Location != -1) {
242 SaveVCALText(Buffer, Length, note->Entries[Location].Text, "LOCATION");
243 }
244 }
245
246 *Length+=sprintf(Buffer+(*Length), "END:VEVENT%c%c",13,10);
247 if (header) *Length+=sprintf(Buffer+(*Length), "END:VCALENDAR%c%c",13,10);
248
249 return ERR_NONE;
250}
251
252void GSM_ToDoFindDefaultTextTimeAlarmCompleted(GSM_ToDoEntry *entry, int *Text, int *Alarm, int *Completed, int *EndTime, int *Phone)
253{
254 int i;
255
256 *Text = -1;
257 *EndTime= -1;
258 *Alarm = -1;
259 *Completed= -1;
260 *Phone = -1;
261 for (i = 0; i < entry->EntriesNum; i++) {
262 switch (entry->Entries[i].EntryType) {
263 case TODO_END_DATETIME :
264 if (*EndTime == -1) *EndTime = i;
265 break;
266 case TODO_ALARM_DATETIME :
267 case TODO_SILENT_ALARM_DATETIME:
268 if (*Alarm == -1) *Alarm = i;
269 break;
270 case TODO_TEXT:
271 if (*Text == -1) *Text = i;
272 break;
273 case TODO_COMPLETED:
274 if (*Completed == -1) *Completed = i;
275 break;
276 case TODO_PHONE:
277 if (*Phone == -1) *Phone = i;
278 break;
279 default:
280 break;
281 }
282 }
283}
284
285GSM_Error GSM_EncodeVTODO(char *Buffer, int *Length, GSM_ToDoEntry *note, bool header, GSM_VToDoVersion Version)
286{
287 int Text, Alarm, Completed, EndTime, Phone;
288
289 GSM_ToDoFindDefaultTextTimeAlarmCompleted(note, &Text, &Alarm, &Completed, &EndTime, &Phone);
290
291 if (header) {
292 *Length+=sprintf(Buffer, "BEGIN:VCALENDAR%c%c",13,10);
293 *Length+=sprintf(Buffer+(*Length), "VERSION:1.0%c%c",13,10);
294 }
295
296 *Length+=sprintf(Buffer+(*Length), "BEGIN:VTODO%c%c",13,10);
297
298 if (Version == Nokia_VToDo) {
299 if (Text == -1) return ERR_UNKNOWN;
300 SaveVCALText(Buffer, Length, note->Entries[Text].Text, "SUMMARY");
301
302 if (Completed == -1) {
303 *Length+=sprintf(Buffer+(*Length), "STATUS:NEEDS ACTION%c%c",13,10);
304 } else {
305 *Length+=sprintf(Buffer+(*Length), "STATUS:COMPLETED%c%c",13,10);
306 }
307
308 switch (note->Priority) {
309 case GSM_Priority_Low: *Length+=sprintf(Buffer+(*Length), "PRIORITY:1%c%c",13,10); break;
310 case GSM_Priority_Medium: *Length+=sprintf(Buffer+(*Length), "PRIORITY:2%c%c",13,10); break;
311 case GSM_Priority_High: *Length+=sprintf(Buffer+(*Length), "PRIORITY:3%c%c",13,10); break;
312 }
313
314 if (EndTime != -1) {
315 SaveVCALDateTime(Buffer, Length, &note->Entries[EndTime].Date, "DUE");
316 }
317
318 if (Alarm != -1) {
319 if (note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) {
320 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "DALARM");
321 } else {
322 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "AALARM");
323 }
324 }
325 } else if (Version == SonyEricsson_VToDo) {
326 if (Text == -1) return ERR_UNKNOWN;
327 SaveVCALText(Buffer, Length, note->Entries[Text].Text, "SUMMARY");
328
329 if (Completed == -1) {
330 *Length+=sprintf(Buffer+(*Length), "STATUS:NEEDS ACTION%c%c",13,10);
331 } else {
332 *Length+=sprintf(Buffer+(*Length), "STATUS:COMPLETED%c%c",13,10);
333 }
334
335 switch (note->Priority) {
336 case GSM_Priority_Low: *Length+=sprintf(Buffer+(*Length), "PRIORITY:3%c%c",13,10); break;
337 case GSM_Priority_Medium: *Length+=sprintf(Buffer+(*Length), "PRIORITY:2%c%c",13,10); break;
338 case GSM_Priority_High: *Length+=sprintf(Buffer+(*Length), "PRIORITY:1%c%c",13,10); break;
339 }
340
341 if (Alarm != -1) {
342 SaveVCALDateTime(Buffer, Length, &note->Entries[Alarm].Date, "AALARM");
343 }
344 }
345
346 *Length+=sprintf(Buffer+(*Length), "END:VTODO%c%c",13,10);
347
348 if (header) {
349 *Length+=sprintf(Buffer+(*Length), "END:VCALENDAR%c%c",13,10);
350 }
351 return ERR_NONE;
352}
353
354GSM_Error GSM_DecodeVCALENDAR_VTODO(unsigned char *Buffer, int *Pos, GSM_CalendarEntry *Calendar, GSM_ToDoEntry *ToDo, GSM_VCalendarVersion CalVer, GSM_VToDoVersion ToDoVer)
355{
356 unsigned char Line[2000],Buff[2000];
357 int Level = 0;
358
359 Calendar->EntriesNum = 0;
360 ToDo->EntriesNum = 0;
361
362 while (1) {
363 MyGetLine(Buffer, Pos, Line, strlen(Buffer));
364 if (strlen(Line) == 0) break;
365 switch (Level) {
366 case 0:
367 if (strstr(Line,"BEGIN:VEVENT")) {
368 Calendar->Type = GSM_CAL_MEMO;
369 Level = 1;
370 }
371 if (strstr(Line,"BEGIN:VTODO")) {
372 ToDo->Priority = GSM_Priority_Low;
373 Level = 2;
374 }
375 break;
376 case 1: /* Calendar note */
377 if (strstr(Line,"END:VEVENT")) {
378 if (Calendar->EntriesNum == 0) return ERR_EMPTY;
379 return ERR_NONE;
380 }
381 if (strstr(Line,"CATEGORIES:REMINDER")) Calendar->Type = GSM_CAL_REMINDER;
382 if (strstr(Line,"CATEGORIES:DATE")) Calendar->Type = GSM_CAL_REMINDER;//SE
383 if (strstr(Line,"CATEGORIES:TRAVEL")) Calendar->Type = GSM_CAL_TRAVEL; //SE
384 if (strstr(Line,"CATEGORIES:VACATION")) Calendar->Type = GSM_CAL_VACATION;//SE
385 if (strstr(Line,"CATEGORIES:MISCELLANEOUS")) Calendar->Type = GSM_CAL_MEMO;
386 if (strstr(Line,"CATEGORIES:PHONE CALL")) Calendar->Type = GSM_CAL_CALL;
387 if (strstr(Line,"CATEGORIES:SPECIAL OCCASION")) Calendar->Type = GSM_CAL_BIRTHDAY;
388 if (strstr(Line,"CATEGORIES:ANNIVERSARY")) Calendar->Type = GSM_CAL_BIRTHDAY;
389 if (strstr(Line,"CATEGORIES:MEETING")) Calendar->Type = GSM_CAL_MEETING;
390 if (strstr(Line,"CATEGORIES:APPOINTMENT")) Calendar->Type = GSM_CAL_MEETING;
391 if (strstr(Line,"RRULE:D1")) {
392 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_RECURRANCE;
393 Calendar->Entries[Calendar->EntriesNum].Number = 1*24;
394 Calendar->EntriesNum++;
395 }
396 if ((strstr(Line,"RRULE:W1")) || (strstr(Line,"RRULE:D7"))) {
397 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_RECURRANCE;
398 Calendar->Entries[Calendar->EntriesNum].Number = 7*24;
399 Calendar->EntriesNum++;
400 }
401 if (strstr(Line,"RRULE:W2")) {
402 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_RECURRANCE;
403 Calendar->Entries[Calendar->EntriesNum].Number = 14*24;
404 Calendar->EntriesNum++;
405 }
406 if (strstr(Line,"RRULE:MD1")) {
407 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_RECURRANCE;
408 Calendar->Entries[Calendar->EntriesNum].Number = 30*24;
409 Calendar->EntriesNum++;
410 }
411 if (strstr(Line,"RRULE:YD1")) {
412 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_RECURRANCE;
413 Calendar->Entries[Calendar->EntriesNum].Number = 365*24;
414 Calendar->EntriesNum++;
415 }
416 if ((ReadVCALText(Line, "SUMMARY", Buff)) || (ReadVCALText(Line, "DESCRIPTION", Buff))) {
417 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_TEXT;
418 CopyUnicodeString(Calendar->Entries[Calendar->EntriesNum].Text,Buff);
419 Calendar->EntriesNum++;
420 }
421 if (ReadVCALText(Line, "LOCATION", Buff)) {
422 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_LOCATION;
423 CopyUnicodeString(Calendar->Entries[Calendar->EntriesNum].Text,Buff);
424 Calendar->EntriesNum++;
425 }
426 if (ReadVCALText(Line, "DTSTART", Buff)) {
427 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_START_DATETIME;
428 ReadVCALDateTime(DecodeUnicodeString(Buff), &Calendar->Entries[Calendar->EntriesNum].Date);
429 Calendar->EntriesNum++;
430 }
431 if (ReadVCALText(Line, "DTEND", Buff)) {
432 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_END_DATETIME;
433 ReadVCALDateTime(DecodeUnicodeString(Buff), &Calendar->Entries[Calendar->EntriesNum].Date);
434 Calendar->EntriesNum++;
435 }
436 if (ReadVCALText(Line, "DALARM", Buff)) {
437 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_SILENT_ALARM_DATETIME;
438 ReadVCALDateTime(DecodeUnicodeString(Buff), &Calendar->Entries[Calendar->EntriesNum].Date);
439 Calendar->EntriesNum++;
440 }
441 if (ReadVCALText(Line, "AALARM", Buff)) {
442 Calendar->Entries[Calendar->EntriesNum].EntryType = CAL_ALARM_DATETIME;
443 ReadVCALDateTime(DecodeUnicodeString(Buff), &Calendar->Entries[Calendar->EntriesNum].Date);
444 Calendar->EntriesNum++;
445 }
446 break;
447 case 2: /* ToDo note */
448 if (strstr(Line,"END:VTODO")) {
449 if (ToDo->EntriesNum == 0) return ERR_EMPTY;
450 return ERR_NONE;
451 }
452 if (ReadVCALText(Line, "DUE", Buff)) {
453 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_END_DATETIME;
454 ReadVCALDateTime(DecodeUnicodeString(Buff), &ToDo->Entries[ToDo->EntriesNum].Date);
455 ToDo->EntriesNum++;
456 }
457 if (ReadVCALText(Line, "DALARM", Buff)) {
458 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_SILENT_ALARM_DATETIME;
459 ReadVCALDateTime(DecodeUnicodeString(Buff), &ToDo->Entries[ToDo->EntriesNum].Date);
460 ToDo->EntriesNum++;
461 }
462 if (ReadVCALText(Line, "AALARM", Buff)) {
463 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_ALARM_DATETIME;
464 ReadVCALDateTime(DecodeUnicodeString(Buff), &ToDo->Entries[ToDo->EntriesNum].Date);
465 ToDo->EntriesNum++;
466 }
467 if (ReadVCALText(Line, "SUMMARY", Buff)) {
468 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_TEXT;
469 CopyUnicodeString(ToDo->Entries[ToDo->EntriesNum].Text,Buff);
470 ToDo->EntriesNum++;
471 }
472 if (ReadVCALText(Line, "PRIORITY", Buff)) {
473 if (ToDoVer == SonyEricsson_VToDo) {
474 ToDo->Priority = GSM_Priority_Low;
475 if (atoi(DecodeUnicodeString(Buff))==2) ToDo->Priority = GSM_Priority_Medium;
476 if (atoi(DecodeUnicodeString(Buff))==1) ToDo->Priority = GSM_Priority_High;
477 dbgprintf("atoi is %i %s\n",atoi(DecodeUnicodeString(Buff)),DecodeUnicodeString(Buff));
478 } else if (ToDoVer == Nokia_VToDo) {
479 ToDo->Priority = GSM_Priority_Low;
480 if (atoi(DecodeUnicodeString(Buff))==2) ToDo->Priority = GSM_Priority_Medium;
481 if (atoi(DecodeUnicodeString(Buff))==3) ToDo->Priority = GSM_Priority_High;
482 }
483 }
484 if (strstr(Line,"STATUS:COMPLETED")) {
485 ToDo->Entries[ToDo->EntriesNum].EntryType = TODO_COMPLETED;
486 ToDo->Entries[ToDo->EntriesNum].Number = 1;
487 ToDo->EntriesNum++;
488 }
489 break;
490 }
491 }
492
493 if (Calendar->EntriesNum == 0 && ToDo->EntriesNum == 0) return ERR_EMPTY;
494 return ERR_NONE;
495}
496
497GSM_Error GSM_EncodeVNTFile(unsigned char *Buffer, int *Length, GSM_NoteEntry *Note)
498{
499 *Length+=sprintf(Buffer+(*Length), "BEGIN:VNOTE%c%c",13,10);
500 *Length+=sprintf(Buffer+(*Length), "VERSION:1.1%c%c",13,10);
501 SaveVCALText(Buffer, Length, Note->Text, "BODY");
502 *Length+=sprintf(Buffer+(*Length), "END:VNOTE%c%c",13,10);
503
504 return ERR_NONE;
505}
506
507/* How should editor hadle tabs in this file? Add editor commands here.
508 * vim: noexpandtab sw=8 ts=8 sts=8:
509 */
diff --git a/gammu/emb/common/service/gsmcal.h b/gammu/emb/common/service/gsmcal.h
new file mode 100644
index 0000000..067a4a4
--- a/dev/null
+++ b/gammu/emb/common/service/gsmcal.h
@@ -0,0 +1,445 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2/* 5210 calendar IDs by Frederick Ros */
3
4#ifndef __gsm_cal_h
5#define __gsm_cal_h
6
7#include "../gsmcomon.h"
8
9/* ---------------------------- calendar ----------------------------------- */
10
11 #define GSM_CALENDAR_ENTRIES 16
12 #define MAX_CALENDAR_TEXT_LENGTH256 /* In 6310 max. 256 chars */
13
14/**
15 * Enum defines types of calendar notes
16 */
17typedef enum {
18 /**
19 * Reminder or Date
20 */
21 GSM_CAL_REMINDER=1,
22 /**
23 * Call
24 */
25 GSM_CAL_CALL,
26 /**
27 * Meeting
28 */
29 GSM_CAL_MEETING,
30 /**
31 * Birthday or Anniversary or Special Occasion
32 */
33 GSM_CAL_BIRTHDAY,
34 /**
35 * Memo or Miscellaneous
36 */
37 GSM_CAL_MEMO,
38 /**
39 * Travel
40 */
41 GSM_CAL_TRAVEL,
42 /**
43 * Vacation
44 */
45 GSM_CAL_VACATION,
46 /**
47 * Training - Athletism
48 */
49 GSM_CAL_T_ATHL,
50 /**
51 * Training - Ball Games
52 */
53 GSM_CAL_T_BALL,
54 /**
55 * Training - Cycling
56 */
57 GSM_CAL_T_CYCL,
58 /**
59 * Training - Budo
60 */
61 GSM_CAL_T_BUDO,
62 /**
63 * Training - Dance
64 */
65 GSM_CAL_T_DANC,
66 /**
67 * Training - Extreme Sports
68 */
69 GSM_CAL_T_EXTR,
70 /**
71 * Training - Football
72 */
73 GSM_CAL_T_FOOT,
74 /**
75 * Training - Golf
76 */
77 GSM_CAL_T_GOLF,
78 /**
79 * Training - Gym
80 */
81 GSM_CAL_T_GYM,
82 /**
83 * Training - Horse Race
84 */
85 GSM_CAL_T_HORS,
86 /**
87 * Training - Hockey
88 */
89 GSM_CAL_T_HOCK,
90 /**
91 * Training - Races
92 */
93 GSM_CAL_T_RACE,
94 /**
95 * Training - Rugby
96 */
97 GSM_CAL_T_RUGB,
98 /**
99 * Training - Sailing
100 */
101 GSM_CAL_T_SAIL,
102 /**
103 * Training - Street Games
104 */
105 GSM_CAL_T_STRE,
106 /**
107 * Training - Swimming
108 */
109 GSM_CAL_T_SWIM,
110 /**
111 * Training - Tennis
112 */
113 GSM_CAL_T_TENN,
114 /**
115 * Training - Travels
116 */
117 GSM_CAL_T_TRAV,
118 /**
119 * Training - Winter Games
120 */
121 GSM_CAL_T_WINT,
122 /**
123 * Alarm
124 */
125 GSM_CAL_ALARM,
126 /**
127 * Alarm repeating each day.
128 */
129 GSM_CAL_DAILY_ALARM
130} GSM_CalendarNoteType;
131
132/**
133 * One value of calendar event.
134 */
135typedef enum {
136 /**
137 * Date and time of event start.
138 */
139 CAL_START_DATETIME = 1,
140 /**
141 * Date and time of event end.
142 */
143 CAL_END_DATETIME,
144 /**
145 * Alarm date and time.
146 */
147 CAL_ALARM_DATETIME,
148 /**
149 * Date and time of silent alarm.
150 */
151 CAL_SILENT_ALARM_DATETIME,
152 /**
153 * Recurrance.
154 */
155 CAL_RECURRANCE,
156 /**
157 * Text.
158 */
159 CAL_TEXT,
160 /**
161 * Location.
162 */
163 CAL_LOCATION,
164 /**
165 * Phone number.
166 */
167 CAL_PHONE,
168 /**
169 * Whether this entry is private.
170 */
171 CAL_PRIVATE,
172 /**
173 * Related contact id.
174 */
175 CAL_CONTACTID,
176 /**
177 * Repeat each x'th day of week.
178 */
179 CAL_REPEAT_DAYOFWEEK,
180 /**
181 * Repeat each x'th day of month.
182 */
183 CAL_REPEAT_DAY,
184 /**
185 * Repeat x'th week of month.
186 */
187 CAL_REPEAT_WEEKOFMONTH,
188 /**
189 * Repeat x'th month.
190 */
191 CAL_REPEAT_MONTH,
192 /**
193 * Repeating frequency.
194 */
195 CAL_REPEAT_FREQUENCY,
196 /**
197 * Repeating start.
198 */
199 CAL_REPEAT_STARTDATE,
200 /**
201 * Repeating end.
202 */
203 CAL_REPEAT_STOPDATE
204} GSM_CalendarType;
205
206/**
207 * One value of calendar event.
208 */
209typedef struct {
210 /**
211 * Type of value.
212 */
213 GSM_CalendarTypeEntryType;
214 /**
215 * Text of value, if applicable.
216 */
217 unsigned char Text[(MAX_CALENDAR_TEXT_LENGTH + 1)*2];
218 /**
219 * Date and time of value, if applicable.
220 */
221 GSM_DateTime Date;
222 /**
223 * Number of value, if applicable.
224 */
225 unsigned int Number;
226} GSM_SubCalendarEntry;
227
228/**
229 * Calendar note values.
230 */
231typedef struct {
232 /**
233 * Type of calendar note.
234 */
235 GSM_CalendarNoteType Type;
236 /**
237 * Location in memory.
238 */
239 int Location;
240 /**
241 * Number of entries.
242 */
243 int EntriesNum;
244 /**
245 * Values of entries.
246 */
247 GSM_SubCalendarEntry Entries[GSM_CALENDAR_ENTRIES];
248} GSM_CalendarEntry;
249
250void GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(GSM_CalendarEntry *entry, int *Text, int *Time, int *Alarm, int *Phone, int *Recurrance, int *EndTime, int *Location);
251
252typedef enum {
253 Nokia_VCalendar = 1,
254 Siemens_VCalendar,
255 SonyEricsson_VCalendar
256} GSM_VCalendarVersion;
257
258GSM_Error GSM_EncodeVCALENDAR(char *Buffer, int *Length, GSM_CalendarEntry *note, bool header, GSM_VCalendarVersion Version);
259
260bool IsCalendarNoteFromThePast(GSM_CalendarEntry *note);
261
262typedef struct {
263 /**
264 * Monday = 1, Tuesday = 2,...
265 */
266 int StartDay;
267 /**
268 * 0 = no delete, 1 = after day,...
269 */
270 int AutoDelete;
271} GSM_CalendarSettings;
272
273/**
274 * Structure used for returning calendar status.
275 */
276typedef struct {
277 /**
278 * Number of used positions.
279 */
280 int Used;
281} GSM_CalendarStatus;
282
283
284/* ------------------------------ to-do ------------------------------------ */
285
286 #define GSM_TODO_ENTRIES 7
287 #define MAX_TODO_TEXT_LENGTH 50 /* Alcatel BE5 50 chars */
288
289/**
290 * Types of to do values. In parenthesis is member of @ref GSM_SubToDoEntry,
291 * where value is stored.
292 */
293typedef enum {
294 /**
295 * Due date. (Date)
296 */
297 TODO_END_DATETIME = 1,
298 /**
299 * Whether is completed. (Number)
300 */
301 TODO_COMPLETED,
302 /**
303 * When should alarm be fired (Date).
304 */
305 TODO_ALARM_DATETIME,
306 /**
307 * When should silent alarm be fired (Date).
308 */
309 TODO_SILENT_ALARM_DATETIME,
310 /**
311 * Text of to do (Text).
312 */
313 TODO_TEXT,
314 /**
315 * Whether entry is private (Number).
316 */
317 TODO_PRIVATE,
318 /**
319 * Category of entry (Number).
320 */
321 TODO_CATEGORY,
322 /**
323 * Related contact ID (Number).
324 */
325 TODO_CONTACTID,
326 /**
327 * Number to call (Text).
328 */
329 TODO_PHONE
330} GSM_ToDoType;
331
332/**
333 * Priority of to do.
334 */
335typedef enum {
336 GSM_Priority_High = 1,
337 GSM_Priority_Medium,
338 GSM_Priority_Low
339} GSM_ToDo_Priority;
340
341/**
342 * Value of to do entry.
343 */
344typedef struct {
345 /**
346 * Type of entry.
347 */
348 GSM_ToDoType EntryType;
349 /**
350 * Text of value, if appropriate, see @ref GSM_ToDoType.
351 */
352 unsigned char Text[(MAX_TODO_TEXT_LENGTH + 1)*2];
353 /**
354 * Date of value, if appropriate, see @ref GSM_ToDoType.
355 */
356 GSM_DateTime Date;
357 /**
358 * Number of value, if appropriate, see @ref GSM_ToDoType.
359 */
360 unsigned int Number;
361} GSM_SubToDoEntry;
362
363/**
364 * To do entry.
365 */
366typedef struct {
367 /**
368 * Priority of entry.
369 */
370 GSM_ToDo_Priority Priority;
371 /**
372 * Location in memory.
373 */
374 int Location;
375 /**
376 * Number of entries.
377 */
378 int EntriesNum;
379 /**
380 * Values of current entry.
381 */
382 GSM_SubToDoEntryEntries[GSM_TODO_ENTRIES];
383} GSM_ToDoEntry;
384
385void GSM_ToDoFindDefaultTextTimeAlarmCompleted(GSM_ToDoEntry *entry, int *Text, int *Alarm, int *Completed, int *EndTime, int *Phone);
386
387typedef enum {
388 Nokia_VToDo = 1,
389 SonyEricsson_VToDo
390} GSM_VToDoVersion;
391
392GSM_Error GSM_EncodeVTODO(char *Buffer, int *Length, GSM_ToDoEntry *note, bool header, GSM_VToDoVersion Version);
393
394/**
395 * Status of to do entries.
396 */
397typedef struct {
398 /**
399 * Number of used positions.
400 */
401 int Used;
402} GSM_ToDoStatus;
403
404/* --------------------------- note ---------------------------------------- */
405
406typedef struct {
407 int Location;
408 char Text[100];
409} GSM_NoteEntry;
410
411GSM_Error GSM_EncodeVNTFile(unsigned char *Buffer, int *Length, GSM_NoteEntry *Note);
412
413/* --------------------------- alarm --------------------------------------- */
414
415/**
416 * Alarm values.
417 */
418typedef struct {
419 /**
420 * Location where it is stored.
421 */
422 int Location;
423 /**
424 * Date and time of alarm.
425 */
426 GSM_DateTime DateTime;
427 /**
428 * Whether it repeats each day.
429 */
430 bool Repeating;
431 /**
432 * Text that is shown on display.
433 */
434 char Text[(MAX_CALENDAR_TEXT_LENGTH + 1) * 2];
435} GSM_Alarm;
436
437/* --------------------------- calendar & todo ----------------------------- */
438
439GSM_Error GSM_DecodeVCALENDAR_VTODO(unsigned char *Buffer, int *Pos, GSM_CalendarEntry *Calendar, GSM_ToDoEntry *ToDo, GSM_VCalendarVersion CalVer, GSM_VToDoVersion ToDoVer);
440
441#endif
442
443/* How should editor hadle tabs in this file? Add editor commands here.
444 * vim: noexpandtab sw=8 ts=8 sts=8:
445 */
diff --git a/gammu/emb/common/service/gsmcall.h b/gammu/emb/common/service/gsmcall.h
new file mode 100644
index 0000000..c5032a5
--- a/dev/null
+++ b/gammu/emb/common/service/gsmcall.h
@@ -0,0 +1,185 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef _gsm_call_h
4#define _gsm_call_h
5
6#include "../misc/misc.h"
7
8/* ------------------ call info -------------------------------------------- */
9
10/**
11 * Enum with status of call.
12 */
13typedef enum {
14 /**
15 * Somebody calls to us
16 */
17 GSM_CALL_IncomingCall=1,
18 /**
19 * We call somewhere
20 */
21 GSM_CALL_OutgoingCall,
22 /**
23 * Call started
24 */
25 GSM_CALL_CallStart,
26 /**
27 * End of call from unknown side
28 */
29 GSM_CALL_CallEnd,
30 /**
31 * End of call from remote side
32 */
33 GSM_CALL_CallRemoteEnd,
34 /**
35 * End of call from our side
36 */
37 GSM_CALL_CallLocalEnd,
38 /**
39 * Call established. Waiting for answer or dropping
40 */
41 GSM_CALL_CallEstablished,
42 /**
43 * Call held
44 */
45 GSM_CALL_CallHeld,
46 /**
47 * Call resumed
48 */
49 GSM_CALL_CallResumed,
50 /**
51 * We switch to call
52 */
53 GSM_CALL_CallSwitched
54} GSM_CallStatus;
55
56/**
57 * Call information.
58 */
59typedef struct {
60 /**
61 * Call status.
62 */
63 GSM_CallStatus Status;
64 /**
65 * Remote phone number.
66 */
67 char PhoneNumber [(GSM_MAX_NUMBER_LENGTH+1)*2];
68 /**
69 * Call ID
70 */
71 int CallID;
72 /**
73 * Whether Call ID is available.
74 */
75 bool CallIDAvailable;
76 /**
77 * Status code.
78 */
79 int StatusCode;
80} GSM_Call;
81
82/* --------------- Data structures for the call divert -------------------- */
83
84/**
85 * Defines when diversion is active.
86 */
87typedef enum {
88 /**
89 * Divert when busy.
90 */
91 GSM_DIVERT_Busy = 0x01,
92 /**
93 * Divert when not answered.
94 */
95 GSM_DIVERT_NoAnswer,
96 /**
97 * Divert when phone off or no coverage.
98 */
99 GSM_DIVERT_OutOfReach,
100 /**
101 * Divert all calls without ringing.
102 */
103 GSM_DIVERT_AllTypes
104} GSM_Divert_DivertTypes;
105
106/**
107 * Which type of calls should be diverted.
108 */
109typedef enum {
110 /**
111 * Voice calls.
112 */
113 GSM_DIVERT_VoiceCalls = 0x01,
114 /**
115 * Fax calls.
116 */
117 GSM_DIVERT_FaxCalls,
118 /**
119 * Data calls.
120 */
121 GSM_DIVERT_DataCalls,
122 /**
123 * All calls.
124 */
125 GSM_DIVERT_AllCalls
126} GSM_Divert_CallTypes;
127
128/**
129 * Call diversion definition.
130 */
131typedef struct {
132 /**
133 * When diversion is active.
134 */
135 GSM_Divert_DivertTypes DivertType;
136 /**
137 * Type of call to divert.
138 */
139 GSM_Divert_CallTypes CallType;
140 /**
141 * Number where to divert.
142 */
143 char Number[(GSM_MAX_NUMBER_LENGTH+1)*2];
144 /**
145 * Timeout for diversion.
146 */
147 unsigned int Timeout;
148} GSM_CallDivert;
149
150/**
151 * Multiple call diversions.
152 */
153typedef struct {
154 GSM_CallDivert Request;
155 struct {
156 int EntriesNum;
157 GSM_CallDivertEntries[10];
158 } Response;
159} GSM_MultiCallDivert;
160
161/* -------------------------------- dial voice ---------------------------- */
162
163/**
164 * How to handle number when initiating voice call.
165 */
166typedef enum {
167 /**
168 * Show number.
169 */
170 GSM_CALL_ShowNumber = 1,
171 /**
172 * Hide number.
173 */
174 GSM_CALL_HideNumber,
175 /**
176 * Keep phone default settings.
177 */
178 GSM_CALL_DefaultNumberPresence
179} GSM_CallShowNumber;
180
181#endif
182
183/* How should editor hadle tabs in this file? Add editor commands here.
184 * vim: noexpandtab sw=8 ts=8 sts=8:
185 */
diff --git a/gammu/emb/common/service/gsmdata.c b/gammu/emb/common/service/gsmdata.c
new file mode 100644
index 0000000..94e9b7b
--- a/dev/null
+++ b/gammu/emb/common/service/gsmdata.c
@@ -0,0 +1,366 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#include <string.h>
4
5#include "gsmdata.h"
6#include "../misc/coding/coding.h"
7
8/* SNIFFS, specs somewhere in http://www.wapforum.org */
9void GSM_EncodeMMSIndicatorSMSText(unsigned char *Buffer, int *Length, GSM_MMSIndicator Indicator)
10{
11 unsigned char buffer[200];
12 int i;
13
14 strcpy(Buffer+(*Length),"\xE6\x06\"");
15 (*Length)=(*Length)+3;
16 strcpy(Buffer+(*Length),"application/vnd.wap.mms-message");
17 (*Length)=(*Length)+31;
18 Buffer[(*Length)++] = 0x00;
19
20 strcpy(Buffer+(*Length),"\xAF\x84\x8C\x82\x98");
21 (*Length)=(*Length)+5;
22
23 i = strlen(Indicator.Address);
24 while (Indicator.Address[i] != '/' && i!=0) i--;
25 strcpy(Buffer+(*Length),Indicator.Address+i+1);
26 (*Length)=(*Length)+strlen(Indicator.Address+i+1);
27 Buffer[(*Length)++] = 0x00;
28
29 strcpy(Buffer+(*Length),"\x8D\x90\x89");
30 (*Length)=(*Length)+3;
31
32 sprintf(buffer,"%s/TYPE=PLMN",Indicator.Sender);
33 Buffer[(*Length)++] = strlen(buffer);
34 Buffer[(*Length)++] = 0x80;
35 strcpy(Buffer+(*Length),buffer);
36 (*Length)=(*Length)+strlen(buffer);
37 Buffer[(*Length)++] = 0x00;
38
39 Buffer[(*Length)++] = 0x96;
40 strcpy(Buffer+(*Length),Indicator.Title);
41 (*Length)=(*Length)+strlen(Indicator.Title);
42 Buffer[(*Length)++] = 0x00;
43
44 strcpy(Buffer+(*Length),"\x8A\x80\x8E\x02\x47\xBB\x88\x05\x81\x03\x02\xA3");
45 (*Length)=(*Length)+12;
46 Buffer[(*Length)++] = 0x00;
47
48 Buffer[(*Length)++] = 0x83;
49 strcpy(Buffer+(*Length),Indicator.Address);
50 (*Length)=(*Length)+strlen(Indicator.Address);
51 Buffer[(*Length)++] = 0x00;
52}
53
54/* http://forum.nokia.com: OTA MMS Settings 1.0, OTA Settings 7.0 */
55static void AddWAPSMSParameterText(unsigned char *Buffer, int *Length, unsigned char ID, char *Text, int Len)
56{
57 int i;
58
59 Buffer[(*Length)++] = 0x87; //PARM with attributes
60 Buffer[(*Length)++] = ID;
61 Buffer[(*Length)++] = 0x11; //VALUE
62 Buffer[(*Length)++] = 0x03; //Inline string
63 for (i=0;i<Len;i++) {
64 Buffer[(*Length)++] = Text[i]; //Text
65 }
66 Buffer[(*Length)++] = 0x00; //END Inline string
67 Buffer[(*Length)++] = 0x01; //END PARMeter
68}
69
70/* http://forum.nokia.com: OTA MMS Settings 1.0, OTA Settings 7.0 */
71static void AddWAPSMSParameterInt(unsigned char *Buffer, int *Length, unsigned char ID, unsigned char Value)
72{
73 Buffer[(*Length)++] = 0x87; //PARM with attributes
74 Buffer[(*Length)++] = ID;
75 Buffer[(*Length)++] = Value;
76 Buffer[(*Length)++] = 0x01; //END PARMeter
77}
78
79/* http://forum.nokia.com : OTA MMS Settings 1.0, OTA Settings 7.0
80 * http://www.wapforum.org : Wireless Datagram Protocol
81 */
82void NOKIA_EncodeWAPMMSSettingsSMSText(unsigned char *Buffer, int *Length, GSM_WAPSettings *settings, bool MMS)
83{
84 int i;
85 unsigned char buffer[400];
86
87 Buffer[(*Length)++] = 0x01; //Push ID
88 Buffer[(*Length)++] = 0x06; //PDU Type (push)
89 Buffer[(*Length)++] = 0x2C; //Headers length (content type + headers)
90 strcpy(Buffer+(*Length),"\x1F\x2A");
91 (*Length)=(*Length)+2; //Value length
92 strcpy(Buffer+(*Length),"application/x-wap-prov.browser-settings");
93 (*Length)=(*Length)+39; //MIME-Type
94 Buffer[(*Length)++] = 0x00; //end inline string
95 strcpy(Buffer+(*Length),"\x81\xEA");
96 (*Length)=(*Length)+2; //charset UTF-8 short int.
97 strcpy(Buffer+(*Length),"\x01\x01");
98 (*Length)=(*Length)+2; //version WBXML 1.1
99 Buffer[(*Length)++] = 0x6A; //charset UTF-8
100 Buffer[(*Length)++] = 0x00; //string table length
101
102 Buffer[(*Length)++] = 0x45; //CHARACTERISTIC-LIST with content
103 Buffer[(*Length)++] = 0xC6; //CHARACTERISTIC with content and attributes
104 Buffer[(*Length)++] = 0x06; //TYPE=ADDRESS
105 Buffer[(*Length)++] = 0x01; //END PARMeter
106 switch (settings->Bearer) {
107 case WAPSETTINGS_BEARER_GPRS:
108 /* Bearer */
109 AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x49);
110 /* PPP_LOGINTYPE (manual login or not) */
111 if (settings->ManualLogin) {
112 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x65);
113 } else {
114 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x64);
115 }
116 /* PPP_AUTHTYPE*/
117 if (settings->IsNormalAuthentication) {
118 /* OTA_CSD_AUTHTYPE_PAP */
119 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x70);
120 } else {
121 /* OTA_CSD_AUTHTYPE_CHAP */
122 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x71);
123 }
124 /* GPRS_ACCESSPOINTNAME */
125 AddWAPSMSParameterText(Buffer, Length, 0x1C, DecodeUnicodeString(settings->DialUp), UnicodeLength(settings->DialUp));
126 /* PROXY */
127 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->IPAddress), UnicodeLength(settings->IPAddress));
128 /* PPP_AUTHNAME (user) */
129 AddWAPSMSParameterText(Buffer, Length, 0x23, DecodeUnicodeString(settings->User), UnicodeLength(settings->User));
130 /* PPP_AUTHSECRET (password) */
131 AddWAPSMSParameterText(Buffer, Length, 0x24, DecodeUnicodeString(settings->Password), UnicodeLength(settings->Password));
132 break;
133 case WAPSETTINGS_BEARER_DATA:
134 /* Bearer */
135 AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x45);
136 /* CSD_DIALSTRING */
137 AddWAPSMSParameterText(Buffer, Length, 0x21, DecodeUnicodeString(settings->DialUp), UnicodeLength(settings->DialUp));
138 /* PROXY */
139 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->IPAddress), UnicodeLength(settings->IPAddress));
140 /* PPP_LOGINTYPE (manual login or not) */
141 if (settings->ManualLogin) {
142 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x65);
143 } else {
144 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x64);
145 }
146 /* PPP_AUTHTYPE*/
147 if (settings->IsNormalAuthentication) {
148 /* OTA_CSD_AUTHTYPE_PAP */
149 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x70);
150 } else {
151 /* OTA_CSD_AUTHTYPE_CHAP */
152 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x71);
153 }
154 /* CSD_CALLTYPE (type of call) */
155 if (settings->IsISDNCall) {
156 /* ISDN */
157 AddWAPSMSParameterInt(Buffer, Length, 0x28, 0x73);
158 } else {
159 /* analogue */
160 AddWAPSMSParameterInt(Buffer, Length, 0x28, 0x72);
161 }
162 /* CSD_CALLSPEED (speed of call) */
163 switch (settings->Speed) {
164 case WAPSETTINGS_SPEED_AUTO:
165 AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6A);
166 break;
167 case WAPSETTINGS_SPEED_9600:
168 AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6B);
169 break;
170 case WAPSETTINGS_SPEED_14400:
171 AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6C);
172 }
173 /* PPP_AUTHNAME (user) */
174 AddWAPSMSParameterText(Buffer, Length, 0x23, DecodeUnicodeString(settings->User), UnicodeLength(settings->User));
175 /* PPP_AUTHSECRET (password) */
176 AddWAPSMSParameterText(Buffer, Length, 0x24, DecodeUnicodeString(settings->Password), UnicodeLength(settings->Password));
177 break;
178#ifdef DEVELOP
179 case WAPSETTINGS_BEARER_SMS:
180 /* Bearer */
181 AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x41);
182 /* PROXY */
183 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->Server), UnicodeLength(settings->Server));
184 /* SMS_SMSC_ADDRESS */
185 // .....
186 break;
187 case WAPSETTINGS_BEARER_USSD:
188 /* FIXME */
189 /* Bearer */
190 AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x41);
191 /* PROXY */
192 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->Service), UnicodeLength(settings->Service));
193 /* USSD_SERVICE_CODE */
194 /* FIXME */
195 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->Code), UnicodeLength(settings->Code));
196#else
197 case WAPSETTINGS_BEARER_SMS:
198 case WAPSETTINGS_BEARER_USSD:
199 break;
200#endif
201 }
202 /* PORT */
203 if (settings->IsSecurity) {
204 if (settings->IsContinuous) {
205 /* Port = 9203. Continuous */
206 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x63);
207 } else {
208 /* Port = 9202. Temporary */
209 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x62);
210 }
211 } else {
212 if (settings->IsContinuous) {
213 /* Port = 9201. Continuous */
214 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x61);
215 } else {
216 /* Port = 9200. Temporary */
217 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x60);
218 }
219 }
220 Buffer[(*Length)++] = 0x01; //END PARMeter
221
222 /* URL */
223 Buffer[(*Length)++] = 0x86; //CHARACTERISTIC-LIST with attributes
224 if (MMS) {
225 Buffer[(*Length)++] = 0x7C; //TYPE = MMSURL
226 } else {
227 Buffer[(*Length)++] = 0x07; //TYPE = URL
228 }
229 Buffer[(*Length)++] = 0x11; //VALUE
230 Buffer[(*Length)++] = 0x03; //Inline string
231 sprintf(buffer,"%s",DecodeUnicodeString(settings->HomePage));
232 for (i=0;i<(int)strlen(buffer);i++) {
233 Buffer[(*Length)++] = buffer[i];//Text
234 }
235 Buffer[(*Length)++] = 0x00; //END Inline string
236 Buffer[(*Length)++] = 0x01; //END PARMeter
237
238 /* ISP_NAME (name) */
239 Buffer[(*Length)++] = 0xC6; //CHARACTERISTIC with content and attributes
240 Buffer[(*Length)++] = 0x08; //TYPE=NAME
241 Buffer[(*Length)++] = 0x01; //END PARMeter
242 /* Settings name */
243 AddWAPSMSParameterText(Buffer, Length, 0x15, DecodeUnicodeString(settings->Title), UnicodeLength(settings->Title));
244 Buffer[(*Length)++] = 0x01; //END PARMeter
245 Buffer[(*Length)++] = 0x01; //END PARMeter
246}
247
248/* http://forum.nokia.com: OTA Settings 7.0 */
249void NOKIA_EncodeWAPBookmarkSMSText(unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark)
250{
251 unsigned charbuffer[100];
252 bool UnicodeCoding = false;
253
254 EncodeUTF8QuotedPrintable(buffer,bookmark->Title);
255 if (UnicodeLength(bookmark->Title)!=strlen(buffer)) UnicodeCoding = true;
256
257 Buffer[(*Length)++] = 0x01; //Push ID
258 Buffer[(*Length)++] = 0x06; //PDU Type (push)
259 Buffer[(*Length)++] = 0x2D; //Headers length (content type + headers)
260 strcpy(Buffer+(*Length),"\x1F\x2B");
261 (*Length)=(*Length)+2; //Value length
262 strcpy(Buffer+(*Length),"application/x-wap-prov.browser-bookmarks");
263 (*Length)=(*Length)+40; //MIME-Type
264 Buffer[(*Length)++] = 0x00; //end inline string
265 strcpy(Buffer+(*Length),"\x81\xEA");
266 (*Length)=(*Length)+2; //charset UTF-8 short int.
267
268 /* Block from sniffs. UNKNOWN */
269 if (!UnicodeCoding) {
270 Buffer[(*Length)++] = 0x00;
271 Buffer[(*Length)++] = 0x01;
272 } else {
273 strcpy(Buffer+(*Length),"\x01\x01\x87\x68");
274 (*Length)=(*Length)+4;
275 }
276 Buffer[(*Length)++] = 0x00;
277
278 Buffer[(*Length)++] = 0x45; //CHARACTERISTIC-LIST with content
279 /* URL */
280 Buffer[(*Length)++] = 0xC6; //CHARACTERISTIC with content and attributes
281 Buffer[(*Length)++] = 0x7F; //TYPE = BOOKMARK
282 Buffer[(*Length)++] = 0x01; //END PARMeter
283 if (!UnicodeCoding) {
284 /* TITLE */
285 AddWAPSMSParameterText(Buffer, Length, 0x15, DecodeUnicodeString(bookmark->Title), UnicodeLength(bookmark->Title));
286 /* URL */
287 AddWAPSMSParameterText(Buffer, Length, 0x17, DecodeUnicodeString(bookmark->Address), UnicodeLength(bookmark->Address));
288 } else {
289 /* TITLE */
290 AddWAPSMSParameterText(Buffer, Length, 0x15, bookmark->Title, UnicodeLength(bookmark->Title)*2+1);
291 /* URL */
292 AddWAPSMSParameterText(Buffer, Length, 0x17, bookmark->Address, UnicodeLength(bookmark->Address)*2+1);
293 }
294 Buffer[(*Length)++] = 0x01; //END PARMeter
295 Buffer[(*Length)++] = 0x01; //END PARMeter
296}
297
298void GSM_EncodeMMSFile(GSM_EncodeMultiPartMMSInfo *Info, unsigned char *Buffer, int *Length)
299{
300 int i;
301
302 strcpy(Buffer+(*Length),"\x8C\x80\x98\x4F");
303 (*Length)=(*Length)+4;
304
305 /* Unique MMS ID ? */
306 strcpy(Buffer+(*Length),"123456789");
307 (*Length)=(*Length)+9;
308 Buffer[(*Length)++] = 0x00;
309
310 strcpy(Buffer+(*Length),"\x8D\x90\x89");
311 (*Length)=(*Length)+3;
312
313 strcpy(Buffer+(*Length),"\x01\x81\x86\x81\x96");
314 (*Length)=(*Length)+5;
315
316 if (UnicodeLength(Info->Subject) != 0) {
317 sprintf(Buffer+(*Length),"%s",DecodeUnicodeString(Info->Subject));
318 (*Length)=(*Length)+UnicodeLength(Info->Subject);
319 Buffer[(*Length)++] = 0x00;
320 }
321
322 for (i=0;i<Info->EntriesNum;i++) {
323 switch(Info->Entries[i].ID) {
324 case MMS_Text:
325 strcpy(Buffer+(*Length),"\x84\xA3\x01\x04\x04\x03\x83\x81\xEA");
326 (*Length)=(*Length)+9;
327
328 sprintf(Buffer+(*Length),"%s",DecodeUnicodeString(Info->Entries[i].Buffer));
329 (*Length)=(*Length)+UnicodeLength(Info->Entries[i].Buffer);
330 break;
331 default:
332 break;
333 }
334 }
335}
336
337void GSM_ClearMultiPartMMSInfo(GSM_EncodeMultiPartMMSInfo *Info)
338{
339 Info->EntriesNum= 0;
340 Info->Subject[0]= 0x00;
341 Info->Subject[1]= 0x00;
342 Info->Source[0] = 0x00;
343 Info->Source[1] = 0x00;
344 Info->Destination[0] = 0x00;
345 Info->Destination[1] = 0x00;
346}
347
348GSM_Error GSM_EncodeURLFile(unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark)
349{
350 *Length+=sprintf(Buffer+(*Length), "BEGIN:VBKM%c%c",13,10);
351 *Length+=sprintf(Buffer+(*Length), "VERSION:1.0%c%c",13,10);
352 *Length+=sprintf(Buffer+(*Length), "TITLE:%s%c%c",DecodeUnicodeString(bookmark->Title),13,10);
353 *Length+=sprintf(Buffer+(*Length), "URL:%s%c%c",DecodeUnicodeString(bookmark->Address),13,10);
354 *Length+=sprintf(Buffer+(*Length), "BEGIN:ENV%c%c",13,10);
355 *Length+=sprintf(Buffer+(*Length), "X-IRMC-URL;QUOTED-PRINTABLE:=%c%c",13,10);
356 *Length+=sprintf(Buffer+(*Length), "[InternetShortcut] =%c%c",13,10);
357 *Length+=sprintf(Buffer+(*Length), "URL=%s%c%c",DecodeUnicodeString(bookmark->Address),13,10);
358 *Length+=sprintf(Buffer+(*Length), "END:ENV%c%c",13,10);
359 *Length+=sprintf(Buffer+(*Length), "END:VBKM%c%c",13,10);
360
361 return ERR_NONE;
362}
363
364/* How should editor hadle tabs in this file? Add editor commands here.
365 * vim: noexpandtab sw=8 ts=8 sts=8:
366 */
diff --git a/gammu/emb/common/service/gsmdata.h b/gammu/emb/common/service/gsmdata.h
new file mode 100644
index 0000000..f5f8e07
--- a/dev/null
+++ b/gammu/emb/common/service/gsmdata.h
@@ -0,0 +1,152 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2
3#ifndef __gsm_wap_h
4#define __gsm_wap_h
5
6#include "gsmmisc.h"
7#include "../misc/misc.h"
8
9/* --------------------------- WAP or MMS settings ------------------------- */
10
11typedef enum {
12 WAPSETTINGS_SPEED_9600,
13 WAPSETTINGS_SPEED_14400,
14 WAPSETTINGS_SPEED_AUTO
15} WAPSettings_Speed;
16
17typedef enum {
18 WAPSETTINGS_BEARER_SMS = 1,
19 WAPSETTINGS_BEARER_DATA,
20 WAPSETTINGS_BEARER_USSD,
21 WAPSETTINGS_BEARER_GPRS
22} WAPSettings_Bearer;
23
24typedef struct {
25 char Title [(20+1)*2];
26 char HomePage[(100+1)*2];
27 WAPSettings_BearerBearer;
28 bool IsSecurity;
29 bool IsContinuous;
30
31 /* for data bearer */
32 bool IsISDNCall;
33 bool IsNormalAuthentication;
34
35 /* for sms bearer */
36 char Server [(21+1)*2];
37
38 /* for sms or ussd bearer */
39 char Service [(20+1)*2];
40 bool IsIP;
41
42 /* for ussd bearer */
43 char Code [(10+1)*2];
44
45 /* for data or gprs */
46 char IPAddress[(20+1)*2];
47 bool ManualLogin;
48 char DialUp [(20+1)*2];
49 char User [(50+1)*2]; /*is length OK ?*/
50 char Password[(50+1)*2]; /*is length OK ?*/
51 WAPSettings_SpeedSpeed;
52} GSM_WAPSettings;
53
54typedef struct {
55 int Location;
56 unsigned char Number;
57 GSM_WAPSettings Settings[4];
58 bool Active;
59 bool ReadOnly;
60 char Proxy [(100+1)*2];
61 int ProxyPort;
62 char Proxy2 [(100+1)*2];
63 int Proxy2Port;
64
65 WAPSettings_BearerActiveBearer;
66} GSM_MultiWAPSettings;
67
68void NOKIA_EncodeWAPMMSSettingsSMSText(unsigned char *Buffer, int *Length, GSM_WAPSettings *settings, bool MMS);
69
70/* -------------------------------- WAP Bookmark --------------------------- */
71
72typedef struct {
73 char Address [(255+1)*2];
74 char Title [(50+1)*2];
75 int Location;
76} GSM_WAPBookmark;
77
78 void NOKIA_EncodeWAPBookmarkSMSText(unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark);
79 GSM_Error GSM_EncodeURLFile (unsigned char *Buffer, int *Length, GSM_WAPBookmark *bookmark);
80
81/* ------------------------------ MMS Indicator ---------------------------- */
82
83typedef struct {
84 unsigned char Address[500];
85 unsigned char Title[200];
86 unsigned char Sender[200];
87} GSM_MMSIndicator;
88
89void GSM_EncodeMMSIndicatorSMSText(unsigned char *Buffer, int *Length, GSM_MMSIndicator Indicator);
90
91/* ------------------------------ MMS file --------------------------------- */
92
93#define MAX_MULTI_MMS 20
94
95typedef enum {
96 MMS_Text = 1,
97 MMS_Bitmap_JPG
98} EncodeMultiPartMMSID;
99
100typedef struct {
101 EncodeMultiPartMMSID ID;
102
103 GSM_File File;
104 unsigned char *Buffer;
105} EncodeMultiPartMMSEntry;
106
107typedef struct {
108 /* Input values */
109 EncodeMultiPartMMSEntry Entries[MAX_MULTI_MMS];
110 int EntriesNum;
111
112 unsigned char Source[200];
113 unsigned char Destination[200];
114 unsigned char Subject[200];
115} GSM_EncodeMultiPartMMSInfo;
116
117 void GSM_EncodeMMSFile (GSM_EncodeMultiPartMMSInfo *Info, unsigned char *Buffer, int *Length);
118 void GSM_ClearMultiPartMMSInfo(GSM_EncodeMultiPartMMSInfo *Info);
119
120/* ------------------------------------------------------------------------ */
121
122typedef struct {
123 int Location;
124 bool Active;
125 bool SyncPhonebook;
126 bool SyncCalendar;
127 char Name[(20+1)*2];
128 char PhonebookDataBase[(50+1)*2];
129 char CalendarDataBase[(50+1)*2];
130 char User[(30+1)*2];
131 char Password[(20+1)*2];
132 char Server[(128+1)*2];
133 GSM_MultiWAPSettingsConnection;
134} GSM_SyncMLSettings;
135
136/* ------------------------------------------------------------------------ */
137
138typedef struct {
139 char Name[(50+1)*2];
140 char HomePage[(200+1)*2];
141 char User[(50+1)*2];
142 char Password[(50+1)*2];
143 int Location;
144 bool Active;
145 GSM_MultiWAPSettingsConnection;
146} GSM_ChatSettings;
147
148#endif
149
150/* How should editor hadle tabs in this file? Add editor commands here.
151 * vim: noexpandtab sw=8 ts=8 sts=8:
152 */
diff --git a/gammu/emb/common/service/gsmlogo.c b/gammu/emb/common/service/gsmlogo.c
new file mode 100644
index 0000000..c992915
--- a/dev/null
+++ b/gammu/emb/common/service/gsmlogo.c
@@ -0,0 +1,1003 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2
3#include <string.h>
4#include <stdlib.h>
5
6#include "../misc/misc.h"
7#include "../misc/coding/coding.h"
8#include "gsmlogo.h"
9#include "gsmnet.h"
10
11void PHONE_GetBitmapWidthHeight(GSM_Phone_Bitmap_Types Type, int *width, int *height)
12{
13 *width = 0;
14 *height= 0;
15 switch (Type) {
16 case GSM_EMSSmallPicture: *width=8; *height=8; break;
17 case GSM_EMSMediumPicture: *width=16; *height=16; break;
18 case GSM_EMSBigPicture : *width=32; *height=32; break;
19 case GSM_NokiaOperatorLogo:
20 case GSM_NokiaCallerLogo: *width=72; *height=14; break;
21 case GSM_NokiaPictureImage: *width=72; *height=28; break;
22 case GSM_Nokia7110OperatorLogo:
23 case GSM_Nokia6510OperatorLogo: *width=78; *height=21; break;
24 case GSM_NokiaStartupLogo: *width=84; *height=48; break;
25 case GSM_Nokia6210StartupLogo: *width=96; *height=60; break;
26 case GSM_Nokia7110StartupLogo: *width=96; *height=65; break;
27 case GSM_EMSVariablePicture : break;
28 case GSM_AlcatelBMMIPicture : break;
29 }
30}
31
32int PHONE_GetBitmapSize(GSM_Phone_Bitmap_Types Type, int Width, int Height)
33{
34 int width, height, x;
35
36 PHONE_GetBitmapWidthHeight(Type, &width, &height);
37 if (width == 0 && height == 0) {
38 width = Width;
39 height = Height;
40 }
41 switch (Type) {
42 case GSM_Nokia6510OperatorLogo:
43 x = width * height;
44 return x/8 + (x%8 > 0);
45 case GSM_Nokia7110OperatorLogo:
46 return (width*height + 7)/8;
47 case GSM_NokiaStartupLogo:
48 case GSM_NokiaOperatorLogo:
49 case GSM_NokiaCallerLogo:
50 case GSM_NokiaPictureImage:
51 case GSM_EMSSmallPicture:
52 case GSM_EMSMediumPicture:
53 case GSM_EMSBigPicture:
54 case GSM_EMSVariablePicture:
55 return height*width/8;
56 case GSM_Nokia7110StartupLogo:
57 case GSM_Nokia6210StartupLogo:
58 return (height+7)/8*width;
59 case GSM_AlcatelBMMIPicture:
60 return width*((height+7)/8);
61 }
62 return 0;
63}
64
65static bool PHONE_IsPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
66{
67 int i=0, pixel;
68
69 switch (Type) {
70 case GSM_NokiaStartupLogo:
71 case GSM_Nokia6210StartupLogo:
72 case GSM_Nokia7110StartupLogo:
73 case GSM_Nokia6510OperatorLogo:
74 i=(buffer[(y/8*width) + x] & 1<<(y%8));
75 break;
76 case GSM_NokiaOperatorLogo:
77 case GSM_Nokia7110OperatorLogo:
78 case GSM_NokiaCallerLogo:
79 case GSM_EMSVariablePicture:
80 case GSM_EMSSmallPicture:
81 case GSM_EMSMediumPicture:
82 case GSM_EMSBigPicture:
83 pixel=width*y + x;
84 i=(buffer[pixel/8] & 1<<(7-(pixel%8)));
85 break;
86 case GSM_NokiaPictureImage:
87 i=(buffer[9*y + x/8] & 1<<(7-(x%8)));
88 break;
89 case GSM_AlcatelBMMIPicture:
90 break;
91 }
92 if (i) return true; else return false;
93}
94
95static void PHONE_SetPointBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int x, int y, int width, int height)
96{
97 int pixel;
98
99 switch (Type) {
100 case GSM_NokiaStartupLogo:
101 case GSM_Nokia6210StartupLogo:
102 case GSM_Nokia7110StartupLogo:
103 case GSM_Nokia6510OperatorLogo:
104 buffer[(y/8*width)+x] |= 1 << (y%8);
105 break;
106 case GSM_NokiaOperatorLogo:
107 case GSM_Nokia7110OperatorLogo:
108 case GSM_NokiaCallerLogo:
109 case GSM_EMSSmallPicture:
110 case GSM_EMSMediumPicture:
111 case GSM_EMSBigPicture:
112 case GSM_EMSVariablePicture:
113 pixel = width*y + x;
114 buffer[pixel/8] |= 1 << (7-(pixel%8));
115 break;
116 case GSM_NokiaPictureImage:
117 buffer[9*y + x/8] |= 1 << (7-(x%8));
118 break;
119 case GSM_AlcatelBMMIPicture:
120 pixel = height / 8;
121 if ((height % 8) != 0) pixel++;
122 buffer[pixel*x + y/8] |= 1 << (7 - (y%8));
123 break;
124 }
125}
126
127void PHONE_DecodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
128{
129 int width, height, x,y;
130
131 PHONE_GetBitmapWidthHeight(Type, &width, &height);
132 if (Type != GSM_Nokia6510OperatorLogo && Type != GSM_Nokia7110OperatorLogo && Type != GSM_EMSVariablePicture) {
133 Bitmap->BitmapHeight= height;
134 Bitmap->BitmapWidth= width;
135 }
136 switch (Type) {
137 case GSM_NokiaOperatorLogo:
138 case GSM_Nokia7110OperatorLogo:
139 case GSM_Nokia6510OperatorLogo : Bitmap->Type=GSM_OperatorLogo;break;
140 case GSM_NokiaCallerLogo : Bitmap->Type=GSM_CallerGroupLogo;break;
141 case GSM_AlcatelBMMIPicture :
142 case GSM_NokiaStartupLogo:
143 case GSM_Nokia7110StartupLogo:
144 case GSM_Nokia6210StartupLogo : Bitmap->Type=GSM_StartupLogo; break;
145 case GSM_NokiaPictureImage:
146 case GSM_EMSVariablePicture:
147 case GSM_EMSSmallPicture:
148 case GSM_EMSMediumPicture:
149 case GSM_EMSBigPicture : Bitmap->Type=GSM_PictureImage;break;
150 }
151
152 Bitmap->Location = 0;
153 Bitmap->Text[0] = 0;
154 Bitmap->Text[1] = 0;
155 Bitmap->BitmapEnabled = false;
156 Bitmap->DefaultName = false;
157 Bitmap->DefaultBitmap = false;
158 Bitmap->DefaultRingtone = false;
159 Bitmap->RingtoneID = 0;
160 Bitmap->NetworkCode[0] = 0;
161 Bitmap->Sender[0] = 0;
162 Bitmap->Sender[1] = 0;
163 Bitmap->ID = 0;
164
165 GSM_ClearBitmap(Bitmap);
166 for (x=0;x<Bitmap->BitmapWidth;x++) {
167 for (y=0;y<Bitmap->BitmapHeight;y++) {
168 if (PHONE_IsPointBitmap(Type, buffer, x, y, Bitmap->BitmapWidth, Bitmap->BitmapHeight)) {
169 GSM_SetPointBitmap(Bitmap,x,y);
170 }
171 }
172 }
173}
174
175void PHONE_ClearBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, int width, int height)
176{
177 memset(buffer,0,PHONE_GetBitmapSize(Type,width,height));
178}
179
180void PHONE_EncodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
181{
182 int width, height, x, y;
183 GSM_Bitmapdest;
184
185 PHONE_GetBitmapWidthHeight(Type, &width, &height);
186 if (width == 0 && height == 0) {
187 width = Bitmap->BitmapWidth;
188 height = Bitmap->BitmapHeight;
189 }
190 GSM_ResizeBitmap(&dest, Bitmap, width, height);
191 PHONE_ClearBitmap(Type, buffer, width, height);
192
193 for (x=0;x<width;x++) {
194 for (y=0;y<height;y++) {
195 if (GSM_IsPointBitmap(&dest,x,y)) PHONE_SetPointBitmap(Type, buffer, x, y, width, height);
196 }
197 }
198}
199
200void GSM_GetMaxBitmapWidthHeight(GSM_Bitmap_Types Type, unsigned char *width, unsigned char *height)
201{
202 switch (Type) {
203 case GSM_CallerGroupLogo: *width=72; *height=14; break;
204 case GSM_OperatorLogo: *width=101;*height=21; break;
205 case GSM_StartupLogo: *width=96; *height=65; break;
206 case GSM_PictureImage: *width=72; *height=28; break;
207 default : break;
208 }
209}
210
211void GSM_SetPointBitmap(GSM_Bitmap *bmp, int x, int y)
212{
213 SetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x);
214}
215
216void GSM_ClearPointBitmap(GSM_Bitmap *bmp, int x, int y)
217{
218 ClearBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x);
219}
220
221bool GSM_IsPointBitmap(GSM_Bitmap *bmp, int x, int y)
222{
223 if (GetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x)) return true; else return false;
224}
225
226void GSM_ClearBitmap(GSM_Bitmap *bmp)
227{
228 memset(bmp->BitmapPoints,0,GSM_GetBitmapSize(bmp));
229}
230
231int GSM_GetBitmapSize(GSM_Bitmap *bmp)
232{
233 return bmp->BitmapWidth*bmp->BitmapHeight/8+1;
234}
235
236void GSM_PrintBitmap(FILE *file, GSM_Bitmap *bitmap)
237{
238 int x,y;
239
240 for (y=0;y<bitmap->BitmapHeight;y++) {
241 for (x=0;x<bitmap->BitmapWidth;x++) {
242 if (GSM_IsPointBitmap(bitmap,x,y)) {
243 fprintf(file,"#");
244 } else {
245 fprintf(file," ");
246 }
247 }
248 fprintf(file,"\n");
249 }
250}
251
252void GSM_ReverseBitmap(GSM_Bitmap *Bitmap)
253{
254 int x, y;
255
256 for (x=0;x<Bitmap->BitmapWidth;x++) {
257 for (y=0;y<Bitmap->BitmapHeight;y++) {
258 if (GSM_IsPointBitmap(Bitmap,x,y)) {
259 GSM_ClearPointBitmap(Bitmap, x, y);
260 } else {
261 GSM_SetPointBitmap(Bitmap, x, y);
262 }
263 }
264 }
265}
266
267void GSM_ResizeBitmap(GSM_Bitmap *dest, GSM_Bitmap *src, int width, int height)
268{
269 int startx=0,endx=0,setx=0, starty=0,endy=0,sety=0, x, y;
270
271 if (src->BitmapWidth<=width) {
272 startx= 0;
273 endx= src->BitmapWidth;
274 setx= (width-src->BitmapWidth)/2;
275 } else {
276 startx= (src->BitmapWidth-width)/2;
277 endx= startx + width;
278 setx= 0;
279 }
280 if (src->BitmapHeight<=height) {
281 starty= 0;
282 endy= src->BitmapHeight;
283 sety= (height-src->BitmapHeight)/2;
284 } else {
285 starty= (src->BitmapHeight-height)/2;
286 endy= starty + height;
287 sety= 0;
288 }
289 dest->BitmapHeight= height;
290 dest->BitmapWidth= width;
291 GSM_ClearBitmap(dest);
292 for (x=startx;x<endx;x++) {
293 for (y=starty;y<endy;y++) {
294 if (GSM_IsPointBitmap(src,x,y))
295 GSM_SetPointBitmap(dest,setx+x-startx,sety+y-starty);
296 }
297 }
298}
299
300GSM_Error Bitmap2BMP(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
301{
302 int x,y,pos,i,sizeimage,buffpos=0;
303 unsigned charbuff[1];
304 div_t division;
305 bool isfile=false;
306
307 unsigned char header[]={
308/*1'st header*/ 'B','M', /* BMP file ID */
309 0x00,0x00,0x00,0x00, /* Size of file */
310 0x00,0x00, /* Reserved for future use */
311 0x00,0x00, /* Reserved for future use */
312 62,0x00,0x00,0x00, /* Offset for image data */
313
314/*2'nd header*/ 40,0x00,0x00,0x00, /* Length of this part of header */
315 0x00,0x00,0x00,0x00, /* Width of image */
316 0x00,0x00,0x00,0x00, /* Height of image */
317 1,0x00, /* How many planes in target device */
318 1,0x00, /* How many colors in image. 1 means 2^1=2 colors */
319 0x00,0x00,0x00,0x00, /* Type of compression. 0 means no compression */
320/*Sometimes */ 0x00,0x00,0x00,0x00, /* Size of part with image data */
321/*ttttttt...*/ 0xE8,0x03,0x00,0x00, /* XPelsPerMeter */
322 /*hhiiiiissss*/ 0xE8,0x03,0x00,0x00, /* YPelsPerMeter */
323/*part of header*/0x02,0x00,0x00,0x00, /* How many colors from palette is used */
324/*doesn't exist*/ 0x00,0x00,0x00,0x00, /* How many colors from palette is required to display image. 0 means all */
325
326/*Color palette*/ 0x00,0x00,0x00, /* First color in palette in Blue, Green, Red. Here white */
327 0x00, /* Each color in palette is end by 4'th byte */
328 102, 204, 102, /* Second color in palette in Blue, Green, Red. Here green */
329 0x00}; /* Each color in palette is end by 4'th byte */
330
331 if (file!=NULL) isfile=true;
332
333 header[22]=bitmap->BitmapHeight;
334 header[18]=bitmap->BitmapWidth;
335
336 pos = 7;
337 sizeimage = 0;
338 /*lines are written from the last to the first*/
339 for (y=bitmap->BitmapHeight-1;y>=0;y--) {
340 i=1;
341 for (x=0;x<bitmap->BitmapWidth;x++) {
342 /*new byte !*/
343 if (pos==7) {
344 if (x!=0) sizeimage++;
345 i++;
346 /*each line is written in multiply of 4 bytes*/
347 if(i==5) i=1;
348 }
349 pos--;
350 /*going to new byte*/
351 if (pos<0) pos=7;
352 }
353 /*going to new byte*/
354 pos=7;
355 sizeimage++;
356 if (i!=1) {
357 /*each line is written in multiply of 4 bytes*/
358 while (i!=5) {
359 sizeimage++;
360 i++;
361 }
362 }
363 }
364 dbgprintf("Data size in BMP file: %i\n",sizeimage);
365 division=div(sizeimage,256);
366 header[35]=division.quot;
367 header[34]=sizeimage-(division.quot*256);
368 sizeimage=sizeimage+sizeof(header);
369 dbgprintf("Size of BMP file: %i\n",sizeimage);
370 division=div(sizeimage,256);
371 header[3]=division.quot;
372 header[2]=sizeimage-(division.quot*256);
373
374 if (isfile) {
375 fwrite(header,1,sizeof(header),file);
376 } else {
377 memcpy(buffer,header,sizeof(header));
378 buffpos += sizeof(header);
379 }
380
381 pos=7;
382 /*lines are written from the last to the first*/
383 for (y=bitmap->BitmapHeight-1;y>=0;y--) {
384 i=1;
385 for (x=0;x<bitmap->BitmapWidth;x++) {
386 /*new byte !*/
387 if (pos==7) {
388 if (x!=0) {
389 if (isfile) {
390 fwrite(buff, 1, sizeof(buff), file);
391 } else {
392 memcpy (buffer+buffpos,buff,1);
393 buffpos++;
394 }
395 }
396 i++;
397 /*each line is written in multiply of 4 bytes*/
398 if(i==5) i=1;
399 buff[0]=0;
400 }
401 if (!GSM_IsPointBitmap(bitmap,x,y)) buff[0]|=(1<<pos);
402 pos--;
403 /*going to new byte*/
404 if (pos<0) pos=7;
405 }
406 /*going to new byte*/
407 pos=7;
408 if (isfile) {
409 fwrite(buff, 1, sizeof(buff), file);
410 } else {
411 memcpy (buffer+buffpos,buff,1);
412 buffpos++;
413 }
414 if (i!=1) {
415 /*each line is written in multiply of 4 bytes*/
416 while (i!=5) {
417 buff[0]=0;
418 if (isfile) {
419 fwrite(buff, 1, sizeof(buff), file);
420 } else {
421 memcpy (buffer+buffpos,buff,1);
422 buffpos++;
423 }
424 i++;
425 }
426 }
427 }
428 return ERR_NONE;
429}
430
431static GSM_Error savebmp(FILE *file, GSM_MultiBitmap *bitmap)
432{
433 GSM_Error error;
434
435 error=Bitmap2BMP(NULL,file,&bitmap->Bitmap[0]);
436 return error;
437}
438
439static void PrivSaveNLMWBMP(FILE *file, GSM_Bitmap *Bitmap)
440{
441 unsigned charbuffer[1000];
442 int x,y,pos,pos2;
443 div_t division;
444
445 pos=0;pos2=7;
446 for (y=0;y<Bitmap->BitmapHeight;y++) {
447 for (x=0;x<Bitmap->BitmapWidth;x++) {
448 if (pos2==7) buffer[pos]=0;
449 if (GSM_IsPointBitmap(Bitmap,x,y)) buffer[pos]|=(1<<pos2);
450 pos2--;
451 /* going to new line */
452 if (pos2<0) {pos2=7;pos++;}
453 }
454 /* for startup logos - new line with new byte */
455 if (pos2!=7) {pos2=7;pos++;}
456 }
457
458 division=div(Bitmap->BitmapWidth,8);
459 /* For startup logos */
460 if (division.rem!=0) division.quot++;
461
462 fwrite(buffer,1,(division.quot*Bitmap->BitmapHeight),file);
463}
464
465static GSM_Error savenlm(FILE *file, GSM_MultiBitmap *bitmap)
466{
467 int i;
468 char header[]={
469 'N','L','M',' ', /* Nokia Logo Manager file ID. */
470 0x01,
471 0x00, /* 0x00 (OP), 0x01 (CLI), 0x02 (Startup), 0x03 (Picture)*/
472 0x00, /* Number of images inside file - 1. 0x01==2 images, 0x03==4 images, etc. */
473 0x00, /* Width. */
474 0x00, /* Height. */
475 0x01};
476
477 switch (bitmap->Bitmap[0].Type) {
478 case GSM_OperatorLogo : header[5]=0x00; break;
479 case GSM_CallerGroupLogo : header[5]=0x01; break;
480 case GSM_StartupLogo : header[5]=0x02; break;
481 case GSM_PictureImage : header[5]=0x03; break;
482 default : return ERR_UNKNOWN;
483 }
484 header[6] = bitmap->Number - 1;
485 header[7] = bitmap->Bitmap[0].BitmapWidth;
486 header[8] = bitmap->Bitmap[0].BitmapHeight;
487 fwrite(header,1,sizeof(header),file);
488
489 for (i=0;i<bitmap->Number;i++) {
490 PrivSaveNLMWBMP(file, &bitmap->Bitmap[i]);
491 }
492
493 return ERR_NONE;
494}
495
496static void PrivSaveNGGNOL(FILE *file, GSM_MultiBitmap *bitmap)
497{
498 char buffer[GSM_BITMAP_SIZE];
499 intx,y,current=0;
500
501 for (y=0;y<bitmap->Bitmap[0].BitmapHeight;y++) {
502 for (x=0;x<bitmap->Bitmap[0].BitmapWidth;x++) {
503 if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
504 buffer[current++] = '1';
505 } else {
506 buffer[current++] = '0';
507 }
508 }
509 }
510 fwrite(buffer,1,current,file);
511}
512
513static GSM_Error savengg(FILE *file, GSM_MultiBitmap *bitmap)
514{
515 char header[]={
516 'N','G','G',0x00,0x01,0x00,
517 0x00,0x00,/* Width */
518 0x00,0x00,/* Height */
519 0x01,0x00,0x01,0x00,
520 0x00, /* Unknown.Can't be checksum - for */
521 /* the same logo files can be different */
522 0x00};
523
524 header[6] = bitmap->Bitmap[0].BitmapWidth;
525 header[8] = bitmap->Bitmap[0].BitmapHeight;
526 fwrite(header,1,sizeof(header),file);
527
528 PrivSaveNGGNOL(file,bitmap);
529
530 return ERR_NONE;
531}
532
533static GSM_Error savenol(FILE *file, GSM_MultiBitmap *bitmap)
534{
535 int country,net;
536 char header[]={
537 'N','O','L',0x00,0x01,0x00,
538 0x00,0x00, /* MCC */
539 0x00,0x00, /* MNC */
540 0x00,0x00, /* Width */
541 0x00,0x00, /* Height */
542 0x01,0x00,0x01,0x00,
543 0x00, /* Unknown.Can't be checksum - for */
544 /* the same logo files can be different */
545 0x00};
546
547 if (bitmap->Bitmap[0].Type == GSM_OperatorLogo) sscanf(bitmap->Bitmap[0].NetworkCode, "%d %d", &country, &net);
548
549 header[6]= country%256;
550 header[7]= country/256;
551 header[8]= net%256;
552 header[9]= net/256;
553 header[10]= bitmap->Bitmap[0].BitmapWidth;
554 header[12]= bitmap->Bitmap[0].BitmapHeight;
555 fwrite(header,1,sizeof(header),file);
556
557 PrivSaveNGGNOL(file,bitmap);
558
559 return ERR_NONE;
560}
561
562static GSM_Error savexpm(FILE *file, GSM_MultiBitmap *bitmap)
563{
564 int x,y;
565
566 fprintf(file,"/* XPM */\n");
567 fprintf(file,"static char * ala_xpm[] = {\n");
568 fprintf(file,"\"%i %i 2 1\",\n",bitmap->Bitmap[0].BitmapWidth,bitmap->Bitmap[0].BitmapHeight);
569 fprintf(file,"\". s c m #000000 g4 #000000 g #000000c #000000\",\n");
570 fprintf(file,"\"# s c m #ffffff g4 #ffffff g #ffffffc #ffffff\",\n");
571
572 for (y=0;y<bitmap->Bitmap[0].BitmapHeight;y++) {
573 fprintf(file,"\"");
574 for (x=0;x<bitmap->Bitmap[0].BitmapWidth;x++)
575 if (GSM_IsPointBitmap(&bitmap->Bitmap[0],x,y)) {
576 fprintf(file,".");
577 } else {
578 fprintf(file,"#");
579 }
580 fprintf(file,"\"");
581 if (y==bitmap->Bitmap[0].BitmapHeight-1) {
582 fprintf(file,"};\n");
583 } else {
584 fprintf(file,",\n");
585 }
586 }
587
588 return ERR_NONE;
589}
590
591static GSM_Error savensl(FILE *file, GSM_MultiBitmap *bitmap)
592{
593 char buffer[GSM_BITMAP_SIZE];
594 unsigned char header[]={
595 'F','O','R','M', 0x01,0xFE,/* File ID block, size 1*256+0xFE=510*/
596 'N','S','L','D', 0x01,0xF8};/* Startup Logo block, size 1*256+0xF8=504*/
597
598 fwrite(header,1,sizeof(header),file);
599 PHONE_EncodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
600 fwrite(buffer,1,PHONE_GetBitmapSize(GSM_NokiaStartupLogo,0,0),file);
601
602 return ERR_NONE;
603}
604
605static GSM_Error savewbmp(FILE *file, GSM_MultiBitmap *bitmap)
606{
607 unsigned char buffer[4];
608
609 buffer[0] = 0x00;
610 buffer[1] = 0x00;
611 buffer[2] = bitmap->Bitmap[0].BitmapWidth;
612 buffer[3] = bitmap->Bitmap[0].BitmapHeight;
613 fwrite(buffer,1,4,file);
614
615 PrivSaveNLMWBMP(file, &bitmap->Bitmap[0]);
616
617 return ERR_NONE;
618}
619
620GSM_Error GSM_SaveBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
621{
622 FILE *file;
623 GSM_Error error=ERR_NONE;
624
625 file = fopen(FileName, "wb");
626 if (file == NULL) return ERR_CANTOPENFILE;
627
628 /* Attempt to identify filetype */
629 if (strstr(FileName,".nlm")) {
630 error=savenlm(file,bitmap);
631 } else if (strstr(FileName,".ngg")) {
632 error=savengg(file,bitmap);
633 } else if (strstr(FileName,".nol")) {
634 error=savenol(file,bitmap);
635 } else if (strstr(FileName,".xpm")) {
636 error=savexpm(file,bitmap);
637 } else if (strstr(FileName,".nsl")) {
638 error=savensl(file,bitmap);
639 } else if (strstr(FileName,".wbmp")) {
640 error=savewbmp(file,bitmap);
641 } else {
642 error=savebmp(file,bitmap);
643 }
644 fclose(file);
645
646 return error;
647}
648
649GSM_Error BMP2Bitmap(unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap)
650{
651 bool first_white,isfile=false;
652 unsigned char buff[34];
653 int w,h,pos,y,x,i,buffpos=0;
654#ifdef DEBUG
655 int sizeimage=0;
656#endif
657
658 if (bitmap->Type == GSM_None) bitmap->Type = GSM_StartupLogo;
659 if (file!=NULL) isfile=true;
660 if (isfile) {
661 fread(buff, 1, 34, file);
662 } else {
663 memcpy(buff,buffer,34);
664 }
665
666 /* height and width of image in the file */
667 h=buff[22]+256*buff[21];
668 w=buff[18]+256*buff[17];
669 dbgprintf("Image Size in BMP file: %dx%d\n",w,h);
670
671 GSM_GetMaxBitmapWidthHeight(bitmap->Type, &bitmap->BitmapWidth, &bitmap->BitmapHeight);
672 if (h<bitmap->BitmapHeight)bitmap->BitmapHeight=h;
673 if (w<bitmap->BitmapWidth)bitmap->BitmapWidth=w;
674 dbgprintf("Height %i %i, width %i %i\n",h,bitmap->BitmapHeight,w,bitmap->BitmapWidth);
675
676 GSM_ClearBitmap(bitmap);
677
678#ifdef DEBUG
679 dbgprintf("Number of colors in BMP file: ");
680 switch (buff[28]) {
681 case 1 : dbgprintf("2 (supported)\n"); break;
682 case 4 : dbgprintf("16 (NOT SUPPORTED)\n"); break;
683 case 8 : dbgprintf("256 (NOT SUPPORTED)\n"); break;
684 case 24 : dbgprintf("True Color (NOT SUPPORTED)\n"); break;
685 default : dbgprintf("unknown\n"); break;
686 }
687#endif
688 if (buff[28]!=1) {
689 dbgprintf("Wrong number of colors\n");
690 return ERR_FILENOTSUPPORTED;
691 }
692
693#ifdef DEBUG
694 dbgprintf("Compression in BMP file: ");
695 switch (buff[30]) {
696 case 0 :dbgprintf("no compression (supported)\n"); break;
697 case 1 :dbgprintf("RLE8 (NOT SUPPORTED)\n"); break;
698 case 2 :dbgprintf("RLE4 (NOT SUPPORTED)\n"); break;
699 default :dbgprintf("unknown\n"); break;
700 }
701#endif
702 if (buff[30]!=0) {
703 dbgprintf("Compression type not supported\n");
704 return ERR_FILENOTSUPPORTED;
705 }
706
707 /* read rest of header (if exists) and color palette */
708 if (isfile) {
709 pos=buff[10]-34;
710 fread(buff, 1, pos, file);
711 } else {
712 pos=buff[10]-34;
713 buffpos=buff[10];
714 memcpy (buff,buffer+34,pos);
715 }
716
717#ifdef DEBUG
718 dbgprintf("First color in BMP file: %i %i %i ",buff[pos-8], buff[pos-7], buff[pos-6]);
719 if (buff[pos-8]==0 && buff[pos-7]==0 && buff[pos-6]==0) dbgprintf("(white)");
720 if (buff[pos-8]==0xFF && buff[pos-7]==0xFF && buff[pos-6]==0xFF) dbgprintf("(black)");
721 if (buff[pos-8]==102 && buff[pos-7]==204 && buff[pos-6]==102) dbgprintf("(green)");
722 dbgprintf("\n");
723 dbgprintf("Second color in BMP file: %i %i %i ",buff[pos-38], buff[pos-37], buff[pos-36]);
724 if (buff[pos-4]==0 && buff[pos-3]==0 && buff[pos-2]==0) dbgprintf("(white)");
725 if (buff[pos-4]==0xFF && buff[pos-3]==0xFF && buff[pos-2]==0xFF) dbgprintf("(black)");
726 dbgprintf("\n");
727#endif
728 first_white=true;
729 if (buff[pos-8]!=0 || buff[pos-7]!=0 || buff[pos-6]!=0) first_white=false;
730
731 pos=7;
732 /* lines are written from the last to the first */
733 for (y=h-1;y>=0;y--) { i=1;
734 for (x=0;x<w;x++) { /* new byte ! */
735 if (pos==7) { if (isfile) {
736 fread(buff, 1, 1, file);
737 } else {
738 memcpy (buff,buffer+buffpos,1);
739 buffpos++;
740 }
741#ifdef DEBUG
742 sizeimage++;
743#endif
744 i++;
745 /* each line is written in multiply of 4 bytes */
746 if(i==5) i=1;
747 }
748 /* we have top left corner ! */
749 if (x<=bitmap->BitmapWidth && y<=bitmap->BitmapHeight) { if (first_white) {
750 if ((buff[0]&(1<<pos))<=0) GSM_SetPointBitmap(bitmap,x,y);
751 } else {
752 if ((buff[0]&(1<<pos))>0) GSM_SetPointBitmap(bitmap,x,y);
753 }
754 }
755 pos--;
756 /* going to new byte */
757 if (pos<0) pos=7;
758 }
759 /* going to new byte */
760 pos=7;
761 if (i!=1) {
762 /* each line is written in multiply of 4 bytes */
763 while (i!=5) {
764 if (isfile) {
765 fread(buff, 1, 1, file);
766 } else {
767 memcpy (buff,buffer+buffpos,1);
768 buffpos++;
769 }
770#ifdef DEBUG
771 sizeimage++;
772#endif
773 i++;
774 }
775 }
776 }
777#ifdef DEBUG
778 dbgprintf("Data size in BMP file: %i\n",sizeimage);
779#endif
780 return(ERR_NONE);
781}
782
783static GSM_Error loadbmp(FILE *file, GSM_MultiBitmap *bitmap)
784{
785 GSM_Error error;
786
787 error=BMP2Bitmap(NULL,file,&bitmap->Bitmap[0]);
788 bitmap->Number = 1;
789 return error;
790}
791
792static GSM_Error loadnlm (FILE *file, GSM_MultiBitmap *bitmap)
793{
794 unsigned char buffer[1000];
795 int pos,pos2,x,y,h,w,i,number;
796 div_t division;
797
798 fread(buffer,1,5,file);
799
800 fread(buffer,1,1,file);
801 switch (buffer[0]) {
802 case 0x00:
803 dbgprintf("Operator logo\n");
804 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
805 break;
806 case 0x01:
807 dbgprintf("Caller logo\n");
808 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerGroupLogo;
809 break;
810 case 0x02:
811 dbgprintf("Startup logo\n");
812 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_StartupLogo;
813 break;
814 case 0x03:
815 dbgprintf("Picture Image logo\n");
816 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_PictureImage;
817 break;
818 }
819
820 bitmap->Number = 0;
821 fread(buffer,1,4,file);
822 number = buffer[0] + 1;
823 w = buffer[1];
824 h = buffer[2];
825 for (i=0;i<number;i++) {
826 bitmap->Bitmap[i].Type = bitmap->Bitmap[0].Type;
827 GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[i].Type, &bitmap->Bitmap[i].BitmapWidth, &bitmap->Bitmap[i].BitmapHeight);
828 if (h < bitmap->Bitmap[i].BitmapHeight) bitmap->Bitmap[i].BitmapHeight= h;
829 if (w < bitmap->Bitmap[i].BitmapWidth) bitmap->Bitmap[i].BitmapWidth = w;
830
831 division=div(w,8);
832 /* For startup logos */
833 if (division.rem!=0) division.quot++;
834 if (fread(buffer,1,(division.quot*h),file)!=(unsigned int)(division.quot*h)) return ERR_UNKNOWN;
835
836 GSM_ClearBitmap(&bitmap->Bitmap[i]);
837
838 pos=0;pos2=7;
839 for (y=0;y<h;y++) {
840 for (x=0;x<w;x++) {
841 if ((buffer[pos]&(1<<pos2))>0) {
842 if (y<bitmap->Bitmap[i].BitmapHeight && x<bitmap->Bitmap[i].BitmapWidth) GSM_SetPointBitmap(&bitmap->Bitmap[i],x,y);
843 }
844 pos2--;
845 /* going to new byte */
846 if (pos2<0) {pos2=7;pos++;}
847 }
848 /* for startup logos-new line means new byte */
849 if (pos2!=7) {pos2=7;pos++;}
850 }
851 bitmap->Number++;
852 if (bitmap->Number == MAX_MULTI_BITMAP) break;
853 }
854 return (ERR_NONE);
855}
856
857static GSM_Error loadnolngg(FILE *file, GSM_MultiBitmap *bitmap, bool nolformat)
858{
859 unsigned char buffer[2000];
860 int i,h,w,x,y;
861
862 fread(buffer, 1, 6, file);
863
864 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_CallerGroupLogo;
865 if (nolformat) {
866 fread(buffer, 1, 4, file);
867 sprintf(bitmap->Bitmap[0].NetworkCode, "%d %02d", buffer[0]+256*buffer[1], buffer[2]);
868 if (bitmap->Bitmap[0].Type == GSM_None) bitmap->Bitmap[0].Type = GSM_OperatorLogo;
869 }
870
871 fread(buffer, 1, 4, file);
872 w = buffer[0];
873 h = buffer[2];
874 GSM_GetMaxBitmapWidthHeight(bitmap->Bitmap[0].Type, &bitmap->Bitmap[0].BitmapWidth, &bitmap->Bitmap[0].BitmapHeight);
875 if (h < bitmap->Bitmap[0].BitmapHeight) bitmap->Bitmap[0].BitmapHeight= h;
876 if (w < bitmap->Bitmap[0].BitmapWidth) bitmap->Bitmap[0].BitmapWidth= w;
877
878 /* Unknown bytes. */
879 fread(buffer, 1, 6, file);
880
881 GSM_ClearBitmap(&bitmap->Bitmap[0]);
882
883 x=0; y=0;
884 for (i=0; i<w*h; i++) {
885 if (fread(buffer, 1, 1, file)!=1) return ERR_UNKNOWN;
886 if (buffer[0]=='1') GSM_SetPointBitmap(&bitmap->Bitmap[0],x,y);
887 x++;
888 if (x==w) {x=0; y++;}
889 }
890
891#ifdef DEBUG
892 /* Some programs writes here fileinfo */
893 if (fread(buffer, 1, 1, file)==1) {
894 dbgprintf("Fileinfo: %c",buffer[0]);
895 while (fread(buffer, 1, 1, file)==1) {
896 if (buffer[0]!=0x0A) dbgprintf("%c",buffer[0]);
897 }
898 dbgprintf("\n");
899 }
900#endif
901 bitmap->Number = 1;
902 return(ERR_NONE);
903}
904
905static GSM_Error loadnsl(FILE *file, GSM_MultiBitmap *bitmap)
906{
907 unsigned char block[6],buffer[505];
908 int block_size;
909 GSM_Bitmap_TypesOldType;
910
911 while (fread(block,1,6,file)==6) {
912 block_size = block[4]*256 + block[5];
913 dbgprintf("Block %c%c%c%c, size %i\n",block[0],block[1],block[2],block[3],block_size);
914 if (!strncmp(block, "FORM", 4)) {
915 dbgprintf("File ID\n");
916 } else {
917 if (block_size>504) return ERR_UNKNOWN;
918 if (block_size!=0) {
919 fread(buffer,1,block_size,file);
920 /* if it's string, we end it with 0 */
921 buffer[block_size]=0;
922#ifdef DEBUG
923 if (!strncmp(block, "VERS", 4)) dbgprintf("File saved by: %s\n",buffer);
924 if (!strncmp(block, "MODL", 4)) dbgprintf("Logo saved from: %s\n",buffer);
925 if (!strncmp(block, "COMM", 4)) dbgprintf("Phone was connected to COM port: %s\n",buffer);
926#endif
927 if (!strncmp(block, "NSLD", 4)) {
928 bitmap->Bitmap[0].BitmapHeight = 48;
929 bitmap->Bitmap[0].BitmapWidth = 84;
930 OldType = bitmap->Bitmap[0].Type;
931 PHONE_DecodeBitmap(GSM_NokiaStartupLogo, buffer, &bitmap->Bitmap[0]);
932 if (OldType != GSM_None) bitmap->Bitmap[0].Type = OldType;
933 dbgprintf("Startup logo (size %i)\n",block_size);
934 }
935 }
936 }
937 }
938 bitmap->Number = 1;
939 return(ERR_NONE);
940}
941
942static GSM_Error loadwbmp(FILE *file, GSM_MultiBitmap *bitmap)
943{
944 unsigned char buffer[10000];
945
946 fread(buffer,1,4,file);
947 bitmap->Bitmap[0].BitmapWidth = buffer[2];
948 bitmap->Bitmap[0].BitmapHeight = buffer[3];
949 bitmap->Number = 1;
950
951 fread(buffer,1,10000,file);
952 PHONE_DecodeBitmap(GSM_Nokia7110OperatorLogo, buffer, &bitmap->Bitmap[0]);
953 GSM_ReverseBitmap(&bitmap->Bitmap[0]);
954
955 return ERR_NONE;
956}
957
958GSM_Error GSM_ReadBitmapFile(char *FileName, GSM_MultiBitmap *bitmap)
959{
960 FILE *file;
961 unsigned charbuffer[300];
962
963 file = fopen(FileName, "rb");
964 if (file == NULL) return ERR_CANTOPENFILE;
965
966 fread(buffer, 1, 9, file); /* Read the header of the file. */
967 rewind(file);
968
969 bitmap->Bitmap[0].DefaultBitmap = false;
970
971 /* Attempt to identify filetype */
972 if (memcmp(buffer, "BM",2)==0) {
973 return loadbmp(file,bitmap);
974 } else if (buffer[0] == 0x00 && buffer[1] == 0x00) {
975 return loadwbmp(file,bitmap);
976 } else if (memcmp(buffer, "NLM",3)==0) {
977 return loadnlm(file,bitmap);
978 } else if (memcmp(buffer, "NOL",3)==0) {
979 return loadnolngg(file,bitmap,true);
980 } else if (memcmp(buffer, "NGG",3)==0) {
981 return loadnolngg(file,bitmap,false);
982 } else if (memcmp(buffer, "FORM",4)==0) {
983 return loadnsl(file,bitmap);
984 }
985 return ERR_UNKNOWN;
986}
987
988void NOKIA_CopyBitmap(GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, int *Length)
989{
990 int Width, Height;
991
992 Buffer[(*Length)++] = 0x00;
993 PHONE_GetBitmapWidthHeight(Type, &Width, &Height);
994 Buffer[(*Length)++] = Width;
995 Buffer[(*Length)++] = Height;
996 Buffer[(*Length)++] = 0x01;
997 PHONE_EncodeBitmap(Type, Buffer + (*Length), Bitmap);
998 (*Length) = (*Length) + PHONE_GetBitmapSize(Type,0,0);
999}
1000
1001/* How should editor hadle tabs in this file? Add editor commands here.
1002 * vim: noexpandtab sw=8 ts=8 sts=8:
1003 */
diff --git a/gammu/emb/common/service/gsmlogo.h b/gammu/emb/common/service/gsmlogo.h
new file mode 100644
index 0000000..b1b579d
--- a/dev/null
+++ b/gammu/emb/common/service/gsmlogo.h
@@ -0,0 +1,180 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef __gsm_bitmaps_h
4#define __gsm_bitmaps_h
5
6#include "../gsmcomon.h"
7
8/**
9 * Enum to handle all possible bitmaps, which are not saved in various filesystems.
10 */
11typedef enum {
12 GSM_None = 1,
13 /**
14 * ID of static file in filesystem displayed during startup
15 */
16 GSM_ColourStartupLogo_ID,
17 /**
18 * Static mono bitmap/ID of animated mono bitmap displayed during startup
19 */
20 GSM_StartupLogo,
21 /**
22 * ID of static file in filesystem displayed instead of operator name
23 */
24 GSM_ColourOperatorLogo_ID,
25 /**
26 * Mono bitmap displayed instead of operator name
27 */
28 GSM_OperatorLogo,
29 /**
30 * ID of static file in filesystem displayed as wallpaper
31 */
32 GSM_ColourWallPaper_ID,
33 /**
34 * Mono bitmap assigned to caller group
35 */
36 GSM_CallerGroupLogo,
37 /**
38 * Text displayed during startup, which can't be removed from phone menu
39 */
40 GSM_DealerNote_Text,
41 /**
42 * Text displayed during startup
43 */
44 GSM_WelcomeNote_Text,
45 /**
46 * Image defined in Smart Messaging specification
47 */
48 GSM_PictureImage
49} GSM_Bitmap_Types;
50
51 #define GSM_BITMAP_SIZE(65+7)/8*96
52#define GSM_BITMAP_TEXT_LENGTH 128
53
54/**
55 * Structure for all possible bitmaps, which are not saved in various filesystems
56 */
57typedef struct {
58 /**
59 * For all: bitmap type
60 */
61 GSM_Bitmap_Types Type;
62 /**
63 * For caller group logos: number of group
64 * For startup logos: number of animated bitmap
65 */
66 unsigned char Location;
67 /**
68 * For dealer/welcome note text: text
69 * For caller group logo: name of group
70 * For picture images: text assigned to it
71 */
72 unsigned char Text[2 * (GSM_BITMAP_TEXT_LENGTH + 1)];
73 /**
74 * For caller group logo: true, when logo is enabled in group
75 */
76 bool BitmapEnabled;
77 /**
78 * For caller group logo: true, when group has default name
79 */
80 bool DefaultName;
81 /**
82 * For caller group logo: true, when group has default bitmap
83 */
84 bool DefaultBitmap;
85 /**
86 * For caller group logo: true, when group has default ringtone
87 */
88 bool DefaultRingtone;
89 /**
90 * For caller group logo: ringtone ID. Phone model specific
91 */
92 unsigned char RingtoneID;
93 bool FileSystemRingtone;
94 /**
95 * For mono bitmaps: body of bitmap
96 */
97 unsigned char BitmapPoints[GSM_BITMAP_SIZE];
98 /**
99 * For mono bitmaps: height specified in pixels
100 */
101 unsigned char BitmapHeight;
102 /**
103 * For mono bitmaps: width specified in pixels
104 */
105 unsigned char BitmapWidth;
106 /**
107 * For operator logos: Network operator code
108 */
109 char NetworkCode[7];
110 /**
111 * For picture images: number of sender
112 */
113 unsigned char Sender[2 * (GSM_MAX_NUMBER_LENGTH + 1)];
114 /**
115 * For colour bitmaps: ID
116 */
117 unsigned char ID;
118} GSM_Bitmap;
119
120#define MAX_MULTI_BITMAP 6
121
122/**
123 * Structure to handle more than one bitmap
124 */
125typedef struct {
126 /**
127 * Number of bitmaps
128 */
129 unsigned char Number;
130 /**
131 * All bitmaps
132 */
133 GSM_Bitmap Bitmap[MAX_MULTI_BITMAP];
134} GSM_MultiBitmap;
135
136typedef enum {
137 GSM_NokiaStartupLogo = 1,/*size 84*48*/
138 GSM_NokiaOperatorLogo, /*size 72*14*/
139 GSM_Nokia7110OperatorLogo,/*size 78*21*/
140 GSM_Nokia6510OperatorLogo,/*size 78*21*/
141 GSM_NokiaCallerLogo, /*size 72*14*/
142 GSM_NokiaPictureImage, /*size 72*28*/
143 GSM_Nokia7110StartupLogo,/*size 96*65*/
144 GSM_Nokia6210StartupLogo,/*size 96*60*/
145 GSM_AlcatelBMMIPicture,
146 GSM_EMSSmallPicture, /*size 8* 8*/
147 GSM_EMSMediumPicture, /*size 16*16*/
148 GSM_EMSBigPicture, /*size 32*32*/
149 GSM_EMSVariablePicture
150} GSM_Phone_Bitmap_Types;
151
152 bool GSM_IsPointBitmap (GSM_Bitmap *bmp, int x, int y);
153 void GSM_SetPointBitmap (GSM_Bitmap *bmp, int x, int y);
154 void GSM_ClearPointBitmap (GSM_Bitmap *bmp, int x, int y);
155 void GSM_ClearBitmap (GSM_Bitmap *bmp);
156 void GSM_ResizeBitmap (GSM_Bitmap *dest, GSM_Bitmap *src, int width, int height);
157 void GSM_ReverseBitmap (GSM_Bitmap *Bitmap);
158 void GSM_GetMaxBitmapWidthHeight(GSM_Bitmap_Types Type, unsigned char *width, unsigned char *height);
159 int GSM_GetBitmapSize (GSM_Bitmap *bmp);
160 void GSM_PrintBitmap (FILE *file, GSM_Bitmap *bitmap);
161
162 GSM_Error GSM_SaveBitmapFile(char *FileName, GSM_MultiBitmap *bitmap);
163 GSM_Error GSM_ReadBitmapFile(char *FileName, GSM_MultiBitmap *bitmap);
164
165GSM_Error BMP2Bitmap (unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap);
166GSM_Error Bitmap2BMP (unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap);
167
168 void PHONE_GetBitmapWidthHeight(GSM_Phone_Bitmap_Types Type, int *width, int *height);
169 int PHONE_GetBitmapSize(GSM_Phone_Bitmap_Types Type, int width, int height);
170 void PHONE_ClearBitmap (GSM_Phone_Bitmap_Types Type, char *buffer, int width, int height);
171 void PHONE_DecodeBitmap (GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap);
172 void PHONE_EncodeBitmap (GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap);
173
174 void NOKIA_CopyBitmap (GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, int *Length);
175
176#endif
177
178/* How should editor hadle tabs in this file? Add editor commands here.
179 * vim: noexpandtab sw=8 ts=8 sts=8:
180 */
diff --git a/gammu/emb/common/service/gsmmisc.c b/gammu/emb/common/service/gsmmisc.c
new file mode 100644
index 0000000..6959a22
--- a/dev/null
+++ b/gammu/emb/common/service/gsmmisc.c
@@ -0,0 +1,262 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#include <string.h>
4#include <stdlib.h>
5#include <sys/stat.h>
6#ifdef WIN32
7# include <io.h>
8# include <fcntl.h>
9#endif
10
11#include "../misc/coding/coding.h"
12#include "../gsmcomon.h"
13#include "gsmmisc.h"
14
15struct keys_table_position {
16 char whatchar;
17 int whatcode;
18};
19
20static struct keys_table_position Keys[] = {
21 {'m',GSM_KEY_MENU}, {'M',GSM_KEY_MENU},
22 {'n',GSM_KEY_NAMES}, {'N',GSM_KEY_NAMES},
23 {'p',GSM_KEY_POWER}, {'P',GSM_KEY_POWER},
24 {'u',GSM_KEY_UP}, {'U',GSM_KEY_UP},
25 {'d',GSM_KEY_DOWN}, {'D',GSM_KEY_DOWN},
26 {'+',GSM_KEY_INCREASEVOLUME},{'-',GSM_KEY_DECREASEVOLUME},
27 {'1',GSM_KEY_1}, {'2',GSM_KEY_2},{'3',GSM_KEY_3},
28 {'4',GSM_KEY_4}, {'5',GSM_KEY_5},{'6',GSM_KEY_6},
29 {'7',GSM_KEY_7}, {'8',GSM_KEY_8},{'9',GSM_KEY_9},
30 {'*',GSM_KEY_ASTERISK}, {'0',GSM_KEY_0},{'#',GSM_KEY_HASH},
31 {'g',GSM_KEY_GREEN}, {'G',GSM_KEY_GREEN},
32 {'r',GSM_KEY_RED}, {'R',GSM_KEY_RED},
33 {' ',0}
34};
35
36GSM_Error MakeKeySequence(char *text, GSM_KeyCode *KeyCode, int *Length)
37{
38 int i,j;
39 unsigned char key;
40
41 for (i=0;i<(int)(strlen(text));i++) {
42 key = text[i];
43 KeyCode[i] = GSM_KEY_NONE;
44 j = 0;
45 while (Keys[j].whatchar!=' ') {
46 if (Keys[j].whatchar==key) {
47 KeyCode[i]=Keys[j].whatcode;
48 break;
49 }
50 j++;
51 }
52 if (KeyCode[i] == GSM_KEY_NONE) {
53 *Length = i;
54 return ERR_NOTSUPPORTED;
55 }
56 }
57 *Length = i;
58 return ERR_NONE;
59}
60
61GSM_Error GSM_ReadFile(char *FileName, GSM_File *File)
62{
63 int i = 1000;
64 FILE *file;
65 struct statfileinfo;
66
67 if (FileName[0] == 0x00) return ERR_UNKNOWN;
68 file = fopen(FileName,"rb");
69 if (file == NULL) return ERR_CANTOPENFILE;
70
71 free(File->Buffer);
72 File->Buffer = NULL;
73 File->Used = 0;
74 while (i == 1000) {
75 File->Buffer = realloc(File->Buffer,File->Used + 1000);
76 i = fread(File->Buffer+File->Used,1,1000,file);
77 File->Used = File->Used + i;
78 }
79 File->Buffer = realloc(File->Buffer,File->Used);
80 fclose(file);
81
82 File->ModifiedEmpty = true;
83 if (stat(FileName,&fileinfo) == 0) {
84 File->ModifiedEmpty = false;
85 dbgprintf("File info read correctly\n");
86 //st_mtime is time of last modification of file
87 Fill_GSM_DateTime(&File->Modified, fileinfo.st_mtime);
88 File->Modified.Year = File->Modified.Year + 1900;
89 dbgprintf("FileTime: %02i-%02i-%04i %02i:%02i:%02i\n",
90 File->Modified.Day,File->Modified.Month,File->Modified.Year,
91 File->Modified.Hour,File->Modified.Minute,File->Modified.Second);
92 }
93
94 return ERR_NONE;
95}
96
97static void GSM_JADFindLine(GSM_File File, char *Name, char *Value)
98{
99 unsigned char Line[2000];
100 int Pos = 0;
101
102 Value[0] = 0;
103
104 while (1) {
105 MyGetLine(File.Buffer, &Pos, Line, File.Used);
106 if (strlen(Line) == 0) break;
107 if (!strncmp(Line,Name,strlen(Name))) {
108 Pos = strlen(Name);
109 while (Line[Pos] == 0x20) Pos++;
110 strcpy(Value,Line+Pos);
111 return;
112 }
113 }
114}
115
116GSM_Error GSM_JADFindData(GSM_File File, char *Vendor, char *Name, char *JAR, char *Version, int *Size)
117{
118 char Size2[200];
119
120 GSM_JADFindLine(File, "MIDlet-Vendor:", Vendor);
121 if (Vendor[0] == 0x00) return ERR_FILENOTSUPPORTED;
122 dbgprintf("Vendor: \"%s\"\n",Vendor);
123
124 GSM_JADFindLine(File, "MIDlet-Name:", Name);
125 if (Name[0] == 0x00) return ERR_FILENOTSUPPORTED;
126 dbgprintf("Name: \"%s\"\n",Name);
127
128 GSM_JADFindLine(File, "MIDlet-Jar-URL:", JAR);
129 if (JAR[0] == 0x00) return ERR_FILENOTSUPPORTED;
130 dbgprintf("JAR file URL: \"%s\"\n",JAR);
131
132 GSM_JADFindLine(File, "MIDlet-Jar-Size:", Size2);
133 *Size = -1;
134 if (Size2[0] == 0x00) return ERR_FILENOTSUPPORTED;
135 dbgprintf("JAR size: \"%s\"\n",Size2);
136 (*Size) = atoi(Size2);
137
138 GSM_JADFindLine(File, "MIDlet-Version:", Version);
139 dbgprintf("Version: \"%s\"\n",Version);
140
141 return ERR_NONE;
142}
143
144void GSM_IdentifyFileFormat(GSM_File *File)
145{
146 File->Type = GSM_File_Other;
147 if (File->Used > 2) {
148 if (memcmp(File->Buffer, "BM",2)==0) {
149 File->Type = GSM_File_Image_BMP;
150 } else if (memcmp(File->Buffer, "GIF",3)==0) {
151 File->Type = GSM_File_Image_GIF;
152 } else if (File->Buffer[0] == 0x00 && File->Buffer[1] == 0x00) {
153 File->Type = GSM_File_Image_WBMP;
154 } else if (memcmp(File->Buffer+1, "PNG",3)==0) {
155 File->Type = GSM_File_Image_PNG;
156 } else if (File->Buffer[0] == 0xFF && File->Buffer[1] == 0xD8) {
157 File->Type = GSM_File_Image_JPG;
158 } else if (memcmp(File->Buffer, "MThd",4)==0) {
159 File->Type = GSM_File_Sound_MIDI;
160 } else if (File->Buffer[0] == 0x00 && File->Buffer[1] == 0x02) {
161 File->Type = GSM_File_Sound_NRT;
162 }
163 }
164}
165
166void SaveVCALDateTime(char *Buffer, int *Length, GSM_DateTime *Date, char *Start)
167{
168 if (Start != NULL) {
169 *Length+=sprintf(Buffer+(*Length), "%s:",Start);
170 }
171 *Length+=sprintf(Buffer+(*Length), "%04d%02d%02dT%02d%02d%02d%c%c",
172 Date->Year, Date->Month, Date->Day,
173 Date->Hour, Date->Minute, Date->Second,13,10);
174}
175
176void ReadVCALDateTime(char *Buffer, GSM_DateTime *dt)
177{
178 char year[5]="", month[3]="", day[3]="", hour[3]="", minute[3]="", second[3]="";
179
180 memset(dt,0,sizeof(dt));
181
182 strncpy(year, Buffer, 4);
183 strncpy(month, Buffer+4, 2);
184 strncpy(day, Buffer+6, 2);
185 strncpy(hour, Buffer+9,2);
186 strncpy(minute, Buffer+11,2);
187 strncpy(second, Buffer+13,2);
188
189 /* FIXME: Should check ranges... */
190 dt->Year= atoi(year);
191 dt->Month= atoi(month);
192 dt->Day = atoi(day);
193 dt->Hour= atoi(hour);
194 dt->Minute= atoi(minute);
195 dt->Second= atoi(second);
196 /* FIXME */
197 dt->Timezone= 0;
198}
199
200void SaveVCALText(char *Buffer, int *Length, char *Text, char *Start)
201{
202 char buffer[1000];
203
204 if (UnicodeLength(Text) != 0) {
205 EncodeUTF8QuotedPrintable(buffer,Text);
206 if (UnicodeLength(Text)==strlen(buffer)) {
207 *Length+=sprintf(Buffer+(*Length), "%s:%s%c%c",Start,DecodeUnicodeString(Text),13,10);
208 } else {
209 *Length+=sprintf(Buffer+(*Length), "%s;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:%s%c%c",Start,buffer,13,10);
210 }
211 }
212}
213
214bool ReadVCALText(char *Buffer, char *Start, char *Value)
215{
216 unsigned char buff[200];
217
218 Value[0] = 0x00;
219 Value[1] = 0x00;
220
221 strcpy(buff,Start);
222 strcat(buff,":");
223 if (!strncmp(Buffer,buff,strlen(buff))) {
224 EncodeUnicode(Value,Buffer+strlen(Start)+1,strlen(Buffer)-(strlen(Start)+1));
225 dbgprintf("ReadVCalText is \"%s\"\n",DecodeUnicodeConsole(Value));
226 return true;
227 }
228 /* SE T68i */
229 strcpy(buff,Start);
230 strcat(buff,";ENCODING=QUOTED-PRINTABLE:");
231 if (!strncmp(Buffer,buff,strlen(buff))) {
232 DecodeUTF8QuotedPrintable(Value,Buffer+strlen(Start)+27,strlen(Buffer)-(strlen(Start)+27));
233 dbgprintf("ReadVCalText is \"%s\"\n",DecodeUnicodeConsole(Value));
234 return true;
235 }
236 strcpy(buff,Start);
237 strcat(buff,";CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:");
238 if (!strncmp(Buffer,buff,strlen(buff))) {
239 DecodeUTF8QuotedPrintable(Value,Buffer+strlen(Start)+41,strlen(Buffer)-(strlen(Start)+41));
240 dbgprintf("ReadVCalText is \"%s\"\n",DecodeUnicodeConsole(Value));
241 return true;
242 }
243 strcpy(buff,Start);
244 strcat(buff,";CHARSET=UTF-8:");
245 if (!strncmp(Buffer,buff,strlen(buff))) {
246 DecodeUTF8(Value,Buffer+strlen(Start)+15,strlen(Buffer)-(strlen(Start)+15));
247 dbgprintf("ReadVCalText is \"%s\"\n",DecodeUnicodeConsole(Value));
248 return true;
249 }
250 strcpy(buff,Start);
251 strcat(buff,";CHARSET=UTF-7:");
252 if (!strncmp(Buffer,buff,strlen(buff))) {
253 DecodeUTF7(Value,Buffer+strlen(Start)+15,strlen(Buffer)-(strlen(Start)+15));
254 dbgprintf("ReadVCalText is \"%s\"\n",DecodeUnicodeConsole(Value));
255 return true;
256 }
257 return false;
258}
259
260/* How should editor hadle tabs in this file? Add editor commands here.
261 * vim: noexpandtab sw=8 ts=8 sts=8:
262 */
diff --git a/gammu/emb/common/service/gsmmisc.h b/gammu/emb/common/service/gsmmisc.h
new file mode 100644
index 0000000..37501ad
--- a/dev/null
+++ b/gammu/emb/common/service/gsmmisc.h
@@ -0,0 +1,316 @@
1/* (c) 2001-2004 by Marcin Wiacek, Walek and Michal Cihar */
2
3#ifndef __gsm_misc_h
4#define __gsm_misc_h
5
6#include "../gsmcomon.h"
7
8/**
9 * Enum defines ID for various phone and SIM memories.
10 * Phone modules can translate them to values specific for concrete models
11 * Two letter codes (excluding VM) are from GSM 07.07
12 */
13typedef enum {
14 /**
15 * Internal memory of the mobile equipment
16 */
17 MEM_ME=1,
18 /**
19 * SIM card memory
20 */
21 MEM_SM,
22 /**
23 * Own numbers
24 */
25 MEM_ON,
26 /**
27 * Dialled calls
28 */
29 MEM_DC,
30 /**
31 * Received calls
32 */
33 MEM_RC,
34 /**
35 * Missed calls
36 */
37 MEM_MC,
38 /**
39 * Combined ME and SIM phonebook
40 */
41 MEM_MT,
42 /**
43 * Fixed dial
44 */
45 MEM_FD,
46
47 /**
48 * Voice mailbox
49 */
50 MEM_VM
51} GSM_MemoryType;
52
53/* --------------------------- resetting phone settings ------------------- */
54
55typedef enum {
56 GSM_RESET_PHONESETTINGS = 1,
57 GSM_RESET_USERINTERFACE,
58 GSM_RESET_USERINTERFACE_PHONESETTINGS,
59 GSM_RESET_DEVICE,
60 GSM_RESET_FULLFACTORY
61} GSM_ResetSettingsType;
62
63/* --------------------------- security codes ------------------------------ */
64
65/**
66 * Definition of security codes.
67 */
68typedef enum {
69 /**
70 * Security code.
71 */
72 SEC_SecurityCode = 0x01,
73 /**
74 * PIN.
75 */
76 SEC_Pin,
77 /**
78 * PIN 2.
79 */
80 SEC_Pin2,
81 /**
82 * PUK.
83 */
84 SEC_Puk,
85 /**
86 * PUK 2.
87 */
88 SEC_Puk2,
89 /**
90 * Code not needed.
91 */
92 SEC_None
93} GSM_SecurityCodeType;
94
95 #define GSM_SECURITY_CODE_LEN15
96
97/**
98 * Security code definition.
99 */
100typedef struct {
101 /**
102 * Actual code.
103 */
104 char Code[GSM_SECURITY_CODE_LEN+1];
105 /**
106 * Type of the code.
107 */
108 GSM_SecurityCodeType Type;
109} GSM_SecurityCode;
110
111/* ---------------------------- keyboard ----------------------------------- */
112
113typedef enum {
114 GSM_KEY_NONE = 0x00,
115 GSM_KEY_1 = 0x01,
116 GSM_KEY_2,
117 GSM_KEY_3,
118 GSM_KEY_4,
119 GSM_KEY_5,
120 GSM_KEY_6,
121 GSM_KEY_7,
122 GSM_KEY_8,
123 GSM_KEY_9,
124 GSM_KEY_0,
125 /**
126 * #
127 */
128 GSM_KEY_HASH,
129 /**
130 * *
131 */
132 GSM_KEY_ASTERISK,
133 GSM_KEY_POWER,
134 /**
135 * in some phone ie. N5110 sometimes works identical to POWER
136 */
137 GSM_KEY_GREEN,
138 /**
139 * (c) key in some phone: ie. N5110
140 */
141 GSM_KEY_RED,
142 /**
143 * doesn't available in some phones as separate button: ie. N5110
144 */
145 GSM_KEY_INCREASEVOLUME,
146 /**
147 * doesn't available in some phones as separate button: ie. N5110
148 */
149 GSM_KEY_DECREASEVOLUME,
150 GSM_KEY_UP = 0x17,
151 GSM_KEY_DOWN,
152 GSM_KEY_MENU,
153 /**
154 * doesn't available in some phone: ie. N5110
155 */
156 GSM_KEY_NAMES
157} GSM_KeyCode;
158
159GSM_Error MakeKeySequence(char *text, GSM_KeyCode *KeyCode, int *Length);
160
161/* ------------------------------- display features ------------------------ */
162
163typedef enum {
164 GSM_CallActive = 1,
165 /**
166 * blinking envelope
167 */
168 GSM_SMSMemoryFull,
169 GSM_FaxCall,
170 GSM_UnreadSMS,
171 GSM_DataCall,
172 GSM_VoiceCall,
173 GSM_KeypadLocked
174} GSM_DisplayFeature;
175
176typedef struct {
177 int Number;
178 GSM_DisplayFeature Feature[7];
179} GSM_DisplayFeatures;
180
181/* ----------------------------- power source ------------------------------ */
182
183typedef enum {
184 GSM_BatteryPowered = 1,
185 GSM_BatteryConnected,
186 GSM_BatteryNotConnected,
187 GSM_PowerFault
188} GSM_ChargeState;
189
190typedef struct {
191 /**
192 * Signal strength in percent, -1 = unknown
193 */
194 int BatteryPercent;
195 /**
196 * Charge state
197 */
198 GSM_ChargeState ChargeState;
199} GSM_BatteryCharge;
200
201/* ------------------------------ categories ------------------------------- */
202
203#define GSM_MAX_CATEGORY_NAME_LENGTH 50
204
205typedef enum {
206 Category_ToDo = 1,
207 Category_Phonebook
208} GSM_CategoryType;
209
210typedef struct {
211 GSM_CategoryType Type;
212 int Location;
213 unsigned char Name[(GSM_MAX_CATEGORY_NAME_LENGTH + 1)*2];
214} GSM_Category;
215
216typedef struct {
217 GSM_CategoryType Type;
218 int Used;
219} GSM_CategoryStatus;
220
221/* ------------------- radio FM stations ---------------------------------- */
222
223 #defineGSM_MAX_FMSTATION_LENGTH 12
224 #define GSM_MAX_FM_STATION 20
225
226typedef struct {
227 int Location;
228 char StationName [(GSM_MAX_FMSTATION_LENGTH+1)*2];
229 double Frequency;
230} GSM_FMStation;
231
232/* ----------------------- filesystem ------------------------------------- */
233
234typedef enum {
235 GSM_File_Java_JAR = 1,
236 GSM_File_Image_JPG,
237 GSM_File_Image_BMP,
238 GSM_File_Image_GIF,
239 GSM_File_Image_PNG,
240 GSM_File_Image_WBMP,
241 GSM_File_Video_3GP,
242 GSM_File_Sound_AMR,
243 GSM_File_Sound_NRT, /* DCT4 binary format */
244 GSM_File_Sound_MIDI,
245#ifdef DEVELOP
246 GSM_File_MMS,
247#endif
248 GSM_File_Other
249} GSM_FileType;
250
251typedef struct {
252 int Used; /* how many bytes used */
253 unsigned char Name[300]; /* Name */
254 bool Folder; /* true, when folder */
255 int Level;
256 GSM_FileTypeType;
257 unsigned charID_FullName[400];
258 unsigned char*Buffer;
259
260 GSM_DateTimeModified;
261 bool ModifiedEmpty;
262
263 /* File attributes */
264 bool Protected;
265 bool ReadOnly;
266 bool Hidden;
267 bool System;
268} GSM_File;
269
270GSM_Error GSM_ReadFile(char *FileName, GSM_File *File);
271
272GSM_Error GSM_JADFindData(GSM_File File, char *Vendor, char *Name, char *JAR, char *Version, int *Size);
273
274void GSM_IdentifyFileFormat(GSM_File *File);
275
276typedef struct {
277 int Free;
278 int Used;
279} GSM_FileSystemStatus;
280
281/* ----------------------------- GPRS access points ----------------------- */
282
283typedef struct {
284 int Location;
285 unsigned char Name[300];
286 unsigned char URL[500];
287 bool Active;
288} GSM_GPRSAccessPoint;
289
290/* ------------------------------------------------------------------------ */
291
292typedef enum {
293 GSM_Date_DDMMYYYY = 1,
294 GSM_Date_MMDDYYYY,
295 GSM_Date_YYYYMMDD
296} GSM_DateFormat;
297
298typedef struct {
299 unsigned char DateSeparator;
300 GSM_DateFormatDateFormat;
301 bool AMPMTime;
302} GSM_Locale;
303
304/* ------------------------------------------------------------------------ */
305
306void ReadVCALDateTime(char *Buffer, GSM_DateTime *dt);
307void SaveVCALDateTime(char *Buffer, int *Length, GSM_DateTime *Date, char *Start);
308
309void SaveVCALText(char *Buffer, int *Length, char *Text, char *Start);
310bool ReadVCALText(char *Buffer, char *Start, char *Value);
311
312#endif
313
314/* How should editor hadle tabs in this file? Add editor commands here.
315 * vim: noexpandtab sw=8 ts=8 sts=8:
316 */
diff --git a/gammu/emb/common/service/gsmnet.c b/gammu/emb/common/service/gsmnet.c
new file mode 100644
index 0000000..a0ddaa7
--- a/dev/null
+++ b/gammu/emb/common/service/gsmnet.c
@@ -0,0 +1,444 @@
1/* (c) 2001-2003 by Marcin Wiacek */
2
3#include <string.h>
4
5#include "gsmnet.h"
6#include "../misc/coding/coding.h"
7
8unsigned char *GSM_Countries[] = {
9 "202", "Greece",
10 "204", "Netherlands",
11 "206", "Belgium",
12 "208", "France",
13 "213", "Andorra" ,
14 "214", "Spain",
15 "216", "Hungary",
16 "218", "Bosnia Herzegovina",
17 "219", "Croatia",
18 "220", "Yugoslavia",
19 "222", "Italy",
20 "226", "Romania",
21 "228", "Switzerland",
22 "230", "Czech Republic",
23 "231", "Slovak Republic",
24 "232", "Austria",
25 "234", "United Kingdom",
26 "238", "Denmark",
27 "240", "Sweden",
28 "242", "Norway",
29 "244", "Finland",
30 "246", "Lithuania",
31 "247", "Latvia",
32 "248", "Estonia",
33 "250", "Russia",
34 "255", "Ukraine",
35 "259", "Moldova",
36 "260", "Poland",
37 "262", "Germany",
38 "266", "Gibraltar",
39 "268", "Portugal",
40 "270", "Luxembourg",
41 "272", "Ireland",
42 "274", "Iceland",
43 "276", "Albania",
44 "278", "Malta",
45 "280", "Cyprus",
46 "282", "Georgia",
47 "283", "Armenia",
48 "284", "Bulgaria",
49 "286", "Turkey",
50 "290", "Greenland",
51 "293", "Slovenia",
52 "294", "Macedonia",
53 "302", "Canada",
54 "310", "U.S.A.",
55 "340", "French West Indies",
56 "400", "Azerbaijan",
57 "404", "India",
58 "410", "Pakistan",
59 "413", "Sri Lanka",
60 "415", "Lebanon",
61 "416", "Jordan",
62 "417", "Syria",
63 "418", "Iraq",
64 "419", "Kuwait",
65 "420", "Saudi Arabia",
66 "422", "Oman",
67 "424", "United Arab Emirates",
68 "425", "Israel",
69 "426", "Bahrain",
70 "427", "Qatar",
71 "432", "Iran",
72 "434", "Uzbekistan",
73 "437", "Kyrgyz Republic",
74 "452", "Vietnam",
75 "454", "Hong Kong",
76 "455", "Macau",
77 "456", "Cambodia",
78 "457", "Lao",
79 "460", "China",
80 "466", "Taiwan",
81 "470", "Bangladesh",
82 "502", "Malaysia",
83 "505", "Australia",
84 "510", "Indonesia",
85 "515", "Philippines",
86 "520", "Thailand",
87 "525", "Singapore",
88 "528", "Brunei Darussalam",
89 "530", "New Zealand",
90 "542", "Fiji",
91 "546", "New Caledonia",
92 "547", "French Polynesia",
93 "602", "Egypt",
94 "603", "Algeria",
95 "604", "Morocco",
96 "605", "Tunisia",
97 "608", "Senegal",
98 "611", "Guinea",
99 "612", "Cote d'Ivoire",
100 "615", "Togo",
101 "617", "Mauritius",
102 "618", "Liberia",
103 "620", "Ghana",
104 "624", "Cameroon",
105 "625", "Cape Verde",
106 "633", "Seychelles",
107 "634", "Mozambique",
108 "634", "Sudan",
109 "635", "Rwanda",
110 "636", "Ethiopia",
111 "640", "Tanzania",
112 "641", "Uganda",
113 "645", "Zambia",
114 "646", "Madagascar",
115 "647", "Reunion",
116 "648", "Zimbabwe",
117 "649", "Namibia",
118 "650", "Malawi",
119 "651", "Lesotho",
120 "652", "Botswana",
121 "655", "South Africa",
122 "730", "Chile",
123 "734", "Venezuela",
124
125 NULL
126};
127
128unsigned char *GSM_Networks[] = {
129 "202 01", "Cosmote",
130 "202 05", "PANAFON",
131 "202 10", "TELESTET",
132 "204 04", "LIBERTEL",
133 "204 08", "KPN Telecom",
134 "204 12", "O2",
135 "204 16", "BEN",
136 "204 20", "Dutchtone NV",
137 "206 01", "PROXIMUS",
138 "206 10", "Mobistar",
139 "206 20", "Base",
140 "208 01", "ITINERIS",
141 "208 10", "SFR",
142 "208 20", "Bouygues Telecom",
143 "213 03", "MOBILAND",
144 "214 01", "Airtel GSM 900-Spain",
145 "214 03", "Retevision Movil",
146 "214 07", "MOVISTAR",
147 "216 01", "Pannon GSM",
148 "216 70", "Vodafone",
149 "216 30", "Westel 900",
150 "218 90", "GSMBIH",
151 "219 01", "CRONET",
152 "219 10", "VIP",
153 "220 01", "MOBTEL",
154 "220 02", "ProMonte GSM",
155 "220 03", "Telekom Srbije",
156 "222 01", "Telecom Italia Mobile",
157 "222 10", "OMNITEL",
158 "222 88", "Wind Telecomunicazioni SpA",
159 "226 01", "CONNEX GSM",
160 "226 10", "DIALOG",
161 "228 01", "NATEL International",
162 "228 02", "diAx Mobile AG",
163 "230 01", "T-Mobile CZ",
164 "230 02", "EuroTel",
165 "230 03", "Oskar",
166 "231 01", "Orange",
167 "231 02", "EuroTel GSM",
168 "232 01", "A1",
169 "232 03", "T-Mobile AT",
170 "232 05", "ONE",
171 "232 07", "tele.ring",
172 "234 10", "Cellnet",
173 "234 15", "Vodafone",
174 "234 30", "T-Mobile UK",
175 "234 33", "ORANGE",
176 "234 50", "Jersey Telecoms GSM",
177 "234 55", "Guernsey Telecoms GSM",
178 "234 58", "PRONTO GSM",
179 "238 01", "TDK-MOBIL",
180 "238 02", "SONOFON",
181 "238 20", "TELIA DK",
182 "238 30", "Mobilix",
183 "240 01", "Telia AB",
184 "240 07", "COMVIQ",
185 "240 08", "EUROPOLITAN",
186 "242 01", "Telenor Mobil",
187 "242 02", "NetCom GSM",
188 "244 03", "Telia City (Finland)",
189 "244 05", "Radiolinja",
190 "244 09", "Finnet",
191 "244 12", "DNA (FI2G)",
192 "244 14", "Alands Mobiltelefon",
193 "244 91", "Sonera",
194 "246 01", "OMNITEL",
195 "246 02", "Bite GSM",
196 "247 01", "LMT LV",
197 "247 02", "BALTCOM GSM",
198 "248 01", "EMT GSM",
199 "248 02", "Radiolinja Eesti AS",
200 "248 03", "Q GSM",
201 "250 01", "Mobile Telesystems",
202 "250 02", "North-West GSM",
203 "250 05", "Siberian Cellular Systems 900",
204 "250 07", "BM Telecom",
205 "250 10", "Don Telecom",
206 "250 12", "FECS-900",
207 "250 13", "Kuban GSM",
208 "250 39", "Uraltel",
209 "250 44", "North Caucasian GSM",
210 "250 99", "BeeLine",
211 "255 01", "UMC",
212 "255 02", "WellCOM",
213 "255 03", "Kyivstar",
214 "255 05", "Golden Telecom",
215 "259 01", "VOXTEL",
216 "260 01", "PLUS GSM",
217 "260 02", "ERA GSM",
218 "260 03", "IDEA Centertel",
219 "262 01", "T-Mobile D",
220 "262 02", "D2 PRIVAT",
221 "262 03", "E-Plus",
222 "262 07", "Interkom",
223 "266 01", "Gibtel GSM",
224 "268 01", "TELECEL",
225 "268 03", "OPTIMUS",
226 "268 06", "TMN",
227 "270 01", "LUXGSM",
228 "270 77", "TANGO",
229 "272 01", "EIRCELL-GSM",
230 "272 02", "Digifone",
231 "274 01", "Landssiminn GSM 900",
232 "274 02", "TAL hf",
233 "276 01", "AMC",
234 "278 01", "Vodafone Malta Limited",
235 "280 01", "CYTAGSM",
236 "282 01", "Geocell Limited",
237 "282 02", "Magti GSM",
238 "283 01", "ArmGSM",
239 "284 01", "M-TEL GSM BG",
240 "286 01", "Turkcell",
241 "286 02", "TELSIM GSM",
242 "288 01", "Faroese Telecom",
243 "290 01", "Tele Greenland",
244 "293 40", "SI.MOBIL d. d.",
245 "293 41", "MOBITEL",
246 "293 70", "SI VEGA 070",
247 "294 01", "MobiMak",
248 "302 37", "Microcell Connexions Inc",
249 "302 72", "Rogers AT&T",
250 "310 01", "Cellnet",
251 "310 02", "Sprint Spectrum",
252 "310 11", "Wireless 2000 Telephone Co.",
253 "310 15", "BellSouth Mobility DCS",
254 "310 16", "T-Mobile",
255 "310 17", "Pac Bell",
256 "310 20", "T-Mobile",
257 "310 21", "T-Mobile",
258 "310 22", "T-Mobile",
259 "310 23", "T-Mobile",
260 "310 24", "T-Mobile",
261 "310 25", "T-Mobile",
262 "310 26", "T-Mobile",
263 "310 27", "T-Mobile",
264 "310 31", "T-Mobile",
265 "310 38", "AT&T Wireless",
266 "310 58", "T-Mobile",
267 "310 66", "T-Mobile",
268 "310 77", "Iowa Wireless Services LP",
269 "310 80", "T-Mobile",
270 "340 01", "AMERIS",
271 "400 01", "AZERCELL GSM",
272 "400 02", "Bakcell GSM 2000",
273 "404 07", "TATA Cellular",
274 "404 10", "AirTel",
275 "404 11", "Essar Cellphone",
276 "404 12", "Escotel",
277 "404 14", "Modicom",
278 "404 15", "Essar Cellphone",
279 "404 20", "Max Touch",
280 "404 21", "BPL - Mobile",
281 "404 27", "BPL USWEST Cellular",
282 "404 30", "Command",
283 "404 40", "SkyCell",
284 "404 41", "RPG Cellular",
285 "404 42", "AIRCEL",
286 "410 01", "Mobilink",
287 "413 02", "DIALOG GSM",
288 "415 01", "CELLIS",
289 "415 03", "LIBANCELL",
290 "416 01", "Fastlink",
291 "417 09", "MOBILE SYRIA",
292 "419 02", "MTCNet",
293 "420 01", "Al Jawwal",
294 "420 07", "E.A.E",
295 "422 02", "GTO",
296 "424 02", "UAE-ETISALAT",
297 "425 01", "Partner Communications Company Ltd",
298 "425 02", "Cellcom Israel Ltd",
299 "426 01", "BHR MOBILE PLUS",
300 "427 01", "QATARNET",
301 "432 11", "TCI",
302 "434 04", "Daewoo Unitel",
303 "434 05", "Coscom",
304 "437 01", "Bitel",
305 "454 00", "TCSL GSM",
306 "454 04", "HKGHT",
307 "454 06", "SMARTONE GSM",
308 "454 10", "New World PCS",
309 "454 12", "PEOPLES",
310 "454 16", "SUNDAY",
311 "455 01", "TELEMOVEL+ GSM900-Macau",
312 "456 01", "MobiTel",
313 "456 02", "SAMART-GSM",
314 "457 01", "Lao Shinawatra Telecom",
315 "460 00", "China Telecom GSM",
316 "460 01", "CU-GSM",
317 "466 01", "Far EasTone Telecoms 900",
318 "466 06", "TUNTEX GSM 1800",
319 "466 88", "KG Telecom",
320 "466 92", "Chunghwa GSM",
321 "466 93", "MobiTai",
322 "466 97", "TWNGSM",
323 "466 99", "TransAsia",
324 "470 01", "GrameenPhone Ltd",
325 "470 19", "Mobile 2000",
326 "502 12", "Maxis Mobile",
327 "502 13", "TM Touch",
328 "502 16", "DiGi 1800",
329 "502 17", "ADAM",
330 "502 19", "CELCOM",
331 "505 01", "MobileNet",
332 "505 02", "OPTUS",
333 "505 03", "VODAFONE",
334 "505 08", "One.Tel",
335 "510 01", "SATELINDO",
336 "510 08", "LIPPO TELECOM",
337 "510 10", "TELKOMSEL",
338 "510 11", "Excelcom",
339 "510 21", "INDOSAT",
340 "515 01", "ISLACOM",
341 "515 02", "Globe Telecom",
342 "520 01", "AIS GSM",
343 "520 10", "WCS",
344 "520 18", "Worldphone 1800",
345 "520 23", "HELLO",
346 "525 01", "SingTel Mobile",
347 "525 02", "ST-PCN",
348 "525 03", "MOBILEONE",
349 "528 11", "DSTCom",
350 "530 01", "Vodafone New Zealand Limited",
351 "542 01", "Vodafone",
352 "546 01", "Mobilis",
353 "547 20", "VINI",
354 "602 01", "MobiNil",
355 "602 02", "Tunicell",
356 "603 01", "ALGERIAN MOBILE NETWORK",
357 "604 01", "I A M",
358 "608 01", "ALIZE",
359 "611 02", "Lagui",
360 "612 03", "IVOIRIS",
361 "612 05", "Telecel",
362 "615 01", "TOGO CELL",
363 "617 01", "Cellplus Mobile Comms",
364 "618 01", "Omega",
365 "620 01", "SPACEFON",
366 "625 01", "CVMOVEL",
367 "633 01", "Seychelles Cellular Services",
368 "633 10", "AIRTEL",
369 "634 01", "MobiTel",
370 "635 10", "Rwandacell",
371 "636 01", "ETMTN",
372 "640 01", "TRITEL",
373 "641 10", "MTN-Uganda",
374 "642 02", "ANTARIS",
375 "643 01", "T.D.M GSM 900",
376 "645 01", "ZAMCELL",
377 "646 01", "Madacom",
378 "646 03", "Sacel Madagascar S.A.",
379 "647 10", "SRR",
380 "648 01", "NET*ONE",
381 "648 03", "Telecel",
382 "649 01", "MTC",
383 "650 01", "Callpoint 900",
384 "651 01", "Vodacom Lesotho (Pty) Ltd",
385 "655 01", "Vodacom",
386 "655 10", "MTN",
387 "680 38", "NPI Wireless",
388 "730 01", "Entel Telefonia Movi",
389 "730 10", "Entel PCS",
390 "734 01", "Infonet",
391
392 NULL
393};
394
395char *GSM_GetNetworkName(char *NetworkCode)
396{
397 int i = 0;
398 static charretval[200];
399
400 EncodeUnicode(retval,"unknown",7);
401 while (GSM_Networks[i*2] != NULL) {
402 if (!strncmp(GSM_Networks[i*2],NetworkCode,6)) {
403 EncodeUnicode(retval, GSM_Networks[i*2+1], strlen(GSM_Networks[i*2+1]));
404 break;
405 }
406 i++;
407 }
408 return retval;
409}
410
411char *GSM_GetCountryName(char *CountryCode)
412{
413 int i = 0;
414 static charretval[200];
415
416 EncodeUnicode(retval,"unknown",7);
417 while (GSM_Countries[i*2] != NULL) {
418 if (!strncmp(GSM_Countries[i*2],CountryCode,3)) {
419 EncodeUnicode(retval, GSM_Countries[i*2+1], strlen(GSM_Countries[i*2+1]));
420 break;
421 }
422 i++;
423 }
424 return retval;
425}
426
427void NOKIA_EncodeNetworkCode(unsigned char* buffer, unsigned char* output)
428{
429 EncodeBCD(buffer, output, 6, false);
430 buffer[1] = buffer[1] | 0xf0;
431}
432
433void NOKIA_DecodeNetworkCode(unsigned char* buffer, unsigned char* output)
434{
435 DecodeBCD(output, buffer, 3);
436 output[6] = output[5];
437 output[5] = output[4];
438 output[4] = output[3];
439 output[3] = ' ';
440}
441
442/* How should editor hadle tabs in this file? Add editor commands here.
443 * vim: noexpandtab sw=8 ts=8 sts=8:
444 */
diff --git a/gammu/emb/common/service/gsmnet.h b/gammu/emb/common/service/gsmnet.h
new file mode 100644
index 0000000..aaea22f
--- a/dev/null
+++ b/gammu/emb/common/service/gsmnet.h
@@ -0,0 +1,98 @@
1/* (c) 2002-2003 by Marcin Wiacek & Michal Cihar */
2
3#ifndef __gsm_net_h
4#define __gsm_net_h
5
6/**
7 * Find network name from given network code.
8 */
9char *GSM_GetNetworkName(char *NetworkCode);
10
11/**
12 * Find country name from given country code.
13 */
14char *GSM_GetCountryName(char *CountryCode);
15
16/**
17 * Status of network logging
18 */
19typedef enum {
20 /**
21 * Home network for used SIM card.
22 */
23 GSM_HomeNetwork = 1,
24 /**
25 * No network available for used SIM card.
26 */
27 GSM_NoNetwork,
28 /**
29 * SIM card uses roaming.
30 */
31 GSM_RoamingNetwork,
32 /**
33 * Network registration denied - card blocked or expired or disabled.
34 */
35 GSM_RegistrationDenied,
36 /**
37 * Unknown network status.
38 */
39 GSM_NetworkStatusUnknown,
40 /**
41 * Network explicitely requested by user.
42 */
43 GSM_RequestingNetwork
44} GSM_NetworkInfo_State;
45
46/**
47 * Structure for getting the current network info.
48 */
49typedef struct {
50 /**
51 * Cell ID (CID)
52 */
53 unsigned char CID[10];
54 /**
55 * GSM network code.
56 */
57 char NetworkCode[10];
58 /**
59 * Status of network logging. If phone is not logged into any network,
60 * some values are not filled
61 */
62 GSM_NetworkInfo_State State;
63 /**
64 * LAC (Local Area Code).
65 */
66 unsigned char LAC[10];
67 /**
68 * Name of current network like returned from phone (or empty).
69 */
70 unsigned char NetworkName[15*2];
71} GSM_NetworkInfo;
72
73void NOKIA_EncodeNetworkCode (unsigned char* buffer, unsigned char* output);
74void NOKIA_DecodeNetworkCode (unsigned char* buffer, unsigned char* output);
75
76/**
77 * Information about signal quality, all these should be -1 when unknown.
78 */
79typedef struct {
80 /*
81 * Signal strength in dBm
82 */
83 int SignalStrength;
84 /**
85 * Signal strength in percent.
86 */
87 int SignalPercent;
88 /**
89 * Bit error rate in percent.
90 */
91 int BitErrorRate;
92} GSM_SignalQuality;
93
94#endif
95
96/* How should editor hadle tabs in this file? Add editor commands here.
97 * vim: noexpandtab sw=8 ts=8 sts=8:
98 */
diff --git a/gammu/emb/common/service/gsmpbk.c b/gammu/emb/common/service/gsmpbk.c
new file mode 100644
index 0000000..05e5cb9
--- a/dev/null
+++ b/gammu/emb/common/service/gsmpbk.c
@@ -0,0 +1,370 @@
1/* (c) 2001-2003 by Marcin Wiacek,... */
2
3#include <string.h>
4
5#include "../misc/coding/coding.h"
6#include "gsmpbk.h"
7#include "gsmmisc.h"
8
9unsigned char *GSM_PhonebookGetEntryName (GSM_MemoryEntry *entry)
10{
11 /* We possibly store here "LastName, FirstName" so allocate enough memory */
12 static char dest[(GSM_PHONEBOOK_TEXT_LENGTH*2+2+1)*2];
13 static char split[] = { '\0', ',', '\0', ' ', '\0', '\0'};
14 int i;
15 int first = -1, last = -1, name = -1;
16 int len = 0;
17
18 for (i = 0; i < entry->EntriesNum; i++) {
19 switch (entry->Entries[i].EntryType) {
20 case PBK_Text_LastName:
21 last = i;
22 break;
23 case PBK_Text_FirstName:
24 first = i;
25 break;
26 case PBK_Text_Name:
27 name = i;
28 break;
29 default:
30 break;
31 }
32 }
33
34 if (name != -1) {
35 CopyUnicodeString(dest, entry->Entries[name].Text);
36 } else {
37 if (last != -1 && first != -1) {
38 len = UnicodeLength(entry->Entries[last].Text);
39 CopyUnicodeString(dest, entry->Entries[last].Text);
40 CopyUnicodeString(dest + 2*len, split);
41 CopyUnicodeString(dest + 2*len + 4, entry->Entries[first].Text);
42 } else if (last != -1) {
43 CopyUnicodeString(dest, entry->Entries[last].Text);
44 } else if (first != -1) {
45 CopyUnicodeString(dest, entry->Entries[first].Text);
46 } else {
47 return NULL;
48 }
49 }
50
51 return dest;
52}
53
54void GSM_PhonebookFindDefaultNameNumberGroup(GSM_MemoryEntry *entry, int *Name, int *Number, int *Group)
55{
56 int i;
57
58 *Name = -1;
59 *Number = -1;
60 *Group = -1;
61 for (i = 0; i < entry->EntriesNum; i++) {
62 switch (entry->Entries[i].EntryType) {
63 case PBK_Number_General : if (*Number == -1) *Number = i; break;
64 case PBK_Text_Name : if (*Name == -1) *Name = i; break;
65 case PBK_Caller_Group : if (*Group == -1) *Group = i; break;
66 default : break;
67 }
68 }
69 if ((*Number) == -1) {
70 for (i = 0; i < entry->EntriesNum; i++) {
71 switch (entry->Entries[i].EntryType) {
72 case PBK_Number_Mobile:
73 case PBK_Number_Work:
74 case PBK_Number_Fax:
75 case PBK_Number_Home:
76 case PBK_Number_Pager:
77 case PBK_Number_Other:
78 *Number = i;
79 break;
80 default:
81 break;
82 }
83 if (*Number != -1) break;
84 }
85 }
86 if ((*Name) == -1) {
87 for (i = 0; i < entry->EntriesNum; i++) {
88 if (entry->Entries[i].EntryType != PBK_Text_LastName) continue;
89 *Name = i;
90 break;
91 }
92 }
93 if ((*Name) == -1) {
94 for (i = 0; i < entry->EntriesNum; i++) {
95 if (entry->Entries[i].EntryType != PBK_Text_FirstName) continue;
96 *Name = i;
97 break;
98 }
99 }
100}
101
102void GSM_EncodeVCARD(char *Buffer, int *Length, GSM_MemoryEntry *pbk, bool header, GSM_VCardVersion Version)
103{
104 int Name, Number, Group, i;
105 bool ignore;
106
107 GSM_PhonebookFindDefaultNameNumberGroup(pbk, &Name, &Number, &Group);
108
109 if (Version == Nokia_VCard10) {
110 if (header) *Length+=sprintf(Buffer+(*Length),"BEGIN:VCARD%c%c",13,10);
111 if (Name != -1) {
112 *Length+=sprintf(Buffer+(*Length),"N:%s%c%c",DecodeUnicodeString(pbk->Entries[Name].Text),13,10);
113 }
114 if (Number != -1) {
115 *Length +=sprintf(Buffer+(*Length),"TEL:%s%c%c",DecodeUnicodeString(pbk->Entries[Number].Text),13,10);
116 }
117 if (header) *Length+=sprintf(Buffer+(*Length),"END:VCARD%c%c",13,10);
118 } else if (Version == Nokia_VCard21) {
119 if (header) *Length+=sprintf(Buffer+(*Length),"BEGIN:VCARD%c%cVERSION:2.1%c%c",13,10,13,10);
120 if (Name != -1) {
121 SaveVCALText(Buffer, Length, pbk->Entries[Name].Text, "N");
122 }
123 for (i=0; i < pbk->EntriesNum; i++) {
124 if (i != Name) {
125 ignore = false;
126 switch(pbk->Entries[i].EntryType) {
127 case PBK_Text_Name :
128 case PBK_Date :
129 case PBK_Caller_Group :
130 ignore = true;
131 break;
132 case PBK_Number_General :
133 *Length+=sprintf(Buffer+(*Length),"TEL");
134 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
135 break;
136 case PBK_Number_Mobile :
137 *Length+=sprintf(Buffer+(*Length),"TEL");
138 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
139 *Length+=sprintf(Buffer+(*Length),";CELL");
140 break;
141 case PBK_Number_Work :
142 *Length+=sprintf(Buffer+(*Length),"TEL");
143 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
144 *Length+=sprintf(Buffer+(*Length),";WORK;VOICE");
145 break;
146 case PBK_Number_Fax :
147 *Length+=sprintf(Buffer+(*Length),"TEL");
148 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
149 *Length+=sprintf(Buffer+(*Length),";FAX");
150 break;
151 case PBK_Number_Home :
152 *Length+=sprintf(Buffer+(*Length),"TEL");
153 if (Number == i) (*Length)+=sprintf(Buffer+(*Length),";PREF");
154 *Length+=sprintf(Buffer+(*Length),";HOME;VOICE");
155 break;
156 case PBK_Text_Note :
157 *Length+=sprintf(Buffer+(*Length),"NOTE");
158 break;
159 case PBK_Text_Postal :
160 /* Don't ask why. Nokia phones save postal address
161 * double - once like LABEL, second like ADR
162 */
163 SaveVCALText(Buffer, Length, pbk->Entries[i].Text, "LABEL");
164 *Length+=sprintf(Buffer+(*Length),"ADR");
165 break;
166 case PBK_Text_Email :
167 case PBK_Text_Email2 :
168 *Length+=sprintf(Buffer+(*Length),"EMAIL");
169 break;
170 case PBK_Text_URL :
171 *Length+=sprintf(Buffer+(*Length),"URL");
172 break;
173 default :
174 ignore = true;
175 break;
176 }
177 if (!ignore) {
178 SaveVCALText(Buffer, Length, pbk->Entries[i].Text, "");
179 }
180 }
181 }
182 if (header) *Length+=sprintf(Buffer+(*Length),"END:VCARD%c%c",13,10);
183 }
184}
185
186GSM_Error GSM_DecodeVCARD(unsigned char *Buffer, int *Pos, GSM_MemoryEntry *Pbk, GSM_VCardVersion Version)
187{
188 unsigned char Line[2000],Buff[2000];
189 int Level = 0;
190
191 Buff[0] = 0;
192 Pbk->EntriesNum = 0;
193
194 while (1) {
195 MyGetLine(Buffer, Pos, Line, strlen(Buffer));
196 if (strlen(Line) == 0) break;
197 switch (Level) {
198 case 0:
199 if (strstr(Line,"BEGIN:VCARD")) Level = 1;
200 break;
201 case 1:
202 if (strstr(Line,"END:VCARD")) {
203 if (Pbk->EntriesNum == 0) return ERR_EMPTY;
204 return ERR_NONE;
205 }
206 if (ReadVCALText(Line, "N", Buff)) {
207 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
208 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Name;
209 Pbk->EntriesNum++;
210 }
211 if (ReadVCALText(Line, "TEL", Buff) ||
212 ReadVCALText(Line, "TEL;VOICE", Buff) ||
213 ReadVCALText(Line, "TEL;PREF", Buff) ||
214 ReadVCALText(Line, "TEL;PREF;VOICE", Buff)) {
215 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
216 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_General;
217 Pbk->EntriesNum++;
218 }
219 if (ReadVCALText(Line, "TEL;CELL", Buff) ||
220 ReadVCALText(Line, "TEL;CELL;VOICE", Buff) ||
221 ReadVCALText(Line, "TEL;PREF;CELL", Buff) ||
222 ReadVCALText(Line, "TEL;PREF;CELL;VOICE", Buff)) {
223 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
224 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Mobile;
225 Pbk->EntriesNum++;
226 }
227 if (ReadVCALText(Line, "TEL;WORK", Buff) ||
228 ReadVCALText(Line, "TEL;PREF;WORK", Buff) ||
229 ReadVCALText(Line, "TEL;WORK;VOICE", Buff) ||
230 ReadVCALText(Line, "TEL;PREF;WORK;VOICE", Buff)) {
231 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
232 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Work;
233 Pbk->EntriesNum++;
234 }
235 if (ReadVCALText(Line, "TEL;FAX", Buff) ||
236 ReadVCALText(Line, "TEL;PREF;FAX", Buff) ||
237 ReadVCALText(Line, "TEL;FAX;VOICE", Buff) ||
238 ReadVCALText(Line, "TEL;PREF;FAX;VOICE", Buff)) {
239 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
240 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Fax;
241 Pbk->EntriesNum++;
242 }
243 if (ReadVCALText(Line, "TEL;HOME", Buff) ||
244 ReadVCALText(Line, "TEL;PREF;HOME", Buff) ||
245 ReadVCALText(Line, "TEL;HOME;VOICE", Buff) ||
246 ReadVCALText(Line, "TEL;PREF;HOME;VOICE", Buff)) {
247 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
248 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Number_Home;
249 Pbk->EntriesNum++;
250 }
251 if (ReadVCALText(Line, "NOTE", Buff)) {
252 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
253 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Note;
254 Pbk->EntriesNum++;
255 }
256 if (ReadVCALText(Line, "ADR", Buff)) {
257 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
258 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Postal;
259 Pbk->EntriesNum++;
260 }
261 if (ReadVCALText(Line, "EMAIL", Buff)) {
262 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
263 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_Email;
264 Pbk->EntriesNum++;
265 }
266 if (ReadVCALText(Line, "URL", Buff)) {
267 CopyUnicodeString(Pbk->Entries[Pbk->EntriesNum].Text,Buff);
268 Pbk->Entries[Pbk->EntriesNum].EntryType = PBK_Text_URL;
269 Pbk->EntriesNum++;
270 }
271 break;
272 }
273 }
274
275 if (Pbk->EntriesNum == 0) return ERR_EMPTY;
276 return ERR_NONE;
277}
278
279/* -------------- OLD functions (c) by Timo Teras -------------------------- */
280
281#ifndef ENABLE_LGPL
282
283static void ParseVCardLine(char **pos, char *Name, char *Parameters, char *Value)
284{
285 int i;
286
287 Name[0] = Parameters[0] = Value[0] = 0;
288
289 if (**pos == 0) return;
290
291 for (i=0; **pos && **pos != ':' && **pos != ';'; i++, (*pos)++) Name[i] = **pos;
292 Name[i] = 0;
293
294 //dbgprintf("ParseVCardLine: name tag = '%s'\n", Name);
295 if (**pos == ';') {
296 (*pos)++;
297 for (i=0; **pos && **pos != ':'; i++, (*pos)++) Parameters[i] = **pos;
298 Parameters[i] = ';';
299 Parameters[i+1] = 0;
300 //dbgprintf("ParseVCardLine: parameter tag = '%s'\n", Parameters);
301 }
302
303 if (**pos != 0) (*pos)++;
304
305 i=0;
306 while (**pos) {
307 if ((*pos)[0] == '\x0d' && (*pos)[1] == '\x0a') {
308 (*pos) += 2;
309 if (**pos != '\t' && **pos != ' ') break;
310 while (**pos == '\t' || **pos == ' ') (*pos)++;
311 continue;
312 }
313 Value[i++] = **pos;
314 (*pos)++;
315 }
316 Value[i] = 0;
317
318 //dbgprintf("ParseVCardLine: value tag = '%s'\n", Value);
319}
320
321void DecodeVCARD21Text(char *VCard, GSM_MemoryEntry *pbk)
322{
323 char *pos = VCard;
324 char Name[32], Parameters[256], Value[1024];
325
326 dbgprintf("Parsing VCard:\n%s\n", VCard);
327
328 ParseVCardLine(&pos, Name, Parameters, Value);
329 if (!mystrncasecmp(Name, "BEGIN", 0) || !mystrncasecmp(Value, "VCARD", 0)) {
330 dbgprintf("No valid VCARD signature\n");
331 return;
332 }
333
334 while (1) {
335 GSM_SubMemoryEntry *pbe = &pbk->Entries[pbk->EntriesNum];
336
337 ParseVCardLine(&pos, Name, Parameters, Value);
338 if (Name[0] == 0x00 ||
339 (mystrncasecmp(Name, "END", 0) && mystrncasecmp(Value, "VCARD", 0)))
340 return;
341
342 if (mystrncasecmp(Name, "N", 0)) {
343 //FIXME: Name is tagged field which should be parsed
344 pbe->EntryType = PBK_Text_Name;
345 EncodeUnicode(pbe->Text, Value, strlen(Value));
346 pbk->EntriesNum++;
347 } else if (mystrncasecmp(Name, "EMAIL", 0)) {
348 pbe->EntryType = PBK_Text_Email;
349 EncodeUnicode(pbe->Text, Value, strlen(Value));
350 pbk->EntriesNum++;
351 } else if (mystrncasecmp(Name, "TEL", 0)) {
352 if (strstr(Parameters, "WORK;"))
353 pbe->EntryType = PBK_Number_Work;
354 else if (strstr(Name, "HOME;"))
355 pbe->EntryType = PBK_Number_Home;
356 else if (strstr(Name, "FAX;"))
357 pbe->EntryType = PBK_Number_Fax;
358 else pbe->EntryType = PBK_Number_General;
359
360 EncodeUnicode(pbe->Text, Value, strlen(Value));
361 pbk->EntriesNum++;
362 }
363 }
364}
365
366#endif
367
368/* How should editor hadle tabs in this file? Add editor commands here.
369 * vim: noexpandtab sw=8 ts=8 sts=8:
370 */
diff --git a/gammu/emb/common/service/gsmpbk.h b/gammu/emb/common/service/gsmpbk.h
new file mode 100644
index 0000000..e556793
--- a/dev/null
+++ b/gammu/emb/common/service/gsmpbk.h
@@ -0,0 +1,270 @@
1/* (c) 2001-2004 by Marcin Wiacek and Michal Cihar */
2
3#ifndef __gsm_pbk_h
4#define __gsm_pbk_h
5
6#include <stdlib.h>
7
8#include "../gsmcomon.h"
9#include "gsmmisc.h"
10
11/**
12 * Structure contains info about number of used/free entries in phonebook
13 * memory
14 */
15typedef struct {
16 /**
17 * Number of used entries
18 */
19 int MemoryUsed;
20 /**
21 * Memory type
22 */
23 GSM_MemoryType MemoryType;
24 /**
25 * Number of free entries
26 */
27 int MemoryFree;
28} GSM_MemoryStatus;
29
30/**
31 * Type of specific phonebook entry. In parenthesis is specified in which
32 * member of @ref GSM_SubMemoryEntry value is stored.
33 */
34typedef enum {
35 /**
36 * General number. (Text)
37 */
38 PBK_Number_General = 1,
39 /**
40 * Mobile number. (Text)
41 */
42 PBK_Number_Mobile,
43 /**
44 * Work number. (Text)
45 */
46 PBK_Number_Work,
47 /**
48 * Fax number. (Text)
49 */
50 PBK_Number_Fax,
51 /**
52 * Home number. (Text)
53 */
54 PBK_Number_Home,
55 /**
56 * Pager number. (Text)
57 */
58 PBK_Number_Pager,
59 /**
60 * Other number. (Text)
61 */
62 PBK_Number_Other,
63 /**
64 * Note. (Text)
65 */
66 PBK_Text_Note,
67 /**
68 * Complete postal address. (Text)
69 */
70 PBK_Text_Postal,
71 /**
72 * Email. (Text)
73 */
74 PBK_Text_Email,
75 /**
76 * Second email. (Text)
77 */
78 PBK_Text_Email2,
79 /**
80 * URL (Text)
81 */
82 PBK_Text_URL,
83 /**
84 * Date and time. FIXME: describe better (Date)
85 */
86 PBK_Date,
87 /**
88 * Caller group. (Text)
89 */
90 PBK_Caller_Group,
91 /**
92 * Name (Text)
93 */
94 PBK_Text_Name,
95 /**
96 * Last name. (Text)
97 */
98 PBK_Text_LastName,
99 /**
100 * First name. (Text)
101 */
102 PBK_Text_FirstName,
103 /**
104 * Company. (Text)
105 */
106 PBK_Text_Company,
107 /**
108 * Job title. (Text)
109 */
110 PBK_Text_JobTitle,
111 /**
112 * Category. (Number)
113 */
114 PBK_Category,
115 /**
116 * Whether entry is private. (Number)
117 */
118 PBK_Private,
119 /**
120 * Street address. (Text)
121 */
122 PBK_Text_StreetAddress,
123 /**
124 * City. (Text)
125 */
126 PBK_Text_City,
127 /**
128 * State. (Text)
129 */
130 PBK_Text_State,
131 /**
132 * Zip code. (Text)
133 */
134 PBK_Text_Zip,
135 /**
136 * Country. (Text)
137 */
138 PBK_Text_Country,
139 /**
140 * Custom information 1. (Text)
141 */
142 PBK_Text_Custom1,
143 /**
144 * Custom information 2. (Text)
145 */
146 PBK_Text_Custom2,
147 /**
148 * Custom information 3. (Text)
149 */
150 PBK_Text_Custom3,
151 /**
152 * Custom information 4. (Text)
153 */
154 PBK_Text_Custom4,
155 /**
156 * Ringtone ID. (Number)
157 */
158 PBK_RingtoneID,
159 /**
160 * Ringtone ID in phone filesystem. (Number)
161 */
162 PBK_RingtoneFileSystemID,
163 /**
164 * Picture ID. (Number)
165 */
166 PBK_PictureID,
167 PBK_SMSListID,
168 /**
169 * User ID. (Text)
170 */
171 PBK_Text_UserID
172} GSM_EntryType;
173
174#define GSM_PHONEBOOK_TEXT_LENGTH 200
175 #define GSM_PHONEBOOK_ENTRIES 26
176
177/**
178 * One value of phonebook memory entry.
179 */
180typedef struct {
181 /**
182 * Type of entry.
183 */
184 GSM_EntryType EntryType;
185 /**
186 * Text of entry (if applicable, see @ref GSM_EntryType).
187 */
188 unsigned char Text[(GSM_PHONEBOOK_TEXT_LENGTH+1)*2];
189 /**
190 * Text of entry (if applicable, see @ref GSM_EntryType).
191 */
192 GSM_DateTime Date;
193 /**
194 * Number of entry (if applicable, see @ref GSM_EntryType).
195 */
196 int Number;
197 /**
198 * Voice dialling tag.
199 */
200 int VoiceTag;
201 int SMSList[20];
202} GSM_SubMemoryEntry;
203
204/**
205 * Structure for saving phonebook entries
206 */
207typedef struct {
208 /**
209 * Used memory for phonebook entry
210 */
211 GSM_MemoryType MemoryType;
212 /**
213 * Used location for phonebook entry
214 */
215 int Location;
216 /**
217 * Number of SubEntries in Entries table.
218 */
219 int EntriesNum;
220 /**
221 * Values of SubEntries.
222 */
223 GSM_SubMemoryEntry Entries[GSM_PHONEBOOK_ENTRIES];
224} GSM_MemoryEntry;
225
226typedef enum {
227 Nokia_VCard10 = 1,
228 Nokia_VCard21,
229 SonyEricsson_VCard10,
230 SonyEricsson_VCard21
231} GSM_VCardVersion;
232
233void GSM_PhonebookFindDefaultNameNumberGroup(GSM_MemoryEntry *entry, int *Name, int *Number, int *Group);
234unsigned char *GSM_PhonebookGetEntryName (GSM_MemoryEntry *entry);
235
236void GSM_EncodeVCARD(char *Buffer, int *Length, GSM_MemoryEntry *pbk, bool header, GSM_VCardVersion Version);
237GSM_Error GSM_DecodeVCARD(unsigned char *Buffer, int *Pos, GSM_MemoryEntry *Pbk, GSM_VCardVersion Version);
238
239#ifndef ENABLE_LGPL
240/* (c) by Timo Teras */
241void DecodeVCARD21Text(char *VCard, GSM_MemoryEntry *pbk);
242#endif
243
244/**
245 * Structure for saving speed dials
246 */
247typedef struct {
248 /**
249 * Number of speed dial: 2,3..,8,9
250 */
251 int Location;
252 /**
253 * ID of phone number used in phonebook entry
254 */
255 int MemoryNumberID;
256 /**
257 * Memory, where is saved used phonebook entry
258 */
259 GSM_MemoryType MemoryType;
260 /**
261 * Location in memory, where is saved used phonebook entry
262 */
263 int MemoryLocation;
264} GSM_SpeedDial;
265
266#endif
267
268/* How should editor hadle tabs in this file? Add editor commands here.
269 * vim: noexpandtab sw=8 ts=8 sts=8:
270 */
diff --git a/gammu/emb/common/service/gsmprof.h b/gammu/emb/common/service/gsmprof.h
new file mode 100644
index 0000000..2e3d087
--- a/dev/null
+++ b/gammu/emb/common/service/gsmprof.h
@@ -0,0 +1,104 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef __gsm_prof_h
4#define __gsm_prof_h
5
6typedef enum {
7 PROFILE_KEYPAD_LEVEL1 = 1,
8 PROFILE_KEYPAD_LEVEL2,
9 PROFILE_KEYPAD_LEVEL3,
10 PROFILE_KEYPAD_OFF,
11 PROFILE_CALLALERT_RINGING,
12 PROFILE_CALLALERT_BEEPONCE,
13 PROFILE_CALLALERT_OFF,
14 PROFILE_CALLALERT_RINGONCE,
15 PROFILE_CALLALERT_ASCENDING,
16 PROFILE_CALLALERT_CALLERGROUPS,
17 PROFILE_VOLUME_LEVEL1,
18 PROFILE_VOLUME_LEVEL2,
19 PROFILE_VOLUME_LEVEL3,
20 PROFILE_VOLUME_LEVEL4,
21 PROFILE_VOLUME_LEVEL5,
22 PROFILE_MESSAGE_NOTONE,
23 PROFILE_MESSAGE_STANDARD,
24 PROFILE_MESSAGE_SPECIAL,
25 PROFILE_MESSAGE_BEEPONCE,
26 PROFILE_MESSAGE_ASCENDING,
27 PROFILE_MESSAGE_PERSONAL,
28 PROFILE_VIBRATION_OFF,
29 PROFILE_VIBRATION_ON,
30 PROFILE_VIBRATION_FIRST,
31 PROFILE_WARNING_ON,
32 PROFILE_WARNING_OFF,
33 PROFILE_AUTOANSWER_ON,
34 PROFILE_AUTOANSWER_OFF,
35 PROFILE_LIGHTS_OFF,
36 PROFILE_LIGHTS_AUTO,
37 PROFILE_SAVER_ON,
38 PROFILE_SAVER_OFF,
39 PROFILE_SAVER_TIMEOUT_5SEC,
40 PROFILE_SAVER_TIMEOUT_20SEC,
41 PROFILE_SAVER_TIMEOUT_1MIN,
42 PROFILE_SAVER_TIMEOUT_2MIN,
43 PROFILE_SAVER_TIMEOUT_5MIN,
44 PROFILE_SAVER_TIMEOUT_10MIN
45} GSM_Profile_Feat_Value;
46
47typedef enum {
48 Profile_KeypadTone = 1,
49 Profile_CallAlert,
50 Profile_RingtoneVolume,
51 Profile_MessageTone,
52 Profile_Vibration,
53 Profile_WarningTone,
54 Profile_AutoAnswer,
55 Profile_Lights,
56 Profile_ScreenSaverTime,
57 Profile_ScreenSaver,
58
59 Profile_ScreenSaverNumber,
60 Profile_RingtoneID,
61 Profile_MessageToneID,
62 Profile_CallerGroups
63} GSM_Profile_Feat_ID;
64
65/**
66 * It contains phone profiles
67 */
68typedef struct {
69 bool Active;
70
71 /**
72 * Profile number
73 */
74 int Location;
75 /**
76 * Profile name
77 */
78 char Name[40*2];
79 /**
80 * Is it default name for profile ?
81 */
82 bool DefaultName;
83 bool HeadSetProfile;
84 bool CarKitProfile;
85
86 int FeaturesNumber;
87 GSM_Profile_Feat_ValueFeatureValue[15];
88 GSM_Profile_Feat_IDFeatureID[15];
89
90 bool CallerGroups[5];
91} GSM_Profile;
92
93typedef struct {
94 GSM_Profile_Feat_IDID;
95 GSM_Profile_Feat_ValueValue;
96 unsigned char PhoneID;
97 unsigned char PhoneValue;
98} GSM_Profile_PhoneTableValue;
99
100#endif
101
102/* How should editor hadle tabs in this file? Add editor commands here.
103 * vim: noexpandtab sw=8 ts=8 sts=8:
104 */
diff --git a/gammu/emb/common/service/gsmring.c b/gammu/emb/common/service/gsmring.c
new file mode 100644
index 0000000..5a1ff87
--- a/dev/null
+++ b/gammu/emb/common/service/gsmring.c
@@ -0,0 +1,1600 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* Based on some work from Ralf Thelen (7110 ringtones),
3 * Gnokii (RTTL and SM) and others
4 */
5
6#include <stdlib.h>
7#include <string.h>
8#include <ctype.h>
9#include <math.h>
10#ifdef WIN32
11# include <windows.h>
12#endif
13
14#include "../gsmcomon.h"
15#include "../misc/coding/coding.h"
16#include "../gsmstate.h"
17#include "gsmring.h"
18#include "sms/gsmsms.h"
19
20int GSM_RingNoteGetFrequency(GSM_RingNote Note)
21{
22 double freq=0;
23
24 /* Values according to the software from http://iki.fi/too/sw/xring/
25 * generated with:
26 * perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)'
27 */
28 switch (Note.Note) {
29 case Note_C : freq = 523.3; break;
30 case Note_Cis: freq = 554.4; break;
31 case Note_D : freq = 587.3; break;
32 case Note_Dis: freq = 622.3; break;
33 case Note_E : freq = 659.3; break;
34 case Note_F : freq = 698.5; break;
35 case Note_Fis: freq = 740; break;
36 case Note_G : freq = 784; break;
37 case Note_Gis: freq = 830.6; break;
38 case Note_A : freq = 880; break;
39 case Note_Ais: freq = 932.3; break;
40 case Note_H : freq = 987.8; break;
41 case Note_Pause: break;
42 }
43 switch (Note.Scale) {
44 case Scale_440 : freq = freq / 2; break;
45 case Scale_880 : break;
46 case Scale_1760: freq = freq * 2; break;
47 case Scale_3520: freq = freq * 4; break;
48 default : break;
49 }
50 return (int)freq;
51}
52
53int GSM_RingNoteGetFullDuration(GSM_RingNote Note)
54{
55 int duration = 1;
56
57 switch (Note.Duration) {
58 case Duration_Full : duration = 128; break;
59 case Duration_1_2 : duration = 64; break;
60 case Duration_1_4 : duration = 32; break;
61 case Duration_1_8 : duration = 16; break;
62 case Duration_1_16 : duration = 8; break;
63 case Duration_1_32 : duration = 4; break;
64 }
65 switch (Note.DurationSpec) {
66 case NoSpecialDuration : break;
67 case DottedNote : duration = duration * 3/2;break;
68 case DoubleDottedNote : duration = duration * 9/4;break;
69 case Length_2_3 : duration = duration * 2/3;break;
70 }
71 return duration;
72}
73
74#ifndef PI
75# define PI 3.141592654
76#endif
77
78#define WAV_SAMPLE_RATE 44100
79
80GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone)
81{
82 unsigned char WAV_Header[] = {
83 'R','I','F','F',
84 0x00,0x00,0x00,0x00,/* Length */
85 'W','A','V','E'};
86 unsigned char FMT_Header[] = {'f','m','t',' ',
87 0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x44,0xac,
88 0x00,0x00,0x88,0x58,0x01,0x00,0x02,0x00,0x10,0x00};
89 unsigned char DATA_Header[] = {
90 'd','a','t','a',
91 0x00,0x00,0x00,0x00};/* Length */
92 short DATA_Buffer[60000];
93 long wavfilesize;
94 GSM_RingNote *Note;
95 long i,j,length=0;
96 double phase=0,phase_step;
97
98 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file);
99 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file);
100 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file);
101
102 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
103 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
104 Note = &ringtone->NoteTone.Commands[i].Note;
105 phase_step = GSM_RingNoteGetFrequency(*Note)*WAV_SAMPLE_RATE*1.5;
106 for (j=0;j<((long)(GSM_RingNoteGetFullDuration(*Note)*WAV_SAMPLE_RATE/70));j++) {
107 DATA_Buffer[j] = ((int)(sin(phase*PI)*50000));
108 phase = phase + phase_step;
109 length++;
110 }
111 fwrite(&DATA_Buffer,sizeof(short),j,file);
112 }
113 }
114
115 wavfilesize = sizeof(WAV_Header) + sizeof(FMT_Header) + sizeof(DATA_Header) + length*2;
116 WAV_Header[4] = ((unsigned char)wavfilesize % 256);
117 WAV_Header[5] = ((unsigned char)wavfilesize / 256);
118 WAV_Header[6] = ((unsigned char)wavfilesize / (256*256));
119 WAV_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
120 wavfilesize = wavfilesize - 54;
121 DATA_Header[4] = ((unsigned char)wavfilesize % 256);
122 DATA_Header[5] = ((unsigned char)wavfilesize / 256);
123 DATA_Header[6] = ((unsigned char)wavfilesize / (256*256));
124 DATA_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
125
126 fseek( file, 0, SEEK_SET);
127 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file);
128 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file);
129 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file);
130
131 return ERR_NONE;
132}
133
134static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone)
135{
136 char nullchar=0x00;
137
138 fwrite(&nullchar,1,1,file);
139 fwrite(&nullchar,1,1,file);
140 fprintf(file,"\x0C\x01\x2C");
141 fprintf(file,"%s",DecodeUnicodeString(ringtone->Name));
142 fwrite(&nullchar,1,1,file);
143 fwrite(&nullchar,1,1,file);
144 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
145 return ERR_NONE;
146}
147
148static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone)
149{
150 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
151 return ERR_NONE;
152}
153
154GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone)
155{
156 GSM_RingNoteScaleDefNoteScale;
157 GSM_RingNoteDurationDefNoteDuration;
158
159 GSM_RingNoteStyleDefNoteStyle=0;
160 int DefNoteTempo=0;
161
162 bool started = false, firstcomma = true;
163 GSM_RingNote *Note;
164
165 unsigned char buffer[15];
166 int i,j,k=0;
167
168 /* Saves ringtone name */
169 fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name));
170
171 /* Find the most frequently used duration */
172 for (i=0;i<6;i++) buffer[i]=0;
173 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
174 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
175 Note = &ringtone->NoteTone.Commands[i].Note;
176 /* some durations need 2 bytes in file, some 1 */
177 if (Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) {
178 buffer[Note->Duration/32]++;
179 }
180 if (Note->Duration >= Duration_1_16 && Note->Duration <= Duration_1_32) {
181 buffer[Note->Duration/32]+=2;
182 }
183 }
184 }
185 /* Now find the most frequently used */
186 j=0;
187 for (i=0;i<6;i++) {
188 if (buffer[i]>j) {
189 k=i;
190 j=buffer[i];
191 }
192 }
193 /* Finally convert the default duration */
194 DefNoteDuration = k * 32;
195 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration);
196 switch (DefNoteDuration) {
197 case Duration_Full:fprintf(file,"d=1"); break;
198 case Duration_1_2 :fprintf(file,"d=2"); break;
199 case Duration_1_4 :fprintf(file,"d=4"); break;
200 case Duration_1_8 :fprintf(file,"d=8"); break;
201 case Duration_1_16:fprintf(file,"d=16");break;
202 case Duration_1_32:fprintf(file,"d=32");break;
203 }
204
205 /* Find the most frequently used scale */
206 for (i=0;i<9;i++) buffer[i]=0;
207 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
208 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
209 Note = &ringtone->NoteTone.Commands[i].Note;
210 if (Note->Note!=Note_Pause &&
211 Note->Scale >= Scale_55 && Note->Scale <= Scale_14080) {
212 buffer[Note->Scale - 1]++;
213 }
214 }
215 }
216 j=0;
217 for (i=0;i<9;i++) {
218 if (buffer[i]>j) {
219 k = i;
220 j=buffer[i];
221 }
222 }
223 DefNoteScale = k + 1;
224 /* Save the default scale */
225 fprintf(file,",o=%i,",DefNoteScale);
226 dbgprintf("DefNoteScale=%d\n", DefNoteScale);
227
228 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
229 if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue;
230
231 Note = &ringtone->NoteTone.Commands[i].Note;
232
233 /* Trick from PPM Edit */
234 if (Note->DurationSpec == DoubleDottedNote) {
235 switch (Note->Duration) {
236 case Duration_Full:Note->Duration = Duration_Full;break;
237 case Duration_1_2 :Note->Duration = Duration_Full;break;
238 case Duration_1_4 :Note->Duration = Duration_1_2; break;
239 case Duration_1_8 :Note->Duration = Duration_1_4; break;
240 case Duration_1_16:Note->Duration = Duration_1_8; break;
241 case Duration_1_32:Note->Duration = Duration_1_16;break;
242 }
243 Note->DurationSpec = NoSpecialDuration;
244 }
245
246 if (!started) {
247 DefNoteTempo=Note->Tempo;
248 DefNoteStyle=Note->Style;
249 switch (Note->Style) {
250 case StaccatoStyle: fprintf(file,"s=S,"); break;
251 case NaturalStyle : fprintf(file,"s=N,"); break;
252 case ContinuousStyle : break;
253 }
254 /* Save the default tempo */
255 fprintf(file,"b=%i:",DefNoteTempo);
256 dbgprintf("DefNoteTempo=%d\n", DefNoteTempo);
257 started = true;
258 firstcomma = true;
259 }
260
261 if (!started) continue;
262
263 if (Note->Style!=DefNoteStyle) {
264 /* And a separator */
265 if (!firstcomma) fprintf(file,",");
266 firstcomma = false;
267 DefNoteStyle=Note->Style;
268 switch (Note->Style) {
269 case StaccatoStyle : fprintf(file,"s=S"); break;
270 case NaturalStyle : fprintf(file,"s=N"); break;
271 case ContinuousStyle: fprintf(file,"s=C"); break;
272 }
273 }
274 if (Note->Tempo!=DefNoteTempo) {
275 /* And a separator */
276 if (!firstcomma) fprintf(file,",");
277 firstcomma = false;
278 DefNoteTempo=Note->Tempo;
279 fprintf(file,"b=%i",DefNoteTempo);
280 }
281 /* This note has a duration different than the default. We must save it */
282 if (Note->Duration!=DefNoteDuration) {
283 /* And a separator */
284 if (!firstcomma) fprintf(file,",");
285 firstcomma = false;
286 switch (Note->Duration) {
287 case Duration_Full:fprintf(file,"1"); break;
288 case Duration_1_2 :fprintf(file,"2"); break;
289 case Duration_1_4 :fprintf(file,"4"); break;
290 case Duration_1_8 :fprintf(file,"8"); break;
291 case Duration_1_16:fprintf(file,"16");break;
292 case Duration_1_32:fprintf(file,"32");break;
293 }
294 } else {
295 /* And a separator */
296 if (!firstcomma) fprintf(file,",");
297 firstcomma = false;
298 }
299 /* Now save the actual note */
300 switch (Note->Note) {
301 case Note_C :fprintf(file,"c");break;
302 case Note_Cis:fprintf(file,"c#");break;
303 case Note_D :fprintf(file,"d");break;
304 case Note_Dis:fprintf(file,"d#");break;
305 case Note_E :fprintf(file,"e");break;
306 case Note_F :fprintf(file,"f");break;
307 case Note_Fis:fprintf(file,"f#");break;
308 case Note_G :fprintf(file,"g");break;
309 case Note_Gis:fprintf(file,"g#");break;
310 case Note_A :fprintf(file,"a");break;
311 case Note_Ais:fprintf(file,"a#");break;
312 case Note_H :fprintf(file,"h");break;
313 default :fprintf(file,"p");break; /*Pause ?*/
314 }
315 switch (Note->DurationSpec) {
316 case DottedNote : fprintf(file,".");break;
317 default : break;
318 }
319 if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) {
320 fprintf(file,"%i",Note->Scale);
321 }
322 }
323 return ERR_NONE;
324}
325
326void saveimelody(FILE *file, GSM_Ringtone *ringtone)
327{
328 char Buffer[2000];
329 int i=2000;
330
331 GSM_EncodeEMSSound(*ringtone, Buffer, &i, (float)1.2, true);
332
333 fwrite(Buffer, 1, i, file);
334}
335
336#ifndef ENABLE_LGPL
337
338static void WriteVarLen(unsigned char* midifile, int* current, long value)
339{
340 long buffer;
341
342 buffer = value & 0x7f;
343
344 while (value >>= 7) {
345 buffer <<= 8;
346 buffer |= 0x80;
347 buffer += (value & 0x7f);
348 }
349
350 while (1) {
351 midifile[(*current)++] = (unsigned char)buffer;
352 if (buffer & 0x80) {
353 buffer >>= 8;
354 } else {
355 break;
356 }
357 }
358}
359
360#define singlepauses
361
362/* FIXME: need adding tempo before each note and scale too ? */
363void savemid(FILE* file, GSM_Ringtone *ringtone)
364{
365 int pause = 0, current = 26, duration, i, note=0, length = 20;
366 bool started = false;
367 GSM_RingNote *Note;
368 unsigned char midifile[3000] = {
369 0x4D, 0x54, 0x68, 0x64, // MThd
370 0x00, 0x00, 0x00, 0x06, // chunk length
371 0x00, 0x00, // format 0
372 0x00, 0x01, // one track
373 0x00, 0x20, // 32 per quarter note
374 0x4D, 0x54, 0x72, 0x6B, // MTrk
375 0x00, 0x00, 0x00, 0x00, // chunk length
376 0x00, 0xFF, 0x51, 0x03, // tempo meta event
377 0x00, 0x00, 0x00}; // 3 bytes for us for a quarter note
378
379 for (i = 0; i < ringtone->NoteTone.NrCommands; i++) {
380 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
381 Note = &ringtone->NoteTone.Commands[i].Note;
382 if (!started) {
383 /* readmid does not read pauses at the beginning */
384 if (Note->Note != Note_Pause) {
385 /* FIXME: we need add tempo before each note or so... */
386 long duration=60000000/Note->Tempo;
387
388 midifile[current++] = (unsigned char)(duration >> 16);
389 midifile[current++] = (unsigned char)(duration >> 8);
390 midifile[current++] = (unsigned char)duration;
391
392 started = true;
393 }
394 }
395 if (!started) continue;
396 duration = GSM_RingNoteGetFullDuration(*Note);
397 if (Note->Note == Note_Pause) {
398 pause += duration;
399#ifdef singlepauses
400 WriteVarLen(midifile,&current,pause);
401 pause=0;
402 midifile[current++]=0x00; // pause
403 midifile[current++]=0x00;
404#endif
405 } else {
406 if (Note->Note >= Note_C && Note->Note <= Note_H) {
407 note = Note->Note/16 + 12 * Note->Scale - 1;
408 }
409
410 WriteVarLen(midifile,&current,pause);
411 pause=0;
412 midifile[current++]=0x90; // note on
413 midifile[current++]=note;
414 midifile[current++]=0x64; // forte
415
416 WriteVarLen(midifile,&current,duration);
417 midifile[current++]=0x80; // note off
418 midifile[current++]=note;
419 midifile[current++]=0x64;
420 }
421 }
422 }
423 if (pause) {
424 WriteVarLen(midifile,&current,pause);
425 midifile[current++]=0x00; // pause
426 midifile[current++]=0x00; //
427 }
428 midifile[current++] = 0x00;
429 midifile[current++] = 0xFF; // track end
430 midifile[current++] = 0x2F;
431 midifile[current++] = 0x00;
432 midifile[length++] = (current-22) >> 8;
433 midifile[length++] = current-22;
434
435 fwrite(midifile,1,current,file);
436}
437
438#endif
439
440void saveott(FILE *file, GSM_Ringtone *ringtone)
441{
442 char Buffer[2000];
443 int i=2000;
444
445 GSM_EncodeNokiaRTTLRingtone(*ringtone, Buffer, &i);
446
447 fwrite(Buffer, 1, i, file);
448}
449
450GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
451{
452 FILE *file;
453
454 file = fopen(FileName, "wb");
455 if (file == NULL) return ERR_CANTOPENFILE;
456
457 switch (ringtone->Format) {
458 case RING_NOTETONE:
459 if (strstr(FileName,".ott")) {
460 saveott(file,ringtone);
461#ifndef ENABLE_LGPL
462 } else if (strstr(FileName,".mid")) {
463 savemid(file,ringtone);
464#endif
465 } else if (strstr(FileName,".rng")) {
466 saveott(file,ringtone);
467 } else if (strstr(FileName,".imy")) {
468 saveimelody(file,ringtone);
469 } else if (strstr(FileName,".ime")) {
470 saveimelody(file,ringtone);
471 } else if (strstr(FileName,".wav")) {
472 savewav(file,ringtone);
473 } else {
474 saverttl(file, ringtone);
475 }
476 break;
477 case RING_NOKIABINARY:
478 savebin(file, ringtone);
479 break;
480 case RING_MIDI:
481 savepuremidi(file, ringtone);
482 break;
483 }
484
485 fclose(file);
486
487 return ERR_NONE;
488}
489
490static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone)
491{
492 GSM_RingNoteScale DefNoteScale= Scale_880;
493 GSM_RingNoteDuration DefNoteDuration= Duration_1_4;
494 GSM_RingNoteStyle DefNoteStyle= NaturalStyle;
495 int DefNoteTempo= 63, i=0;
496
497 unsigned char buffer[2000],Name[100];
498 GSM_RingNote *Note;
499
500 fread(buffer, 2000, 1, file);
501
502 ringtone->NoteTone.NrCommands = 0;
503
504 /* -------------- name ---------------- */
505 while (buffer[i] != ':') {
506 if (buffer[i] == 0x00) return ERR_NONE;
507 i++;
508 }
509 if (i == 0) {
510 /* This is for RTTL ringtones without name. */
511 EncodeUnicode(ringtone->Name,"Gammu",5);
512 } else {
513 memcpy(Name,buffer,i);
514 Name[i] = 0x00;
515 EncodeUnicode(ringtone->Name,Name,strlen(Name));
516 }
517 i++;
518
519 /* --------- section with default ringtone settings ----------- */
520 while(1) {
521 switch (buffer[i]) {
522 case ':':
523 break;
524 case 0x00:
525 return ERR_NONE;
526 case 'd': case 'D':
527 switch (atoi(buffer+i+2)) {
528 case 1: DefNoteDuration = Duration_Full; break;
529 case 2: DefNoteDuration = Duration_1_2 ; break;
530 case 4: DefNoteDuration = Duration_1_4 ; break;
531 case 8: DefNoteDuration = Duration_1_8 ; break;
532 case 16: DefNoteDuration = Duration_1_16; break;
533 case 32: DefNoteDuration = Duration_1_32; break;
534 }
535 break;
536 case 'o': case 'O':
537 switch (atoi(buffer+i+2)) {
538 case 4: DefNoteScale = Scale_440 ; break;
539 case 5: DefNoteScale = Scale_880 ; break;
540 case 6: DefNoteScale = Scale_1760; break;
541 case 7: DefNoteScale = Scale_3520; break;
542 }
543 break;
544 case 'b': case 'B':
545 DefNoteTempo=atoi(buffer+i+2);
546 dbgprintf("Tempo = %i\n",DefNoteTempo);
547 break;
548 case 's': case 'S':
549 switch (buffer[i+1]) {
550 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
551 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
552 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
553 }
554 switch (buffer[i+2]) {
555 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
556 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
557 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
558 }
559 break;
560 }
561 while (buffer[i] != ':' && buffer[i] != ',') {
562 if (buffer[i] == 0x00) return ERR_NONE;
563 i++;
564 }
565 if (buffer[i] == ',') i++;
566 if (buffer[i] == ':') break;
567 }
568 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration);
569 dbgprintf("DefNoteScale=%d\n", DefNoteScale);
570 i++;
571
572 /* ------------------------- notes ------------------------------ */
573 while (buffer[i] != 0x00 && ringtone->NoteTone.NrCommands != MAX_RINGTONE_NOTES) {
574 switch(buffer[i]) {
575 case 'z': case 'Z':
576 switch (buffer[i+1]) {
577 case 'd':
578 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLED;
579 ringtone->NoteTone.NrCommands++;
580 break;
581 case 'D':
582 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLED;
583 ringtone->NoteTone.NrCommands++;
584 break;
585 case 'v':
586 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableVibra;
587 ringtone->NoteTone.NrCommands++;
588 break;
589 case 'V':
590 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableVibra;
591 ringtone->NoteTone.NrCommands++;
592 break;
593 case 'l':
594 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLight;
595 ringtone->NoteTone.NrCommands++;
596 break;
597 case 'L':
598 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLight;
599 ringtone->NoteTone.NrCommands++;
600 }
601 break;
602 case 'o': case 'O':
603 switch (buffer[i+2]) {
604 case 4: DefNoteScale = Scale_440 ; break;
605 case 5: DefNoteScale = Scale_880 ; break;
606 case 6: DefNoteScale = Scale_1760; break;
607 case 7: DefNoteScale = Scale_3520; break;
608 }
609 break;
610 case 's': case 'S':
611 switch (buffer[i+1]) {
612 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
613 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
614 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
615 }
616 switch (buffer[i+2]) {
617 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
618 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
619 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
620 }
621 break;
622 default:
623 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note;
624 Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note;
625 Note->Style = DefNoteStyle;
626 Note->Tempo = DefNoteTempo;
627 Note->Scale = DefNoteScale;
628 Note->Duration = DefNoteDuration;
629 Note->DurationSpec = NoSpecialDuration;
630 Note->Note = Note_Pause;
631
632 /* Duration */
633 switch (atoi(buffer+i)) {
634 case 1: Note->Duration = Duration_Full ; break;
635 case 2: Note->Duration = Duration_1_2 ; break;
636 case 4: Note->Duration = Duration_1_4 ; break;
637 case 8: Note->Duration = Duration_1_8 ; break;
638 case 16: Note->Duration = Duration_1_16 ; break;
639 case 32: Note->Duration = Duration_1_32 ; break;
640 }
641 /* We skip all numbers from duration specification */
642 while(isdigit(buffer[i])) i++;
643
644 /* Some files can have special duration here */
645 if (buffer[i]=='.') {
646 Note->DurationSpec = DottedNote;
647 i++;
648 }
649
650 /* Note */
651 /* B or b is not in specs, but I decided to put it, because
652 * it's in some RTTL files. It's the same to H note */
653 switch (buffer[i]) {
654 case 'A': case 'a': Note->Note = Note_A; break;
655 case 'B': case 'b': Note->Note = Note_H; break;
656 case 'C': case 'c': Note->Note = Note_C; break;
657 case 'D': case 'd': Note->Note = Note_D; break;
658 case 'E': case 'e': Note->Note = Note_E; break;
659 case 'F': case 'f': Note->Note = Note_F; break;
660 case 'G': case 'g': Note->Note = Note_G; break;
661 case 'H': case 'h': Note->Note = Note_H; break;
662 }
663 i++;
664
665 if (buffer[i]=='#') {
666 switch (Note->Note) {
667 case Note_A : Note->Note = Note_Ais; break;
668 case Note_C : Note->Note = Note_Cis; break;
669 case Note_D : Note->Note = Note_Dis; break;
670 case Note_F : Note->Note = Note_Fis; break;
671 case Note_G : Note->Note = Note_Gis; break;
672 default : break;
673 }
674 i++;
675 }
676
677 /* Some files can have special duration here */
678 if (buffer[i]=='.') {
679 Note->DurationSpec = DottedNote;
680 i++;
681 }
682
683 /* Scale */
684 if (Note->Note!=Note_Pause && isdigit(buffer[i])) {
685 switch (atoi(buffer+i)) {
686 case 4: Note->Scale = Scale_440 ; break;
687 case 5: Note->Scale = Scale_880 ; break;
688 case 6: Note->Scale = Scale_1760; break;
689 case 7: Note->Scale = Scale_3520; break;
690 }
691 i++;
692 }
693
694 ringtone->NoteTone.NrCommands++;
695 break;
696 }
697 while (buffer[i] != ',') {
698 if (buffer[i] == 0x00) return ERR_NONE;
699 i++;
700 }
701 if (buffer[i] == ',') i++;
702 }
703
704 return ERR_NONE;
705}
706
707static GSM_Error loadott(FILE *file, GSM_Ringtone *ringtone)
708{
709 char Buffer[2000];
710 int i;
711
712 i=fread(Buffer, 1, 2000, file);
713
714 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer, i);
715}
716
717static GSM_Error loadcommunicator(FILE *file, GSM_Ringtone *ringtone)
718{
719 char Buffer[4000];
720 int i,j;
721
722 i=fread(Buffer, 1, 4000, file);
723
724 i=0;j=0;
725 while (true) {
726 if (Buffer[j] ==0x00 && Buffer[j+1]==0x02 &&
727 Buffer[j+2]==0x4a && Buffer[j+3]==0x3a) break;
728 if (j==i-4) return ERR_UNKNOWN;
729 j++;
730 }
731 j++;
732
733 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer+j, i-j);
734}
735
736static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone)
737{
738 int i;
739 unsigned charbuffer[2000];
740
741 dbgprintf("loading binary\n");
742 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
743 i=5;
744 while (buffer[i]!=0x00) i++;
745 EncodeUnicode(ringtone->Name,buffer+5,i-5);
746 while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) {
747 i++;
748 }
749 ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i;
750 memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length);
751 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
752 return ERR_NONE;
753}
754
755static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone)
756{
757 unsigned char buffer[30000];
758
759 dbgprintf("loading midi\n");
760 EncodeUnicode(ringtone->Name,"MIDI",4);
761 ringtone->NokiaBinary.Length=fread(buffer, 1, 30000, file);
762 memcpy(ringtone->NokiaBinary.Frame,buffer,ringtone->NokiaBinary.Length);
763 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
764 return ERR_NONE;
765}
766
767static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone)
768{
769 unsigned char buffer[2000];
770
771 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
772
773 if (buffer[18]==0x00 && buffer[21]!=0x02) {
774 /* DCT3, Unicode subformat, 62xx & 7110 */
775 CopyUnicodeString(ringtone->Name,buffer+18);
776 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2);
777 memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length);
778 } else {
779 /* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */
780 EncodeUnicode(ringtone->Name,buffer+17,buffer[16]);
781 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name));
782 memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length);
783 }
784 dbgprintf("Name \"%s\"\n",DecodeUnicodeString(ringtone->Name));
785 return ERR_NONE;
786}
787
788GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
789{
790 FILE *file;
791 unsigned charbuffer[300];
792 GSM_Errorerror = ERR_UNKNOWN;
793
794 dbgprintf("Loading ringtone %s\n",FileName);
795 file = fopen(FileName, "rb");
796 if (file == NULL) return ERR_CANTOPENFILE;
797
798 /* Read the header of the file. */
799 fread(buffer, 1, 4, file);
800 if (ringtone->Format == 0x00) {
801 ringtone->Format = RING_NOTETONE;
802 if (buffer[0]==0x00 && buffer[1]==0x00 &&
803 buffer[2]==0x0C && buffer[3]==0x01) {
804 ringtone->Format = RING_NOKIABINARY;
805 }
806 if (buffer[0]==0x00 && buffer[1]==0x00 &&
807 buffer[2]==0x00) {
808 ringtone->Format = RING_NOKIABINARY;
809 }
810 if (buffer[0]==0x4D && buffer[1]==0x54 &&
811 buffer[2]==0x68 && buffer[3]==0x64) {
812 ringtone->Format = RING_MIDI;
813 }
814 }
815 rewind(file);
816 switch (ringtone->Format) {
817 case RING_NOTETONE:
818 if (buffer[0]==0x02 && buffer[1]==0x4A) {
819 error=loadott(file,ringtone);
820 } else if (buffer[0]==0xC7 && buffer[1]==0x45) {
821 error=loadcommunicator(file,ringtone);
822 } else {
823 error=loadrttl(file,ringtone);
824 }
825 ringtone->NoteTone.AllNotesScale=false;
826 break;
827 case RING_NOKIABINARY:
828 if (buffer[0]==0x00 && buffer[1]==0x00 &&
829 buffer[2]==0x0C && buffer[3]==0x01) {
830 error=loadbin(file,ringtone);
831 }
832 if (buffer[0]==0x00 && buffer[1]==0x00 &&
833 buffer[2]==0x00) {
834 error=loadre(file,ringtone);
835 }
836 break;
837 case RING_MIDI:
838 EncodeUnicode(ringtone->Name,FileName,strlen(FileName));
839 error = loadpuremidi(file,ringtone);
840 }
841 fclose(file);
842 return(error);
843}
844
845/* -------------------------- required with Nokia & RTTL ------------------- */
846
847/* Beats per Minute like written in Smart Messaging */
848static int SM_BeatsPerMinute[] = {
849 25, 28, 31, 35, 40, 45, 50, 56, 63,70,
850 80, 90, 100, 112, 125, 140, 160, 180, 200,225,
851 250, 285, 320, 355, 400, 450, 500, 565, 635,715,
852 800,900
853};
854
855int GSM_RTTLGetTempo(int Beats)
856{
857 int i=0;
858
859 while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++;
860
861 return i<<3;
862}
863
864/* This function packs the ringtone from the structure "ringtone" to
865 "package", where maxlength means length of package.
866 Function returns number of packed notes and change maxlength to
867 number of used chars in "package" */
868unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength)
869{
870 unsigned char CommandLength = 0x02;
871 unsigned char Loop = 0x15;/* Infinite */
872
873 unsigned char Buffer[200];
874 int StartBit=0, OldStartBit;
875 int StartBitHowManyCommands;
876 int HowManyCommands = 0;/* How many instructions packed */
877 int HowManyNotes= 0;
878 int i,j;
879 bool started;
880 GSM_RingNote *Note;
881
882 GSM_RingNoteScale DefScale = 255;
883 GSM_RingNoteStyle DefStyle = 255;
884 int DefTempo = 255;
885
886 AddBufferByte(package, &StartBit, CommandLength, 8);
887 AddBufferByte(package, &StartBit, SM_Command_RingingToneProgramming, 7);
888
889 /* According to specification we need have next part octet-aligned */
890 BufferAlign(package, &StartBit);
891
892 AddBufferByte(package, &StartBit, SM_Command_Sound, 7);
893 AddBufferByte(package, &StartBit, SM_Song_BasicSongType, 3);
894
895 /* Packing the name of the tune. */
896 EncodeUnicodeSpecialNOKIAChars(Buffer, ringtone.Name, UnicodeLength(ringtone.Name));
897 AddBufferByte(package, &StartBit, ((unsigned char)(UnicodeLength(Buffer)<<4)), 4);
898 AddBuffer(package, &StartBit, DecodeUnicodeString(Buffer), 8*UnicodeLength(Buffer));
899
900 /* Packing info about song pattern */
901 AddBufferByte(package, &StartBit, 0x01, 8); //one pattern
902 AddBufferByte(package, &StartBit, SM_InstructionID_PatternHeaderId, 3);
903 AddBufferByte(package, &StartBit, SM_PatternID_A_part, 2);
904 AddBufferByte(package, &StartBit, ((unsigned char)(Loop<<4)), 4);
905
906 /* Later here will be HowManyCommands */
907 StartBitHowManyCommands=StartBit;
908 StartBit = StartBit + 8;
909
910 started = false;
911 for (i=0; i<ringtone.NoteTone.NrCommands; i++) {
912 if (ringtone.NoteTone.Commands[i].Type != RING_Note) {
913 HowManyNotes++;
914 continue;
915 }
916 Note = &ringtone.NoteTone.Commands[i].Note;
917 if (!started) {
918 /* First note can't be Pause - it makes problems
919 * for example with PC Composer
920 */
921 if (Note->Note != Note_Pause) started = true;
922 }
923 if (!started) {
924 HowManyNotes++;
925 continue;
926 }
927 OldStartBit = StartBit;
928 /* we don't write Scale & Style info before "Pause" note - it saves place */
929 if (Note->Note!=Note_Pause) {
930 if (DefScale != Note->Scale || ringtone.NoteTone.AllNotesScale) {
931 j = StartBit+5+8;
932 BufferAlignNumber(&j);
933 if ((j/8)>(*maxlength)) {
934 StartBit = OldStartBit;
935 break;
936 }
937 DefScale = Note->Scale;
938 AddBufferByte(package, &StartBit, SM_InstructionID_ScaleInstructionId, 3);
939 AddBufferByte(package, &StartBit, ((unsigned char)((DefScale-4)<<6)), 2);
940 HowManyCommands++;
941 }
942 if (DefStyle != Note->Style) {
943 j = StartBit+5+8;
944 BufferAlignNumber(&j);
945 if ((j/8)>(*maxlength)) {
946 StartBit = OldStartBit;
947 break;
948 }
949 DefStyle = Note->Style;
950 AddBufferByte(package, &StartBit, SM_InstructionID_StyleInstructionId, 3);
951 AddBufferByte(package, &StartBit, ((unsigned char)DefStyle), 2);
952 HowManyCommands++;
953 }
954 }
955 /* Beats per minute/tempo of the tune */
956 if (DefTempo != GSM_RTTLGetTempo(Note->Tempo)) {
957 j = StartBit+8+8;
958 BufferAlignNumber(&j);
959 if ((j/8)>(*maxlength)) {
960 StartBit = OldStartBit;
961 break;
962 }
963 DefTempo=GSM_RTTLGetTempo(Note->Tempo);
964 /* Adding beats per minute (tempo) of the tune */
965 AddBufferByte(package, &StartBit, SM_InstructionID_TempoInstructionId, 3);
966 AddBufferByte(package, &StartBit, ((unsigned char)DefTempo), 5);
967 HowManyCommands++;
968 }
969 j = StartBit+12+8;
970 BufferAlignNumber(&j);
971 if ((j/8)>(*maxlength)) {
972 StartBit = OldStartBit;
973 break;
974 }
975 /* Note */
976 AddBufferByte(package, &StartBit, SM_InstructionID_NoteInstructionId, 3);
977 AddBufferByte(package, &StartBit, ((unsigned char)Note->Note), 4);
978 AddBufferByte(package, &StartBit, ((unsigned char)Note->Duration), 3);
979 AddBufferByte(package, &StartBit, ((unsigned char)Note->DurationSpec), 2);
980 HowManyCommands++;
981 /* We are sure, we pack it for SMS or setting to phone, not for OTT file */
982 if (*maxlength<1000) {
983 /* Like Pc Composer say - before of phone limitations...*/
984 if (HowManyNotes==130-1) break;
985 }
986 HowManyNotes++;
987 }
988
989 BufferAlign(package, &StartBit);
990 AddBufferByte(package, &StartBit, SM_CommandEnd_CommandEnd, 8);
991
992 OldStartBit = StartBit;
993 StartBit = StartBitHowManyCommands;
994 /* HowManyCommands */
995 AddBufferByte(package, &StartBit, ((unsigned char)HowManyCommands), 8);
996 StartBit = OldStartBit;
997
998 *maxlength=StartBit/8;
999
1000 return(i);
1001}
1002
1003GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, int maxlength)
1004{
1005 int StartBit=0, HowMany, l, q, i, spec;
1006 char Buffer[100];
1007 GSM_RingNote *Note;
1008
1009 /* Default ringtone parameters */
1010 GSM_RingNoteScale DefScale= Scale_880;
1011 GSM_RingNoteStyle DefStyle = NaturalStyle;
1012 int DefTempo= 63;
1013
1014 ringtone->Format = RING_NOTETONE;
1015 ringtone->NoteTone.NrCommands = 0;
1016
1017 GetBufferInt(package,&StartBit,&l,8);
1018 if (l!=0x02) {
1019 dbgprintf("Not header\n");
1020 return ERR_NOTSUPPORTED;
1021 }
1022
1023 GetBufferInt(package,&StartBit,&l,7);
1024 if (l!=SM_Command_RingingToneProgramming) {
1025 dbgprintf("Not RingingToneProgramming\n");
1026 return ERR_NOTSUPPORTED;
1027 }
1028
1029 /* According to specification we need have next part octet-aligned */
1030 BufferAlignNumber(&StartBit);
1031
1032 GetBufferInt(package,&StartBit,&l,7);
1033 if (l!=SM_Command_Sound) {
1034 dbgprintf("Not Sound\n");
1035 return ERR_NOTSUPPORTED;
1036 }
1037
1038 GetBufferInt(package,&StartBit,&l,3);
1039 if (l!=SM_Song_BasicSongType) {
1040 dbgprintf("Not BasicSongType\n");
1041 return ERR_NOTSUPPORTED;
1042 }
1043
1044 /* Getting length of the tune name */
1045 GetBufferInt(package,&StartBit,&l,4);
1046 l=l>>4;
1047
1048 /* Unpacking the name of the tune. */
1049 GetBuffer(package, &StartBit, Buffer, 8*l);
1050 Buffer[l]=0;
1051 EncodeUnicode(ringtone->Name,Buffer,strlen(Buffer));
1052 DecodeUnicodeSpecialNOKIAChars(Buffer, ringtone->Name, UnicodeLength(ringtone->Name));
1053 CopyUnicodeString(ringtone->Name,Buffer);
1054
1055 GetBufferInt(package,&StartBit,&l,8);
1056 dbgprintf("Number of song patterns: %i\n",l);
1057 /* we support only one song pattern */
1058 if (l!=1) return ERR_NOTSUPPORTED;
1059
1060 GetBufferInt(package,&StartBit,&l,3);
1061 if (l!=SM_InstructionID_PatternHeaderId) {
1062 dbgprintf("Not PatternHeaderId\n");
1063 return ERR_NOTSUPPORTED;
1064 }
1065
1066 /* Pattern ID - we ignore it */
1067 StartBit+=2;
1068
1069 GetBufferInt(package,&StartBit,&l,4);
1070 l=l>>4;
1071 dbgprintf("Loop value: %i\n",l);
1072
1073 HowMany=0;
1074 GetBufferInt(package, &StartBit, &HowMany, 8);
1075
1076 for (i=0;i<HowMany;i++) {
1077 GetBufferInt(package,&StartBit,&q,3);
1078 switch (q) {
1079 case SM_InstructionID_VolumeInstructionId:
1080 StartBit+=4;
1081 break;
1082 case SM_InstructionID_StyleInstructionId:
1083 GetBufferInt(package,&StartBit,&l,2);
1084 if (l>=NaturalStyle && l<=StaccatoStyle) DefStyle = l;
1085 break;
1086 case SM_InstructionID_TempoInstructionId:
1087 GetBufferInt(package,&StartBit,&l,5);
1088 DefTempo=SM_BeatsPerMinute[l>>3];
1089 break;
1090 case SM_InstructionID_ScaleInstructionId:
1091 GetBufferInt(package,&StartBit,&l,2);
1092 DefScale=(l>>6)+4;
1093 break;
1094 case SM_InstructionID_NoteInstructionId:
1095 Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note;
1096 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note;
1097
1098 GetBufferInt(package,&StartBit,&l,4);
1099 Note->Note=Note_Pause;
1100 if (l >= Note_C && l <= Note_H) Note->Note = l;
1101
1102 GetBufferInt(package,&StartBit,&l,3);
1103 if (l >= Duration_Full && l <= Duration_1_32) Note->Duration = l;
1104
1105 GetBufferInt(package,&StartBit,&spec,2);
1106 if (spec >= NoSpecialDuration && spec <= Length_2_3) {
1107 Note->DurationSpec = spec;
1108 }
1109
1110 Note->Scale = DefScale;
1111 Note->Style = DefStyle;
1112 Note->Tempo = DefTempo;
1113 if (ringtone->NoteTone.NrCommands==MAX_RINGTONE_NOTES) break;
1114 ringtone->NoteTone.NrCommands++;
1115 break;
1116 default:
1117 dbgprintf("Unsupported block %i %i\n",q,i);
1118 return ERR_NOTSUPPORTED;
1119 }
1120 }
1121 return ERR_NONE;
1122}
1123
1124static void RTTL2Binary(GSM_Ringtone *dest, GSM_Ringtone *src)
1125{
1126 int current = 0, i, note, lastnote = 0, duration;
1127 GSM_RingNote *Note;
1128 unsigned char end[] = {0x40, 0x7D, 0x40, 0x5C, 0x0A, 0xFE, 0x40,
1129 0x20, 0x40, 0x7D, 0x40, 0x37, 0x0A, 0xFE,
1130 0x0A, 0x0A, 0x40, 0x32, 0x07, 0x0B};
1131
1132 strcpy(dest->NokiaBinary.Frame+current,"\x02\xFC\x09");current=current+3;
1133 dest->NokiaBinary.Frame[current++]=0x00;
1134
1135 /*This command can be used to loop, where 0xLL = 0x01 - 0x10
1136 *0x01=loop once [...] 0x10=loop infinite
1137 *Commented now
1138
1139 dest->NokiaBinary.Frame[current++]=0x05;
1140 dest->NokiaBinary.Frame[current++]=0xLL;
1141 */
1142 strcpy(dest->NokiaBinary.Frame+current,"\x0A\x01");current=current+2;
1143
1144 for (i=0; i<src->NoteTone.NrCommands; i++) {
1145 if (src->NoteTone.Commands[i].Type != RING_Note) continue;
1146
1147 Note = &src->NoteTone.Commands[i].Note;
1148 note = 64; /* Pause */
1149 if (Note->Note!=Note_Pause) {
1150 if (Note->Note >= Note_C && Note->Note <= Note_H) {
1151 note = 113 + Note->Note/16;
1152 }
1153 switch (Note->Scale) {
1154 case Scale_440 : break;
1155 case Scale_880 : note = note + 12; break;
1156 case Scale_1760: note = note + 24;break;
1157 case Scale_3520: note = note + 36; break;
1158 default : break;
1159 }
1160 }
1161
1162 /* In 7110 we have 8 ms long sounds */
1163 duration = 60000 * GSM_RingNoteGetFullDuration(*Note) / Note->Tempo / 256;
1164
1165 switch (Note->Style) {
1166 case StaccatoStyle:
1167 if (duration) {
1168 /* Note needs only one sound */
1169 dest->NokiaBinary.Frame[current++] = note;
1170 dest->NokiaBinary.Frame[current++] = 1;
1171 duration--;
1172 }
1173 note = 0x40; /* The rest is pause */
1174 case NaturalStyle:
1175 if (note != 0x40 && duration) {
1176 dest->NokiaBinary.Frame[current++] = 0x40;
1177 /* There is small pause between notes */
1178 dest->NokiaBinary.Frame[current++] = 1;
1179 duration--;
1180 }
1181 default:
1182 if (note != 0x40 && note == lastnote && duration) {
1183 dest->NokiaBinary.Frame[current++] = 0x40;
1184 /* There is small pause between same notes */
1185 dest->NokiaBinary.Frame[current++] = 1;
1186 duration--;
1187 }
1188 while (duration > 125) {
1189 dest->NokiaBinary.Frame[current++] = note;
1190 dest->NokiaBinary.Frame[current++] = 125;
1191 duration -= 125;
1192 }
1193 dest->NokiaBinary.Frame[current++] = note;
1194 dest->NokiaBinary.Frame[current++] = duration;
1195 }
1196 lastnote = note;
1197 }
1198 for (i = 0; i < (int)sizeof(end); i++) dest->NokiaBinary.Frame[current++] = end[i];
1199 dest->NokiaBinary.Length=current;
1200}
1201
1202static void Binary2RTTL(GSM_Ringtone *dest, GSM_Ringtone *src)
1203{
1204 int i = 3, j, z, NrNotes = 0, repeat = 0, accuracy;
1205 int StartRepeat = 0, EndRepeat, Speed;
1206 unsigned char command,length=0;
1207 int NotesLen[500];
1208 GSM_RingNoteScale NotesScale[500];
1209 GSM_RingNoteNote Notes[500];
1210 int Lengths[6*4];
1211 GSM_RingNoteDurationSpec DurationSpec[6*4];
1212 GSM_RingNoteDuration Duration[6*4];
1213 bool foundlen;
1214 GSM_RingNote *Note;
1215
1216 while (i<src->NokiaBinary.Length) {
1217 command = src->NokiaBinary.Frame[i];
1218 i++;
1219 if (command != 0x06 && command != 0x00 && command != 0x09) {
1220 length = src->NokiaBinary.Frame[i];
1221 i++;
1222 dbgprintf("Block %02x %02x - ",length,command);
1223 } else dbgprintf("Block %02x - ",command);
1224 if (command >= 114 && command <= 161) {
1225 dbgprintf("note\n");
1226 if (command >= 114 && command <= 124) {
1227 NotesScale[NrNotes] = Scale_440; command -= 114;
1228 } else if (command >= 125 && command <= 137) {
1229 NotesScale[NrNotes] = Scale_880; command -= 126;
1230 } else if (command >= 138 && command <= 149) {
1231 NotesScale[NrNotes] = Scale_1760; command -= 138;
1232 } else if (command >= 150 && command <= 161) {
1233 NotesScale[NrNotes] = Scale_3520; command -= 150;
1234 }
1235 switch (command) {
1236 case 0 : Notes[NrNotes] = Note_C;break;
1237 case 1 : Notes[NrNotes] = Note_Cis;break;
1238 case 2 : Notes[NrNotes] = Note_D;break;
1239 case 3 : Notes[NrNotes] = Note_Dis;break;
1240 case 4 : Notes[NrNotes] = Note_E;break;
1241 case 5 : Notes[NrNotes] = Note_F;break;
1242 case 6 : Notes[NrNotes] = Note_Fis;break;
1243 case 7 : Notes[NrNotes] = Note_G;break;
1244 case 8 : Notes[NrNotes] = Note_Gis;break;
1245 case 9 : Notes[NrNotes] = Note_A;break;
1246 case 10 : Notes[NrNotes] = Note_Ais;break;
1247 case 11 : Notes[NrNotes] = Note_H;break;
1248 }
1249 if (NrNotes > 0) {
1250 if (Notes[NrNotes-1] == Notes[NrNotes] &&
1251 NotesScale[NrNotes-1] == NotesScale[NrNotes]) {
1252 NotesLen[NrNotes-1]+=length;
1253 } else {
1254 NotesLen[NrNotes]=length;
1255 NrNotes++;
1256 }
1257 } else {
1258 NotesLen[NrNotes]=length;
1259 NrNotes++;
1260 }
1261 } else switch (command) {
1262 case 0x00:
1263 dbgprintf("Unknown\n");
1264 break;
1265 case 0x05:
1266 dbgprintf("repeat %i times\n",length);
1267 repeat = length;
1268 StartRepeat = NrNotes;
1269 break;
1270 case 0x06:
1271 dbgprintf("end repeat\n");
1272 EndRepeat = NrNotes;
1273 for (z=0;z<repeat-1;z++) {
1274 for (j=StartRepeat;j<EndRepeat;j++) {
1275 Notes[NrNotes] = Notes[j];
1276 NotesScale[NrNotes] = NotesScale[j];
1277 NotesLen[NrNotes] = NotesLen[j];
1278 NrNotes++;
1279 dbgprintf("Adding repeat note %i %i\n",Notes[j],NotesLen[j]);
1280 }
1281 }
1282 break;
1283 case 0x07:
1284 if (length == 0x0B) {
1285 dbgprintf("Ringtone end\n");
1286 i = src->NokiaBinary.Length + 1;
1287 }
1288 break;
1289 case 0x09:
1290 dbgprintf("Unknown\n");
1291 break;
1292 case 0x0A:
1293 if (length == 0x01) {
1294 dbgprintf("Let's start our song\n");
1295 break;
1296 }
1297 if (length == 0x0A) {
1298 dbgprintf("Ending joining note\n");
1299 break;
1300 }
1301 if (length == 0xFE) {
1302 dbgprintf("Starting joining note\n");
1303 break;
1304 }
1305 break;
1306 case 0x40:
1307 dbgprintf("Pause\n");
1308 Notes[NrNotes] = Note_Pause;
1309 if (NrNotes > 0) {
1310 if (Notes[NrNotes-1] == Notes[NrNotes] &&
1311 NotesScale[NrNotes-1] == NotesScale[NrNotes]) {
1312 NotesLen[NrNotes-1]+=length;
1313 } else {
1314 NotesLen[NrNotes]=length;
1315 NrNotes++;
1316 }
1317 } else {
1318 NotesLen[NrNotes]=length;
1319 NrNotes++;
1320 }
1321 break;
1322 default:
1323 dbgprintf("Unknown\n");
1324 }
1325 }
1326
1327 while (NrNotes>0) {
1328 if (Notes[NrNotes-1] == Note_Pause) {
1329 NrNotes--;
1330 } else break;
1331 }
1332
1333 for (accuracy=1; accuracy<5; accuracy++) {
1334 i = 1;
1335 while (i < 1000) {
1336 Lengths[0] = 30000/i;
1337 for (j=0;j<5;j++) Lengths[j+1] = Lengths[j] / 2;
1338 for (j=0;j<6;j++) Lengths[6+j] = Lengths[j] * 3/2;
1339 for (j=0;j<6;j++) Lengths[12+j] = Lengths[j] * 9/4;
1340 for (j=0;j<6;j++) Lengths[18+j] = Lengths[j] * 2/3;
1341
1342#ifdef DEBUG
1343 dbgprintf("Length matrix (%i) : ",i);
1344 for (j=0;j<6*4;j++) dbgprintf("%i ",Lengths[j]);
1345 dbgprintf("\n");
1346#endif
1347 foundlen = false;
1348
1349 for (j=0;j<NrNotes;j++) {
1350 dbgprintf("Comparing to %i\n",NotesLen[j]);
1351 foundlen = false;
1352 for (z=0;z<6*4;z++) {
1353 if (NotesLen[j] - Lengths[z] > -accuracy &&
1354 NotesLen[j] - Lengths[z] < accuracy) {
1355 foundlen = true;
1356 break;
1357 }
1358 }
1359 if (!foundlen) break;
1360 }
1361 if (foundlen) break;
1362 i++;
1363 }
1364
1365 if (foundlen) {
1366 Speed = i;
1367 Duration[5] = Duration_1_32; Duration[4] = Duration_1_16;
1368 Duration[3] = Duration_1_8; Duration[2] = Duration_1_4;
1369 Duration[1] = Duration_1_2; Duration[0] = Duration_Full;
1370 for (i=0;i<6;i++) Duration[i] = Duration[i];
1371 for (i=0;i<6;i++) Duration[i+6] = Duration[i];
1372 for (i=0;i<6;i++) Duration[i+12] = Duration[i];
1373 for (i=0;i<6;i++) Duration[i+18] = Duration[i];
1374 for (i=0;i<6;i++) DurationSpec[i] = NoSpecialDuration;
1375 for (i=0;i<6;i++) DurationSpec[i+6] = DottedNote;
1376 for (i=0;i<6;i++) DurationSpec[i+12] = DoubleDottedNote;
1377 for (i=0;i<6;i++) DurationSpec[i+18] = Length_2_3;
1378
1379 for (i=0;i<NrNotes;i++) {
1380 dest->NoteTone.Commands[i].Type= RING_Note;
1381 Note = &dest->NoteTone.Commands[i].Note;
1382 Note->Note = Notes[i];
1383 Note->Tempo = Speed;
1384 Note->Style = ContinuousStyle;
1385 if (Notes[i] != Note_Pause) Note->Scale = NotesScale[i];
1386 for (z=0;z<6*4;z++) {
1387 if (NotesLen[i] - Lengths[z] > -accuracy &&
1388 NotesLen[i] - Lengths[z] < accuracy) {
1389 Note->Duration = Duration[z];
1390 Note->DurationSpec = DurationSpec[z];
1391 /* Trick from PPM Edit */
1392 if (Note->DurationSpec == DoubleDottedNote) {
1393 switch (Note->Duration) {
1394 case Duration_Full:Note->Duration = Duration_Full;break;
1395 case Duration_1_2 :Note->Duration = Duration_Full;break;
1396 case Duration_1_4 :Note->Duration = Duration_1_2; break;
1397 case Duration_1_8 :Note->Duration = Duration_1_4; break;
1398 case Duration_1_16:Note->Duration = Duration_1_8; break;
1399 case Duration_1_32:Note->Duration = Duration_1_16;break;
1400 }
1401 Note->DurationSpec = NoSpecialDuration;
1402 }
1403 /* Here happy creation */
1404 if (Note->DurationSpec == Length_2_3) {
1405 Note->DurationSpec = NoSpecialDuration;
1406 }
1407
1408 break;
1409 }
1410 }
1411 }
1412 dest->NoteTone.NrCommands = NrNotes;
1413 dbgprintf("speed = %i\n",Speed);
1414 break;
1415 }
1416 }
1417
1418 if (!foundlen) dest->NoteTone.NrCommands = 0;
1419}
1420
1421 GSM_Error GSM_RingtoneConvert(GSM_Ringtone *dest, GSM_Ringtone *src, GSM_RingtoneFormatFormat)
1422{
1423 dest->Format = Format;
1424 CopyUnicodeString(dest->Name,src->Name);
1425 if (src->Format==RING_NOTETONE && Format==RING_NOKIABINARY) {
1426 RTTL2Binary(dest, src);
1427 return ERR_NONE;
1428 }
1429 if (src->Format==RING_NOKIABINARY && Format==RING_NOTETONE) {
1430 Binary2RTTL(dest, src);
1431 return ERR_NONE;
1432 }
1433 /* The same source and target format */
1434 if (src->Format==Format) {
1435 memcpy(dest,src,sizeof(GSM_Ringtone));
1436 return ERR_NONE;
1437 }
1438 return ERR_NOTIMPLEMENTED;
1439}
1440
1441/* 0 = No header and footer, 0.5 = partial header and footer,
1442 * 1.0 = IMelody 1.0, 1.2 = IMelody 1.2 */
1443unsigned char GSM_EncodeEMSSound(GSM_Ringtone ringtone, unsigned char *package, int *maxlength, double version, bool start)
1444{
1445 int i, NrNotes = 0, Len, Max = *maxlength;
1446
1447 GSM_RingNote *Note;
1448
1449 GSM_RingNoteScaleDefNoteScale;
1450 GSM_RingNoteStyleDefNoteStyle=0;
1451 int DefNoteTempo=0;
1452
1453 bool started = false, end;
1454
1455 *maxlength = 0;
1456
1457 if (start) {
1458 if (version != 0) *maxlength+=sprintf(package,"BEGIN:IMELODY%c%c",13,10);
1459 if (version == 1.0) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.0%c%c",13,10);
1460 if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"VERSION:1.2%c%c",13,10);
1461 if (version >= 1.0) *maxlength+=sprintf(package+(*maxlength),"FORMAT:CLASS1.0%c%c",13,10);
1462 if (version == 1.2) *maxlength+=sprintf(package+(*maxlength),"NAME:%s%c%c",DecodeUnicodeString(ringtone.Name),13,10);
1463 }
1464
1465 DefNoteScale = Scale_880; /* by iMelody definition */
1466
1467 for (i=0;i<ringtone.NoteTone.NrCommands;i++) {
1468 Len = *maxlength;
1469 if (ringtone.NoteTone.Commands[i].Type != RING_Note) continue;
1470
1471 Note = &ringtone.NoteTone.Commands[i].Note;
1472 if (Note->Note == Note_Pause) continue;
1473
1474 if (version == 1.2 && start) {
1475 /* Save the default tempo */
1476 DefNoteTempo = Note->Tempo;
1477 Len+=sprintf(package+Len,"BEAT:%i%c%c",DefNoteTempo,13,10);
1478 dbgprintf("DefNoteTempo=%d\n",DefNoteTempo);
1479
1480 /* Save default style */
1481 DefNoteStyle = Note->Style;
1482 switch (DefNoteStyle) {
1483 case NaturalStyle :Len+=sprintf(package+Len,"STYLE:S0%c%c",13,10); break;
1484 case ContinuousStyle:Len+=sprintf(package+Len,"STYLE:S1%c%c",13,10); break;
1485 case StaccatoStyle :Len+=sprintf(package+Len,"STYLE:S2%c%c",13,10); break;
1486 }
1487 }
1488 Len+=sprintf(package+Len,"MELODY:");
1489 if (version != 0) {
1490 /* 15 = Len of END:IMELODY... */
1491 if ((Len+15) > Max) { end = true; break; }
1492 } else {
1493 if (Len > Max) { end = true; break; }
1494 }
1495 *maxlength = Len;
1496 break;
1497 }
1498
1499 for (i=0;i<ringtone.NoteTone.NrCommands;i++) {
1500 end = false;
1501 Len = *maxlength;
1502 switch (ringtone.NoteTone.Commands[i].Type) {
1503 case RING_Note:
1504 Note = &ringtone.NoteTone.Commands[i].Note;
1505 if (!started && Note->Note != Note_Pause) started = true;
1506 if (!started) break;
1507 if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) {
1508 Len+=sprintf(package+Len,"*%i",Note->Scale-1);
1509 }
1510 switch (Note->Note) {
1511 case Note_C :Len+=sprintf(package+Len,"c");break;
1512 case Note_Cis:Len+=sprintf(package+Len,"#c");break;
1513 case Note_D :Len+=sprintf(package+Len,"d");break;
1514 case Note_Dis:Len+=sprintf(package+Len,"#d");break;
1515 case Note_E :Len+=sprintf(package+Len,"e");break;
1516 case Note_F :Len+=sprintf(package+Len,"f");break;
1517 case Note_Fis:Len+=sprintf(package+Len,"#f");break;
1518 case Note_G :Len+=sprintf(package+Len,"g");break;
1519 case Note_Gis:Len+=sprintf(package+Len,"#g");break;
1520 case Note_A :Len+=sprintf(package+Len,"a");break;
1521 case Note_Ais:Len+=sprintf(package+Len,"#a");break;
1522 case Note_H :Len+=sprintf(package+Len,"b");break;
1523 case Note_Pause :Len+=sprintf(package+Len,"r");break;
1524 }
1525 switch (Note->Duration) {
1526 case Duration_Full : package[Len++]='0';break;
1527 case Duration_1_2 : package[Len++]='1';break;
1528 case Duration_1_4 : package[Len++]='2';break;
1529 case Duration_1_8 : package[Len++]='3';break;
1530 case Duration_1_16 : package[Len++]='4';break;
1531 case Duration_1_32 : package[Len++]='5';break;
1532 default : break;
1533 }
1534 switch (Note->DurationSpec) {
1535 case DottedNote : package[Len++] = '.'; break;
1536 case DoubleDottedNote: package[Len++] = ':'; break;
1537 case Length_2_3 : package[Len++] = ';'; break;
1538 default : break;
1539 }
1540 if (version != 0) {
1541 /* 15 = Len of END:IMELODY... */
1542 if ((Len+15) > Max) { end = true; break; }
1543 } else {
1544 if (Len > Max) { end = true; break; }
1545 }
1546 *maxlength = Len;
1547 break;
1548 case RING_DisableLED:
1549 if ((Len + 6) > Max) { end = true; break; }
1550 (*maxlength)+=sprintf(package+Len,"ledoff");
1551 break;
1552 case RING_EnableLED:
1553 if ((Len + 5) > Max) { end = true; break; }
1554 (*maxlength)+=sprintf(package+Len,"ledon");
1555 break;
1556 case RING_DisableVibra:
1557 if ((Len + 7) > Max) { end = true; break; }
1558 (*maxlength)+=sprintf(package+Len,"vibeoff");
1559 break;
1560 case RING_EnableVibra:
1561 if ((Len + 6) > Max) { end = true; break; }
1562 (*maxlength)+=sprintf(package+Len,"vibeon");
1563 break;
1564 case RING_DisableLight:
1565 if ((Len + 7) > Max) { end = true; break; }
1566 (*maxlength)+=sprintf(package+Len,"backoff");
1567 break;
1568 case RING_EnableLight:
1569 if ((Len + 6) > Max) { end = true; break; }
1570 (*maxlength)+=sprintf(package+Len,"backon");
1571 break;
1572 default:
1573 break;
1574 }
1575 if (end) break;
1576 NrNotes ++;
1577 }
1578
1579 if (version != 0) *maxlength+=sprintf(package+(*maxlength),"%c%cEND:IMELODY%c%c",13,10,13,10);
1580
1581 return NrNotes;
1582}
1583
1584char *GSM_GetRingtoneName(GSM_AllRingtonesInfo *Info, int ID)
1585{
1586 int i;
1587 static char ala[2];
1588
1589 for (i=0;i<Info->Number;i++) {
1590 if (Info->Ringtone[i].ID == ID) return Info->Ringtone[i].Name;
1591 }
1592
1593 ala[0] = 0;
1594 ala[1] = 0;
1595 return ala;
1596}
1597
1598/* How should editor hadle tabs in this file? Add editor commands here.
1599 * vim: noexpandtab sw=8 ts=8 sts=8:
1600 */
diff --git a/gammu/emb/common/service/gsmring.h b/gammu/emb/common/service/gsmring.h
new file mode 100644
index 0000000..207cf31
--- a/dev/null
+++ b/gammu/emb/common/service/gsmring.h
@@ -0,0 +1,202 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef __gsm_ring_h
4#define __gsm_ring_h
5
6/* --------------- Smart Messaging Specification 2.0 & 3.0 ----------------- */
7
8 #define SM_CommandEnd_CommandEnd 0x00
9
10/* specification gives also other */
11 #define SM_Command_RingingToneProgramming 0x25<<1
12 #define SM_Command_Sound 0x1d<<1
13/* specification gives also other */
14
15 #define SM_Song_BasicSongType 0x01<<5
16/* specification gives also other */
17
18 #define SM_PatternID_A_part 0x00<<6
19/* specification gives also other */
20
21 #define SM_InstructionID_PatternHeaderId 0x00<<5
22 #define SM_InstructionID_NoteInstructionId 0x01<<5
23 #define SM_InstructionID_ScaleInstructionId 0x02<<5
24 #define SM_InstructionID_StyleInstructionId 0x03<<5
25 #define SM_InstructionID_TempoInstructionId 0x04<<5
26 #define SM_InstructionID_VolumeInstructionId 0x05<<5
27
28/* ------ end of Smart Messaging Specification 2.0 & 3.0 definitions ------- */
29
30#define MAX_RINGTONE_NOTES 255
31
32typedef enum {
33 /**
34 * Natural style (rest between notes)
35 */
36 NaturalStyle = 0x00<<6,
37 /**
38 * Continuous style (no rest between notes)
39 */
40 ContinuousStyle = 0x01<<6,
41 /**
42 * Staccato style (shorter notes and longer rest period)
43 */
44 StaccatoStyle = 0x02<<6
45} GSM_RingNoteStyle;
46
47typedef enum {
48 Note_Pause = 0x00<<4,
49 Note_C = 0x01<<4,
50 Note_Cis = 0x02<<4,
51 Note_D = 0x03<<4,
52 Note_Dis = 0x04<<4,
53 Note_E = 0x05<<4,
54 Note_F = 0x06<<4,
55 Note_Fis = 0x07<<4,
56 Note_G = 0x08<<4,
57 Note_Gis = 0x09<<4,
58 Note_A = 0x0a<<4,
59 Note_Ais = 0x0b<<4,
60 Note_H = 0x0c<<4
61} GSM_RingNoteNote;
62
63typedef enum {
64 Duration_Full = 0x00<<5,
65 Duration_1_2 = 0x01<<5,
66 Duration_1_4 = 0x02<<5,
67 Duration_1_8 = 0x03<<5,
68 Duration_1_16 = 0x04<<5,
69 Duration_1_32 = 0x05<<5
70} GSM_RingNoteDuration;
71
72typedef enum {
73 NoSpecialDuration = 0x00<<6,
74 DottedNote = 0x01<<6,
75 DoubleDottedNote = 0x02<<6,
76 Length_2_3 = 0x03<<6
77} GSM_RingNoteDurationSpec;
78
79typedef enum {
80 Scale_55 = 1, /* 55 Hz for note A */
81 Scale_110, /* 110 Hz for note A */
82 Scale_220,
83 Scale_440, /* first scale for Nokia */
84 Scale_880,
85 Scale_1760,
86 Scale_3520, /* last scale for Nokia */
87 Scale_7040,
88 Scale_14080
89} GSM_RingNoteScale;
90
91typedef struct {
92 GSM_RingNoteDuration Duration;
93 GSM_RingNoteDurationSpec DurationSpec;
94 GSM_RingNoteNote Note;
95 GSM_RingNoteStyle Style;
96 GSM_RingNoteScale Scale;
97 int Tempo;
98} GSM_RingNote;
99
100typedef enum {
101 RING_Note = 1,
102 RING_EnableVibra,
103 RING_DisableVibra,
104 RING_EnableLight,
105 RING_DisableLight,
106 RING_EnableLED,
107 RING_DisableLED,
108 RING_Repeat
109} GSM_RingCommandType;
110
111typedef struct {
112 GSM_RingCommandType Type;
113 GSM_RingNote Note;
114 unsigned char Value;
115} GSM_RingCommand;
116
117typedef struct {
118 int NrCommands;
119 GSM_RingCommand Commands[MAX_RINGTONE_NOTES];
120 bool AllNotesScale;
121} GSM_NoteRingtone;
122
123/* Structure to hold Nokia binary ringtones. */
124typedef struct {
125 unsigned char Frame[30000];
126 int Length;
127} GSM_NokiaBinaryRingtone;
128
129typedef struct {
130 unsigned char *Frame;
131 int Length;
132} GSM_BinaryTone;
133
134typedef enum {
135 RING_NOTETONE = 1,
136 RING_NOKIABINARY,
137 RING_MIDI
138} GSM_RingtoneFormat;
139
140/**
141 * Structure for saving various ringtones formats
142 */
143typedef struct {
144 /**
145 * Ringtone saved in one of three formats
146 */
147 GSM_NokiaBinaryRingtone NokiaBinary;
148 GSM_BinaryTone BinaryTone;
149 GSM_NoteRingtone NoteTone;
150 /**
151 * Ringtone format
152 */
153 GSM_RingtoneFormat Format;
154 /**
155 * Ringtone name
156 */
157 char Name[20*2];
158 /**
159 * Ringtone location
160 */
161 int Location;
162} GSM_Ringtone;
163
164typedef struct {
165 int Group;//Nokia specific
166 int ID;
167 char Name[30*2];
168} GSM_RingtoneInfo;
169
170typedef struct {
171 int Number;
172 GSM_RingtoneInfo Ringtone[100];
173} GSM_AllRingtonesInfo;
174
175GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone);
176GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone);
177
178void saveott(FILE *file, GSM_Ringtone *ringtone);
179void savemid(FILE *file, GSM_Ringtone *ringtone);
180void saverng(FILE *file, GSM_Ringtone *ringtone);
181void saveimelody(FILE *file, GSM_Ringtone *ringtone);
182GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone);
183GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone);
184
185 unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength);
186 unsigned char GSM_EncodeEMSSound (GSM_Ringtone ringtone, unsigned char *package, int *maxlength, double version, bool start);
187
188 GSM_Error GSM_DecodeNokiaRTTLRingtone(GSM_Ringtone *ringtone, unsigned char *package, int maxlength);
189
190 GSM_Error GSM_RingtoneConvert(GSM_Ringtone *dest, GSM_Ringtone *src, GSM_RingtoneFormatFormat);
191
192 int GSM_RTTLGetTempo (int Beats);
193 int GSM_RingNoteGetFrequency(GSM_RingNote Note);
194 int GSM_RingNoteGetFullDuration(GSM_RingNote Note);
195
196char *GSM_GetRingtoneName(GSM_AllRingtonesInfo *Info, int ID);
197
198#endif
199
200/* How should editor hadle tabs in this file? Add editor commands here.
201 * vim: noexpandtab sw=8 ts=8 sts=8:
202 */
diff --git a/gammu/emb/common/service/sms/gsmems.c b/gammu/emb/common/service/sms/gsmems.c
new file mode 100644
index 0000000..a7e20f4
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmems.c
@@ -0,0 +1,765 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#include <ctype.h>
4#include <string.h>
5#include <time.h>
6
7#include "../../gsmcomon.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmcal.h"
10#include "../gsmpbk.h"
11#include "../gsmlogo.h"
12#include "../gsmring.h"
13#include "../gsmdata.h"
14#include "../gsmnet.h"
15#include "gsmsms.h"
16#include "gsmmulti.h"
17
18/* EMS Developers' Guidelines from www.sonyericsson.com
19 * docs from Alcatel
20 */
21 GSM_Error GSM_EncodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
22 GSM_MultiSMSMessage *SMS,
23 GSM_UDH UDHType)
24{
25 unsigned char Buffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
26 int i,UsedText,j,Length,Width,Height,z,x,y;
27 unsigned int Len;
28 int Used,FreeText,FreeBytes,Width2,CopiedText,CopiedSMSText;
29 unsigned char UDHID;
30 GSM_Bitmap Bitmap,Bitmap2;
31 GSM_Ringtone Ring;
32 GSM_Coding_Type Coding = SMS_Coding_Default;
33 GSM_Phone_Bitmap_TypesBitmapType;
34 MultiPartSMSEntry *Entry;
35 bool start;
36 GSM_DateTime Date;
37
38#ifdef DEBUG
39 if (UDHType != UDH_NoUDH) dbgprintf("linked EMS\n");
40#endif
41
42 if (Info->UnicodeCoding) Coding = SMS_Coding_Unicode;
43
44 /* Cleaning on the start */
45 for (i=0;i<MAX_MULTI_SMS;i++) {
46 GSM_SetDefaultSMSData(&SMS->SMS[i]);
47 SMS->SMS[i].UDH.Type = UDHType;
48 GSM_EncodeUDHHeader(&SMS->SMS[i].UDH);
49 SMS->SMS[i].Coding = Coding;
50 }
51
52 /* Packing */
53 for (i=0;i<Info->EntriesNum;i++) {
54 Entry = &Info->Entries[i];
55
56 switch (Entry->ID) {
57 case SMS_ConcatenatedTextLong:
58 case SMS_ConcatenatedTextLong16bit:
59 Len = 0;
60 while(1) {
61 if (Entry->Left || Entry->Right ||
62 Entry->Center || Entry->Large ||
63 Entry->Small || Entry->Bold ||
64 Entry->Italic || Entry->Underlined ||
65 Entry->Strikethrough) {
66 Buffer[0] = 0x0A;/* ID for text format */
67 Buffer[1] = 0x03; /* length of rest*/
68 Buffer[2] = 0x00; /* Position in EMS msg*/
69 Buffer[3] = 0x00; /* how many chars */
70 Buffer[4] = 0x00; /* formatting bits*/
71 if (Entry->Left) {
72 } else if (Entry->Right) {Buffer[4] |= 1;
73 } else if (Entry->Center) {Buffer[4] |= 2;
74 } else Buffer[4] |= 3;
75 if (Entry->Large) { Buffer[4] |= 4;
76 } else if (Entry->Small) {Buffer[4] |= 8;}
77 if (Entry->Bold) Buffer[4] |= 16;
78 if (Entry->Italic) Buffer[4] |= 32;
79 if (Entry->Underlined) Buffer[4] |= 64;
80 if (Entry->Strikethrough) Buffer[4] |= 128;
81 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5,true,&UsedText,&CopiedText,&CopiedSMSText);
82 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
83 if (FreeText == 0) continue;
84 }
85 GSM_AddSMS_Text_UDH(SMS,Coding,Entry->Buffer+Len*2,UnicodeLength(Entry->Buffer) - Len,false,&UsedText,&CopiedText,&CopiedSMSText);
86 if (Entry->Left || Entry->Right ||
87 Entry->Center || Entry->Large ||
88 Entry->Small || Entry->Bold ||
89 Entry->Italic || Entry->Underlined ||
90 Entry->Strikethrough) {
91 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3] = UsedText;
92 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-2] = CopiedSMSText;
93 }
94 Len += CopiedText;
95 if (Len == UnicodeLength(Entry->Buffer)) break;
96 dbgprintf("%i %i\n",Len,UnicodeLength(Entry->Buffer));
97 }
98 break;
99 case SMS_EMSPredefinedSound:
100 case SMS_EMSPredefinedAnimation:
101 if (Entry->ID == SMS_EMSPredefinedSound) {
102 Buffer[0] = 0x0B; /* ID for def.sound*/
103 } else {
104 Buffer[0] = 0x0D; /* ID for def.animation*/
105 }
106 Buffer[1] = 0x02; /* Length of rest */
107 Buffer[2] = 0x00; /* Position in EMS msg*/
108 Buffer[3] = Entry->Number; /* Number of anim.*/
109 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
110 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-2] = UsedText;
111 break;
112 case SMS_EMSSonyEricssonSound:
113 case SMS_EMSSound10:
114 case SMS_EMSSound12:
115 if (Entry->Protected) {
116 Buffer[0] = 0x17; /* ID for ODI */
117 Buffer[1] = 2; /* Length of rest */
118 Buffer[2] = 1; /* Number of protected objects */
119 Buffer[3] = 1; /* 1=Protected,0=Not protected */
120 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
121 }
122
123 Length = 128; /* 128 bytes is maximal length from specs */
124 switch (Entry->ID) {
125 case SMS_EMSSound10:
126 Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 1.0, true);
127 break;
128 case SMS_EMSSound12:
129 Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 1.2, true);
130 break;
131 case SMS_EMSSonyEricssonSound:
132 Entry->RingtoneNotes = GSM_EncodeEMSSound(*Entry->Ringtone, Buffer+3, &Length, 0, true);
133 break;
134 default:
135 break;
136 }
137
138 Buffer[0] = 0x0C; /* ID for EMS sound */
139 Buffer[1] = Length+1; /* Length of rest */
140 Buffer[2] = 0x00; /* Position in EMS msg */
141 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
142 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
143 break;
144 case SMS_EMSSonyEricssonSoundLong:
145 case SMS_EMSSound10Long:
146 case SMS_EMSSound12Long:
147 Ring = *Entry->Ringtone;
148
149 /* First check if we can use classic format */
150 Length = 128; /* 128 bytes is maximal length from specs */
151 switch (Entry->ID) {
152 case SMS_EMSSound10Long:
153 Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, true);
154 break;
155 case SMS_EMSSound12Long:
156 Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, true);
157 break;
158 case SMS_EMSSonyEricssonSoundLong:
159 Entry->RingtoneNotes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, true);
160 break;
161 default:
162 break;
163 }
164 if (Entry->RingtoneNotes == Ring.NoteTone.NrCommands) {
165 if (Entry->Protected) {
166 Buffer[0] = 0x17; /* ID for ODI */
167 Buffer[1] = 2; /* Length of rest */
168 Buffer[2] = 1; /* Number of protected objects */
169 Buffer[3] = 1; /* 1=Protected,0=Not protected */
170 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
171 }
172
173 Buffer[0] = 0x0C; /* ID for EMS sound */
174 Buffer[1] = Length+1; /* Length of rest */
175 Buffer[2] = 0x00; /* Position in EMS msg */
176 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
177 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
178 break;
179 }
180
181 /* Find free place in first SMS */
182 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
183 Length = FreeBytes - 3;
184 if (Entry->Protected) Length = Length - 4;
185 if (Length < 0) Length = 128;
186 if (Length > 128) Length = 128;
187
188 Ring = *Entry->Ringtone;
189
190 /* Checking number of SMS */
191 Used = 0;
192 FreeBytes = 0;
193 start = true;
194 while (1) {
195 if (FreeBytes != 0) {
196 z = 0;
197 for (j=FreeBytes;j<Ring.NoteTone.NrCommands;j++) {
198 Ring.NoteTone.Commands[z] = Ring.NoteTone.Commands[j];
199 z++;
200 }
201 Ring.NoteTone.NrCommands -= FreeBytes;
202 if (Ring.NoteTone.NrCommands == 0) break;
203 Length = 128; /* 128 bytes is maximal length from specs */
204 }
205 switch (Entry->ID) {
206 case SMS_EMSSound10Long:
207 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, start);
208 break;
209 case SMS_EMSSound12Long:
210 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, start);
211 break;
212 case SMS_EMSSonyEricssonSoundLong:
213 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, start);
214 break;
215 default:
216 break;
217 }
218 start = false;
219 Used++;
220 }
221 dbgprintf("Used SMS: %i\n",Used);
222
223 if (Entry->Protected) {
224 Buffer[0] = 0x17; /* ID for ODI */
225 Buffer[1] = 2; /* Length of rest */
226 Buffer[2] = Used+1; /* Number of protected objects */
227 Buffer[3] = 1; /* 1=Protected,0=Not protected */
228 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
229 }
230
231 /* Save UPI UDH */
232 Buffer[0] = 0x13; /* ID for UPI */
233 Buffer[1] = 1; /* Length of rest */
234 Buffer[2] = Used; /* Number of used parts*/
235 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3,true,&UsedText,&CopiedText,&CopiedSMSText);
236
237 /* Find free place in first SMS */
238 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
239 Length = FreeBytes - 3;
240 if (Length < 0) Length = 128;
241 if (Length > 128) Length = 128;
242
243 Ring = *Entry->Ringtone;
244
245 /* Saving */
246 FreeBytes = 0;
247 start = true;
248 while (1) {
249 if (FreeBytes != 0) {
250 z = 0;
251 for (j=FreeBytes;j<Ring.NoteTone.NrCommands;j++) {
252 Ring.NoteTone.Commands[z] = Ring.NoteTone.Commands[j];
253 z++;
254 }
255 Ring.NoteTone.NrCommands -= FreeBytes;
256 if (Ring.NoteTone.NrCommands == 0) break;
257 Length = 128; /* 128 bytes is maximal length from specs */
258 }
259 switch (Entry->ID) {
260 case SMS_EMSSound10Long:
261 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.0, start);
262 break;
263 case SMS_EMSSound12Long:
264 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 1.2, start);
265 break;
266 case SMS_EMSSonyEricssonSoundLong:
267 FreeBytes = GSM_EncodeEMSSound(Ring, Buffer+3, &Length, 0, start);
268 break;
269 default:
270 break;
271 }
272 Buffer[0] = 0x0C; /* ID for EMS sound */
273 Buffer[1] = Length+1; /* Length of rest */
274 Buffer[2] = 0x00; /* Position in EMS msg */
275 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,Length+3,true,&UsedText,&CopiedText,&CopiedSMSText);
276 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-Length-1] = UsedText;
277 start = false;
278 }
279
280 Entry->RingtoneNotes = Entry->Ringtone->NoteTone.NrCommands;
281
282 break;
283 case SMS_EMSAnimation:
284 if (Entry->Protected) {
285 Buffer[0] = 0x17; /* ID for ODI */
286 Buffer[1] = 2; /* Length of rest */
287 Buffer[2] = 1; /* Number of protected objects */
288 Buffer[3] = 1; /* 1=Protected,0=Not protected */
289 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
290 }
291
292 if (Entry->Bitmap->Bitmap[0].BitmapWidth > 8 || Entry->Bitmap->Bitmap[0].BitmapHeight > 8) {
293 BitmapType = GSM_EMSMediumPicture;/* Bitmap 16x16 */
294 Buffer[0] = 0x0E; /* ID for 16x16 animation */
295 } else {
296 BitmapType = GSM_EMSSmallPicture;/* Bitmap 8x8 */
297 Buffer[0] = 0x0F; /* ID for 8x8 animation */
298 }
299 Length = PHONE_GetBitmapSize(BitmapType,0,0);
300
301 Buffer[1] = Length*Entry->Bitmap->Number + 1; /* Length of rest */
302 Buffer[2] = 0x00; /* Position in EMS msg */
303 for (j=0;j<Entry->Bitmap->Number;j++) {
304 PHONE_EncodeBitmap(BitmapType, Buffer+3+j*Length, &Entry->Bitmap->Bitmap[j]);
305 }
306 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3+Length*Entry->Bitmap->Number,true,&UsedText,&CopiedText,&CopiedSMSText);
307 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-1-Length*Entry->Bitmap->Number] = UsedText;
308 break;
309 case SMS_EMSFixedBitmap:
310 if (Entry->Protected) {
311 Buffer[0] = 0x17; /* ID for ODI */
312 Buffer[1] = 2; /* Length of rest */
313 Buffer[2] = 1; /* Number of protected objects */
314 Buffer[3] = 1; /* 1=Protected,0=Not protected */
315 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
316 }
317
318 if (Entry->Bitmap->Bitmap[0].BitmapWidth > 16 || Entry->Bitmap->Bitmap[0].BitmapHeight > 16) {
319 BitmapType = GSM_EMSBigPicture; /* Bitmap 32x32 */
320 Buffer[0] = 0x10; /* ID for EMS bitmap*/
321 } else {
322 BitmapType = GSM_EMSMediumPicture; /* Bitmap 16x16 */
323 Buffer[0] = 0x11; /* ID for EMS bitmap*/
324 }
325 Length = PHONE_GetBitmapSize(BitmapType,0,0);
326 PHONE_GetBitmapWidthHeight(BitmapType, &Width, &Height);
327
328 Buffer[1] = Length + 1; /* Length of rest */
329 Buffer[2] = 0x00; /* Position in EMS msg*/
330 PHONE_EncodeBitmap(BitmapType,Buffer+3, &Entry->Bitmap->Bitmap[0]);
331 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
332 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-1-Length] = UsedText;
333 break;
334 case SMS_EMSVariableBitmapLong:
335 BitmapType = GSM_EMSVariablePicture;
336 Width = Entry->Bitmap->Bitmap[0].BitmapWidth;
337 Height = Entry->Bitmap->Bitmap[0].BitmapHeight;
338 Bitmap = Entry->Bitmap->Bitmap[0];
339
340 /* First check if we can use classical format */
341 while (1) {
342 /* Width should be multiply of 8 */
343 while (Width % 8 != 0) Width--;
344
345 /* specs */
346 if (Width <= 96 && Height <= 128) break;
347
348 Height--;
349 }
350 Length = PHONE_GetBitmapSize(BitmapType,Width,Height);
351 if (Length <= 128) {
352 if (Entry->Protected) {
353 Buffer[0] = 0x17; /* ID for ODI */
354 Buffer[1] = 2; /* Length of rest */
355 Buffer[2] = 1; /* Number of protected objects */
356 Buffer[3] = 1; /* 1=Protected,0=Not protected */
357 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
358 }
359
360 Buffer[0] = 0x12; /* ID for EMS bitmap*/
361 Buffer[1] = Length + 3; /* Length of rest */
362 Buffer[2] = 0x00; /* Position in EMS msg*/
363 Buffer[3] = Width/8; /* Bitmap width/8 */
364 Buffer[4] = Height; /* Bitmap height */
365
366 GSM_ResizeBitmap(&Bitmap, &Entry->Bitmap->Bitmap[0], Width, Height);
367#ifdef DEBUG
368 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
369#endif
370 PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap);
371 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
372 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
373 break;
374 }
375
376 /* Find free place in first SMS */
377 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
378 Used = 0;
379 Length = FreeBytes - 3;
380 if (Entry->Protected)Length = Length - 4;
381 if (Length < 0) Length = 128;
382 if (Length > 128) Length = 128;
383
384 /* Checking number of SMS */
385 FreeBytes = 0;
386 while (FreeBytes != Width) {
387 Width2 = 8;
388 while (FreeBytes + Width2 != Width) {
389 if (PHONE_GetBitmapSize(BitmapType,Width2+8,Height) > Length) break;
390
391 Width2 = Width2 + 8;
392 }
393 FreeBytes = FreeBytes + Width2;
394 Length = 128;
395 Used ++;
396 }
397 dbgprintf("Used SMS: %i\n",Used);
398
399 if (Entry->Protected) {
400 Buffer[0] = 0x17; /* ID for ODI */
401 Buffer[1] = 2; /* Length of rest */
402 Buffer[2] = Used+1; /* Number of protected objects */
403 Buffer[3] = 1; /* 1=Protected,0=Not protected */
404 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
405 }
406
407 /* Save UPI UDH */
408 Buffer[0] = 0x13; /* ID for UPI */
409 Buffer[1] = 1; /* Length of rest */
410 Buffer[2] = Used; /* Number of used parts*/
411
412 /* Find free place in first SMS */
413 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,3,true,&UsedText,&CopiedText,&CopiedSMSText);
414 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], &UsedText, &FreeText, &FreeBytes);
415 Length = FreeBytes - 3;
416 if (Length < 0) Length = 128;
417 if (Length > 128) Length = 128;
418
419#ifdef DEBUG
420 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
421#endif
422
423 /* Saving SMS */
424 FreeBytes = 0;
425 while (FreeBytes != Width) {
426 Width2 = 8;
427 while (FreeBytes + Width2 != Width) {
428 if (PHONE_GetBitmapSize(BitmapType,Width2+8,Height) > Length) break;
429
430 Width2 = Width2 + 8;
431 }
432
433 /* Copying part of bitmap to new structure */
434 Bitmap2.BitmapWidth = Width2;
435 Bitmap2.BitmapHeight = Height;
436 GSM_ClearBitmap(&Bitmap2);
437 for (x=0;x<Width2;x++) {
438 for (y=0;y<Height;y++) {
439 if (GSM_IsPointBitmap(&Bitmap,x+FreeBytes,y)) {
440 GSM_SetPointBitmap(&Bitmap2, x, y);
441 }
442 }
443 }
444#ifdef DEBUG
445 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap2);
446#endif
447
448 /* Adding new bitmap to SMS */
449 Length = PHONE_GetBitmapSize(BitmapType,Width2,Height);
450 Buffer[0] = 0x12; /* ID for EMS bitmap*/
451 Buffer[1] = Length + 3; /* Length of rest */
452 Buffer[2] = 0x00; /* Position in EMS msg*/
453 Buffer[3] = Width2/8; /* Bitmap width/8 */
454 Buffer[4] = Height; /* Bitmap height */
455 PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap2);
456 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
457 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
458
459 FreeBytes = FreeBytes + Width2;
460 Length = 128;
461 }
462 break;
463 case SMS_EMSVariableBitmap:
464 if (Entry->Protected) {
465 Buffer[0] = 0x17; /* ID for ODI */
466 Buffer[1] = 2; /* Length of rest */
467 Buffer[2] = 1; /* Number of protected objects */
468 Buffer[3] = 1; /* 1=Protected,0=Not protected */
469 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,4,true,&UsedText,&CopiedText,&CopiedSMSText);
470 }
471
472 BitmapType = GSM_EMSVariablePicture;
473 Width = Entry->Bitmap->Bitmap[0].BitmapWidth;
474 Height = Entry->Bitmap->Bitmap[0].BitmapHeight;
475
476 while (1) {
477 /* Width should be multiply of 8 */
478 while (Width % 8 != 0) Width--;
479
480 /* specs */
481 if (PHONE_GetBitmapSize(BitmapType,Width,Height) <= 128) break;
482
483 Height--;
484 }
485
486 Length = PHONE_GetBitmapSize(BitmapType,Width,Height);
487
488 Buffer[0] = 0x12; /* ID for EMS bitmap*/
489 Buffer[1] = Length + 3; /* Length of rest */
490 Buffer[2] = 0x00; /* Position in EMS msg*/
491 Buffer[3] = Width/8; /* Bitmap width/8 */
492 Buffer[4] = Height; /* Bitmap height */
493
494 GSM_ResizeBitmap(&Bitmap, &Entry->Bitmap->Bitmap[0], Width, Height);
495#ifdef DEBUG
496 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Bitmap);
497#endif
498 PHONE_EncodeBitmap(BitmapType,Buffer+5, &Bitmap);
499 GSM_AddSMS_Text_UDH(SMS,Coding,Buffer,5+Length,true,&UsedText,&CopiedText,&CopiedSMSText);
500 SMS->SMS[SMS->Number].UDH.Text[SMS->SMS[SMS->Number].UDH.Length-3-Length] = UsedText;
501 break;
502 default:
503 break;
504 }
505 }
506
507 SMS->Number++;
508
509 if (UDHType == UDH_ConcatenatedMessages) {
510 UDHID = GSM_MakeSMSIDFromTime();
511 for (i=0;i<SMS->Number;i++) {
512 SMS->SMS[i].UDH.Text[2+1] = UDHID;
513 SMS->SMS[i].UDH.Text[3+1] = SMS->Number;
514 SMS->SMS[i].UDH.Text[4+1] = i+1;
515 }
516 }
517 if (UDHType == UDH_ConcatenatedMessages16bit) {
518 UDHID = GSM_MakeSMSIDFromTime();
519 GSM_GetCurrentDateTime (&Date);
520 for (i=0;i<SMS->Number;i++) {
521 SMS->SMS[i].UDH.Text[2+1] = Date.Hour;
522 SMS->SMS[i].UDH.Text[3+1] = UDHID;
523 SMS->SMS[i].UDH.Text[4+1] = SMS->Number;
524 SMS->SMS[i].UDH.Text[5+1] = i+1;
525 }
526 }
527
528#ifdef DEBUG
529 dbgprintf("SMS number is %i\n",SMS->Number);
530 for (i=0;i<SMS->Number;i++) {
531 dbgprintf("UDH length %i\n",SMS->SMS[i].UDH.Length);
532 DumpMessage(di.df, di.dl, SMS->SMS[i].UDH.Text, SMS->SMS[i].UDH.Length);
533 dbgprintf("SMS length %i\n",UnicodeLength(SMS->SMS[i].Text)*2);
534 DumpMessage(di.df, di.dl, SMS->SMS[i].Text, UnicodeLength(SMS->SMS[i].Text)*2);
535 }
536#endif
537 return ERR_NONE;
538}
539
540static bool AddEMSText(GSM_SMSMessage *SMS, GSM_MultiPartSMSInfo *Info, int *Pos, int Len)
541{
542 int BufferLen;
543
544 if (Len==0) return true;
545
546 if (Info->Entries[Info->EntriesNum].ID!=SMS_ConcatenatedTextLong &&
547 Info->Entries[Info->EntriesNum].ID!=0) {
548 (Info->EntriesNum)++;
549 }
550 BufferLen = UnicodeLength(Info->Entries[Info->EntriesNum].Buffer)*2;
551 switch (SMS->Coding) {
552 case SMS_Coding_8bit:
553 // memcpy(Info->Entries[Info->EntriesNum].Buffer+BufferLen,SMS->Text+(*Pos),Len);
554 // BufferLen+=Len;
555 // (*Pos)+=Len;
556 break;
557 case SMS_Coding_Unicode:
558 case SMS_Coding_Default:
559 Info->Entries[Info->EntriesNum].Buffer = realloc(Info->Entries[Info->EntriesNum].Buffer, BufferLen + (Len * 2) + 2);
560 if (Info->Entries[Info->EntriesNum].Buffer == NULL) return false;
561 memcpy(Info->Entries[Info->EntriesNum].Buffer + BufferLen, SMS->Text + (*Pos) *2, Len * 2);
562 BufferLen += Len * 2;
563 break;
564 }
565 (*Pos)+=Len;
566 Info->Entries[Info->EntriesNum].Buffer[BufferLen]= 0;
567 Info->Entries[Info->EntriesNum].Buffer[BufferLen+1]= 0;
568 Info->Entries[Info->EntriesNum].ID = SMS_ConcatenatedTextLong;
569 return true;
570}
571
572 bool GSM_DecodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
573 GSM_MultiSMSMessage *SMS)
574{
575 int i, w, Pos, z, UPI = 1, width, height;
576 bool RetVal = false, NewPicture = true;
577 GSM_Phone_Bitmap_Types BitmapType;
578 GSM_Bitmap Bitmap,Bitmap2;
579
580 for (i=0;i<MAX_MULTI_SMS;i++) {
581 Info->Entries[i].ID = 0;
582 }
583
584 for (i=0;i<SMS->Number;i++) {
585 Pos = 0;
586 w= 1;
587 while (w < SMS->SMS[i].UDH.Length) {
588 if (Info->EntriesNum + 1 == MAX_MULTI_SMS) {
589 dbgprintf("Couldn't parse SMS, contains too many EMS parts!\n");
590 return false;
591 }
592 switch(SMS->SMS[i].UDH.Text[w]) {
593 case 0x00:
594 dbgprintf("UDH part - linked SMS with 8 bit ID\n");
595 break;
596 case 0x08:
597 dbgprintf("UDH part - linked SMS with 16 bit ID\n");
598 break;
599 // case 0x0A:
600 // dbgprintf("UDH part - EMS text formatting\n");
601 // break;
602 case 0x0B:
603 dbgprintf("UDH part - default EMS sound\n");
604 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
605 z = Pos;
606 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
607 }
608 if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
609 Info->Entries[Info->EntriesNum].Number = SMS->SMS[i].UDH.Text[w+3];
610 Info->Entries[Info->EntriesNum].ID = SMS_EMSPredefinedSound;
611 RetVal = true;
612 break;
613 // case 0x0C:
614 // dbgprintf("UDH part - EMS sound\n");
615 // break;
616 case 0x0D:
617 dbgprintf("UDH part - default EMS animation\n");
618 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
619 z = Pos;
620 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
621 }
622 if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
623 Info->Entries[Info->EntriesNum].Number = SMS->SMS[i].UDH.Text[w+3];
624 Info->Entries[Info->EntriesNum].ID = SMS_EMSPredefinedAnimation;
625 RetVal = true;
626 break;
627 case 0x0E:
628 case 0x0F:
629 if (SMS->SMS[i].UDH.Text[w] == 0x0E) {
630 dbgprintf("UDH part - EMS 16x16 animation\n");
631 BitmapType = GSM_EMSMediumPicture;
632 } else {
633 dbgprintf("UDH part - EMS 8x8 animation\n");
634 BitmapType = GSM_EMSSmallPicture;
635 }
636 dbgprintf("Position - %i\n",SMS->SMS[i].UDH.Text[w+2]);
637 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
638 z = Pos;
639 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
640 }
641 (Info->EntriesNum)++;
642 Info->Entries[Info->EntriesNum].ID = SMS_EMSAnimation;
643 Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
644 if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
645 Info->Entries[Info->EntriesNum].Bitmap->Number = 0;
646 for (z=0;z<((SMS->SMS[i].UDH.Text[w+1]-1)/PHONE_GetBitmapSize(BitmapType,0,0));z++) {
647 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[z].Type = GSM_PictureImage;
648 PHONE_DecodeBitmap(BitmapType,
649 SMS->SMS[i].UDH.Text + w + 3 + PHONE_GetBitmapSize(BitmapType,0,0) * z,
650 &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[z]);
651 Info->Entries[Info->EntriesNum].Bitmap->Number++;
652 }
653 RetVal = true;
654 break;
655 case 0x10:
656 case 0x11:
657 if (SMS->SMS[i].UDH.Text[w] == 0x10) {
658 dbgprintf("UDH part - EMS 32x32 picture\n");
659 BitmapType = GSM_EMSBigPicture;
660 } else {
661 dbgprintf("UDH part - EMS 16x16 picture\n");
662 BitmapType = GSM_EMSMediumPicture;
663 }
664 dbgprintf("Position - %i\n",SMS->SMS[i].UDH.Text[w+2]);
665 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
666 z = Pos;
667 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
668 }
669 if (Info->Entries[Info->EntriesNum].ID != 0) (Info->EntriesNum)++;
670 Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
671 if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
672 PHONE_DecodeBitmap(BitmapType,
673 SMS->SMS[i].UDH.Text + w + 3,
674 &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0]);
675 Info->Entries[Info->EntriesNum].Bitmap->Number = 1;
676 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[0] = 0;
677 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[1] = 0;
678 Info->Entries[Info->EntriesNum].ID = SMS_EMSFixedBitmap;
679 RetVal = true;
680 break;
681 case 0x12:
682 dbgprintf("UDH part - EMS variable width bitmap\n");
683 if (SMS->SMS[i].UDH.Text[w+2] > Pos) {
684 z = Pos;
685 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].UDH.Text[w+2]-z)) return false;
686 }
687 if (NewPicture) {
688 (Info->EntriesNum)++;
689 Info->Entries[Info->EntriesNum].Bitmap->Number = 0;
690 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = 0;
691 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = 0;
692 }
693 Bitmap.BitmapWidth = SMS->SMS[i].UDH.Text[w+3]*8;
694 Bitmap.BitmapHeight = SMS->SMS[i].UDH.Text[w+4];
695 Info->Entries[Info->EntriesNum].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
696 if (Info->Entries[Info->EntriesNum].Bitmap == NULL) return false;
697 if (NewPicture) {
698 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = Bitmap.BitmapWidth;
699 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = Bitmap.BitmapHeight;
700 PHONE_DecodeBitmap(GSM_EMSVariablePicture,
701 SMS->SMS[i].UDH.Text + w + 5,
702 &Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0]);
703 } else {
704 PHONE_DecodeBitmap(GSM_EMSVariablePicture,
705 SMS->SMS[i].UDH.Text + w + 5,
706 &Bitmap);
707 Bitmap2 = Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0];
708 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapWidth = Bitmap.BitmapWidth+Bitmap2.BitmapWidth;
709 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].BitmapHeight = Bitmap2.BitmapHeight;
710 for (width=0;width<Bitmap2.BitmapWidth;width++) {
711 for (height=0;height<Bitmap2.BitmapHeight;height++) {
712 if (GSM_IsPointBitmap(&Bitmap2, width, height)) {
713 GSM_SetPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width,height);
714 } else {
715 GSM_ClearPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width,height);
716 }
717 }
718 }
719 for (width=0;width<Bitmap.BitmapWidth;width++) {
720 for (height=0;height<Bitmap2.BitmapHeight;height++) {
721 if (GSM_IsPointBitmap(&Bitmap, width, height)) {
722 GSM_SetPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width+Bitmap2.BitmapWidth,height);
723 } else {
724 GSM_ClearPointBitmap(&Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0],width+Bitmap2.BitmapWidth,height);
725 }
726 }
727 }
728 }
729 if (UPI == 1) {
730 Info->Entries[Info->EntriesNum].Bitmap->Number = 1;
731 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[0] = 0;
732 Info->Entries[Info->EntriesNum].Bitmap->Bitmap[0].Text[1] = 0;
733 Info->Entries[Info->EntriesNum].ID = SMS_EMSVariableBitmap;
734 RetVal = true;
735 NewPicture = true;
736 dbgprintf("New variable picture\n");
737 } else {
738 NewPicture = false;
739 UPI--;
740 }
741 break;
742 case 0x13:
743 dbgprintf("UDH part - UPI\n");
744 dbgprintf("Value %i\n",SMS->SMS[i].UDH.Text[w+2]);
745 UPI = SMS->SMS[i].UDH.Text[w+2];
746 break;
747 case 0x17:
748 dbgprintf("UDH part - Object Distribution Indicator (Media Rights Protecting) ignored now\n");
749 break;
750 default:
751 dbgprintf("UDH part - block %02x\n",SMS->SMS[i].UDH.Text[w]);
752 Info->Unknown = true;
753 } /* switch */
754 w=w+SMS->SMS[i].UDH.Text[w+1]+2;
755 } /* while */
756 if (!AddEMSText(&SMS->SMS[i], Info, &Pos, SMS->SMS[i].Length-Pos)) return false;
757 RetVal = true;
758 }
759 if (RetVal) (Info->EntriesNum)++;
760 return RetVal;
761}
762
763/* How should editor hadle tabs in this file? Add editor commands here.
764 * vim: noexpandtab sw=8 ts=8 sts=8:
765 */
diff --git a/gammu/emb/common/service/sms/gsmems.h b/gammu/emb/common/service/sms/gsmems.h
new file mode 100644
index 0000000..6701d28
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmems.h
@@ -0,0 +1,20 @@
1/* (c) 2002-2003 by Marcin Wiacek */
2
3#ifndef __gsm_ems_h
4#define __gsm_ems_h
5
6#include "../../gsmcomon.h"
7#include "gsmmulti.h"
8
9 GSM_Error GSM_EncodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
10 GSM_MultiSMSMessage *SMS,
11 GSM_UDH UDHType);
12
13 bool GSM_DecodeEMSMultiPartSMS(GSM_MultiPartSMSInfo *Info,
14 GSM_MultiSMSMessage *SMS);
15
16#endif
17
18/* How should editor hadle tabs in this file? Add editor commands here.
19 * vim: noexpandtab sw=8 ts=8 sts=8:
20 */
diff --git a/gammu/emb/common/service/sms/gsmmulti.c b/gammu/emb/common/service/sms/gsmmulti.c
new file mode 100644
index 0000000..6c1cdcd
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmmulti.c
@@ -0,0 +1,1148 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#include <ctype.h>
4#include <string.h>
5#include <time.h>
6
7#include "../../gsmcomon.h"
8#include "../../misc/coding/coding.h"
9#include "../gsmcal.h"
10#include "../gsmpbk.h"
11#include "../gsmlogo.h"
12#include "../gsmring.h"
13#include "../gsmdata.h"
14#include "../gsmnet.h"
15#include "gsmsms.h"
16#include "gsmmulti.h"
17#include "gsmems.h"
18
19/* ----------------- Splitting SMS into parts ------------------------------ */
20
21unsigned char GSM_MakeSMSIDFromTime(void)
22{
23 GSM_DateTime Date;
24 unsigned charretval;
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}
36
37void GSM_Find_Free_Used_SMS2(GSM_Coding_Type Coding,GSM_SMSMessage SMS, int *UsedText, int *FreeText, int *FreeBytes)
38{
39 int UsedBytes;
40
41 switch (Coding) {
42 case SMS_Coding_Default:
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;
49 case SMS_Coding_Unicode:
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 }
61 dbgprintf("UDH len %i, UsedBytes %i, FreeText %i, UsedText %i, FreeBytes %i\n",SMS.UDH.Length,UsedBytes,*FreeText,*UsedText,*FreeBytes);
62}
63
64 GSM_Error GSM_AddSMS_Text_UDH(GSM_MultiSMSMessage *SMS,
65 GSM_Coding_Type Coding,
66 char *Buffer,
67 int BufferLen,
68 bool UDH,
69 int *UsedText,
70 int *CopiedText,
71 int *CopiedSMSText)
72{
73 int FreeText,FreeBytes,Copy,i,j;
74
75 dbgprintf("Checking used\n");
76 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes);
77
78 if (UDH) {
79 dbgprintf("Adding UDH\n");
80 if (FreeBytes - BufferLen <= 0) {
81 dbgprintf("Going to the new SMS\n");
82 SMS->Number++;
83 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes);
84 }
85 if (SMS->SMS[SMS->Number].UDH.Length == 0) {
86 SMS->SMS[SMS->Number].UDH.Length = 1;
87 SMS->SMS[SMS->Number].UDH.Text[0] = 0x00;
88 }
89 memcpy(SMS->SMS[SMS->Number].UDH.Text+SMS->SMS[SMS->Number].UDH.Length,Buffer,BufferLen);
90 SMS->SMS[SMS->Number].UDH.Length += BufferLen;
91 SMS->SMS[SMS->Number].UDH.Text[0] += BufferLen;
92 SMS->SMS[SMS->Number].UDH.Type = UDH_UserUDH;
93 dbgprintf("UDH added %i\n",BufferLen);
94 } else {
95 dbgprintf("Adding text\n");
96 if (FreeText == 0) {
97 dbgprintf("Going to the new SMS\n");
98 SMS->Number++;
99 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes);
100 }
101
102 Copy = FreeText;
103 dbgprintf("copy %i\n",Copy);
104 if (BufferLen < Copy) Copy = BufferLen;
105 dbgprintf("copy %i\n",Copy);
106
107 switch (Coding) {
108 case SMS_Coding_Default:
109 FindDefaultAlphabetLen(Buffer,&i,&j,FreeText);
110 dbgprintf("def length %i %i\n",i,j);
111 SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+i*2] = 0;
112 SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+i*2+1] = 0;
113 memcpy(SMS->SMS[SMS->Number].Text+UnicodeLength(SMS->SMS[SMS->Number].Text)*2,Buffer,i*2);
114 *CopiedText = i;
115 *CopiedSMSText = j;
116 SMS->SMS[SMS->Number].Length += i;
117 break;
118 case SMS_Coding_Unicode:
119 SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+Copy*2] = 0;
120 SMS->SMS[SMS->Number].Text[UnicodeLength(SMS->SMS[SMS->Number].Text)*2+Copy*2+1] = 0;
121 memcpy(SMS->SMS[SMS->Number].Text+UnicodeLength(SMS->SMS[SMS->Number].Text)*2,Buffer,Copy*2);
122 *CopiedText = *CopiedSMSText = Copy;
123 SMS->SMS[SMS->Number].Length += Copy;
124 break;
125 case SMS_Coding_8bit:
126 memcpy(SMS->SMS[SMS->Number].Text+SMS->SMS[SMS->Number].Length,Buffer,Copy);
127 SMS->SMS[SMS->Number].Length += Copy;
128 *CopiedText = *CopiedSMSText = Copy;
129 break;
130 }
131 dbgprintf("Text added\n");
132 }
133
134 dbgprintf("Checking on the end\n");
135 GSM_Find_Free_Used_SMS2(Coding,SMS->SMS[SMS->Number], UsedText, &FreeText, &FreeBytes);
136
137 return ERR_NONE;
138}
139
140 void GSM_MakeMultiPartSMS(GSM_MultiSMSMessage*SMS,
141 unsigned char *MessageBuffer,
142 int MessageLength,
143 GSM_UDH UDHType,
144 GSM_Coding_TypeCoding,
145 int Class,
146 unsigned char ReplaceMessage)
147{
148 int j,Len,UsedText,CopiedText,CopiedSMSText;
149 unsigned char UDHID;
150 GSM_DateTime Date;
151
152 Len = 0;
153 while(1) {
154 GSM_SetDefaultSMSData(&SMS->SMS[SMS->Number]);
155 SMS->SMS[SMS->Number].Class = Class;
156 SMS->SMS[SMS->Number].Coding = Coding;
157
158 SMS->SMS[SMS->Number].UDH.Type = UDHType;
159 GSM_EncodeUDHHeader(&SMS->SMS[SMS->Number].UDH);
160
161 if (Coding == SMS_Coding_8bit) {
162 GSM_AddSMS_Text_UDH(SMS,Coding,MessageBuffer+Len,MessageLength - Len,false,&UsedText,&CopiedText,&CopiedSMSText);
163 } else {
164 GSM_AddSMS_Text_UDH(SMS,Coding,MessageBuffer+Len*2,MessageLength - Len,false,&UsedText,&CopiedText,&CopiedSMSText);
165 }
166 Len += CopiedText;
167 dbgprintf("%i %i\n",Len,MessageLength);
168 if (Len == MessageLength) break;
169 if (SMS->Number == MAX_MULTI_SMS) break;
170 SMS->Number++;
171 }
172
173 SMS->Number++;
174
175 UDHID = GSM_MakeSMSIDFromTime();
176 GSM_GetCurrentDateTime (&Date);
177 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);
184 }
185 if (SMS->Number == 1) SMS->SMS[0].ReplaceMessage = ReplaceMessage;
186}
187
188/* Calculates number of SMS and number of left chars in SMS */
189 void GSM_SMSCounter(int MessageLength,
190 unsigned char *MessageBuffer,
191 GSM_UDH UDHType,
192 GSM_Coding_Type Coding,
193 int *SMSNum,
194 int *CharsLeft)
195{
196 int UsedText,FreeBytes;
197 GSM_MultiSMSMessage MultiSMS;
198
199 MultiSMS.Number = 0;
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;
203}
204
205/* Nokia Smart Messaging 3.0 */
206static void GSM_EncodeSMS30MultiPartSMS(GSM_MultiPartSMSInfo *Info,
207 char *Buffer, int *Length)
208{
209 int len;
210
211 /*SM version. Here 3.0*/
212 Buffer[(*Length)++] = 0x30;
213
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);
222 }
223 }
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) */
232 len = 196;
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;
237 }
238 }
239 if (Info->Entries[0].Bitmap != NULL) {
240 if (Info->Entries[0].ID == SMS_NokiaPictureImageLong) {
241 Buffer[(*Length)++] = SM30_OTA;
242 } else {
243 Buffer[(*Length)++] = SM30_SCREENSAVER;
244 }
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;
256 } else {
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);
263 }
264 }
265 }
266}
267
268/* Alcatel docs from www.alcatel.com/wap/ahead */
269 GSM_Error GSM_EncodeAlcatelMultiPartSMS(GSM_MultiSMSMessage *SMS,
270 unsigned char *Data,
271 int Len,
272 unsigned char *Name,
273 int Type)
274{
275 unsigned char buff[100],UDHID;
276 int p,i;
277 GSM_UDHHeaderMyUDH;
278
279 for (i=0;i<MAX_MULTI_SMS;i++) {
280 GSM_SetDefaultSMSData(&SMS->SMS[i]);
281 SMS->SMS[i].UDH.Type = UDH_UserUDH;
282 SMS->SMS[i].UDH.Text[1] = 0x80;/* Alcatel */
283 p = UnicodeLength(Name);
284 EncodeDefault(buff, Name, &p, true, NULL);
285 SMS->SMS[i].UDH.Text[2]= GSM_PackSevenBitsToEight(0, buff, SMS->SMS[i].UDH.Text+3, p) + 4;
286 SMS->SMS[i].UDH.Text[3]= GSM_PackSevenBitsToEight(0, buff, SMS->SMS[i].UDH.Text+3, p);
287 SMS->SMS[i].UDH.Text[4] = Type;
288 SMS->SMS[i].UDH.Text[5] = Len / 256;
289 SMS->SMS[i].UDH.Text[6] = Len % 256;
290 SMS->SMS[i].UDH.Text[0] = 6 + SMS->SMS[i].UDH.Text[3];
291 SMS->SMS[i].UDH.Length = SMS->SMS[i].UDH.Text[0] + 1;
292
293 if (Len > 140 - SMS->SMS[i].UDH.Length) {
294 MyUDH.Type = UDH_ConcatenatedMessages;
295 GSM_EncodeUDHHeader(&MyUDH);
296
297 memcpy(SMS->SMS[i].UDH.Text+SMS->SMS[i].UDH.Length,MyUDH.Text+1,MyUDH.Length-1);
298 SMS->SMS[i].UDH.Text[0] += MyUDH.Length-1;
299 SMS->SMS[i].UDH.Length += MyUDH.Length-1;
300 }
301
302 SMS->SMS[i].Coding = SMS_Coding_8bit;
303 SMS->SMS[i].Class = 1;
304 }
305
306 p = 0;
307 while (p != Len) {
308 i = 140-SMS->SMS[SMS->Number].UDH.Length;
309 if (Len - p < i) i = Len - p;
310 memcpy(SMS->SMS[SMS->Number].Text,Data+p,i);
311 p += i;
312 SMS->SMS[SMS->Number].Length = i;
313 SMS->Number++;
314
315 }
316
317 /* Linked sms UDH */
318 if (SMS->Number != 1) {
319 UDHID = GSM_MakeSMSIDFromTime();
320 for (i=0;i<SMS->Number;i++) {
321 SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-3] = UDHID;
322 SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-2] = SMS->Number;
323 SMS->SMS[i].UDH.Text[SMS->SMS[i].UDH.Length-1] = i+1;
324 }
325 }
326
327 return ERR_NONE;
328}
329
330/* Alcatel docs from www.alcatel.com/wap/ahead and other */
331 GSM_Error GSM_EncodeMultiPartSMS(GSM_MultiPartSMSInfo *Info,
332 GSM_MultiSMSMessage *SMS)
333{
334 unsigned charBuffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
335 unsigned charBuffer2[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
336 int Length = 0,smslen,i, Class = -1, j,p;
337 GSM_Errorerror;
338 GSM_Coding_Type Coding = SMS_Coding_8bit;
339 GSM_UDH UDH= UDH_NoUDH;
340 GSM_UDHHeader UDHHeader;
341 bool EMS= false;
342 int textnum = 0;
343
344 SMS->Number = 0;
345
346 if (Info->Entries[0].ID == SMS_AlcatelSMSTemplateName) {
347 Buffer[Length++] = 0x00; //number of elements
348 for (i=1;i<Info->EntriesNum;i++) {
349 switch (Info->Entries[i].ID) {
350 case SMS_EMSSound10:
351 case SMS_EMSSound12:
352 case SMS_EMSSonyEricssonSound:
353 case SMS_EMSSound10Long:
354 case SMS_EMSSound12Long:
355 case SMS_EMSSonyEricssonSoundLong:
356 case SMS_EMSVariableBitmap:
357 case SMS_EMSAnimation:
358 case SMS_EMSVariableBitmapLong:
359 break;
360 case SMS_EMSPredefinedSound:
361 Buffer[0]++;
362 Buffer[Length++] = 0x01; //type of data
363 Buffer[Length++] = 1 % 256;//len
364 Buffer[Length++] = 1 / 256; //len
365 Buffer[Length++] = Info->Entries[i].Number;
366 break;
367 case SMS_EMSPredefinedAnimation:
368 Buffer[0]++;
369 Buffer[Length++] = 0x02; //type of data
370 Buffer[Length++] = 1 % 256;//len
371 Buffer[Length++] = 1 / 256; //len
372 Buffer[Length++] = Info->Entries[i].Number;
373 break;
374 case SMS_ConcatenatedTextLong:
375 Buffer[0]++;
376 p = UnicodeLength(Info->Entries[i].Buffer);
377 EncodeDefault(Buffer2, Info->Entries[i].Buffer, &p, true, NULL);
378 Buffer[Length++] = 0x00; //type of data
379 Length = Length + 2;
380 smslen = GSM_PackSevenBitsToEight(0, Buffer2, Buffer+Length, p);
381 Buffer[Length-2] = smslen % 256; //len
382 Buffer[Length-1] = smslen / 256; //len
383 Length = Length + smslen;
384 break;
385 default:
386 return ERR_UNKNOWN;
387 }
388 }
389 Buffer[0] = Buffer[0] * 2;
390 return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Buffer,ALCATELTDD_SMSTEMPLATE);
391 }
392
393 for (i=0;i<Info->EntriesNum;i++) {
394 switch (Info->Entries[i].ID) {
395 case SMS_EMSPredefinedAnimation:
396 case SMS_EMSPredefinedSound:
397 case SMS_EMSSound10:
398 case SMS_EMSSound12:
399 case SMS_EMSSonyEricssonSound:
400 case SMS_EMSSound10Long:
401 case SMS_EMSSound12Long:
402 case SMS_EMSSonyEricssonSoundLong:
403 case SMS_EMSFixedBitmap:
404 case SMS_EMSVariableBitmap:
405 case SMS_EMSAnimation:
406 case SMS_EMSVariableBitmapLong:
407 EMS = true;
408 break;
409 case SMS_ConcatenatedTextLong:
410 case SMS_ConcatenatedTextLong16bit:
411
412 /* This covers situation, when somebody will call function
413 * with two or more SMS_Concatenated.... entries only.
414 * It will be still only linked sms, but functions below
415 * will pack only first entry according to own limits.
416 * We redirect to EMS functions, because they are more generic
417 * here and will handle it correctly and produce linked sms
418 * from all entries
419 */
420 textnum ++;
421 if (textnum > 1) EMS = true;
422
423 if (Info->Entries[i].Left || Info->Entries[i].Right ||
424 Info->Entries[i].Center || Info->Entries[i].Large ||
425 Info->Entries[i].Small || Info->Entries[i].Bold ||
426 Info->Entries[i].Italic || Info->Entries[i].Underlined ||
427 Info->Entries[i].Strikethrough) {
428 EMS = true;
429 }
430 default:
431 break;
432 }
433 if (EMS) break;
434 }
435 if (EMS) {
436 error=GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_NoUDH);
437 if (error != ERR_NONE) return error;
438 if (SMS->Number != 1) {
439 SMS->Number = 0;
440 for (i=0;i<Info->EntriesNum;i++) {
441 if (Info->Entries[i].ID == SMS_ConcatenatedTextLong16bit) {
442 return GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_ConcatenatedMessages);
443 }
444 }
445 return GSM_EncodeEMSMultiPartSMS(Info,SMS,UDH_ConcatenatedMessages16bit);
446 }
447 return error;
448 }
449
450 if (Info->EntriesNum != 1) return ERR_UNKNOWN;
451
452 switch (Info->Entries[0].ID) {
453 case SMS_AlcatelMonoBitmapLong:
454 Buffer[0] = Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth;
455 Buffer[1] = Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight;
456 PHONE_EncodeBitmap(GSM_AlcatelBMMIPicture, Buffer+2, &Info->Entries[0].Bitmap->Bitmap[0]);
457 Length = PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight)+2;
458 return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Bitmap->Bitmap[0].Text,ALCATELTDD_PICTURE);
459 case SMS_AlcatelMonoAnimationLong:
460 /* Number of sequence words */
461 Buffer[0] = (Info->Entries[0].Bitmap->Number+1) % 256;
462 Buffer[1] = (Info->Entries[0].Bitmap->Number+1) / 256;
463 /* Picture display time 1 second (1 = 100ms) */
464 Buffer[2] = 10 % 256;
465 Buffer[3] = 10 / 256 + 0xF0;
466
467 Length = 4;
468 j = 0;
469
470 /* Offsets to bitmaps */
471 for (i=0;i<Info->Entries[0].Bitmap->Number;i++) {
472 Buffer[Length++] = (4+j+Info->Entries[0].Bitmap->Number*2) % 256;
473 Buffer[Length++] = (4+j+Info->Entries[0].Bitmap->Number*2) / 256;
474 j += PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight)+2;
475 }
476
477 /* Bitmaps */
478 for (i=0;i<Info->Entries[0].Bitmap->Number;i++) {
479 Buffer[Length++] = Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth;
480 Buffer[Length++] = Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight;
481 PHONE_EncodeBitmap(GSM_AlcatelBMMIPicture, Buffer+Length, &Info->Entries[0].Bitmap->Bitmap[i]);
482 Length += PHONE_GetBitmapSize(GSM_AlcatelBMMIPicture,Info->Entries[0].Bitmap->Bitmap[i].BitmapWidth,Info->Entries[0].Bitmap->Bitmap[i].BitmapHeight);
483 }
484 return GSM_EncodeAlcatelMultiPartSMS(SMS,Buffer,Length,Info->Entries[0].Bitmap->Bitmap[0].Text,ALCATELTDD_ANIMATION);
485 case SMS_MMSIndicatorLong:
486 Class= 1;
487 UDH= UDH_MMSIndicatorLong;
488 GSM_EncodeMMSIndicatorSMSText(Buffer,&Length,*Info->Entries[0].MMSIndicator);
489 break;
490 case SMS_NokiaRingtoneLong:
491 case SMS_NokiaRingtone:
492 UDH= UDH_NokiaRingtone;
493 Class= 1;
494 /* 7 = length of UDH_NokiaRingtone UDH header */
495 Length = GSM_MAX_8BIT_SMS_LENGTH-7;
496 Info->Entries[0].RingtoneNotes = GSM_EncodeNokiaRTTLRingtone(*Info->Entries[0].Ringtone,Buffer,&Length);
497 if (Info->Entries[0].ID == SMS_NokiaRingtone) break;
498 if (Info->Entries[0].RingtoneNotes != Info->Entries[0].Ringtone->NoteTone.NrCommands) {
499 UDH = UDH_NokiaRingtoneLong;
500 Length = (GSM_MAX_8BIT_SMS_LENGTH-12)*3;
501 Info->Entries[0].RingtoneNotes = GSM_EncodeNokiaRTTLRingtone(*Info->Entries[0].Ringtone,Buffer,&Length);
502 }
503 break;
504 case SMS_NokiaOperatorLogoLong:
505 if (Info->Entries[0].Bitmap->Bitmap[0].BitmapWidth > 72 || Info->Entries[0].Bitmap->Bitmap[0].BitmapHeight > 14) {
506 UDH= UDH_NokiaOperatorLogoLong;
507 Class = 1;
508 NOKIA_EncodeNetworkCode(Buffer, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode);
509 Length = Length + 3;
510 NOKIA_CopyBitmap(GSM_Nokia7110OperatorLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length);
511 break;
512 }
513 case SMS_NokiaOperatorLogo:
514 UDH= UDH_NokiaOperatorLogo;
515 Class = 1;
516 NOKIA_EncodeNetworkCode(Buffer, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode);
517 Length = Length + 3;
518 NOKIA_CopyBitmap(GSM_NokiaOperatorLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length);
519 break;
520 case SMS_NokiaCallerLogo:
521 UDH= UDH_NokiaCallerLogo;
522 Class = 1;
523 NOKIA_CopyBitmap(GSM_NokiaCallerLogo, &Info->Entries[0].Bitmap->Bitmap[0], Buffer, &Length);
524 break;
525 case SMS_NokiaProfileLong:
526 case SMS_NokiaPictureImageLong:
527 case SMS_NokiaScreenSaverLong:
528 Class = 1;
529 UDH= UDH_NokiaProfileLong;
530 GSM_EncodeSMS30MultiPartSMS(Info,Buffer,&Length);
531 break;
532 case SMS_NokiaWAPBookmarkLong:
533 Class= 1;
534 NOKIA_EncodeWAPBookmarkSMSText(Buffer,&Length,Info->Entries[0].Bookmark);
535 /* 7 = length of UDH_NokiaWAP UDH header */
536 if (Length>(GSM_MAX_8BIT_SMS_LENGTH-7)) {
537 UDH=UDH_NokiaWAPLong;
538 } else {
539 UDH=UDH_NokiaWAP;
540 }
541 break;
542 case SMS_NokiaWAPSettingsLong:
543 Class= 1;
544 UDH= UDH_NokiaWAPLong;
545 NOKIA_EncodeWAPMMSSettingsSMSText(Buffer,&Length,Info->Entries[0].Settings,false);
546 break;
547 case SMS_NokiaMMSSettingsLong:
548 Class= 1;
549 UDH= UDH_NokiaWAPLong;
550 NOKIA_EncodeWAPMMSSettingsSMSText(Buffer,&Length,Info->Entries[0].Settings,true);
551 break;
552 case SMS_NokiaVCARD10Long:
553 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10);
554 /* is 1 SMS ? 8 = length of ..SCKE2 */
555 if (Length<=GSM_MAX_SMS_LENGTH-8) {
556 sprintf(Buffer,"//SCKE2 ");
557 Length = 8;
558 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10);
559 } else {
560 /* FIXME: It wasn't checked */
561 UDH = UDH_NokiaPhonebookLong;
562 }
563 Coding = SMS_Coding_Default;
564 memcpy(Buffer2,Buffer,Length);
565 EncodeUnicode(Buffer,Buffer2,Length);
566 break;
567 case SMS_NokiaVCARD21Long:
568 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21);
569 /* Is 1 SMS ? 12 = length of ..SCKL23F4 */
570 if (Length<=GSM_MAX_SMS_LENGTH-12) {
571 sprintf(Buffer,"//SCKL23F4%c%c",13,10);
572 Length = 12;
573 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21);
574 } else {
575 UDH = UDH_NokiaPhonebookLong;
576 /* Here can be also 8 bit coding */
577 }
578 Coding = SMS_Coding_Default;
579 memcpy(Buffer2,Buffer,Length);
580 EncodeUnicode(Buffer,Buffer2,Length);
581 break;
582 case SMS_VCARD10Long:
583 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard10);
584 if (Length>GSM_MAX_SMS_LENGTH) UDH = UDH_ConcatenatedMessages;
585 Coding = SMS_Coding_Default;
586 memcpy(Buffer2,Buffer,Length);
587 EncodeUnicode(Buffer,Buffer2,Length);
588 break;
589 case SMS_VCARD21Long:
590 GSM_EncodeVCARD(Buffer,&Length,Info->Entries[0].Phonebook,true,Nokia_VCard21);
591 if (Length>GSM_MAX_SMS_LENGTH) UDH = UDH_ConcatenatedMessages;
592 Coding = SMS_Coding_Default;
593 memcpy(Buffer2,Buffer,Length);
594 EncodeUnicode(Buffer,Buffer2,Length);
595 break;
596 case SMS_NokiaVCALENDAR10Long:
597 error=GSM_EncodeVCALENDAR(Buffer,&Length,Info->Entries[0].Calendar,true,Nokia_VCalendar);
598 if (error != ERR_NONE) return error;
599 /* Is 1 SMS ? 8 = length of ..SCKE4 */
600 if (Length<=GSM_MAX_SMS_LENGTH-8) {
601 sprintf(Buffer,"//SCKE4 ");
602 Length = 8;
603 GSM_EncodeVCALENDAR(Buffer,&Length,Info->Entries[0].Calendar,true,Nokia_VCalendar);
604 } else {
605 UDH = UDH_NokiaCalendarLong;
606 /* can be here 8 bit coding ? */
607 }
608 Coding = SMS_Coding_Default;
609 memcpy(Buffer2,Buffer,Length);
610 EncodeUnicode(Buffer,Buffer2,Length);
611 break;
612 case SMS_NokiaVTODOLong:
613 error=GSM_EncodeVTODO(Buffer,&Length,Info->Entries[0].ToDo,true,Nokia_VToDo);
614 if (error != ERR_NONE) return error;
615 UDH = UDH_NokiaCalendarLong;
616 Coding = SMS_Coding_Default;
617 memcpy(Buffer2,Buffer,Length);
618 EncodeUnicode(Buffer,Buffer2,Length);
619 break;
620 case SMS_DisableVoice:
621 case SMS_DisableFax:
622 case SMS_DisableEmail:
623 case SMS_EnableVoice:
624 case SMS_EnableFax:
625 case SMS_EnableEmail:
626 case SMS_VoidSMS:
627 case SMS_Text:
628 Class = Info->Class;
629 switch (Info->Entries[0].ID) {
630 case SMS_DisableVoice: UDH = UDH_DisableVoice; break;
631 case SMS_DisableFax : UDH = UDH_DisableFax; break;
632 case SMS_DisableEmail: UDH = UDH_DisableEmail; break;
633 case SMS_EnableVoice: UDH = UDH_EnableVoice; break;
634 case SMS_EnableFax : UDH = UDH_EnableFax; break;
635 case SMS_EnableEmail: UDH = UDH_EnableEmail; break;
636 case SMS_VoidSMS : UDH = UDH_VoidSMS; break;
637 case SMS_Text : UDH = UDH_NoUDH; break;
638 default : break;
639 }
640 UDHHeader.Type = UDH;
641 GSM_EncodeUDHHeader(&UDHHeader);
642 memcpy(Buffer,Info->Entries[0].Buffer,UnicodeLength(Info->Entries[0].Buffer)*2+2);
643 if (Info->UnicodeCoding) {
644 Coding = SMS_Coding_Unicode;
645 Length = UnicodeLength(Info->Entries[0].Buffer);
646 if (Length>(140-UDHHeader.Length)/2) Length = (140-UDHHeader.Length)/2;
647 } else {
648 Coding = SMS_Coding_Default;
649 FindDefaultAlphabetLen(Info->Entries[0].Buffer,&Length,&smslen,(GSM_MAX_8BIT_SMS_LENGTH-UDHHeader.Length)*8/7);
650 }
651 break;
652 case SMS_ConcatenatedAutoTextLong:
653 case SMS_ConcatenatedAutoTextLong16bit:
654 smslen = UnicodeLength(Info->Entries[0].Buffer);
655 memcpy(Buffer,Info->Entries[0].Buffer,smslen*2);
656 EncodeDefault(Buffer2, Buffer, &smslen, true, NULL);
657 DecodeDefault(Buffer, Buffer2, smslen, true, NULL);
658#ifdef DEBUG
659 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) {
660 dbgprintf("Info->Entries[0].Buffer:\n");
661 DumpMessage(di.df, di.dl, Info->Entries[0].Buffer, UnicodeLength(Info->Entries[0].Buffer)*2);
662 dbgprintf("Buffer:\n");
663 DumpMessage(di.df, di.dl, Buffer, UnicodeLength(Buffer)*2);
664 }
665#endif
666 Info->UnicodeCoding = false;
667 for (smslen=0;smslen<(int)(UnicodeLength(Info->Entries[0].Buffer)*2);smslen++) {
668 if (Info->Entries[0].Buffer[smslen] != Buffer[smslen]) {
669 Info->UnicodeCoding = true;
670 dbgprintf("Setting to Unicode %i\n",smslen);
671 break;
672 }
673 }
674 /* No break here - we go to the SMS_ConcatenatedTextLong */
675 case SMS_ConcatenatedTextLong:
676 case SMS_ConcatenatedTextLong16bit:
677 Class = Info->Class;
678 memcpy(Buffer,Info->Entries[0].Buffer,UnicodeLength(Info->Entries[0].Buffer)*2+2);
679 UDH = UDH_NoUDH;
680 if (Info->UnicodeCoding) {
681 Coding = SMS_Coding_Unicode;
682 Length = UnicodeLength(Info->Entries[0].Buffer);
683 if (Info->Entries[0].ID == SMS_ConcatenatedTextLong16bit ||
684 Info->Entries[0].ID == SMS_ConcatenatedAutoTextLong16bit) {
685 if (Length>70) UDH=UDH_ConcatenatedMessages16bit;
686 } else {
687 if (Length>70) UDH=UDH_ConcatenatedMessages;
688 }
689 } else {
690 Coding = SMS_Coding_Default;
691 FindDefaultAlphabetLen(Info->Entries[0].Buffer,&Length,&smslen,5000);
692 if (Info->Entries[0].ID == SMS_ConcatenatedTextLong16bit ||
693 Info->Entries[0].ID == SMS_ConcatenatedAutoTextLong16bit) {
694 if (smslen>GSM_MAX_SMS_LENGTH) UDH=UDH_ConcatenatedMessages16bit;
695 } else {
696 if (smslen>GSM_MAX_SMS_LENGTH) UDH=UDH_ConcatenatedMessages;
697 }
698 }
699 default:
700 break;
701 }
702 GSM_MakeMultiPartSMS(SMS,Buffer,Length,UDH,Coding,Class,Info->ReplaceMessage);
703 return ERR_NONE;
704}
705
706void GSM_ClearMultiPartSMSInfo(GSM_MultiPartSMSInfo *Info)
707{
708 int i;
709
710 for (i=0;i<MAX_MULTI_SMS;i++) {
711 Info->Entries[i].Number = 0;
712 Info->Entries[i].Ringtone= NULL;
713 Info->Entries[i].Bitmap = NULL;
714 Info->Entries[i].Bookmark= NULL;
715 Info->Entries[i].Settings= NULL;
716 Info->Entries[i].MMSIndicator= NULL;
717 Info->Entries[i].Phonebook= NULL;
718 Info->Entries[i].Calendar= NULL;
719 Info->Entries[i].ToDo = NULL;
720 Info->Entries[i].Protected= false;
721
722 Info->Entries[i].Buffer = NULL;
723 Info->Entries[i].Left = false;
724 Info->Entries[i].Right = false;
725 Info->Entries[i].Center = false;
726 Info->Entries[i].Large = false;
727 Info->Entries[i].Small = false;
728 Info->Entries[i].Bold = false;
729 Info->Entries[i].Italic = false;
730 Info->Entries[i].Underlined= false;
731 Info->Entries[i].Strikethrough= false;
732
733 Info->Entries[i].RingtoneNotes= 0;
734 }
735 Info->Unknown = false;
736 Info->EntriesNum= 0;
737 Info->Class = -1;
738 Info->ReplaceMessage= 0;
739 Info->UnicodeCoding= false;
740}
741
742void GSM_FreeMultiPartSMSInfo(GSM_MultiPartSMSInfo *Info)
743{
744 int i;
745
746 for (i=0;i<MAX_MULTI_SMS;i++) {
747 free(Info->Entries[i].Ringtone);
748 Info->Entries[i].Ringtone = NULL;
749 free(Info->Entries[i].Bitmap);
750 Info->Entries[i].Bitmap = NULL;
751 free(Info->Entries[i].Bookmark);
752 Info->Entries[i].Bookmark = NULL;
753 free(Info->Entries[i].Settings);
754 Info->Entries[i].Settings = NULL;
755 free(Info->Entries[i].MMSIndicator);
756 Info->Entries[i].MMSIndicator = NULL;
757 free(Info->Entries[i].Phonebook);
758 Info->Entries[i].Phonebook = NULL;
759 free(Info->Entries[i].Calendar);
760 Info->Entries[i].Calendar = NULL;
761 free(Info->Entries[i].ToDo);
762 Info->Entries[i].ToDo = NULL;
763 free(Info->Entries[i].Buffer);
764 Info->Entries[i].Buffer = NULL;
765 }
766}
767
768/* ----------------- Joining SMS from parts -------------------------------- */
769
770 bool GSM_DecodeMultiPartSMS(GSM_MultiPartSMSInfo*Info,
771 GSM_MultiSMSMessage *SMS,
772 bool ems)
773{
774 int i, Length = 0;
775 charBuffer[GSM_MAX_SMS_LENGTH*2*MAX_MULTI_SMS];
776 bool emsexist = false;
777
778 GSM_ClearMultiPartSMSInfo(Info);
779 if (ems) {
780 emsexist = true;
781 for (i=0;i<SMS->Number;i++) {
782 if (SMS->SMS[i].UDH.Type != UDH_ConcatenatedMessages &&
783 SMS->SMS[i].UDH.Type != UDH_ConcatenatedMessages16bit &&
784 SMS->SMS[i].UDH.Type != UDH_UserUDH) {
785 emsexist = false;
786 break;
787 }
788 }
789 }
790
791 /* EMS decoding */
792 if (emsexist) return GSM_DecodeEMSMultiPartSMS(Info,SMS);
793
794 /* Smart Messaging decoding */
795 if (SMS->SMS[0].UDH.Type == UDH_NokiaRingtone && SMS->Number == 1) {
796 Info->Entries[0].Ringtone = (GSM_Ringtone *)malloc(sizeof(GSM_Ringtone));
797 if (Info->Entries[0].Ringtone == NULL) return false;
798 if (GSM_DecodeNokiaRTTLRingtone(Info->Entries[0].Ringtone, SMS->SMS[0].Text, SMS->SMS[0].Length)==ERR_NONE) {
799 Info->Entries[0].ID = SMS_NokiaRingtone;
800 Info->EntriesNum= 1;
801 return true;
802 }
803 }
804 if (SMS->SMS[0].UDH.Type == UDH_NokiaCallerLogo && SMS->Number == 1) {
805 Info->Entries[0].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
806 if (Info->Entries[0].Bitmap == NULL) return false;
807 Info->Entries[0].Bitmap->Number = 1;
808 PHONE_DecodeBitmap(GSM_NokiaCallerLogo, SMS->SMS[0].Text+4, &Info->Entries[0].Bitmap->Bitmap[0]);
809#ifdef DEBUG
810 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]);
811#endif
812 Info->Entries[0].ID = SMS_NokiaCallerLogo;
813 Info->EntriesNum= 1;
814 return true;
815 }
816 if (SMS->SMS[0].UDH.Type == UDH_NokiaOperatorLogo && SMS->Number == 1) {
817 Info->Entries[0].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
818 if (Info->Entries[0].Bitmap == NULL) return false;
819 Info->Entries[0].Bitmap->Number = 1;
820 PHONE_DecodeBitmap(GSM_NokiaOperatorLogo, SMS->SMS[0].Text+7, &Info->Entries[0].Bitmap->Bitmap[0]);
821 NOKIA_DecodeNetworkCode(SMS->SMS[0].Text, Info->Entries[0].Bitmap->Bitmap[0].NetworkCode);
822#ifdef DEBUG
823 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]);
824#endif
825 Info->Entries[0].ID = SMS_NokiaOperatorLogo;
826 Info->EntriesNum= 1;
827 return true;
828 }
829 if (SMS->SMS[0].UDH.Type == UDH_NokiaProfileLong) {
830 for (i=0;i<SMS->Number;i++) {
831 if (SMS->SMS[i].UDH.Type != UDH_NokiaProfileLong ||
832 SMS->SMS[i].UDH.Text[11] != i+1 ||
833 SMS->SMS[i].UDH.Text[10] != SMS->Number) {
834 return false;
835 }
836 memcpy(Buffer+Length,SMS->SMS[i].Text,SMS->SMS[i].Length);
837 Length = Length + SMS->SMS[i].Length;
838 }
839 Info->EntriesNum = 1;
840 Info->Entries[0].ID = SMS_NokiaPictureImageLong;
841 Info->Entries[0].Bitmap = (GSM_MultiBitmap *)malloc(sizeof(GSM_MultiBitmap));
842 if (Info->Entries[0].Bitmap == NULL) return false;
843 Info->Entries[0].Bitmap->Number = 1;
844 Info->Entries[0].Bitmap->Bitmap[0].Text[0] = 0;
845 Info->Entries[0].Bitmap->Bitmap[0].Text[1] = 0;
846 i=1;
847 while (i!=Length) {
848 switch (Buffer[i]) {
849 case SM30_ISOTEXT:
850 dbgprintf("ISO 8859-2 text\n");
851 Info->Unknown = true;
852 break;
853 case SM30_UNICODETEXT:
854 dbgprintf("Unicode text\n");
855 memcpy(Info->Entries[0].Bitmap->Bitmap[0].Text,Buffer+i+3,Buffer[i+1]*256+Buffer[i+2]);
856 Info->Entries[0].Bitmap->Bitmap[0].Text[Buffer[i+1]*256 + Buffer[i+2]] = 0;
857 Info->Entries[0].Bitmap->Bitmap[0].Text[Buffer[i+1]*256 + Buffer[i+2]+ 1] = 0;
858 dbgprintf("Unicode Text \"%s\"\n",DecodeUnicodeString(Info->Entries[0].Bitmap->Bitmap[0].Text));
859 break;
860 case SM30_OTA:
861 dbgprintf("OTA bitmap as Picture Image\n");
862 PHONE_DecodeBitmap(GSM_NokiaPictureImage, Buffer + i + 7, &Info->Entries[0].Bitmap->Bitmap[0]);
863#ifdef DEBUG
864 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]);
865#endif
866 break;
867 case SM30_RINGTONE:
868 dbgprintf("RTTL ringtone\n");
869 Info->Unknown = true;
870 break;
871 case SM30_PROFILENAME:
872 dbgprintf("Profile Name\n");
873 Info->Entries[0].ID = SMS_NokiaProfileLong;
874 Info->Unknown = true;
875 break;
876 case SM30_SCREENSAVER:
877 dbgprintf("OTA bitmap as Screen Saver\n");
878 PHONE_DecodeBitmap(GSM_NokiaPictureImage, Buffer + i + 7, &Info->Entries[0].Bitmap->Bitmap[0]);
879#ifdef DEBUG
880 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) GSM_PrintBitmap(di.df,&Info->Entries[0].Bitmap->Bitmap[0]);
881#endif
882 Info->Entries[0].ID = SMS_NokiaScreenSaverLong;
883 break;
884 }
885 i = i + Buffer[i+1]*256 + Buffer[i+2] + 3;
886 dbgprintf("%i %i\n",i,Length);
887 }
888 return true;
889 }
890
891 /* Linked sms */
892 if (SMS->SMS[0].UDH.Type == UDH_ConcatenatedMessages ||
893 SMS->SMS[0].UDH.Type == UDH_ConcatenatedMessages16bit) {
894 Info->EntriesNum = 1;
895 Info->Entries[0].ID = SMS_ConcatenatedTextLong;
896 if (SMS->SMS[0].UDH.Type == UDH_ConcatenatedMessages16bit) {
897 Info->Entries[0].ID = SMS_ConcatenatedTextLong16bit;
898 }
899
900 for (i=0;i<SMS->Number;i++) {
901 switch (SMS->SMS[i].Coding) {
902 case SMS_Coding_8bit:
903 Info->Entries[0].Buffer = realloc(Info->Entries[0].Buffer, Length + SMS->SMS[i].Length + 2);
904 if (Info->Entries[0].Buffer == NULL) return false;
905
906 memcpy(Info->Entries[0].Buffer + Length, SMS->SMS[i].Text, SMS->SMS[i].Length);
907 Length=Length+SMS->SMS[i].Length;
908 break;
909 case SMS_Coding_Unicode:
910 if (Info->Entries[0].ID == SMS_ConcatenatedTextLong) {
911 Info->Entries[0].ID = SMS_ConcatenatedAutoTextLong;
912 }
913 if (Info->Entries[0].ID == SMS_ConcatenatedTextLong16bit) {
914 Info->Entries[0].ID = SMS_ConcatenatedAutoTextLong16bit;
915 }
916 case SMS_Coding_Default:
917 Info->Entries[0].Buffer = realloc(Info->Entries[0].Buffer, Length + UnicodeLength(SMS->SMS[i].Text)*2 + 2);
918 if (Info->Entries[0].Buffer == NULL) return false;
919
920 memcpy(Info->Entries[0].Buffer+Length,SMS->SMS[i].Text,UnicodeLength(SMS->SMS[i].Text)*2);
921 Length=Length+UnicodeLength(SMS->SMS[i].Text)*2;
922 break;
923 }
924 }
925 Info->Entries[0].Buffer[Length] = 0;
926 Info->Entries[0].Buffer[Length+1] = 0;
927 return true;
928 }
929
930 return false;
931}
932
933GSM_Error GSM_LinkSMS(GSM_MultiSMSMessage **INPUT, GSM_MultiSMSMessage **OUTPUT, bool ems)
934{
935 bool *INPUTSorted, copyit;
936 int i,OUTPUTNum,j,z,w;
937
938 i = 0;
939 while (INPUT[i] != NULL) i++;
940
941 INPUTSorted = calloc(i, sizeof(bool));
942 if (INPUTSorted == NULL) return ERR_MOREMEMORY;
943
944 OUTPUTNum = 0;
945 OUTPUT[0] = NULL;
946
947 if (ems) {
948 i=0;
949 while (INPUT[i] != NULL) {
950 if (INPUT[i]->SMS[0].UDH.Type == UDH_UserUDH) {
951 w=1;
952 while (w < INPUT[i]->SMS[0].UDH.Length) {
953 switch(INPUT[i]->SMS[0].UDH.Text[w]) {
954 case 0x00:
955 dbgprintf("Adding ID to user UDH - linked SMS with 8 bit ID\n");
956 INPUT[i]->SMS[0].UDH.ID8bit= INPUT[i]->SMS[0].UDH.Text[w+2];
957 INPUT[i]->SMS[0].UDH.AllParts= INPUT[i]->SMS[0].UDH.Text[w+3];
958 INPUT[i]->SMS[0].UDH.PartNumber= INPUT[i]->SMS[0].UDH.Text[w+4];
959 break;
960 case 0x08:
961 dbgprintf("Adding ID to user UDH - linked SMS with 16 bit ID\n");
962 INPUT[i]->SMS[0].UDH.ID16bit= INPUT[i]->SMS[0].UDH.Text[w+2]*256+INPUT[i]->SMS[0].UDH.Text[w+3];
963 INPUT[i]->SMS[0].UDH.AllParts= INPUT[i]->SMS[0].UDH.Text[w+4];
964 INPUT[i]->SMS[0].UDH.PartNumber= INPUT[i]->SMS[0].UDH.Text[w+5];
965 break;
966 default:
967 dbgprintf("Block %02x\n",INPUT[i]->SMS[0].UDH.Text[w]);
968 }
969 dbgprintf("%i %i %i %i\n",
970 INPUT[i]->SMS[0].UDH.ID8bit,
971 INPUT[i]->SMS[0].UDH.ID16bit,
972 INPUT[i]->SMS[0].UDH.PartNumber,
973 INPUT[i]->SMS[0].UDH.AllParts);
974 w=w+INPUT[i]->SMS[0].UDH.Text[w+1]+2;
975 }
976 }
977 i++;
978 }
979 }
980
981 i=0;
982 while (INPUT[i]!=NULL) {
983 /* If this one SMS was sorted earlier, do not touch */
984 if (INPUTSorted[i]) {
985 i++;
986 continue;
987 }
988 copyit = false;
989 /* If we have:
990 * - linked sms returned by phone driver
991 * - sms without linking
992 * we copy it to OUTPUT
993 */
994 if (INPUT[i]->Number != 1 ||
995 INPUT[i]->SMS[0].UDH.Type == UDH_NoUDH ||
996 INPUT[i]->SMS[0].UDH.PartNumber == -1) {
997 copyit = true;
998 }
999 /* If we have unknown UDH, we copy it to OUTPUT */
1000 if (INPUT[i]->SMS[0].UDH.Type == UDH_UserUDH) {
1001 if (!ems) copyit = true;
1002 if (ems && INPUT[i]->SMS[0].UDH.PartNumber == -1) copyit = true;
1003 }
1004 if (copyit) {
1005 OUTPUT[OUTPUTNum] = malloc(sizeof(GSM_MultiSMSMessage));
1006 if (OUTPUT[OUTPUTNum] == NULL) {
1007 free(INPUTSorted);
1008 return ERR_MOREMEMORY;
1009 }
1010 OUTPUT[OUTPUTNum+1] = NULL;
1011
1012 memcpy(OUTPUT[OUTPUTNum],INPUT[i],sizeof(GSM_MultiSMSMessage));
1013 INPUTSorted[i]=true;
1014 OUTPUTNum++;
1015 i = 0;
1016 continue;
1017 }
1018 /* We have 1'st part of linked sms. It's single.
1019 * We will try to find other parts
1020 */
1021 if (INPUT[i]->SMS[0].UDH.PartNumber == 1) {
1022 OUTPUT[OUTPUTNum] = malloc(sizeof(GSM_MultiSMSMessage));
1023 if (OUTPUT[OUTPUTNum] == NULL) {
1024 free(INPUTSorted);
1025 return ERR_MOREMEMORY;
1026 }
1027 OUTPUT[OUTPUTNum+1] = NULL;
1028
1029 memcpy(&OUTPUT[OUTPUTNum]->SMS[0],&INPUT[i]->SMS[0],sizeof(GSM_SMSMessage));
1030 OUTPUT[OUTPUTNum]->Number = 1;
1031 INPUTSorted[i]= true;
1032 j = 1;
1033 /* We're searching for other parts in sequence */
1034 while (j!=INPUT[i]->SMS[0].UDH.AllParts) {
1035 z=0;
1036 while(INPUT[z]!=NULL) {
1037 /* This was sorted earlier or is not single */
1038 if (INPUTSorted[z] || INPUT[z]->Number != 1) {
1039 z++;
1040 continue;
1041 }
1042 if (ems && INPUT[i]->SMS[0].UDH.Type != UDH_ConcatenatedMessages &&
1043 INPUT[i]->SMS[0].UDH.Type != UDH_ConcatenatedMessages16bit &&
1044 INPUT[i]->SMS[0].UDH.Type != UDH_UserUDH &&
1045 INPUT[z]->SMS[0].UDH.Type != UDH_ConcatenatedMessages &&
1046 INPUT[z]->SMS[0].UDH.Type != UDH_ConcatenatedMessages16bit &&
1047 INPUT[z]->SMS[0].UDH.Type != UDH_UserUDH) {
1048 if (INPUT[z]->SMS[0].UDH.Type != INPUT[i]->SMS[0].UDH.Type) {
1049 z++;
1050 continue;
1051 }
1052 }
1053 if (!ems && INPUT[z]->SMS[0].UDH.Type != INPUT[i]->SMS[0].UDH.Type) {
1054 z++;
1055 continue;
1056 }
1057 dbgprintf("compare %i %i %i %i %i",
1058 j+1,
1059 INPUT[i]->SMS[0].UDH.ID8bit,
1060 INPUT[i]->SMS[0].UDH.ID16bit,
1061 INPUT[i]->SMS[0].UDH.PartNumber,
1062 INPUT[i]->SMS[0].UDH.AllParts);
1063 dbgprintf(" %i %i %i %i\n",
1064 INPUT[z]->SMS[0].UDH.ID8bit,
1065 INPUT[z]->SMS[0].UDH.ID16bit,
1066 INPUT[z]->SMS[0].UDH.PartNumber,
1067 INPUT[z]->SMS[0].UDH.AllParts);
1068 if (INPUT[z]->SMS[0].UDH.ID8bit != INPUT[i]->SMS[0].UDH.ID8bit||
1069 INPUT[z]->SMS[0].UDH.ID16bit != INPUT[i]->SMS[0].UDH.ID16bit||
1070 INPUT[z]->SMS[0].UDH.AllParts != INPUT[i]->SMS[0].UDH.AllParts ||
1071 INPUT[z]->SMS[0].UDH.PartNumber != j+1) {
1072 z++;
1073 continue;
1074 }
1075 /* For SMS_Deliver compare also SMSC and Sender number */
1076 if (INPUT[z]->SMS[0].PDU == SMS_Deliver &&
1077 (strcmp(DecodeUnicodeString(INPUT[z]->SMS[0].SMSC.Number),DecodeUnicodeString(INPUT[i]->SMS[0].SMSC.Number)) ||
1078 strcmp(DecodeUnicodeString(INPUT[z]->SMS[0].Number),DecodeUnicodeString(INPUT[i]->SMS[0].Number)))) {
1079 z++;
1080 continue;
1081 }
1082 /* DCT4 Outbox: SMS Deliver. Empty number and SMSC. We compare dates */
1083 if (INPUT[z]->SMS[0].PDU == SMS_Deliver &&
1084 UnicodeLength(INPUT[z]->SMS[0].SMSC.Number)==0 &&
1085 UnicodeLength(INPUT[z]->SMS[0].Number)==0 &&
1086 (INPUT[z]->SMS[0].DateTime.Day != INPUT[i]->SMS[0].DateTime.Day ||
1087 INPUT[z]->SMS[0].DateTime.Month != INPUT[i]->SMS[0].DateTime.Month ||
1088 INPUT[z]->SMS[0].DateTime.Year != INPUT[i]->SMS[0].DateTime.Year ||
1089 INPUT[z]->SMS[0].DateTime.Hour != INPUT[i]->SMS[0].DateTime.Hour ||
1090 INPUT[z]->SMS[0].DateTime.Minute != INPUT[i]->SMS[0].DateTime.Minute ||
1091 INPUT[z]->SMS[0].DateTime.Second != INPUT[i]->SMS[0].DateTime.Second)) {
1092 z++;
1093 continue;
1094 }
1095 /* We found correct sms. Copy it */
1096 memcpy(&OUTPUT[OUTPUTNum]->SMS[j],&INPUT[z]->SMS[0],sizeof(GSM_SMSMessage));
1097 OUTPUT[OUTPUTNum]->Number++;
1098 INPUTSorted[z]=true;
1099 break;
1100 }
1101 /* Incomplete sequence */
1102 if (OUTPUT[OUTPUTNum]->Number==j) {
1103 dbgprintf("Incomplete sequence\n");
1104 break;
1105 }
1106 j++;
1107 }
1108 OUTPUTNum++;
1109 i = 0;
1110 continue;
1111 }
1112 /* We have some next linked sms from sequence */
1113 if (INPUT[i]->SMS[0].UDH.PartNumber > 1) {
1114 j = 0;
1115 while (INPUT[j]!=NULL) {
1116 if (INPUTSorted[j]) {
1117 j++;
1118 continue;
1119 }
1120 /* We have some not unassigned first sms from sequence.
1121 * We can't touch other sms from sequences
1122 */
1123 if (INPUT[j]->SMS[0].UDH.PartNumber == 1) break;
1124 j++;
1125 }
1126 if (INPUT[j]==NULL) {
1127 OUTPUT[OUTPUTNum] = malloc(sizeof(GSM_MultiSMSMessage));
1128 if (OUTPUT[OUTPUTNum] == NULL) {
1129 free(INPUTSorted);
1130 return ERR_MOREMEMORY;
1131 }
1132 OUTPUT[OUTPUTNum+1] = NULL;
1133
1134 memcpy(OUTPUT[OUTPUTNum],INPUT[i],sizeof(GSM_MultiSMSMessage));
1135 INPUTSorted[i]=true;
1136 OUTPUTNum++;
1137 i = 0;
1138 continue;
1139 } else i++;
1140 }
1141 }
1142 free(INPUTSorted);
1143 return ERR_NONE;
1144}
1145
1146/* How should editor hadle tabs in this file? Add editor commands here.
1147 * vim: noexpandtab sw=8 ts=8 sts=8:
1148 */
diff --git a/gammu/emb/common/service/sms/gsmmulti.h b/gammu/emb/common/service/sms/gsmmulti.h
new file mode 100644
index 0000000..c672261
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmmulti.h
@@ -0,0 +1,271 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2
3#ifndef __gsm_multi_h
4#define __gsm_multi_h
5
6#include "../../gsmcomon.h"
7#include "../gsmlogo.h"
8#include "../gsmcal.h"
9#include "../gsmpbk.h"
10#include "../gsmdata.h"
11#include "../gsmring.h"
12#include "gsmsms.h"
13
14/* ---------------------- multi SMS --------------------------------------- */
15
16/* Identifiers for Smart Messaging 3.0 multipart SMS */
17
18#define SM30_ISOTEXT 0 /* ISO 8859-1 text */
19#define SM30_UNICODETEXT 1
20 #define SM30_OTA 2
21#define SM30_RINGTONE 3
22#define SM30_PROFILENAME 4
23/* ... */
24#define SM30_SCREENSAVER 6
25
26/* Identifiers for Alcatel Terminal Data Download */
27#define ALCATELTDD_PICTURE 4
28#define ALCATELTDD_ANIMATION 5
29#define ALCATELTDD_SMSTEMPLATE 6
30
31 void GSM_SMSCounter(int MessageLength,
32 unsigned char *MessageBuffer,
33 GSM_UDH UDHType,
34 GSM_Coding_Type Coding,
35 int *SMSNum,
36 int *CharsLeft);
37
38#define MAX_MULTI_SMS 10
39
40/**
41 * Multiple SMS messages, used for Smart Messaging 3.0/EMS.
42 */
43typedef struct {
44 /**
45 * Sender or recipient number.
46 */
47 unsigned char Number;
48 /**
49 * Array of SMSes.
50 */
51 GSM_SMSMessage SMS[MAX_MULTI_SMS];
52} GSM_MultiSMSMessage;
53
54GSM_Error GSM_AddSMS_Text_UDH(GSM_MultiSMSMessage *SMS,
55 GSM_Coding_Type Coding,
56 char *Buffer,
57 int BufferLen,
58 bool UDH,
59 int *UsedText,
60 int *CopiedText,
61 int *CopiedSMSText);
62
63void GSM_MakeMultiPartSMS(GSM_MultiSMSMessage *SMS,
64 unsigned char *MessageBuffer,
65 int MessageLength,
66 GSM_UDH UDHType,
67 GSM_Coding_Type Coding,
68 int Class,
69 unsigned char RejectDuplicates);
70
71void GSM_Find_Free_Used_SMS2(GSM_Coding_Type Coding,GSM_SMSMessage SMS, int *UsedText, int *FreeText, int *FreeBytes);
72
73unsigned char GSM_MakeSMSIDFromTime(void);
74
75/**
76 * ID during packing SMS for Smart Messaging 3.0, EMS and other
77 */
78typedef enum {
79 /**
80 * 1 text SMS.
81 */
82 SMS_Text = 1,
83 /**
84 * Contacenated SMS, when longer than 1 SMS.
85 */
86 SMS_ConcatenatedTextLong,
87 /**
88 * Contacenated SMS, auto Default/Unicode coding.
89 */
90 SMS_ConcatenatedAutoTextLong,
91 SMS_ConcatenatedTextLong16bit,
92 SMS_ConcatenatedAutoTextLong16bit,
93 /**
94 * Nokia profile = Name, Ringtone, ScreenSaver
95 */
96 SMS_NokiaProfileLong,
97 /**
98 * Nokia Picture Image + (text)
99 */
100 SMS_NokiaPictureImageLong,
101 /**
102 * Nokia screen saver + (text)
103 */
104 SMS_NokiaScreenSaverLong,
105 /**
106 * Nokia ringtone - old SM2.0 format, 1 SMS
107 */
108 SMS_NokiaRingtone,
109 /**
110 * Nokia ringtone contacenated, when very long
111 */
112 SMS_NokiaRingtoneLong,
113 /**
114 * Nokia 72x14 operator logo, 1 SMS
115 */
116 SMS_NokiaOperatorLogo,
117 /**
118 * Nokia 72x14 op logo or 78x21 in 2 SMS
119 */
120 SMS_NokiaOperatorLogoLong,
121 /**
122 * Nokia 72x14 caller logo, 1 SMS
123 */
124 SMS_NokiaCallerLogo,
125 /**
126 * Nokia WAP bookmark in 1 or 2 SMS
127 */
128 SMS_NokiaWAPBookmarkLong,
129 /**
130 * Nokia WAP settings in 2 SMS
131 */
132 SMS_NokiaWAPSettingsLong,
133 /**
134 * Nokia MMS settings in 2 SMS
135 */
136 SMS_NokiaMMSSettingsLong,
137 /**
138 * Nokia VCARD 1.0 - only name and default number
139 */
140 SMS_NokiaVCARD10Long,
141 /**
142 * Nokia VCARD 2.1 - all numbers + text
143 */
144 SMS_NokiaVCARD21Long,
145 /**
146 * Nokia VCALENDAR 1.0 - can be in few sms
147 */
148 SMS_NokiaVCALENDAR10Long,
149 SMS_NokiaVTODOLong,
150 SMS_VCARD10Long,
151 SMS_VCARD21Long,
152 SMS_DisableVoice,
153 SMS_DisableFax,
154 SMS_DisableEmail,
155 SMS_EnableVoice,
156 SMS_EnableFax,
157 SMS_EnableEmail,
158 SMS_VoidSMS,
159 /**
160 * IMelody 1.0
161 */
162 SMS_EMSSound10,
163 /**
164 * IMelody 1.2
165 */
166 SMS_EMSSound12,
167 /**
168 * IMelody without header - SonyEricsson extension
169 */
170 SMS_EMSSonyEricssonSound,
171 /**
172 * IMelody 1.0 with UPI.
173 */
174 SMS_EMSSound10Long,
175 /***
176 * IMelody 1.2 with UPI.
177 */
178 SMS_EMSSound12Long,
179 /**
180 * IMelody without header with UPI.
181 */
182 SMS_EMSSonyEricssonSoundLong,
183 SMS_EMSPredefinedSound,
184 SMS_EMSPredefinedAnimation,
185 SMS_EMSAnimation,
186 /**
187 * Fixed bitmap of size 16x16 or 32x32.
188 */
189 SMS_EMSFixedBitmap,
190 SMS_EMSVariableBitmap,
191 SMS_EMSVariableBitmapLong,
192 SMS_MMSIndicatorLong,
193 /**
194 * Variable bitmap with black and white colors
195 */
196 SMS_AlcatelMonoBitmapLong,
197 /**
198 * Variable animation with black and white colors
199 */
200 SMS_AlcatelMonoAnimationLong,
201 SMS_AlcatelSMSTemplateName
202} EncodeMultiPartSMSID;
203
204typedef struct {
205 EncodeMultiPartSMSID ID;
206
207 int Number;
208 GSM_Ringtone *Ringtone;
209 GSM_MultiBitmap *Bitmap;
210 GSM_WAPBookmark *Bookmark;
211 GSM_WAPSettings *Settings;
212 GSM_MMSIndicator*MMSIndicator;
213 GSM_MemoryEntry *Phonebook;
214 GSM_CalendarEntry *Calendar;
215 GSM_ToDoEntry *ToDo;
216 bool Protected;
217
218 unsigned char *Buffer;
219 bool Left;
220 bool Right;
221 bool Center;
222 bool Large;
223 bool Small;
224 bool Bold;
225 bool Italic;
226 bool Underlined;
227 bool Strikethrough;
228
229 /* Return values */
230 int RingtoneNotes;
231} MultiPartSMSEntry;
232
233typedef struct {
234 MultiPartSMSEntryEntries[MAX_MULTI_SMS];
235 int EntriesNum;
236 bool UnicodeCoding;
237 int Class;
238 unsigned char ReplaceMessage;
239 bool Unknown;
240} GSM_MultiPartSMSInfo;
241
242/**
243 * Encodes multi part SMS from "readable" format.
244 */
245GSM_Error GSM_EncodeMultiPartSMS (GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS);
246
247/**
248 * Decodes multi part SMS to "readable" format.
249 */
250bool GSM_DecodeMultiPartSMS (GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS, bool ems);
251
252/**
253 * Clears @ref GSM_MultiPartSMSInfo to default values.
254 */
255void GSM_ClearMultiPartSMSInfo (GSM_MultiPartSMSInfo *Info);
256
257/**
258 * Frees any allocated structures inside @ref GSM_MultiPartSMSInfo.
259 */
260void GSM_FreeMultiPartSMSInfo (GSM_MultiPartSMSInfo *Info);
261
262/**
263 * Links SMS messages according to IDs.
264 */
265GSM_Error GSM_LinkSMS(GSM_MultiSMSMessage **INPUT, GSM_MultiSMSMessage **OUTPUT, bool ems);
266
267#endif
268
269/* How should editor hadle tabs in this file? Add editor commands here.
270 * vim: noexpandtab sw=8 ts=8 sts=8:
271 */
diff --git a/gammu/emb/common/service/sms/gsmsms.c b/gammu/emb/common/service/sms/gsmsms.c
new file mode 100644
index 0000000..9920835
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmsms.c
@@ -0,0 +1,663 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* based on some work from Pawel Kot, others and Gnokii */
3
4#include <ctype.h>
5#include <string.h>
6#include <time.h>
7
8#include "../../gsmcomon.h"
9#include "../../misc/coding/coding.h"
10#include "../gsmcal.h"
11#include "../gsmpbk.h"
12#include "../gsmlogo.h"
13#include "../gsmring.h"
14#include "../gsmdata.h"
15#include "../gsmnet.h"
16#include "gsmsms.h"
17
18/* User data headers */
19static GSM_UDHHeader UDHHeaders[] = {
20 /* See GSM 03.40 section 9.2.3.24.1
21 * 1 byte 0x00
22 * 1 byte 0x03
23 * 1 byte 0x01: unique ID for message series
24 * 1 byte 0x00: how many SMS in sequence
25 * 1 byte 0x00: number of current SMS in sequence */
26 { UDH_ConcatenatedMessages, 0x05, "\x00\x03\x01\x00\x00",2,-1,4,3},
27
28 /* See GSM 03.40 section 9.2.3.24.2 for voice, fax and email messages */
29 { UDH_DisableVoice, 0x04, "\x01\x02\x00\x00",-1,-1,-1,-1},
30 { UDH_DisableFax, 0x04, "\x01\x02\x01\x00",-1,-1,-1,-1},
31 { UDH_DisableEmail, 0x04, "\x01\x02\x02\x00",-1,-1,-1,-1},
32 { UDH_EnableVoice, 0x04, "\x01\x02\x00\x01",-1,-1,-1,-1},
33 { UDH_EnableFax, 0x04, "\x01\x02\x01\x01",-1,-1,-1,-1},
34 { UDH_EnableEmail, 0x04, "\x01\x02\x02\x01",-1,-1,-1,-1},
35
36 /* When send such SMS to some phones, they don't display anything,
37 * only beep and enable vibra/light
38 */
39 { UDH_VoidSMS, 0x08, "\x01\x02\x02\x01\x01\x02\x02\x00",-1,-1,-1,-1},
40
41 /* Nokia Smart Messaging (short version) UDH
42 * General format :
43 * 1 byte 0x05 : IEI application port addressing scheme, 16 bit address
44 * 1 byte 0x04 : IEI length
45 * 2 bytes : destination address : high & low byte
46 * 2 bytes 0x00 0x00 : originator address : high & low byte */
47 { UDH_NokiaRingtone, 0x06, "\x05\x04\x15\x81\x00\x00",-1,-1,-1,-1},
48 { UDH_NokiaOperatorLogo, 0x06, "\x05\x04\x15\x82\x00\x00",-1,-1,-1,-1},
49 { UDH_NokiaCallerLogo, 0x06, "\x05\x04\x15\x83\x00\x00",-1,-1,-1,-1},
50 { UDH_NokiaWAP, 0x06, "\x05\x04\xc3\x4f\x00\x00",-1,-1,-1,-1},
51
52 /* Nokia Smart Messaging (long version) UDH and other
53 * General format:
54 * 1 byte 0x05 : IEI application port addressing scheme, 16 bit address
55 * 1 byte 0x04 : IEI length
56 * 2 bytes 0x00 0x00 : destination address : high & low byte
57 * 2 bytes 0x00 0x00 : originator address : high & low byte
58 * 1 byte 0x00 : SAR
59 * 1 byte 0x03 : SAR length
60 * 1 byte : diagram reference number (unique ID for message series)
61 * 1 byte : number of all SMS
62 * 1 byte : number of current SMS */
63 { UDH_NokiaCalendarLong, 0x0b, "\x05\x04\x00\xe4\x00\x00\x00\x03\xc7\x00\x00",8,-1,10,9},
64 { UDH_MMSIndicatorLong, 0x0b, "\x05\x04\x0b\x84\x23\xf0\x00\x03\xe5\x00\x00",8,-1,10,9},
65 { UDH_NokiaRingtoneLong, 0x0b, "\x05\x04\x15\x81\x00\x00\x00\x03\x01\x00\x00",8,-1,10,9},
66 { UDH_NokiaOperatorLogoLong, 0x0b, "\x05\x04\x15\x82\x00\x00\x00\x03\x02\x00\x00",8,-1,10,9},
67 { UDH_NokiaProfileLong, 0x0b, "\x05\x04\x15\x8a\x00\x00\x00\x03\xce\x00\x00",8,-1,10,9},
68 { UDH_NokiaPhonebookLong, 0x0b, "\x05\x04\x23\xf4\x00\x00\x00\x03\x01\x00\x00",8,-1,10,9},
69 { UDH_NokiaWAPLong, 0x0b, "\x05\x04\xc3\x4f\x00\x00\x00\x03\x7f\x00\x00",8,-1,10,9},
70
71 { UDH_ConcatenatedMessages16bit,0x06, "\x08\x04\x00\x00\x00\x00",-1,2,5,4},
72
73 { UDH_NoUDH, 0x00, "",-1,-1,-1,-1}
74};
75
76/* --------------------------- Unpacking SMS ------------------------------- */
77
78/* See GSM 03.40 section 9.2.3.11 */
79static GSM_Error GSM_DecodeSMSDateTime(GSM_DateTime *DT, unsigned char *req)
80{
81 DT->Year = DecodeWithBCDAlphabet(req[0]);
82 if (DT->Year<90) DT->Year=DT->Year+2000; else DT->Year=DT->Year+1990;
83 DT->Month = DecodeWithBCDAlphabet(req[1]);
84 DT->Day = DecodeWithBCDAlphabet(req[2]);
85 DT->Hour = DecodeWithBCDAlphabet(req[3]);
86 DT->Minute = DecodeWithBCDAlphabet(req[4]);
87 DT->Second = DecodeWithBCDAlphabet(req[5]);
88
89 /* Base for timezone is GMT. It's in quarters */
90 DT->Timezone=(10*(req[6]&0x07)+(req[6]>>4))/4;
91
92 if (req[6]&0x08) DT->Timezone = -DT->Timezone;
93
94 dbgprintf("Decoding date & time: ");
95 dbgprintf("%s %4d/%02d/%02d ", DayOfWeek(DT->Year, DT->Month, DT->Day),
96 DT->Year, DT->Month, DT->Day);
97 dbgprintf("%02d:%02d:%02d %02d00\n", DT->Hour, DT->Minute, DT->Second, DT->Timezone);
98
99 return ERR_NONE;
100}
101
102void GSM_DecodeUDHHeader(GSM_UDHHeader *UDH)
103{
104 inti, tmp, w;
105 boolUDHOK;
106
107 UDH->Type = UDH_UserUDH;
108 UDH->ID8bit= -1;
109 UDH->ID16bit= -1;
110 UDH->PartNumber= -1;
111 UDH->AllParts= -1;
112
113 i=-1;
114 while (true) {
115 i++;
116 if (UDHHeaders[i].Type==UDH_NoUDH) break;
117
118 tmp=UDHHeaders[i].Length;
119 /* if length is the same */
120 if (tmp==UDH->Text[0]) {
121
122 if (tmp==0x05) tmp=tmp-3;/*three last bytes can be different for such UDH*/
123 if (tmp==0x0b) tmp=tmp-3;/*three last bytes can be different for such UDH*/
124 if (tmp==0x06 && UDH->Text[1] == 0x08) tmp=tmp-4;
125
126 UDHOK=true;
127 for (w=0;w<tmp;w++) {
128 if (UDHHeaders[i].Text[w]!=UDH->Text[w+1]) {
129 UDHOK=false;
130 break;
131 }
132 }
133 if (UDHOK) {
134 UDH->Type=UDHHeaders[i].Type;
135
136 if (UDHHeaders[i].ID8bit !=-1) UDH->ID8bit = UDH->Text[UDHHeaders[i].ID8bit+1];
137 if (UDHHeaders[i].ID16bit !=-1) UDH->ID16bit = UDH->Text[UDHHeaders[i].ID16bit+1]*256+UDH->Text[UDHHeaders[i].ID16bit+2];
138 if (UDHHeaders[i].PartNumber !=-1) UDH->PartNumber = UDH->Text[UDHHeaders[i].PartNumber+1];
139 if (UDHHeaders[i].AllParts !=-1) UDH->AllParts = UDH->Text[UDHHeaders[i].AllParts+1];
140 break;
141 }
142 }
143 }
144
145#ifdef DEBUG
146 dbgprintf("Type of UDH: ");
147 switch (UDH->Type) {
148 case UDH_ConcatenatedMessages : dbgprintf("Concatenated (linked) message"); break;
149 case UDH_ConcatenatedMessages16bit : dbgprintf("Concatenated (linked) message"); break;
150 case UDH_DisableVoice : dbgprintf("Disables voice indicator"); break;
151 case UDH_EnableVoice : dbgprintf("Enables voice indicator"); break;
152 case UDH_DisableFax : dbgprintf("Disables fax indicator"); break;
153 case UDH_EnableFax : dbgprintf("Enables fax indicator"); break;
154 case UDH_DisableEmail : dbgprintf("Disables email indicator"); break;
155 case UDH_EnableEmail : dbgprintf("Enables email indicator"); break;
156 case UDH_VoidSMS : dbgprintf("Void SMS"); break;
157 case UDH_NokiaWAP : dbgprintf("Nokia WAP Bookmark"); break;
158 case UDH_NokiaOperatorLogoLong : dbgprintf("Nokia operator logo"); break;
159 case UDH_NokiaWAPLong : dbgprintf("Nokia WAP Bookmark or WAP/MMS Settings");break;
160 case UDH_NokiaRingtone : dbgprintf("Nokia ringtone"); break;
161 case UDH_NokiaRingtoneLong : dbgprintf("Nokia ringtone"); break;
162 case UDH_NokiaOperatorLogo : dbgprintf("Nokia GSM operator logo"); break;
163 case UDH_NokiaCallerLogo : dbgprintf("Nokia caller logo"); break;
164 case UDH_NokiaProfileLong : dbgprintf("Nokia profile"); break;
165 case UDH_NokiaCalendarLong : dbgprintf("Nokia calendar note"); break;
166 case UDH_NokiaPhonebookLong : dbgprintf("Nokia phonebook entry"); break;
167 case UDH_UserUDH : dbgprintf("User UDH"); break;
168 case UDH_MMSIndicatorLong : dbgprintf("MMS indicator"); break;
169 case UDH_NoUDH: break;
170 }
171 if (UDH->ID8bit != -1) dbgprintf(", ID 8 bit %i",UDH->ID8bit);
172 if (UDH->ID16bit != -1) dbgprintf(", ID 16 bit %i",UDH->ID16bit);
173 if (UDH->PartNumber != -1 && UDH->AllParts != -1) {
174 dbgprintf(", part %i of %i",UDH->PartNumber,UDH->AllParts);
175 }
176 dbgprintf("\n");
177 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, UDH->Text, UDH->Length);
178#endif
179}
180
181GSM_Error GSM_DecodeSMSFrameText(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
182{
183 int off=0; // length of the User Data Header
184 int w,i,tmp=0;
185 unsigned charoutput[161];
186
187 SMS->UDH.Length = 0;
188 /* UDH header available */
189 if (buffer[Layout.firstbyte] & 64) {
190 /* Length of UDH header */
191 off = (buffer[Layout.Text] + 1);
192 SMS->UDH.Length = off;
193 dbgprintf("UDH header available (length %i)\n",off);
194
195 /* Copy UDH header into SMS->UDH */
196 for (i = 0; i < off; i++) SMS->UDH.Text[i] = buffer[Layout.Text + i];
197
198 GSM_DecodeUDHHeader(&SMS->UDH);
199 }
200
201 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
202 if ((buffer[Layout.TPDCS] & 0xf4) == 0xf4) SMS->Coding=SMS_Coding_8bit;
203 if ((buffer[Layout.TPDCS] & 0x08) == 0x08) SMS->Coding=SMS_Coding_Unicode;
204
205 switch (SMS->Coding) {
206 case SMS_Coding_Default:
207 i = 0;
208 do {
209 i+=7;
210 w=(i-off)%i;
211 } while (w<0);
212 SMS->Length=buffer[Layout.TPUDL] - (off*8 + w) / 7;
213 tmp=GSM_UnpackEightBitsToSeven(w, buffer[Layout.TPUDL]-off, SMS->Length, buffer+(Layout.Text+off), output);
214 dbgprintf("7 bit SMS, length %i\n",SMS->Length);
215 DecodeDefault (SMS->Text, output, SMS->Length, true, NULL);
216 dbgprintf("%s\n",DecodeUnicodeString(SMS->Text));
217 break;
218 case SMS_Coding_8bit:
219 SMS->Length=buffer[Layout.TPUDL] - off;
220 memcpy(SMS->Text,buffer+(Layout.Text+off),SMS->Length);
221#ifdef DEBUG
222 dbgprintf("8 bit SMS, length %i\n",SMS->Length);
223 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, SMS->Text, SMS->Length);
224#endif
225 break;
226 case SMS_Coding_Unicode:
227 SMS->Length=(buffer[Layout.TPUDL] - off) / 2;
228 DecodeUnicodeSpecialNOKIAChars(SMS->Text,buffer+(Layout.Text+off), SMS->Length);
229#ifdef DEBUG
230 dbgprintf("Unicode SMS, length %i\n",SMS->Length);
231 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, buffer+(Layout.Text+off), SMS->Length*2);
232 dbgprintf("%s\n",DecodeUnicodeString(SMS->Text));
233#endif
234 break;
235 }
236
237 return ERR_NONE;
238}
239
240GSM_Error GSM_DecodeSMSFrameStatusReportData(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
241{
242 SMS->DeliveryStatus = buffer[Layout.TPStatus];
243
244 if (buffer[Layout.TPStatus] < 0x03) {
245 EncodeUnicode(SMS->Text,"Delivered",9);
246 SMS->Length = 9;
247 } else if (buffer[Layout.TPStatus] & 0x40) {
248 EncodeUnicode(SMS->Text,"Failed",6);
249 SMS->Length = 6;
250 } else if (buffer[Layout.TPStatus] & 0x20) {
251 EncodeUnicode(SMS->Text,"Pending",7);
252 SMS->Length = 7;
253 } else {
254 EncodeUnicode(SMS->Text,"Unknown",7);
255 SMS->Length = 7;
256 }
257
258#ifdef DEBUG
259 /* See GSM 03.40 section 9.2.3.15 (TP-Status) */
260 if (buffer[Layout.TPStatus] & 0x40) {
261 if (buffer[Layout.TPStatus] & 0x20) {
262 /* 0x60, 0x61, ... */
263 dbgprintf("Temporary error, SC is not making any more transfer attempts\n");
264 } else {
265 /* 0x40, 0x41, ... */
266 dbgprintf("Permanent error, SC is not making any more transfer attempts\n");
267 }
268 } else if (buffer[Layout.TPStatus] & 0x20) {
269 /* 0x20, 0x21, ... */
270 dbgprintf("Temporary error, SC still trying to transfer SM\n");
271 }
272 switch (buffer[Layout.TPStatus]) {
273 case 0x00: dbgprintf("SM received by the SME"); break;
274 case 0x01: dbgprintf("SM forwarded by the SC to the SME but the SC is unable to confirm delivery");break;
275 case 0x02: dbgprintf("SM replaced by the SC"); break;
276 case 0x20: dbgprintf("Congestion"); break;
277 case 0x21: dbgprintf("SME busy"); break;
278 case 0x22: dbgprintf("No response from SME"); break;
279 case 0x23: dbgprintf("Service rejected"); break;
280 case 0x24: dbgprintf("Quality of service not available"); break;
281 case 0x25: dbgprintf("Error in SME"); break;
282 case 0x40: dbgprintf("Remote procedure error"); break;
283 case 0x41: dbgprintf("Incompatibile destination"); break;
284 case 0x42: dbgprintf("Connection rejected by SME"); break;
285 case 0x43: dbgprintf("Not obtainable"); break;
286 case 0x44: dbgprintf("Quality of service not available"); break;
287 case 0x45: dbgprintf("No internetworking available"); break;
288 case 0x46: dbgprintf("SM Validity Period Expired"); break;
289 case 0x47: dbgprintf("SM deleted by originating SME"); break;
290 case 0x48: dbgprintf("SM Deleted by SC Administration"); break;
291 case 0x49: dbgprintf("SM does not exist"); break;
292 case 0x60: dbgprintf("Congestion"); break;
293 case 0x61: dbgprintf("SME busy"); break;
294 case 0x62: dbgprintf("No response from SME"); break;
295 case 0x63: dbgprintf("Service rejected"); break;
296 case 0x64: dbgprintf("Quality of service not available"); break;
297 case 0x65: dbgprintf("Error in SME"); break;
298 default : dbgprintf("Reserved/Specific to SC: %x",buffer[Layout.TPStatus]);break;
299 }
300 dbgprintf("\n");
301#endif
302
303 return ERR_NONE;
304}
305
306GSM_Error GSM_DecodeSMSFrame(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
307{
308 GSM_DateTimezerodt = {0,0,0,0,0,0,0};
309#ifdef DEBUG
310 if (Layout.firstbyte == 255) {
311 dbgprintf("ERROR: firstbyte in SMS layout not set\n");
312 return ERR_UNKNOWN;
313 }
314 if (Layout.TPDCS != 255) dbgprintf("TPDCS : %02x %i\n",buffer[Layout.TPDCS] ,buffer[Layout.TPDCS]);
315 if (Layout.TPMR != 255) dbgprintf("TPMR : %02x %i\n",buffer[Layout.TPMR] ,buffer[Layout.TPMR]);
316 if (Layout.TPPID != 255) dbgprintf("TPPID : %02x %i\n",buffer[Layout.TPPID] ,buffer[Layout.TPPID]);
317 if (Layout.TPUDL != 255) dbgprintf("TPUDL : %02x %i\n",buffer[Layout.TPUDL] ,buffer[Layout.TPUDL]);
318 if (Layout.firstbyte != 255) dbgprintf("FirstByte : %02x %i\n",buffer[Layout.firstbyte],buffer[Layout.firstbyte]);
319 if (Layout.Text != 255) dbgprintf("Text : %02x %i\n",buffer[Layout.Text] ,buffer[Layout.Text]);
320#endif
321
322 SMS->UDH.Type = UDH_NoUDH;
323 SMS->Coding = SMS_Coding_Default;
324 SMS->Length = 0;
325 SMS->SMSC.Location = 0;
326 SMS->SMSC.DefaultNumber[0]= 0;
327 SMS->SMSC.DefaultNumber[1]= 0;
328 SMS->SMSC.Number[0] = 0;
329 SMS->SMSC.Number[1] = 0;
330 SMS->SMSC.Name[0] = 0;
331 SMS->SMSC.Name[1] = 0;
332 SMS->SMSC.Validity.Format= SMS_Validity_NotAvailable;
333 SMS->SMSC.Format = SMS_FORMAT_Text;
334 SMS->Number[0] = 0;
335 SMS->Number[1] = 0;
336 SMS->Name[0] = 0;
337 SMS->Name[1] = 0;
338 SMS->ReplyViaSameSMSC = false;
339 if (Layout.SMSCNumber!=255) {
340 GSM_UnpackSemiOctetNumber(SMS->SMSC.Number,buffer+Layout.SMSCNumber,false);
341 dbgprintf("SMS center number : \"%s\"\n",DecodeUnicodeString(SMS->SMSC.Number));
342 }
343 if ((buffer[Layout.firstbyte] & 0x80)!=0) SMS->ReplyViaSameSMSC=true;
344#ifdef DEBUG
345 if (SMS->ReplyViaSameSMSC) dbgprintf("SMS centre set for reply\n");
346#endif
347 if (Layout.Number!=255) {
348 GSM_UnpackSemiOctetNumber(SMS->Number,buffer+Layout.Number,true);
349 dbgprintf("Remote number : \"%s\"\n",DecodeUnicodeString(SMS->Number));
350 }
351 if (Layout.Text != 255 && Layout.TPDCS!=255 && Layout.TPUDL!=255) {
352 GSM_DecodeSMSFrameText(SMS, buffer, Layout);
353 }
354 if (Layout.DateTime != 255) {
355 GSM_DecodeSMSDateTime(&SMS->DateTime,buffer+(Layout.DateTime));
356 } else {
357 SMS->DateTime = zerodt;
358 }
359 if (Layout.SMSCTime != 255 && Layout.TPStatus != 255) {
360 /* GSM 03.40 section 9.2.3.11 (TP-Service-Centre-Time-Stamp) */
361 dbgprintf("SMSC response date: ");
362 GSM_DecodeSMSDateTime(&SMS->SMSCTime, buffer+(Layout.SMSCTime));
363 GSM_DecodeSMSFrameStatusReportData(SMS,buffer,Layout);
364 } else {
365 SMS->SMSCTime = zerodt;
366 }
367 SMS->Class = -1;
368 if (Layout.TPDCS != 255) {
369 if ((buffer[Layout.TPDCS] & 0xF3)==0xF0) SMS->Class = 0;
370 if ((buffer[Layout.TPDCS] & 0xF3)==0xF1) SMS->Class = 1;
371 if ((buffer[Layout.TPDCS] & 0xF3)==0xF2) SMS->Class = 2;
372 if ((buffer[Layout.TPDCS] & 0xF3)==0xF3) SMS->Class = 3;
373 }
374 dbgprintf("SMS class: %i\n",SMS->Class);
375
376 SMS->MessageReference = 0;
377 if (Layout.TPMR != 255) SMS->MessageReference = buffer[Layout.TPMR];
378
379 SMS->ReplaceMessage = 0;
380 if (Layout.TPPID != 255) {
381 if (buffer[Layout.TPPID] > 0x40 && buffer[Layout.TPPID] < 0x48) {
382 SMS->ReplaceMessage = buffer[Layout.TPPID] - 0x40;
383 }
384 }
385 SMS->RejectDuplicates = false;
386 if ((buffer[Layout.firstbyte] & 0x04)==0x04) SMS->RejectDuplicates = true;
387
388 return ERR_NONE;
389}
390
391/* ----------------------------- Packing SMS ------------------------------- */
392
393/* See GSM 03.40 section 9.2.3.11 */
394static GSM_Error GSM_EncodeSMSDateTime(GSM_DateTime *DT, unsigned char *req)
395{
396 int Year;
397
398 dbgprintf("Encoding SMS datetime: %02i/%02i/%04i %02i:%02i:%02i\n",
399 DT->Day,DT->Month,DT->Year,DT->Hour,DT->Minute,DT->Second);
400
401 /* We need to have only two last digits of year */
402 if (DT->Year>1900) {
403 if (DT->Year<2000) Year = DT->Year-1900;
404 else Year = DT->Year-2000;
405 } else Year = DT->Year;
406
407 req[0]=EncodeWithBCDAlphabet(Year);
408 req[1]=EncodeWithBCDAlphabet(DT->Month);
409 req[2]=EncodeWithBCDAlphabet(DT->Day);
410 req[3]=EncodeWithBCDAlphabet(DT->Hour);
411 req[4]=EncodeWithBCDAlphabet(DT->Minute);
412 req[5]=EncodeWithBCDAlphabet(DT->Second);
413
414 /* FIXME: do it */
415 req[6]=0; /* TimeZone = +-0 */
416
417 return ERR_NONE;
418}
419
420static int GSM_EncodeSMSFrameText(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout)
421{
422 int off = 0;// length of the User Data Header
423 intsize = 0, size2 = 0, w,p;
424 charbuff[200];
425
426 if (SMS->UDH.Type!=UDH_NoUDH) {
427 buffer[Layout.firstbyte] |= 0x40; /* GSM 03.40 section 9.2.3.23 (TP-User-Data-Header-Indicator) */
428 off = 1 + SMS->UDH.Text[0]; /* off - length of the User Data Header */
429 memcpy(buffer+Layout.Text, SMS->UDH.Text, off); /* we copy the udh */
430#ifdef DEBUG
431 dbgprintf("UDH, length %i\n",off);
432 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, SMS->UDH.Text, off);
433#endif
434 }
435 switch (SMS->Coding) {
436 case SMS_Coding_8bit:
437 /* the mask for the 8-bit data */
438 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme)
439 * and GSM 03.38 section 4 */
440 buffer[Layout.TPDCS] |= 0xf4;
441 memcpy(buffer+(Layout.Text+off), SMS->Text, SMS->Length);
442 size2 = size = SMS->Length+off;
443#ifdef DEBUG
444 dbgprintf("8 bit SMS, length %i\n",SMS->Length);
445 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, SMS->Text, SMS->Length);
446#endif
447 break;
448 case SMS_Coding_Default:
449 p = 0;
450 do {
451 p+=7;
452 w=(p-off)%p;
453 } while (w<0);
454 p = UnicodeLength(SMS->Text);
455 EncodeDefault(buff, SMS->Text, &p, true, NULL);
456 size = GSM_PackSevenBitsToEight(w, buff, buffer+(Layout.Text+off), p);
457 size += off;
458 size2 = (off*8 + w) / 7 + p;
459 dbgprintf("7 bit SMS, length %i, %i\n",size,size2);
460 dbgprintf("%s\n",DecodeUnicodeString(SMS->Text));
461 if (size > GSM_MAX_8BIT_SMS_LENGTH) {
462 size = 0; size2 = 0;
463 }
464 break;
465 case SMS_Coding_Unicode:
466 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme)
467 * and GSM 03.38 section 4 */
468 buffer[Layout.TPDCS] |= 0x08;
469 EncodeUnicodeSpecialNOKIAChars(buffer+(Layout.Text+off), SMS->Text, UnicodeLength(SMS->Text));
470 size=size2=UnicodeLength(buffer+(Layout.Text+off))*2+off;
471#ifdef DEBUG
472 dbgprintf("Unicode SMS, length %i\n",(size2-off)/2);
473 if (di.dl == DL_TEXTALL || di.dl == DL_TEXTALLDATE) DumpMessage(di.df, di.dl, buffer+(Layout.Text+off), size2-off);
474 dbgprintf("%s\n",DecodeUnicodeString(buffer+(Layout.Text+off)));
475#endif
476 break;
477 }
478
479 /* GSM 03.40 section 9.2.3.16 (TP-User-Data-Length)
480 * SMS->Length is:
481 - integer representation of the number od octets within the
482 user data when TP-User-Data is coded using 8 bit data
483 - the sum of the number of septets in UDH including any padding
484 and the number of septets in TP-User-Data in other case
485 */
486 buffer[Layout.TPUDL] = size2;
487 return size;
488}
489
490GSM_Error GSM_EncodeSMSFrame(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout, int *length, bool clear)
491{
492 int i;
493
494 if (clear) {
495 /* Cleaning up to the SMS text */
496 for (i=0;i<Layout.Text;i++) buffer[i] = 0;
497 }
498
499 /* GSM 03.40 section 9.2.3.1 (TP-Message-Type-Indicator) */
500 switch (SMS->PDU) {
501 case SMS_Submit:
502 buffer[Layout.firstbyte] |= 0x01;
503 break;
504 /* SMS_Status_Report when Submit sms should have delivery report */
505 /* We DON'T CREATE FRAME FOR REAL SMS_STATUS_REPORT */
506 case SMS_Status_Report:
507 buffer[Layout.firstbyte] |= 0x01;
508 /* GSM 03.40 section 9.2.3.5 (TP-Status-Raport-Request) */
509 /* Set when want delivery report from SMSC */
510 buffer[Layout.firstbyte] |= 0x20;
511 break;
512 case SMS_Deliver:
513 buffer[Layout.firstbyte] |= 0x00;
514 }
515
516 /* GSM 03.40 section 9.2.3.17 (TP-Reply-Path) */
517 if (SMS->ReplyViaSameSMSC) buffer[Layout.firstbyte] |= 0x80;
518
519 if (Layout.Number!=255) {
520 buffer[Layout.Number] = GSM_PackSemiOctetNumber(SMS->Number,buffer+(Layout.Number+1),true);
521 dbgprintf("Recipient number \"%s\"\n",DecodeUnicodeString(SMS->Number));
522 }
523 if (Layout.SMSCNumber!=255) {
524 buffer[Layout.SMSCNumber]=GSM_PackSemiOctetNumber(SMS->SMSC.Number,buffer+(Layout.SMSCNumber+1), false);
525 dbgprintf("SMSC number \"%s\"\n",DecodeUnicodeString(SMS->SMSC.Number));
526 }
527
528 /* Message Class*/
529 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
530 if (Layout.TPDCS != 255) {
531 if (SMS->Class>=0 && SMS->Class<5) buffer[Layout.TPDCS] |= (240+SMS->Class);
532 dbgprintf("SMS class %i\n",SMS->Class);
533 }
534
535 if (Layout.TPVP != 255) {
536 /* GSM 03.40 section 9.2.3.3 (TP-Validity-Period-Format) */
537 /* Bits 4 and 3: 10. TP-VP field present and integer represent (relative) */
538 buffer[Layout.firstbyte] |= 0x10;
539 buffer[Layout.TPVP]=((unsigned char)SMS->SMSC.Validity.Relative);
540 dbgprintf("SMS validity %02x\n",SMS->SMSC.Validity.Relative);
541 }
542
543 if (Layout.DateTime != 255) {
544 GSM_EncodeSMSDateTime(&SMS->DateTime, buffer+Layout.DateTime);
545 }
546
547 if (Layout.TPMR != 255) {
548 dbgprintf("TPMR: %02x %i\n",SMS->MessageReference,SMS->MessageReference);
549 buffer[Layout.TPMR] = SMS->MessageReference;
550 }
551
552 if (SMS->RejectDuplicates) {
553 /* GSM 03.40 section 9.2.3.25 (TP Reject Duplicates) */
554 buffer[Layout.firstbyte] |= 0x04;
555 }
556
557 if (Layout.TPPID != 255) {
558 buffer[Layout.TPPID] = 0;
559 if (SMS->ReplaceMessage > 0 && SMS->ReplaceMessage < 8) {
560 buffer[Layout.TPPID] = 0x40 + SMS->ReplaceMessage;
561 }
562 }
563
564 /* size is the length of the data in octets including UDH */
565 *length=GSM_EncodeSMSFrameText(SMS,buffer,Layout);
566 //if (*length == 0) return GE_UNKNOWN;
567 *length += Layout.Text;
568
569 return ERR_NONE;
570}
571
572/* ----------------- Some help functions ----------------------------------- */
573
574void GSM_SetDefaultSMSData(GSM_SMSMessage *SMS)
575{
576 SMS->Class = -1;
577 SMS->SMSC.Location = 1;
578 SMS->SMSC.Format = SMS_FORMAT_Text;
579 SMS->SMSC.Validity.Format= SMS_Validity_RelativeFormat;
580 SMS->SMSC.Validity.Relative= SMS_VALID_Max_Time;
581 SMS->ReplyViaSameSMSC = false;
582 SMS->UDH.Type = UDH_NoUDH;
583 SMS->UDH.Length = 0;
584 SMS->UDH.Text[0] = 0;
585 SMS->UDH.ID8bit = 0;
586 SMS->UDH.ID16bit = 0;
587 SMS->UDH.PartNumber = 0;
588 SMS->UDH.AllParts = 0;
589 SMS->Coding = SMS_Coding_Default;
590 SMS->Text[0] = 0;
591 SMS->Text[1] = 0;
592 SMS->PDU = SMS_Submit;
593 SMS->RejectDuplicates = false;
594 SMS->MessageReference = 0;
595 SMS->ReplaceMessage = 0;
596 SMS->Length = 0;
597
598 /* This part is required to save SMS */
599 SMS->State = SMS_UnSent;
600 SMS->Location = 0;
601 SMS->Folder = 0x02;/*Outbox*/
602 GSM_GetCurrentDateTime (&SMS->DateTime);
603 SMS->Name[0] = 0;
604 SMS->Name[1] = 0;
605}
606
607/**
608 * GSM 03.40 section 9.2.3.24
609 */
610void GSM_EncodeUDHHeader(GSM_UDHHeader *UDH)
611{
612 int i=0;
613
614 if (UDH->Type == UDH_NoUDH) {
615 UDH->Length = 0;
616 return;
617 }
618 if (UDH->Type == UDH_UserUDH) {
619 UDH->Length = UDH->Text[0] + 1;
620 return;
621 }
622 while (true) {
623 if (UDHHeaders[i].Type==UDH_NoUDH) {
624 dbgprintf("Not supported UDH type\n");
625 break;
626 }
627 if (UDHHeaders[i].Type!=UDH->Type) {
628 i++;
629 continue;
630 }
631 /* UDH Length */
632 UDH->Text[0] = UDHHeaders[i].Length;
633 memcpy(UDH->Text+1, UDHHeaders[i].Text, UDHHeaders[i].Length);
634 UDH->Length = UDH->Text[0] + 1;
635
636 if (UDHHeaders[i].ID8bit != -1) {
637 UDH->Text[UDHHeaders[i].ID8bit+1] = UDH->ID8bit % 256;
638 } else {
639 UDH->ID8bit = -1;
640 }
641 if (UDHHeaders[i].ID16bit != -1) {
642 UDH->Text[UDHHeaders[i].ID16bit+1] = UDH->ID16bit / 256;
643 UDH->Text[UDHHeaders[i].ID16bit+2] = UDH->ID16bit % 256;
644 } else {
645 UDH->ID16bit = -1;
646 }
647 if (UDHHeaders[i].PartNumber != -1) {
648 UDH->Text[UDHHeaders[i].PartNumber+1] = UDH->PartNumber;
649 } else {
650 UDH->PartNumber = -1;
651 }
652 if (UDHHeaders[i].AllParts != -1) {
653 UDH->Text[UDHHeaders[i].AllParts+1] = UDH->AllParts;
654 } else {
655 UDH->AllParts = -1;
656 }
657 break;
658 }
659}
660
661/* How should editor hadle tabs in this file? Add editor commands here.
662 * vim: noexpandtab sw=8 ts=8 sts=8:
663 */
diff --git a/gammu/emb/common/service/sms/gsmsms.h b/gammu/emb/common/service/sms/gsmsms.h
new file mode 100644
index 0000000..d87ff60
--- a/dev/null
+++ b/gammu/emb/common/service/sms/gsmsms.h
@@ -0,0 +1,492 @@
1/* (c) 2001-2004 by Marcin Wiacek */
2/* based on some work from Pawel Kot, others and Gnokii */
3
4#ifndef __gsm_sms_h
5#define __gsm_sms_h
6
7#include "../../gsmcomon.h"
8#include "../gsmlogo.h"
9#include "../gsmcal.h"
10#include "../gsmpbk.h"
11#include "../gsmdata.h"
12#include "../gsmring.h"
13
14/* --------------------- Some general definitions ------------------------- */
15
16 #define GSM_MAX_UDH_LENGTH 140
17 #define GSM_MAX_SMS_LENGTH 160
18 #define GSM_MAX_8BIT_SMS_LENGTH 140
19
20/* -------------------- Cell Broadcast ------------------------------------ */
21
22/**
23 * Structure for Cell Broadcast messages.
24 */
25typedef struct {
26 /**
27 * Message text.
28 */
29 char Text[300];
30 /**
31 * Channel number.
32 */
33 int Channel;
34} GSM_CBMessage;
35
36/* ------------------------ SMS status ------------------------------------ */
37
38/**
39 * Status of SMS memory.
40 */
41typedef struct {
42 /**
43 * Number of unread messages on SIM.
44 */
45 int SIMUnRead;
46 /**
47 * Number of all saved messages (including unread) on SIM.
48 */
49 int SIMUsed;
50 /**
51 * Number of all possible messages on SIM.
52 */
53 int SIMSize;
54 /**
55 * Number of used templates (62xx/63xx/7110/etc.).
56 */
57 int TemplatesUsed;
58 /**
59 * Number of unread messages in phone.
60 */
61 int PhoneUnRead;
62 /**
63 * Number of all saved messages in phone.
64 */
65 int PhoneUsed;
66 /**
67 * Number of all possible messages on phone.
68 */
69 int PhoneSize;
70} GSM_SMSMemoryStatus;
71
72/* --------------------- SMS Center --------------------------------------- */
73
74/**
75 * Enum defines format of SMS messages. See GSM 03.40 section 9.2.3.9
76 */
77typedef enum {
78 SMS_FORMAT_Pager = 1,
79 SMS_FORMAT_Fax,
80 SMS_FORMAT_Email,
81 SMS_FORMAT_Text
82 /* Some values not handled here */
83} GSM_SMSFormat;
84
85/**
86 * Enum defines some the most often used validity lengths for SMS messages
87 * for relative validity format. See GSM 03.40 section 9.2.3.12.1 - it gives
88 * more values
89 */
90typedef enum {
91 SMS_VALID_1_Hour = 0x0b,
92 SMS_VALID_6_Hours = 0x47,
93 SMS_VALID_1_Day = 0xa7,
94 SMS_VALID_3_Days = 0xa9,
95 SMS_VALID_1_Week = 0xad,
96 SMS_VALID_Max_Time = 0xff
97} GSM_ValidityPeriod;
98
99/**
100 * Enum defines format of validity period for SMS messages.
101 * See GSM 03.40 section 9.2.3.12
102 */
103typedef enum {
104 SMS_Validity_NotAvailable = 1,
105 SMS_Validity_RelativeFormat
106 /* Specification gives also other possibilities */
107} GSM_ValidityPeriodFormat;
108
109/**
110 * Structure for validity of SMS messages
111 */
112typedef struct {
113 GSM_ValidityPeriodFormatFormat;
114 /**
115 * Value defines period for relative format
116 */
117 GSM_ValidityPeriod Relative;
118} GSM_SMSValidity;
119
120 #define GSM_MAX_SMSC_NAME_LENGTH30
121
122/**
123 * Structure for SMSC (SMS Center) information.
124 */
125typedef struct {
126 /**
127 * Number of the SMSC on SIM
128 */
129 int Location;
130 /**
131 * Name of the SMSC
132 */
133 unsigned char Name[(GSM_MAX_SMSC_NAME_LENGTH+1)*2];
134 /**
135 * SMSC phone number.
136 */
137 unsigned char Number[(GSM_MAX_NUMBER_LENGTH+1)*2];
138 /**
139 * Validity of SMS messages.
140 */
141 GSM_SMSValidity Validity;
142 /**
143 * Format of sent SMS messages.
144 */
145 GSM_SMSFormat Format;
146 /**
147 * Default recipient number. In old DCT3 ignored
148 */
149 unsigned char DefaultNumber[(GSM_MAX_NUMBER_LENGTH+1)*2];
150} GSM_SMSC;
151
152/* --------------------- single SMS --------------------------------------- */
153
154/**
155 * Status of SMS message.
156 */
157typedef enum {
158 SMS_Sent = 1,
159 SMS_UnSent,
160 SMS_Read,
161 SMS_UnRead
162} GSM_SMS_State;
163
164/**
165 * Coding type of SMS.
166 */
167typedef enum {
168 /**
169 * Unicode
170 */
171 SMS_Coding_Unicode = 1,
172 /**
173 * Default GSM aplhabet.
174 */
175 SMS_Coding_Default,
176 /**
177 * 8-bit.
178 */
179 SMS_Coding_8bit
180} GSM_Coding_Type;
181
182/**
183 * Types of UDH (User Data Header).
184 */
185typedef enum {
186 UDH_NoUDH = 1,
187 /**
188 * Linked SMS.
189 */
190 UDH_ConcatenatedMessages,
191 /**
192 * Linked SMS with 16 bit reference.
193 */
194 UDH_ConcatenatedMessages16bit,
195 UDH_DisableVoice,
196 UDH_DisableFax,
197 UDH_DisableEmail,
198 UDH_EnableVoice,
199 UDH_EnableFax,
200 UDH_EnableEmail,
201 UDH_VoidSMS,
202 UDH_NokiaRingtone,
203 UDH_NokiaRingtoneLong,
204 UDH_NokiaOperatorLogo,
205 UDH_NokiaOperatorLogoLong,
206 UDH_NokiaCallerLogo,
207 UDH_NokiaWAP,
208 UDH_NokiaWAPLong,
209 UDH_NokiaCalendarLong,
210 UDH_NokiaProfileLong,
211 UDH_NokiaPhonebookLong,
212 UDH_UserUDH,
213 UDH_MMSIndicatorLong
214} GSM_UDH;
215
216/**
217 * Structure for User Data Header.
218 */
219typedef struct {
220 /**
221 * UDH type.
222 */
223 GSM_UDH Type;
224 /**
225 * UDH length.
226 */
227 int Length;
228 /**
229 * UDH text.
230 */
231 unsigned char Text[GSM_MAX_UDH_LENGTH];
232 /**
233 * 8-bit ID, when required (-1 otherwise).
234 */
235 int ID8bit;
236 /**
237 * 16-bit ID, when required (-1 otherwise).
238 */
239 int ID16bit;
240 /**
241 * Number of current part.
242 */
243 int PartNumber;
244 /**
245 * Total number of parts.
246 */
247 int AllParts;
248} GSM_UDHHeader;
249
250/**
251 * TP-Message-Type-Indicator. See GSM 03.40 section 9.2.3.1.
252 */
253 typedef enum {
254 /**
255 * SMS in Inbox.
256 */
257 SMS_Deliver = 1,
258 /**
259 * Delivery Report
260 */
261 SMS_Status_Report,
262 /**
263 * SMS for sending or in Outbox
264 */
265 SMS_Submit
266 /* specification gives more */
267} GSM_SMSMessageType;
268
269/**
270 * Maximal length of SMS name.
271 */
272 #define GSM_MAX_SMS_NAME_LENGTH 40
273
274/**
275 * SMS message data.
276 */
277typedef struct {
278 /**
279 * Message to be replaced.
280 */
281 unsigned char ReplaceMessage;
282 /**
283 * Whether to reject duplicates.
284 */
285 bool RejectDuplicates;
286 /**
287 * UDH (User Data Header)
288 */
289 GSM_UDHHeader UDH;
290 /**
291 * Sender or recipient number.
292 */
293 unsigned char Number[(GSM_MAX_NUMBER_LENGTH+1)*2];
294 /**
295 * SMSC (SMS Center)
296 */
297 GSM_SMSC SMSC;
298 /**
299 * For saved SMS: where exactly it's saved (SIM/phone)
300 */
301 GSM_MemoryType Memory;
302 /**
303 * For saved SMS: location of SMS in memory.
304 */
305 int Location;
306 /**
307 * For saved SMS: number of folder, where SMS is saved
308 */
309 int Folder;
310 /**
311 * For saved SMS: whether SMS is really in Inbox.
312 */
313 bool InboxFolder;
314 /**
315 * Length of the SMS message.
316 */
317 int Length;
318 /**
319 * Status (read/unread/...) of SMS message.
320 */
321 GSM_SMS_State State;
322 /**
323 * Name in Nokia with SMS memory (6210/7110, etc.) Ignored in other.
324 */
325 unsigned char Name[(GSM_MAX_SMS_NAME_LENGTH+1)*2];
326 /**
327 * Text for SMS.
328 */
329 unsigned char Text[(GSM_MAX_SMS_LENGTH+1)*2];
330 /**
331 * Type of message.
332 */
333 GSM_SMSMessageType PDU;
334 /**
335 * Type of coding.
336 */
337 GSM_Coding_Type Coding;
338 /**
339 * Date and time, when SMS was saved or sent
340 */
341 GSM_DateTime DateTime;
342 /**
343 * Date of SMSC response in DeliveryReport messages.
344 */
345 GSM_DateTime SMSCTime;
346 /**
347 * In delivery reports: status.
348 */
349 unsigned char DeliveryStatus;
350 /**
351 * Indicates whether "Reply via same center" is set.
352 */
353 bool ReplyViaSameSMSC;
354 /**
355 * SMS class.
356 */
357 char Class;
358 /**
359 * Message reference.
360 */
361 unsigned char MessageReference;
362} GSM_SMSMessage;
363
364/* In layouts are saved locations for some SMS part. Below are listed
365 * specs, which describe them
366 */
367typedef struct {
368 /**
369 * TP-User-Data. GSM 03.40 section 9.2.3.24.
370 */
371 unsigned char Text;
372 /**
373 * - In SMS-Deliver: TP-Originating-Address. GSM 03.40 section 9.2.3.7.
374 * - In SMS-Submit: TP-Destination-Address. GSM 03.40 section 9.2.3.8.
375 * - In SMS-Status-Report: TP-Recipient-Address. GSM 03.40 section 9.2.3.14.
376 */
377 unsigned char Number;
378 /**
379 * SMSC number
380 */
381 unsigned char SMSCNumber;
382 /**
383 * TP-Data-Coding-Scheme. GSM 03.40 section 9.2.3.10
384 */
385 unsigned char TPDCS;
386 /**
387 * - For SMS-Submit: TP-Validity-Period. GSM 03.40 section 9.2.3.12.
388 * - For SMS-Status-Report: TP-Discharge Time. GSM 03.40 section 9.2.3.13.
389 */
390 unsigned char DateTime;
391 /**
392 * TP-Service-Centre-Time-Stamp in SMS-Status-Report. GSM 03.40 section 9.2.3.11.
393 */
394 unsigned char SMSCTime;
395 /**
396 * TP-Status in SMS-Status-Report. GSM 03.40 section 9.2.3.15.
397 */
398 unsigned char TPStatus;
399 /**
400 * TP-User-Data-Length. GSM 03.40 section 9.2.3.16.
401 */
402 unsigned char TPUDL;
403 /**
404 * TP-Validity Period in SMS-Submit. GSM 03.40 section 9.2.3.12.
405 */
406 unsigned char TPVP;
407 /**
408 * Byte contains in SMS-Deliver:
409 * - TP-Message-Type-Indicator (2 bits) GSM 03.40 section 9.2.3.1
410 * - TP-More-Messages-To-Send (1 bit). GSM 03.40 section 9.2.3.2
411 * - TP-Reply-Path (1 bit). GSM 03.40 section 9.2.3.17
412 * - TP-User-Data-Header-Indicator (1 bit). GSM 03.40 section 9.2.3.23
413 * - TP-Status-Report-Indicator (1 bit). GSM 03.40 section 9.2.3.4
414 *
415 * Byte contains in SMS-Submit:
416 * - TP-Message-Type-Indicator (2 bits) GSM 03.40 section 9.2.3.1
417 * - TP-Reject-Duplicates (1 bit). GSM 03.40 section
418 * - TP-Validity-Period-Format (2 bits).GSM 03.40 section 9.2.3.3
419 * - TP-Reply-Path (1 bit). GSM 03.40 section 9.2.3.17
420 * - TP-User-Data-Header-Indicator (1 bit). GSM 03.40 section 9.2.3.23
421 * - TP-Status-Report-Request (1 bit). GSM 03.40 section 9.2.3.5
422 */
423 unsigned char firstbyte;
424 /**
425 * TP-Message Reference in SMS-Submit. GSM 03.40 section 9.2.3.6
426 */
427 unsigned char TPMR;
428 /**
429 * TP-Protocol-Identifier. GSM 03.40 section 9.2.3.9
430 */
431 unsigned char TPPID;
432} GSM_SMSMessageLayout;
433
434GSM_Error GSM_DecodeSMSFrame(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout);
435GSM_Error GSM_EncodeSMSFrame(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout, int *length, bool clear);
436
437GSM_Error GSM_DecodeSMSFrameStatusReportData (GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout);
438 GSM_Error GSM_DecodeSMSFrameText (GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout);
439
440void GSM_DecodeUDHHeader(GSM_UDHHeader *UDH);
441void GSM_EncodeUDHHeader(GSM_UDHHeader *UDH);
442
443void GSM_SetDefaultSMSData(GSM_SMSMessage *SMS);
444
445/* ---------------------- SMS folders ------------------------------------- */
446
447/**
448 * Number of possible SMS folders.
449 */
450 #define GSM_MAX_SMS_FOLDERS 24
451/**
452 * Maximal length of SMS folder name.
453 */
454#define GSM_MAX_SMS_FOLDER_NAME_LEN 20
455
456/**
457 * Information about SMS folder.
458 */
459typedef struct {
460 /**
461 * Whether it is really inbox.
462 */
463 bool InboxFolder;
464 /**
465 * Where exactly it's saved
466 */
467 GSM_MemoryType Memory;
468 /**
469 * Name for SMS folder.
470 */
471 char Name[(GSM_MAX_SMS_FOLDER_NAME_LEN+1)*2];
472} GSM_OneSMSFolder;
473
474/**
475 * List of SMS folders.
476 */
477typedef struct {
478 /**
479 * Array of structures holding information about each folder.
480 */
481 GSM_OneSMSFolderFolder[GSM_MAX_SMS_FOLDERS];
482 /**
483 * Number of SMS folders.
484 */
485 unsigned char Number;
486} GSM_SMSFolders;
487
488#endif
489
490/* How should editor hadle tabs in this file? Add editor commands here.
491 * vim: noexpandtab sw=8 ts=8 sts=8:
492 */