author | zautrix <zautrix> | 2004-08-07 17:24:40 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-08-07 17:24:40 (UTC) |
commit | 88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22 (patch) (unidiff) | |
tree | 6331418973714243beb674abc87692277b83869d /gammu/emb/common/service | |
parent | ef8a09ce74ad3f0a51484d03fdf009bd5b3677bf (diff) | |
download | kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.zip kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.tar.gz kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.tar.bz2 |
Initial revision
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 | |||
30 | typedef 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 | |||
58 | typedef struct { | ||
59 | GSM_SMSMessage *SMS[GSM_BACKUP_MAX_SMS]; | ||
60 | } GSM_SMS_Backup; | ||
61 | |||
62 | extern GSM_Error GSM_ReadSMSBackupFile(char *FileName, GSM_SMS_Backup *backup); | ||
63 | extern 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 | |||
15 | GSM_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 | |||
26 | GSM_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 | ||
9 | GSM_Error SaveICS(char *FileName, GSM_Backup *backup); | ||
10 | GSM_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 | |||
15 | static 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 | |||
28 | GSM_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 | |||
147 | static 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 | |||
173 | static 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 | |||
260 | GSM_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 | ||
9 | GSM_Error SaveLDIF(char *FileName, GSM_Backup *backup); | ||
10 | GSM_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 | |||
15 | static 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 | |||
55 | static 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 | |||
97 | void 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 | |||
122 | GSM_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 | |||
180 | static 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 | |||
235 | static 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 | |||
286 | static 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 | |||
335 | GSM_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 | ||
9 | GSM_Error SaveLMB(char *FileName, GSM_Backup *backup); | ||
10 | GSM_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 | |||
17 | GSM_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 | |||
76 | static 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 | |||
92 | static 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 | |||
120 | static 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 | |||
139 | static 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 | |||
169 | static 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 | |||
211 | static 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 | |||
221 | static 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 | |||
231 | static 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 | |||
421 | static 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 | |||
537 | static 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 | |||
660 | static 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 | |||
680 | static 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 | |||
706 | static 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 | |||
716 | static 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 | |||
732 | static 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 | |||
765 | static 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 | |||
791 | static 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 | |||
804 | static 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 | |||
866 | static 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 | |||
992 | static 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 | |||
1005 | static 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 | |||
1021 | GSM_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 | |||
1170 | static 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 | |||
1325 | static 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, ¬e->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, ¬e->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, ¬e->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, ¬e->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, ¬e->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 | |||
1513 | static 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 | |||
1609 | static 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 | |||
1636 | static 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 | |||
1680 | static 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 | |||
1698 | static 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 | |||
1708 | static 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 | |||
1721 | static 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 | |||
1762 | static 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 | |||
1910 | static 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 | |||
1939 | static 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 | |||
2153 | static 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 | |||
2172 | static 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 | |||
2200 | static 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 | |||
2208 | GSM_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 | |||
2665 | static 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 | |||
2753 | static 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 | |||
2784 | GSM_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 | |||
2798 | GSM_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 | |||
2890 | GSM_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 | ||
9 | GSM_Error LoadBackup(char *FileName, GSM_Backup *backup, bool UseUnicode); | ||
10 | GSM_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 | |||
15 | GSM_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 | |||
38 | GSM_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 | ||
9 | GSM_Error SaveVCard(char *FileName, GSM_Backup *backup); | ||
10 | GSM_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 | |||
15 | GSM_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 | |||
54 | GSM_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 | ||
9 | GSM_Error SaveVCalendar(char *FileName, GSM_Backup *backup); | ||
10 | GSM_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 | |||
23 | void 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 | |||
121 | GSM_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 | |||
138 | GSM_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 | |||
170 | void 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 | |||
197 | void 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 | |||
259 | void 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 | |||
10 | GSM_Error GSM_SaveBackupFile(char *FileName, GSM_Backup *backup, bool UseUnicode); | ||
11 | GSM_Error GSM_ReadBackupFile(char *FileName, GSM_Backup *backup); | ||
12 | |||
13 | void GSM_ClearBackup (GSM_Backup *backup); | ||
14 | void GSM_FreeBackup (GSM_Backup *backup); | ||
15 | |||
16 | typedef 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 | |||
40 | void GSM_GetBackupFormatFeatures(char *FileName, GSM_Backup_Info *info); | ||
41 | void 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 | |||
9 | bool 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 | |||
44 | void 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 | |||
85 | GSM_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, ¬e->Entries[Time].Date, "DTSTART"); | ||
136 | |||
137 | if (EndTime != -1) { | ||
138 | SaveVCALDateTime(Buffer, Length, ¬e->Entries[EndTime].Date, "DTEND"); | ||
139 | } | ||
140 | |||
141 | if (Alarm != -1) { | ||
142 | if (note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) { | ||
143 | SaveVCALDateTime(Buffer, Length, ¬e->Entries[Alarm].Date, "DALARM"); | ||
144 | } else { | ||
145 | SaveVCALDateTime(Buffer, Length, ¬e->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, ¬e->Entries[Time].Date, "DTSTART"); | ||
178 | |||
179 | if (Alarm != -1) { | ||
180 | SaveVCALDateTime(Buffer, Length, ¬e->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, ¬e->Entries[Time].Date, "DTSTART"); | ||
230 | |||
231 | if (EndTime != -1) { | ||
232 | SaveVCALDateTime(Buffer, Length, ¬e->Entries[EndTime].Date, "DTEND"); | ||
233 | } | ||
234 | |||
235 | if (Alarm != -1) { | ||
236 | SaveVCALDateTime(Buffer, Length, ¬e->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 | |||
252 | void 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 | |||
285 | GSM_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, ¬e->Entries[EndTime].Date, "DUE"); | ||
316 | } | ||
317 | |||
318 | if (Alarm != -1) { | ||
319 | if (note->Entries[Alarm].EntryType == CAL_SILENT_ALARM_DATETIME) { | ||
320 | SaveVCALDateTime(Buffer, Length, ¬e->Entries[Alarm].Date, "DALARM"); | ||
321 | } else { | ||
322 | SaveVCALDateTime(Buffer, Length, ¬e->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, ¬e->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 | |||
354 | GSM_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 | |||
497 | GSM_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 | */ | ||
17 | typedef 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 | */ | ||
135 | typedef 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 | */ | ||
209 | typedef 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 | */ | ||
231 | typedef 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 | |||
250 | void GSM_CalendarFindDefaultTextTimeAlarmPhoneRecurrance(GSM_CalendarEntry *entry, int *Text, int *Time, int *Alarm, int *Phone, int *Recurrance, int *EndTime, int *Location); | ||
251 | |||
252 | typedef enum { | ||
253 | Nokia_VCalendar = 1, | ||
254 | Siemens_VCalendar, | ||
255 | SonyEricsson_VCalendar | ||
256 | } GSM_VCalendarVersion; | ||
257 | |||
258 | GSM_Error GSM_EncodeVCALENDAR(char *Buffer, int *Length, GSM_CalendarEntry *note, bool header, GSM_VCalendarVersion Version); | ||
259 | |||
260 | bool IsCalendarNoteFromThePast(GSM_CalendarEntry *note); | ||
261 | |||
262 | typedef 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 | */ | ||
276 | typedef 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 | */ | ||
293 | typedef 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 | */ | ||
335 | typedef 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 | */ | ||
344 | typedef 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 | */ | ||
366 | typedef 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 | |||
385 | void GSM_ToDoFindDefaultTextTimeAlarmCompleted(GSM_ToDoEntry *entry, int *Text, int *Alarm, int *Completed, int *EndTime, int *Phone); | ||
386 | |||
387 | typedef enum { | ||
388 | Nokia_VToDo = 1, | ||
389 | SonyEricsson_VToDo | ||
390 | } GSM_VToDoVersion; | ||
391 | |||
392 | GSM_Error GSM_EncodeVTODO(char *Buffer, int *Length, GSM_ToDoEntry *note, bool header, GSM_VToDoVersion Version); | ||
393 | |||
394 | /** | ||
395 | * Status of to do entries. | ||
396 | */ | ||
397 | typedef struct { | ||
398 | /** | ||
399 | * Number of used positions. | ||
400 | */ | ||
401 | int Used; | ||
402 | } GSM_ToDoStatus; | ||
403 | |||
404 | /* --------------------------- note ---------------------------------------- */ | ||
405 | |||
406 | typedef struct { | ||
407 | int Location; | ||
408 | char Text[100]; | ||
409 | } GSM_NoteEntry; | ||
410 | |||
411 | GSM_Error GSM_EncodeVNTFile(unsigned char *Buffer, int *Length, GSM_NoteEntry *Note); | ||
412 | |||
413 | /* --------------------------- alarm --------------------------------------- */ | ||
414 | |||
415 | /** | ||
416 | * Alarm values. | ||
417 | */ | ||
418 | typedef 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 | |||
439 | GSM_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 | */ | ||
13 | typedef 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 | */ | ||
59 | typedef 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 | */ | ||
87 | typedef 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 | */ | ||
109 | typedef 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 | */ | ||
131 | typedef 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 | */ | ||
153 | typedef 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 | */ | ||
166 | typedef 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 */ | ||
9 | void 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 */ | ||
55 | static 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 */ | ||
71 | static 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 | */ | ||
82 | void 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 */ | ||
249 | void 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 | |||
298 | void 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 | |||
337 | void 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 | |||
348 | GSM_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 | |||
11 | typedef enum { | ||
12 | WAPSETTINGS_SPEED_9600, | ||
13 | WAPSETTINGS_SPEED_14400, | ||
14 | WAPSETTINGS_SPEED_AUTO | ||
15 | } WAPSettings_Speed; | ||
16 | |||
17 | typedef enum { | ||
18 | WAPSETTINGS_BEARER_SMS = 1, | ||
19 | WAPSETTINGS_BEARER_DATA, | ||
20 | WAPSETTINGS_BEARER_USSD, | ||
21 | WAPSETTINGS_BEARER_GPRS | ||
22 | } WAPSettings_Bearer; | ||
23 | |||
24 | typedef 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 | |||
54 | typedef 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 | |||
68 | void NOKIA_EncodeWAPMMSSettingsSMSText(unsigned char *Buffer, int *Length, GSM_WAPSettings *settings, bool MMS); | ||
69 | |||
70 | /* -------------------------------- WAP Bookmark --------------------------- */ | ||
71 | |||
72 | typedef 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 | |||
83 | typedef struct { | ||
84 | unsigned char Address[500]; | ||
85 | unsigned char Title[200]; | ||
86 | unsigned char Sender[200]; | ||
87 | } GSM_MMSIndicator; | ||
88 | |||
89 | void GSM_EncodeMMSIndicatorSMSText(unsigned char *Buffer, int *Length, GSM_MMSIndicator Indicator); | ||
90 | |||
91 | /* ------------------------------ MMS file --------------------------------- */ | ||
92 | |||
93 | #define MAX_MULTI_MMS 20 | ||
94 | |||
95 | typedef enum { | ||
96 | MMS_Text = 1, | ||
97 | MMS_Bitmap_JPG | ||
98 | } EncodeMultiPartMMSID; | ||
99 | |||
100 | typedef struct { | ||
101 | EncodeMultiPartMMSID ID; | ||
102 | |||
103 | GSM_File File; | ||
104 | unsigned char *Buffer; | ||
105 | } EncodeMultiPartMMSEntry; | ||
106 | |||
107 | typedef 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 | |||
122 | typedef 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 | |||
138 | typedef 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 | |||
11 | void 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 | |||
32 | int 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 | |||
65 | static 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 | |||
95 | static 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 | |||
127 | void 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 | |||
175 | void 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 | |||
180 | void 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 | |||
200 | void 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 | |||
211 | void GSM_SetPointBitmap(GSM_Bitmap *bmp, int x, int y) | ||
212 | { | ||
213 | SetBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x); | ||
214 | } | ||
215 | |||
216 | void GSM_ClearPointBitmap(GSM_Bitmap *bmp, int x, int y) | ||
217 | { | ||
218 | ClearBit(bmp->BitmapPoints,y*bmp->BitmapWidth+x); | ||
219 | } | ||
220 | |||
221 | bool 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 | |||
226 | void GSM_ClearBitmap(GSM_Bitmap *bmp) | ||
227 | { | ||
228 | memset(bmp->BitmapPoints,0,GSM_GetBitmapSize(bmp)); | ||
229 | } | ||
230 | |||
231 | int GSM_GetBitmapSize(GSM_Bitmap *bmp) | ||
232 | { | ||
233 | return bmp->BitmapWidth*bmp->BitmapHeight/8+1; | ||
234 | } | ||
235 | |||
236 | void 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 | |||
252 | void 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 | |||
267 | void 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 | |||
300 | GSM_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 | |||
431 | static 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 | |||
439 | static 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 | |||
465 | static 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 | |||
496 | static 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 | |||
513 | static 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 | |||
533 | static 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 | |||
562 | static 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 | |||
591 | static 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 | |||
605 | static 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 | |||
620 | GSM_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 | |||
649 | GSM_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 | |||
783 | static 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 | |||
792 | static 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 | |||
857 | static 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 | |||
905 | static 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 | |||
942 | static 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 | |||
958 | GSM_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 | |||
988 | void 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 | */ | ||
11 | typedef 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 | */ | ||
57 | typedef 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 | */ | ||
125 | typedef 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 | |||
136 | typedef 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 | |||
165 | GSM_Error BMP2Bitmap (unsigned char *buffer, FILE *file,GSM_Bitmap *bitmap); | ||
166 | GSM_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 | |||
15 | struct keys_table_position { | ||
16 | char whatchar; | ||
17 | int whatcode; | ||
18 | }; | ||
19 | |||
20 | static 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 | |||
36 | GSM_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 | |||
61 | GSM_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 | |||
97 | static 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 | |||
116 | GSM_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 | |||
144 | void 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 | |||
166 | void 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 | |||
176 | void 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 | |||
200 | void 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 | |||
214 | bool 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 | */ | ||
13 | typedef 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 | |||
55 | typedef 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 | */ | ||
68 | typedef 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 | */ | ||
100 | typedef 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 | |||
113 | typedef 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 | |||
159 | GSM_Error MakeKeySequence(char *text, GSM_KeyCode *KeyCode, int *Length); | ||
160 | |||
161 | /* ------------------------------- display features ------------------------ */ | ||
162 | |||
163 | typedef 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 | |||
176 | typedef struct { | ||
177 | int Number; | ||
178 | GSM_DisplayFeature Feature[7]; | ||
179 | } GSM_DisplayFeatures; | ||
180 | |||
181 | /* ----------------------------- power source ------------------------------ */ | ||
182 | |||
183 | typedef enum { | ||
184 | GSM_BatteryPowered = 1, | ||
185 | GSM_BatteryConnected, | ||
186 | GSM_BatteryNotConnected, | ||
187 | GSM_PowerFault | ||
188 | } GSM_ChargeState; | ||
189 | |||
190 | typedef 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 | |||
205 | typedef enum { | ||
206 | Category_ToDo = 1, | ||
207 | Category_Phonebook | ||
208 | } GSM_CategoryType; | ||
209 | |||
210 | typedef struct { | ||
211 | GSM_CategoryType Type; | ||
212 | int Location; | ||
213 | unsigned char Name[(GSM_MAX_CATEGORY_NAME_LENGTH + 1)*2]; | ||
214 | } GSM_Category; | ||
215 | |||
216 | typedef 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 | |||
226 | typedef struct { | ||
227 | int Location; | ||
228 | char StationName [(GSM_MAX_FMSTATION_LENGTH+1)*2]; | ||
229 | double Frequency; | ||
230 | } GSM_FMStation; | ||
231 | |||
232 | /* ----------------------- filesystem ------------------------------------- */ | ||
233 | |||
234 | typedef 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 | |||
251 | typedef 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 | |||
270 | GSM_Error GSM_ReadFile(char *FileName, GSM_File *File); | ||
271 | |||
272 | GSM_Error GSM_JADFindData(GSM_File File, char *Vendor, char *Name, char *JAR, char *Version, int *Size); | ||
273 | |||
274 | void GSM_IdentifyFileFormat(GSM_File *File); | ||
275 | |||
276 | typedef struct { | ||
277 | int Free; | ||
278 | int Used; | ||
279 | } GSM_FileSystemStatus; | ||
280 | |||
281 | /* ----------------------------- GPRS access points ----------------------- */ | ||
282 | |||
283 | typedef struct { | ||
284 | int Location; | ||
285 | unsigned char Name[300]; | ||
286 | unsigned char URL[500]; | ||
287 | bool Active; | ||
288 | } GSM_GPRSAccessPoint; | ||
289 | |||
290 | /* ------------------------------------------------------------------------ */ | ||
291 | |||
292 | typedef enum { | ||
293 | GSM_Date_DDMMYYYY = 1, | ||
294 | GSM_Date_MMDDYYYY, | ||
295 | GSM_Date_YYYYMMDD | ||
296 | } GSM_DateFormat; | ||
297 | |||
298 | typedef struct { | ||
299 | unsigned char DateSeparator; | ||
300 | GSM_DateFormatDateFormat; | ||
301 | bool AMPMTime; | ||
302 | } GSM_Locale; | ||
303 | |||
304 | /* ------------------------------------------------------------------------ */ | ||
305 | |||
306 | void ReadVCALDateTime(char *Buffer, GSM_DateTime *dt); | ||
307 | void SaveVCALDateTime(char *Buffer, int *Length, GSM_DateTime *Date, char *Start); | ||
308 | |||
309 | void SaveVCALText(char *Buffer, int *Length, char *Text, char *Start); | ||
310 | bool 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 | |||
8 | unsigned 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 | |||
128 | unsigned 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 | |||
395 | char *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 | |||
411 | char *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 | |||
427 | void NOKIA_EncodeNetworkCode(unsigned char* buffer, unsigned char* output) | ||
428 | { | ||
429 | EncodeBCD(buffer, output, 6, false); | ||
430 | buffer[1] = buffer[1] | 0xf0; | ||
431 | } | ||
432 | |||
433 | void 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 | */ | ||
9 | char *GSM_GetNetworkName(char *NetworkCode); | ||
10 | |||
11 | /** | ||
12 | * Find country name from given country code. | ||
13 | */ | ||
14 | char *GSM_GetCountryName(char *CountryCode); | ||
15 | |||
16 | /** | ||
17 | * Status of network logging | ||
18 | */ | ||
19 | typedef 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 | */ | ||
49 | typedef 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 | |||
73 | void NOKIA_EncodeNetworkCode (unsigned char* buffer, unsigned char* output); | ||
74 | void NOKIA_DecodeNetworkCode (unsigned char* buffer, unsigned char* output); | ||
75 | |||
76 | /** | ||
77 | * Information about signal quality, all these should be -1 when unknown. | ||
78 | */ | ||
79 | typedef 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 | |||
9 | unsigned 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 | |||
54 | void 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 | |||
102 | void 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 | |||
186 | GSM_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 | |||
283 | static 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 | |||
321 | void 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 | */ | ||
15 | typedef 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 | */ | ||
34 | typedef 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 | */ | ||
180 | typedef 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 | */ | ||
207 | typedef 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 | |||
226 | typedef enum { | ||
227 | Nokia_VCard10 = 1, | ||
228 | Nokia_VCard21, | ||
229 | SonyEricsson_VCard10, | ||
230 | SonyEricsson_VCard21 | ||
231 | } GSM_VCardVersion; | ||
232 | |||
233 | void GSM_PhonebookFindDefaultNameNumberGroup(GSM_MemoryEntry *entry, int *Name, int *Number, int *Group); | ||
234 | unsigned char *GSM_PhonebookGetEntryName (GSM_MemoryEntry *entry); | ||
235 | |||
236 | void GSM_EncodeVCARD(char *Buffer, int *Length, GSM_MemoryEntry *pbk, bool header, GSM_VCardVersion Version); | ||
237 | GSM_Error GSM_DecodeVCARD(unsigned char *Buffer, int *Pos, GSM_MemoryEntry *Pbk, GSM_VCardVersion Version); | ||
238 | |||
239 | #ifndef ENABLE_LGPL | ||
240 | /* (c) by Timo Teras */ | ||
241 | void DecodeVCARD21Text(char *VCard, GSM_MemoryEntry *pbk); | ||
242 | #endif | ||
243 | |||
244 | /** | ||
245 | * Structure for saving speed dials | ||
246 | */ | ||
247 | typedef 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 | |||
6 | typedef 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 | |||
47 | typedef 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 | */ | ||
68 | typedef 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 | |||
93 | typedef 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 | |||
20 | int 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 | |||
53 | int 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 | |||
80 | GSM_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 | |||
134 | static 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 | |||
148 | static 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 | |||
154 | GSM_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 | |||
326 | void 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 | |||
338 | static 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 ? */ | ||
363 | void 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,¤t,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,¤t,pause); | ||
411 | pause=0; | ||
412 | midifile[current++]=0x90; // note on | ||
413 | midifile[current++]=note; | ||
414 | midifile[current++]=0x64; // forte | ||
415 | |||
416 | WriteVarLen(midifile,¤t,duration); | ||
417 | midifile[current++]=0x80; // note off | ||
418 | midifile[current++]=note; | ||
419 | midifile[current++]=0x64; | ||
420 | } | ||
421 | } | ||
422 | } | ||
423 | if (pause) { | ||
424 | WriteVarLen(midifile,¤t,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 | |||
440 | void 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 | |||
450 | GSM_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 | |||
490 | static 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 | |||
707 | static 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 | |||
717 | static 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 | |||
736 | static 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 | |||
755 | static 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 | |||
767 | static 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 | |||
788 | GSM_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 */ | ||
848 | static 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 | |||
855 | int 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" */ | ||
868 | unsigned 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 | |||
1003 | GSM_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 | |||
1124 | static 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 | |||
1202 | static 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 */ | ||
1443 | unsigned 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 | |||
1584 | char *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 | |||
32 | typedef 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 | |||
47 | typedef 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 | |||
63 | typedef 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 | |||
72 | typedef enum { | ||
73 | NoSpecialDuration = 0x00<<6, | ||
74 | DottedNote = 0x01<<6, | ||
75 | DoubleDottedNote = 0x02<<6, | ||
76 | Length_2_3 = 0x03<<6 | ||
77 | } GSM_RingNoteDurationSpec; | ||
78 | |||
79 | typedef 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 | |||
91 | typedef 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 | |||
100 | typedef 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 | |||
111 | typedef struct { | ||
112 | GSM_RingCommandType Type; | ||
113 | GSM_RingNote Note; | ||
114 | unsigned char Value; | ||
115 | } GSM_RingCommand; | ||
116 | |||
117 | typedef 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. */ | ||
124 | typedef struct { | ||
125 | unsigned char Frame[30000]; | ||
126 | int Length; | ||
127 | } GSM_NokiaBinaryRingtone; | ||
128 | |||
129 | typedef struct { | ||
130 | unsigned char *Frame; | ||
131 | int Length; | ||
132 | } GSM_BinaryTone; | ||
133 | |||
134 | typedef enum { | ||
135 | RING_NOTETONE = 1, | ||
136 | RING_NOKIABINARY, | ||
137 | RING_MIDI | ||
138 | } GSM_RingtoneFormat; | ||
139 | |||
140 | /** | ||
141 | * Structure for saving various ringtones formats | ||
142 | */ | ||
143 | typedef 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 | |||
164 | typedef struct { | ||
165 | int Group;//Nokia specific | ||
166 | int ID; | ||
167 | char Name[30*2]; | ||
168 | } GSM_RingtoneInfo; | ||
169 | |||
170 | typedef struct { | ||
171 | int Number; | ||
172 | GSM_RingtoneInfo Ringtone[100]; | ||
173 | } GSM_AllRingtonesInfo; | ||
174 | |||
175 | GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone); | ||
176 | GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone); | ||
177 | |||
178 | void saveott(FILE *file, GSM_Ringtone *ringtone); | ||
179 | void savemid(FILE *file, GSM_Ringtone *ringtone); | ||
180 | void saverng(FILE *file, GSM_Ringtone *ringtone); | ||
181 | void saveimelody(FILE *file, GSM_Ringtone *ringtone); | ||
182 | GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone); | ||
183 | GSM_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 | |||
196 | char *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 | |||
540 | static 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 | |||
21 | unsigned 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 | |||
37 | void 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 */ | ||
206 | static 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 | |||
706 | void 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 | |||
742 | void 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 | |||
933 | GSM_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 | */ | ||
43 | typedef 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 | |||
54 | GSM_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 | |||
63 | void 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 | |||
71 | void GSM_Find_Free_Used_SMS2(GSM_Coding_Type Coding,GSM_SMSMessage SMS, int *UsedText, int *FreeText, int *FreeBytes); | ||
72 | |||
73 | unsigned char GSM_MakeSMSIDFromTime(void); | ||
74 | |||
75 | /** | ||
76 | * ID during packing SMS for Smart Messaging 3.0, EMS and other | ||
77 | */ | ||
78 | typedef 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 | |||
204 | typedef 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 | |||
233 | typedef 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 | */ | ||
245 | GSM_Error GSM_EncodeMultiPartSMS (GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS); | ||
246 | |||
247 | /** | ||
248 | * Decodes multi part SMS to "readable" format. | ||
249 | */ | ||
250 | bool GSM_DecodeMultiPartSMS (GSM_MultiPartSMSInfo *Info, GSM_MultiSMSMessage *SMS, bool ems); | ||
251 | |||
252 | /** | ||
253 | * Clears @ref GSM_MultiPartSMSInfo to default values. | ||
254 | */ | ||
255 | void GSM_ClearMultiPartSMSInfo (GSM_MultiPartSMSInfo *Info); | ||
256 | |||
257 | /** | ||
258 | * Frees any allocated structures inside @ref GSM_MultiPartSMSInfo. | ||
259 | */ | ||
260 | void GSM_FreeMultiPartSMSInfo (GSM_MultiPartSMSInfo *Info); | ||
261 | |||
262 | /** | ||
263 | * Links SMS messages according to IDs. | ||
264 | */ | ||
265 | GSM_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 */ | ||
19 | static 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 */ | ||
79 | static 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 | |||
102 | void 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 | |||
181 | GSM_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 | |||
240 | GSM_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 | |||
306 | GSM_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 */ | ||
394 | static 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 | |||
420 | static 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 | |||
490 | GSM_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 | |||
574 | void 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 | */ | ||
610 | void 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 | */ | ||
25 | typedef 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 | */ | ||
41 | typedef 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 | */ | ||
77 | typedef 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 | */ | ||
90 | typedef 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 | */ | ||
103 | typedef 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 | */ | ||
112 | typedef 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 | */ | ||
125 | typedef 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 | */ | ||
157 | typedef 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 | */ | ||
167 | typedef 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 | */ | ||
185 | typedef 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 | */ | ||
219 | typedef 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 | */ | ||
277 | typedef 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 | */ | ||
367 | typedef 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 | |||
434 | GSM_Error GSM_DecodeSMSFrame(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout); | ||
435 | GSM_Error GSM_EncodeSMSFrame(GSM_SMSMessage *SMS, unsigned char *buffer, GSM_SMSMessageLayout Layout, int *length, bool clear); | ||
436 | |||
437 | GSM_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 | |||
440 | void GSM_DecodeUDHHeader(GSM_UDHHeader *UDH); | ||
441 | void GSM_EncodeUDHHeader(GSM_UDHHeader *UDH); | ||
442 | |||
443 | void 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 | */ | ||
459 | typedef 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 | */ | ||
477 | typedef 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 | */ | ||