wrong character in the GSM 03.38 table (ç for Ç)
[gammu.git] / libgammu / service / gsmdata.c
blob854689544118e4d4dcb3c8befc8b7f192122309c
1 /* (c) 2002-2004 by Marcin Wiacek */
3 #include <string.h>
4 #include <stdio.h>
6 #include <gammu-debug.h>
7 #include <gammu-datetime.h>
9 #include "gsmdata.h"
10 #include "../misc/coding/coding.h"
11 #include "../debug.h"
13 /* http://forum.nokia.com: OTA MMS Settings 1.0, OTA Settings 7.0 */
14 static void AddWAPSMSParameterText(unsigned char *Buffer, size_t *Length, unsigned char ID, char *Text, int Len)
16 int i;
18 Buffer[(*Length)++] = 0x87; /* PARM with attributes */
19 Buffer[(*Length)++] = ID;
20 Buffer[(*Length)++] = 0x11; /* VALUE */
21 Buffer[(*Length)++] = 0x03; /* Inline string */
22 for (i=0;i<Len;i++) {
23 Buffer[(*Length)++] = Text[i]; /* Text */
25 Buffer[(*Length)++] = 0x00; /* END Inline string */
26 Buffer[(*Length)++] = 0x01; /* END PARMeter */
29 /* http://forum.nokia.com: OTA MMS Settings 1.0, OTA Settings 7.0 */
30 static void AddWAPSMSParameterInt(unsigned char *Buffer, size_t *Length, unsigned char ID, unsigned char Value)
32 Buffer[(*Length)++] = 0x87; /* PARM with attributes */
33 Buffer[(*Length)++] = ID;
34 Buffer[(*Length)++] = Value;
35 Buffer[(*Length)++] = 0x01; /* END PARMeter */
38 /* http://forum.nokia.com : OTA MMS Settings 1.0, OTA Settings 7.0
39 * http://www.wapforum.org : Wireless Datagram Protocol
41 void NOKIA_EncodeWAPMMSSettingsSMSText(unsigned char *Buffer, size_t *Length, GSM_WAPSettings *settings, gboolean MMS)
43 int i;
44 unsigned char buffer[400];
46 Buffer[(*Length)++] = 0x01; /* Push ID */
47 Buffer[(*Length)++] = 0x06; /* PDU Type (push) */
48 Buffer[(*Length)++] = 0x2C; /* Headers length (content type + headers) */
49 strcpy(Buffer+(*Length),"\x1F\x2A");
50 (*Length)=(*Length)+2; /* Value length */
51 strcpy(Buffer+(*Length),"application/x-wap-prov.browser-settings");
52 (*Length)=(*Length)+39; /* MIME-Type */
53 Buffer[(*Length)++] = 0x00; /* end inline string */
54 strcpy(Buffer+(*Length),"\x81\xEA");
55 (*Length)=(*Length)+2; /* charset UTF-8 short int. */
56 strcpy(Buffer+(*Length),"\x01\x01");
57 (*Length)=(*Length)+2; /* version WBXML 1.1 */
58 Buffer[(*Length)++] = 0x6A; /* charset UTF-8 */
59 Buffer[(*Length)++] = 0x00; /* string table length */
61 Buffer[(*Length)++] = 0x45; /* CHARACTERISTIC-LIST with content */
62 Buffer[(*Length)++] = 0xC6; /* CHARACTERISTIC with content and attributes */
63 Buffer[(*Length)++] = 0x06; /* TYPE=ADDRESS */
64 Buffer[(*Length)++] = 0x01; /* END PARMeter */
65 switch (settings->Bearer) {
66 case WAPSETTINGS_BEARER_GPRS:
67 /* Bearer */
68 AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x49);
69 /* PPP_LOGINTYPE (manual login or not) */
70 if (settings->ManualLogin) {
71 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x65);
72 } else {
73 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x64);
75 /* PPP_AUTHTYPE*/
76 if (settings->IsNormalAuthentication) {
77 /* OTA_CSD_AUTHTYPE_PAP */
78 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x70);
79 } else {
80 /* OTA_CSD_AUTHTYPE_CHAP */
81 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x71);
83 /* GPRS_ACCESSPOINTNAME */
84 AddWAPSMSParameterText(Buffer, Length, 0x1C, DecodeUnicodeString(settings->DialUp), UnicodeLength(settings->DialUp));
85 /* PROXY */
86 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->IPAddress), UnicodeLength(settings->IPAddress));
87 /* PPP_AUTHNAME (user) */
88 AddWAPSMSParameterText(Buffer, Length, 0x23, DecodeUnicodeString(settings->User), UnicodeLength(settings->User));
89 /* PPP_AUTHSECRET (password) */
90 AddWAPSMSParameterText(Buffer, Length, 0x24, DecodeUnicodeString(settings->Password), UnicodeLength(settings->Password));
91 break;
92 case WAPSETTINGS_BEARER_DATA:
93 /* Bearer */
94 AddWAPSMSParameterInt(Buffer, Length, 0x12, 0x45);
95 /* CSD_DIALSTRING */
96 AddWAPSMSParameterText(Buffer, Length, 0x21, DecodeUnicodeString(settings->DialUp), UnicodeLength(settings->DialUp));
97 /* PROXY */
98 AddWAPSMSParameterText(Buffer, Length, 0x13, DecodeUnicodeString(settings->IPAddress), UnicodeLength(settings->IPAddress));
99 /* PPP_LOGINTYPE (manual login or not) */
100 if (settings->ManualLogin) {
101 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x65);
102 } else {
103 AddWAPSMSParameterInt(Buffer, Length, 0x1D, 0x64);
105 /* PPP_AUTHTYPE*/
106 if (settings->IsNormalAuthentication) {
107 /* OTA_CSD_AUTHTYPE_PAP */
108 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x70);
109 } else {
110 /* OTA_CSD_AUTHTYPE_CHAP */
111 AddWAPSMSParameterInt(Buffer, Length, 0x22, 0x71);
113 /* CSD_CALLTYPE (type of call) */
114 if (settings->IsISDNCall) {
115 /* ISDN */
116 AddWAPSMSParameterInt(Buffer, Length, 0x28, 0x73);
117 } else {
118 /* analogue */
119 AddWAPSMSParameterInt(Buffer, Length, 0x28, 0x72);
121 /* CSD_CALLSPEED (speed of call) */
122 switch (settings->Speed) {
123 case WAPSETTINGS_SPEED_AUTO:
124 AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6A);
125 break;
126 case WAPSETTINGS_SPEED_9600:
127 AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6B);
128 break;
129 case WAPSETTINGS_SPEED_14400:
130 AddWAPSMSParameterInt(Buffer, Length, 0x29, 0x6C);
132 /* PPP_AUTHNAME (user) */
133 AddWAPSMSParameterText(Buffer, Length, 0x23, DecodeUnicodeString(settings->User), UnicodeLength(settings->User));
134 /* PPP_AUTHSECRET (password) */
135 AddWAPSMSParameterText(Buffer, Length, 0x24, DecodeUnicodeString(settings->Password), UnicodeLength(settings->Password));
136 break;
137 case WAPSETTINGS_BEARER_SMS:
138 case WAPSETTINGS_BEARER_USSD:
139 break;
141 /* PORT */
142 if (settings->IsSecurity) {
143 if (settings->IsContinuous) {
144 /* Port = 9203. Continuous */
145 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x63);
146 } else {
147 /* Port = 9202. Temporary */
148 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x62);
150 } else {
151 if (settings->IsContinuous) {
152 /* Port = 9201. Continuous */
153 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x61);
154 } else {
155 /* Port = 9200. Temporary */
156 AddWAPSMSParameterInt(Buffer, Length, 0x14, 0x60);
159 Buffer[(*Length)++] = 0x01; /* END PARMeter */
161 /* URL */
162 Buffer[(*Length)++] = 0x86; /* CHARACTERISTIC-LIST with attributes */
163 if (MMS) {
164 Buffer[(*Length)++] = 0x7C; /* TYPE = MMSURL */
165 } else {
166 Buffer[(*Length)++] = 0x07; /* TYPE = URL */
168 Buffer[(*Length)++] = 0x11; /* VALUE */
169 Buffer[(*Length)++] = 0x03; /* Inline string */
170 sprintf(buffer,"%s",DecodeUnicodeString(settings->HomePage));
171 for (i=0;i<(int)strlen(buffer);i++) {
172 Buffer[(*Length)++] = buffer[i];/* Text */
174 Buffer[(*Length)++] = 0x00; /* END Inline string */
175 Buffer[(*Length)++] = 0x01; /* END PARMeter */
177 /* ISP_NAME (name) */
178 Buffer[(*Length)++] = 0xC6; /* CHARACTERISTIC with content and attributes */
179 Buffer[(*Length)++] = 0x08; /* TYPE=NAME */
180 Buffer[(*Length)++] = 0x01; /* END PARMeter */
181 /* Settings name */
182 AddWAPSMSParameterText(Buffer, Length, 0x15, DecodeUnicodeString(settings->Title), UnicodeLength(settings->Title));
183 Buffer[(*Length)++] = 0x01; /* END PARMeter */
184 Buffer[(*Length)++] = 0x01; /* END PARMeter */
187 /* http://forum.nokia.com: OTA Settings 7.0 */
188 /* first it used default/ISO coding */
189 /* Joergen Thomsen changed to UTF8 */
190 void NOKIA_EncodeWAPBookmarkSMSText(unsigned char *Buffer, size_t *Length, GSM_WAPBookmark *bookmark)
192 unsigned char buffer[100];
194 Buffer[(*Length)++] = 0x01; /* Push ID */
195 Buffer[(*Length)++] = 0x06; /* PDU Type (push) */
196 Buffer[(*Length)++] = 0x2D; /* Headers length (content type + headers) */
197 strcpy(Buffer+(*Length),"\x1F\x2B");
198 (*Length)=(*Length)+2; /* Value length */
199 strcpy(Buffer+(*Length),"application/x-wap-prov.browser-bookmarks");
200 (*Length)=(*Length)+40; /* MIME-Type */
201 Buffer[(*Length)++] = 0x00; /* end inline string */
202 strcpy(Buffer+(*Length),"\x81\xEA");
203 (*Length)=(*Length)+2; /* charset UTF-8 short int. */
205 /* added by Joergen Thomsen */
206 Buffer[(*Length)++] = 0x01; /* Version WBXML 1.1 */
207 Buffer[(*Length)++] = 0x01; /* Unknown public identifier */
208 Buffer[(*Length)++] = 0x6A; /* charset UTF-8 */
209 Buffer[(*Length)++] = 0x00; /* string table length */
211 Buffer[(*Length)++] = 0x45; /* CHARACTERISTIC-LIST with content */
212 /* URL */
213 Buffer[(*Length)++] = 0xC6; /* CHARACTERISTIC with content and attributes */
214 Buffer[(*Length)++] = 0x7F; /* TYPE = BOOKMARK */
215 Buffer[(*Length)++] = 0x01; /* END PARMeter */
217 /* TITLE */
218 EncodeUTF8(buffer, bookmark->Title);
219 AddWAPSMSParameterText(Buffer, Length, 0x15, buffer, strlen(buffer));
220 /* URL */
221 EncodeUTF8(buffer, bookmark->Address);
222 AddWAPSMSParameterText(Buffer, Length, 0x17, buffer, strlen(buffer));
224 Buffer[(*Length)++] = 0x01; /* END (CHARACTERISTIC) */
225 Buffer[(*Length)++] = 0x01; /* END (CHARACTERISTIC-LIST) */
229 * Encodes WAP indicator message.
231 * Produced output is WBXML, as defined in WAP-167.
233 void GSM_EncodeWAPIndicatorSMSText(unsigned char *Buffer, size_t *Length, char *Text, char *URL)
235 size_t i, len;
237 Buffer[(*Length)++] = 0x01; /* Push ID */
238 Buffer[(*Length)++] = 0x06; /* PDU Type (push) */
239 Buffer[(*Length)++] = 0x01; /* Headers length */
240 Buffer[(*Length)++] = 0xAE; /* MIME-Type: application/vnd.wap.sic */
242 Buffer[(*Length)++] = 0x02; /* WBXML 1.2 */
243 Buffer[(*Length)++] = 0x05; /* SI 1.0 Public Identifier */
244 Buffer[(*Length)++] = 0x6A; /* charset UTF-8 */
245 Buffer[(*Length)++] = 0x00; /* string table length */
246 Buffer[(*Length)++] = 0x45; /* SI with content */
247 Buffer[(*Length)++] = 0xC6; /* indication with content and attributes */
248 Buffer[(*Length)++] = 0x0B; /* address */
249 Buffer[(*Length)++] = 0x03; /* Inline string */
250 len = strlen(URL);
251 for (i = 0; i < len; i++) {
252 Buffer[(*Length)++] = URL[i];/* Text */
254 Buffer[(*Length)++] = 0x00; /* END Inline string */
256 #if 0
257 Buffer[(*Length)++] = 0x0A; /* created... */
258 Buffer[(*Length)++] = 0xC3; /* OPAQUE */
259 Buffer[(*Length)++] = 0x07; /* length */
260 Buffer[(*Length)++] = 0x20; /* year */
261 Buffer[(*Length)++] = 0x08; /* year */
262 Buffer[(*Length)++] = 0x12; /* month */
263 Buffer[(*Length)++] = 0x10; /* day */
264 Buffer[(*Length)++] = 0x00; /* hour */
265 Buffer[(*Length)++] = 0x00; /* minute */
266 Buffer[(*Length)++] = 0x00; /* second */
268 Buffer[(*Length)++] = 0x10; /* expires */
269 Buffer[(*Length)++] = 0xC3; /* OPAQUE */
270 Buffer[(*Length)++] = 0x04; /* length */
271 Buffer[(*Length)++] = 0x20; /* year */
272 Buffer[(*Length)++] = 0x10; /* year */
273 Buffer[(*Length)++] = 0x06; /* month */
274 Buffer[(*Length)++] = 0x25; /* day */
275 #endif
277 Buffer[(*Length)++] = 0x01; /* END (indication) */
278 Buffer[(*Length)++] = 0x03; /* Inline string */
279 len = strlen(Text);
280 for (i = 0; i < len; i++) {
281 Buffer[(*Length)++] = Text[i]; /* Text */
283 Buffer[(*Length)++] = 0x00; /* END Inline string */
284 Buffer[(*Length)++] = 0x01; /* END (indication) */
285 Buffer[(*Length)++] = 0x01; /* END (SI) */
288 GSM_Error GSM_EncodeURLFile(unsigned char *Buffer, size_t *Length, GSM_WAPBookmark *bookmark)
290 *Length+=sprintf(Buffer+(*Length), "BEGIN:VBKM%c%c",13,10);
291 *Length+=sprintf(Buffer+(*Length), "VERSION:1.0%c%c",13,10);
292 *Length+=sprintf(Buffer+(*Length), "TITLE:%s%c%c",DecodeUnicodeString(bookmark->Title),13,10);
293 *Length+=sprintf(Buffer+(*Length), "URL:%s%c%c",DecodeUnicodeString(bookmark->Address),13,10);
294 *Length+=sprintf(Buffer+(*Length), "BEGIN:ENV%c%c",13,10);
295 *Length+=sprintf(Buffer+(*Length), "X-IRMC-URL;QUOTED-PRINTABLE:=%c%c",13,10);
296 *Length+=sprintf(Buffer+(*Length), "[InternetShortcut] =%c%c",13,10);
297 *Length+=sprintf(Buffer+(*Length), "URL=%s%c%c",DecodeUnicodeString(bookmark->Address),13,10);
298 *Length+=sprintf(Buffer+(*Length), "END:ENV%c%c",13,10);
299 *Length+=sprintf(Buffer+(*Length), "END:VBKM%c%c",13,10);
301 return ERR_NONE;
304 /* -------------------------------- MMS ------------------------------------ */
306 /* SNIFFS, specs somewhere in http://www.wapforum.org */
307 void GSM_EncodeMMSIndicatorSMSText(unsigned char *Buffer, size_t *Length, GSM_MMSIndicator Indicator)
309 unsigned char buffer[200];
310 int i;
314 * WSP header
317 /* Transaction ID (maybe this should be random?) */
318 Buffer[(*Length)++] = 0xe6;
319 /* PDU type push */
320 Buffer[(*Length)++] = 0x06;
321 /* Header length */
322 Buffer[(*Length)++] = 0x22;
323 /* MIME type (header) */
324 strcpy(Buffer+(*Length),"application/vnd.wap.mms-message");
325 (*Length)=(*Length)+31;
326 Buffer[(*Length)++] = 0x00;
328 /* WAP push (x-wap-application.ua) */
329 Buffer[(*Length)++] = 0xaf;
330 Buffer[(*Length)++] = 0x84;
333 * MMS data
336 /* Transaction type */
337 Buffer[(*Length)++] = 0x8c;
338 /* m-notification-ind */
339 Buffer[(*Length)++] = 0x82;
341 /* Transaction ID, usually last part of address */
342 Buffer[(*Length)++] = 0x98;
343 i = strlen(Indicator.Address);
344 while (Indicator.Address[i] != '/' && i!=0) i--;
345 strcpy(Buffer+(*Length),Indicator.Address+i+1);
346 (*Length)=(*Length)+strlen(Indicator.Address+i+1);
347 Buffer[(*Length)++] = 0x00;
349 /* MMS version */
350 Buffer[(*Length)++] = 0x8d;
351 /* 1.2 (0x90 is 1.0) */
352 Buffer[(*Length)++] = 0x92;
354 /* Message class */
355 switch (Indicator.Class) {
356 case GSM_MMS_None:
357 break;
358 case GSM_MMS_Personal:
359 Buffer[(*Length)++] = 0x8a;
360 Buffer[(*Length)++] = 0x80;
361 break;
362 case GSM_MMS_Advertisement:
363 Buffer[(*Length)++] = 0x8a;
364 Buffer[(*Length)++] = 0x81;
365 break;
366 case GSM_MMS_Info:
367 Buffer[(*Length)++] = 0x8a;
368 Buffer[(*Length)++] = 0x82;
369 break;
370 case GSM_MMS_Auto:
371 Buffer[(*Length)++] = 0x8a;
372 Buffer[(*Length)++] = 0x83;
373 break;
376 if (Indicator.MessageSize > 0) {
377 /* Message size */
378 Buffer[(*Length)++] = 0x8e;
379 /* Length of size */
380 Buffer[(*Length)++] = 0x04;
381 Buffer[(*Length)++] = ((long)Indicator.MessageSize >> 24) & 0xff;
382 Buffer[(*Length)++] = ((long)Indicator.MessageSize >> 16) & 0xff;
383 Buffer[(*Length)++] = ((long)Indicator.MessageSize >> 8) & 0xff;
384 Buffer[(*Length)++] = ((long)Indicator.MessageSize >> 0) & 0xff;
387 /* Sender address */
388 Buffer[(*Length)++] = 0x89;
389 sprintf(buffer,"%s/TYPE=PLMN",Indicator.Sender);
390 /* Field size */
391 Buffer[(*Length)++] = strlen(buffer) + 2;
392 /* Sender address is present */
393 Buffer[(*Length)++] = 0x80;
394 strcpy(Buffer+(*Length),buffer);
395 (*Length)=(*Length)+strlen(buffer);
396 /* Zero terminate */
397 Buffer[(*Length)++] = 0x00;
399 /* Subject */
400 Buffer[(*Length)++] = 0x96;
401 strcpy(Buffer+(*Length),Indicator.Title);
402 (*Length)=(*Length)+strlen(Indicator.Title);
403 Buffer[(*Length)++] = 0x00;
405 strcpy(Buffer+(*Length),"\x88\x05\x81\x03\x02\xA3\xA3");
406 (*Length)=(*Length)+7;
408 /* Content location */
409 Buffer[(*Length)++] = 0x83;
410 strcpy(Buffer+(*Length),Indicator.Address);
411 (*Length)=(*Length)+strlen(Indicator.Address);
412 Buffer[(*Length)++] = 0x00;
415 GSM_Error GSM_ClearMMSMultiPart(GSM_EncodedMultiPartMMSInfo *info)
417 int i;
419 for (i=0;i<GSM_MAX_MULTI_MMS;i++) {
420 if (info->Entries[i].File.Buffer != NULL) {
421 free(info->Entries[i].File.Buffer);
422 info->Entries[i].File.Buffer=NULL;
426 memset(info,0,sizeof(GSM_EncodedMultiPartMMSInfo));
428 for (i=0;i<GSM_MAX_MULTI_MMS;i++) {
429 info->Entries[i].File.Buffer = NULL;
431 info->DateTimeAvailable = FALSE;
433 return ERR_NONE;
436 void GSM_AddWAPMIMEType(int type, char *buffer)
438 char tmpbuf[100];
439 switch (type) {
440 case 3:
441 strcat(buffer, "text/plain");
442 break;
443 case 6:
444 strcat(buffer, "text/x-vCalendar");
445 break;
446 case 7:
447 strcat(buffer, "text/x-vCard");
448 break;
449 case 29:
450 strcat(buffer, "image/gif");
451 break;
452 case 30:
453 strcat(buffer, "image/jpeg");
454 break;
455 case 35:
456 strcat(buffer, "application/vnd.wap.multipart.mixed");
457 break;
458 case 51:
459 strcat(buffer, "application/vnd.wap.multipart.related");
460 break;
461 default:
462 sprintf(tmpbuf, "application/x-%d", type);
463 strcat(buffer, tmpbuf);
464 break;
468 GSM_Error GSM_DecodeMMSFileToMultiPart(GSM_Debug_Info *di, GSM_File *file, GSM_EncodedMultiPartMMSInfo *info)
470 size_t pos = 0;
471 int type=0,parts,j;
472 int i,len2,len3,value2;
473 long value;
474 time_t timet;
475 GSM_DateTime Date;
476 char buff[200],buff2[200];
478 /* header */
479 while(1) {
480 if (pos > file->Used) break;
481 if (!(file->Buffer[pos] & 0x80)) break;
482 switch (file->Buffer[pos++] & 0x7F) {
483 case 0x01:
484 smfprintf(di, " BCC : not done yet\n");
485 return ERR_FILENOTSUPPORTED;
486 case 0x02:
487 smfprintf(di, " CC : ");
488 i = 0;
489 while (file->Buffer[pos]!=0x00) {
490 buff[i++] = file->Buffer[pos++];
492 buff[i] = 0;
493 pos++;
494 if (strstr(buff,"/TYPE=PLMN")!=NULL) {
495 buff[strlen(buff)-10] = 0;
496 info->CCType = MMSADDRESS_PHONE;
497 smfprintf(di, "phone %s\n",buff);
498 } else {
499 info->CCType = MMSADDRESS_UNKNOWN;
500 smfprintf(di, "%s\n",buff);
502 EncodeUnicode(info->CC,buff,strlen(buff));
503 break;
504 case 0x03:
505 smfprintf(di, " Content location : not done yet\n");
506 return ERR_FILENOTSUPPORTED;
507 case 0x04:
508 smfprintf(di, " Content type : ");
509 buff[0] = 0;
510 if (file->Buffer[pos] <= 0x1E) {
511 len2 = file->Buffer[pos++];
512 type = file->Buffer[pos++] & 0x7f;
513 GSM_AddWAPMIMEType(type, buff);
514 i=0;
515 while (i<len2) {
516 switch (file->Buffer[pos+i]) {
517 case 0x89:
518 strcat(buff, "; type=");
519 i++;
520 while (file->Buffer[pos+i]!=0x00) {
521 buff[strlen(buff)+1] = 0;
522 buff[strlen(buff)] = file->Buffer[pos+i];
523 i++;
525 i++;
526 break;
527 case 0x8A:
528 strcat(buff, "; start=");
529 i++;
530 while (file->Buffer[pos+i]!=0x00) {
531 buff[strlen(buff)+1] = 0;
532 buff[strlen(buff)] = file->Buffer[pos+i];
533 i++;
535 i++;
536 break;
537 default:
538 i++;
539 break;
542 pos+=len2-1;
543 } else if (file->Buffer[pos] == 0x1F) {
544 /* hack from coded files */
545 len2 = file->Buffer[pos++];
546 type = file->Buffer[pos++] & 0x7f;
547 type +=2;
548 GSM_AddWAPMIMEType(type, buff);
549 i=0;
550 while (i<len2) {
551 switch (file->Buffer[pos+i]) {
552 case 0x89:
553 strcat(buff, "; type=");
554 i++;
555 while (file->Buffer[pos+i]!=0x00) {
556 buff[strlen(buff)+1] = 0;
557 buff[strlen(buff)] = file->Buffer[pos+i];
558 i++;
560 i++;
561 break;
562 case 0x8A:
563 strcat(buff, "; start=");
564 i++;
565 while (file->Buffer[pos+i]!=0x00) {
566 buff[strlen(buff)+1] = 0;
567 buff[strlen(buff)] = file->Buffer[pos+i];
568 i++;
570 i++;
571 break;
572 default:
573 i++;
574 break;
577 pos+=len2+2;
578 } else if (file->Buffer[pos] >= 0x20 && file->Buffer[pos] <= 0x7F) {
579 smfprintf(di, "not done yet 2\n");
580 return ERR_FILENOTSUPPORTED;
581 } else if (file->Buffer[pos] >= 0x80 && file->Buffer[pos] < 0xFF) {
582 type = file->Buffer[pos++] & 0x7f;
583 GSM_AddWAPMIMEType(type, buff);
585 smfprintf(di, "%s\n",buff);
586 EncodeUnicode(info->ContentType,buff,strlen(buff));
587 break;
588 case 0x05:
589 smfprintf(di, " Date : ");
590 value=0;
591 len2 = file->Buffer[pos++];
592 for (i=0;i<len2;i++) {
593 value=value<<8;
594 value |= file->Buffer[pos++];
596 timet = value;
597 Fill_GSM_DateTime(&Date, timet);
598 smfprintf(di, "%s\n",OSDateTime(Date,0));
599 info->DateTimeAvailable = TRUE;
600 memcpy(&info->DateTime,&Date,sizeof(GSM_DateTime));
601 break;
602 case 0x06:
603 smfprintf(di, " Delivery report : ");
604 info->MMSReportAvailable = TRUE;
605 switch(file->Buffer[pos++]) {
606 case 0x80:
607 smfprintf(di, "yes\n");
608 info->MMSReport = TRUE;
609 break;
610 case 0x81:
611 smfprintf(di, "no\n");
612 info->MMSReport = FALSE;
613 break;
614 default:
615 smfprintf(di, "unknown\n");
616 return ERR_FILENOTSUPPORTED;
618 break;
619 case 0x08:
620 smfprintf(di, " Expiry : ");
621 pos++; /* length? */
622 switch (file->Buffer[pos]) {
623 case 0x80: smfprintf(di, "date - ignored\n"); break;
624 case 0x81: smfprintf(di, "seconds - ignored\n"); break;
625 default : smfprintf(di, "unknown %02x\n",file->Buffer[pos]); break;
627 pos++;
628 pos++; /* expiry */
629 pos++; /* expiry */
630 pos++; /* expiry */
631 pos++; /* expiry */
632 break;
633 case 0x09:
634 pos++;
635 pos++;
636 if (file->Buffer[pos-1] == 128) {
637 smfprintf(di, " From : ");
638 len2=file->Buffer[pos-2]-1;
639 for (i=0;i<len2;i++) {
640 buff[i] = file->Buffer[pos++];
642 buff[i] = 0;
643 if (strstr(buff,"/TYPE=PLMN")!=NULL) {
644 buff[strlen(buff)-10] = 0;
645 info->SourceType = MMSADDRESS_PHONE;
646 smfprintf(di, "phone %s\n",buff);
647 } else {
648 info->SourceType = MMSADDRESS_UNKNOWN;
649 smfprintf(di, "%s\n",buff);
651 EncodeUnicode(info->Source,buff,strlen(buff));
653 break;
654 case 0x0A:
655 smfprintf(di, " Message class : ");
656 switch (file->Buffer[pos++]) {
657 case 0x80: smfprintf(di, "personal\n"); break;
658 case 0x81: smfprintf(di, "advertisment\n"); break;
659 case 0x82: smfprintf(di, "informational\n"); break;
660 case 0x83: smfprintf(di, "auto\n"); break;
661 default : smfprintf(di, "unknown\n"); break;
663 break;
664 case 0x0B:
665 smfprintf(di, " Message ID : ");
666 while (file->Buffer[pos]!=0x00) {
667 smfprintf(di, "%c",file->Buffer[pos]);
668 pos++;
670 smfprintf(di, "\n");
671 pos++;
672 break;
673 case 0x0C:
674 smfprintf(di, " Message type : ");
675 switch (file->Buffer[pos++]) {
676 case 0x80: sprintf(info->MSGType,"m-send-req"); break;
677 case 0x81: sprintf(info->MSGType,"m-send-conf"); break;
678 case 0x82: sprintf(info->MSGType,"m-notification-ind"); break;
679 case 0x83: sprintf(info->MSGType,"m-notifyresp-ind"); break;
680 case 0x84: sprintf(info->MSGType,"m-retrieve-conf"); break;
681 case 0x85: sprintf(info->MSGType,"m-acknowledge-ind"); break;
682 case 0x86: sprintf(info->MSGType,"m-delivery-ind"); break;
683 default : smfprintf(di, "unknown\n"); return ERR_FILENOTSUPPORTED;
685 smfprintf(di, "%s\n",info->MSGType);
686 break;
687 case 0x0D:
688 value2 = file->Buffer[pos] & 0x7F;
689 smfprintf(di, " MMS version : %i.%i\n", (value2 & 0x70) >> 4, value2 & 0x0f);
690 pos++;
691 break;
692 case 0x0E:
693 smfprintf(di, " Message size : ignored for now\n");
694 pos += 2;
695 break;
696 case 0x0F:
697 smfprintf(di, " Priority : ");
698 switch (file->Buffer[pos++]) {
699 case 0x80: smfprintf(di, "low\n"); break;
700 case 0x81: smfprintf(di, "normal\n"); break;
701 case 0x82: smfprintf(di, "high\n"); break;
702 default : smfprintf(di, "unknown\n"); break;
704 break;
705 case 0x10:
706 smfprintf(di, " Read reply : ");
707 switch(file->Buffer[pos++]) {
708 case 0x80: smfprintf(di, "yes\n"); break;
709 case 0x81: smfprintf(di, "no\n"); break;
710 default : smfprintf(di, "unknown\n");
712 break;
713 case 0x11:
714 smfprintf(di, " Report allowed : not done yet\n");
715 return ERR_FILENOTSUPPORTED;
716 case 0x12:
717 smfprintf(di, " Response status : not done yet\n");
718 return ERR_FILENOTSUPPORTED;
719 case 0x13:
720 smfprintf(di, " Response text : not done yet\n");
721 return ERR_FILENOTSUPPORTED;
722 case 0x14:
723 smfprintf(di, " Sender visibility : not done yet\n");
724 return ERR_FILENOTSUPPORTED;
725 case 0x15:
726 smfprintf(di, " Status : ");
727 switch (file->Buffer[pos++]) {
728 case 0x80: smfprintf(di, "expired\n"); break;
729 case 0x81: smfprintf(di, "retrieved\n"); break;
730 case 0x82: smfprintf(di, "rejected\n"); break;
731 case 0x83: smfprintf(di, "deferred\n"); break;
732 case 0x84: smfprintf(di, "unrecognized\n"); break;
733 default : smfprintf(di, "unknown\n");
735 pos++;
736 pos++;
737 break;
738 case 0x16:
739 smfprintf(di, " Subject : ");
740 if (file->Buffer[pos+1]==0xEA) {
741 pos+=2;
743 i = 0;
744 while (file->Buffer[pos]!=0x00) {
745 buff[i++] = file->Buffer[pos++];
747 buff[i] = 0;
748 smfprintf(di, "%s\n",buff);
749 EncodeUnicode(info->Subject,buff,strlen(buff));
750 pos++;
751 break;
752 case 0x17:
753 smfprintf(di, " To : ");
754 i = 0;
755 while (file->Buffer[pos]!=0x00) {
756 buff[i++] = file->Buffer[pos++];
758 buff[i] = 0;
759 if (strstr(buff,"/TYPE=PLMN")!=NULL) {
760 buff[strlen(buff)-10] = 0;
761 info->DestinationType = MMSADDRESS_PHONE;
762 smfprintf(di, "phone %s\n",buff);
763 } else {
764 info->DestinationType = MMSADDRESS_UNKNOWN;
765 smfprintf(di, "%s\n",buff);
767 EncodeUnicode(info->Destination,buff,strlen(buff));
768 pos++;
769 break;
770 case 0x18:
771 smfprintf(di, " Transaction ID : ");
772 while (file->Buffer[pos]!=0x00) {
773 smfprintf(di, "%c",file->Buffer[pos]);
774 pos++;
776 smfprintf(di, "\n");
777 pos++;
778 break;
779 default:
780 smfprintf(di, " unknown1\n");
781 break;
785 /* if we don't have any parts, we exit */
786 if (type != 35 && type != 51) return ERR_NONE;
788 value = 0;
789 while (TRUE) {
790 value = value << 7;
791 value |= file->Buffer[pos] & 0x7F;
792 pos++;
793 if (!(file->Buffer[pos-1] & 0x80)) break;
795 value2 = value;
796 smfprintf(di, " Parts : %i\n",value2);
797 parts = value;
799 for (j=0;j<parts;j++) {
800 value = 0;
801 while (TRUE) {
802 value = value << 7;
803 value |= file->Buffer[pos] & 0x7F;
804 pos++;
805 if (!(file->Buffer[pos-1] & 0x80)) break;
807 smfprintf(di, " Header len: %li",value);
808 len2 = value;
810 value = 0;
811 while (TRUE) {
812 value = value << 7;
813 value |= file->Buffer[pos] & 0x7F;
814 pos++;
815 if (!(file->Buffer[pos-1] & 0x80)) break;
817 smfprintf(di, ", data len: %li\n",value);
818 len3 = value;
820 /* content type */
821 i = 0;
822 buff[0] = 0;
823 smfprintf(di, " Content type : ");
824 if (file->Buffer[pos] >= 0x80) {
825 type = file->Buffer[pos] & 0x7f;
826 GSM_AddWAPMIMEType(type, buff);
827 } else if (file->Buffer[pos+i] == 0x1F) {
828 i++;
829 buff[0] = 0;
830 /* len4 = file->Buffer[pos+i]; */
831 i++;
832 if (!(file->Buffer[pos+i] & 0x80)) {
833 while (file->Buffer[pos+i]!=0x00) {
834 buff[strlen(buff)+1] = 0;
835 buff[strlen(buff)] = file->Buffer[pos+i];
836 i++;
838 i++;
839 } else {
840 value = file->Buffer[pos+i] & 0x7F;
841 GSM_AddWAPMIMEType(value, buff);
842 i++;
844 } else if (file->Buffer[pos+i] < 0x1F) {
845 i++;
846 if (file->Buffer[pos+i] & 0x80) {
847 type = file->Buffer[pos+i] & 0x7f;
848 GSM_AddWAPMIMEType(type, buff);
849 i++;
850 } else {
851 while (file->Buffer[pos+i]!=0x00) {
852 buff[strlen(buff)+1] = 0;
853 buff[strlen(buff)] = file->Buffer[pos+i];
854 i++;
856 i++;
858 } else {
859 while (file->Buffer[pos+i]!=0x00) {
860 buff[strlen(buff)+1] = 0;
861 buff[strlen(buff)] = file->Buffer[pos+i];
862 i++;
865 smfprintf(di, "%s\n",buff);
866 EncodeUnicode(info->Entries[info->EntriesNum].ContentType,buff,strlen(buff));
868 pos+=i;
869 len2-=i;
871 i=0;
872 while (i<len2) {
873 switch (file->Buffer[pos+i]) {
874 case 0x81:
875 i++;
876 break;
877 case 0x83:
878 break;
879 case 0x85:
880 /* mms 1.0 file from GSM operator */
881 buff2[0] = 0;
882 i++;
883 while (file->Buffer[pos+i]!=0x00) {
884 buff2[strlen(buff2)+1] = 0;
885 buff2[strlen(buff2)] = file->Buffer[pos+i];
886 i++;
888 EncodeUnicode(info->Entries[info->EntriesNum].File.Name,buff2,strlen(buff2));
889 break;
890 case 0x86:
891 while (file->Buffer[pos+i]!=0x00) i++;
892 break;
893 case 0x89:
894 strcpy(buff, "; type=");
895 i++;
896 while (file->Buffer[pos+i]!=0x00) {
897 buff[strlen(buff)+1] = 0;
898 buff[strlen(buff)] = file->Buffer[pos+i];
899 i++;
901 i++;
902 break;
903 case 0x8A:
904 strcpy(buff, "; type=");
905 i++;
906 while (file->Buffer[pos+i]!=0x00) {
907 buff[strlen(buff)+1] = 0;
908 buff[strlen(buff)] = file->Buffer[pos+i];
909 i++;
911 i++;
912 break;
913 case 0x8E:
914 i++;
915 buff[0] = 0;
916 smfprintf(di, " Name : ");
917 while (file->Buffer[pos+i]!=0x00) {
918 buff[strlen(buff)+1] = 0;
919 buff[strlen(buff)] = file->Buffer[pos+i];
920 i++;
922 smfprintf(di, "%s\n",buff);
923 EncodeUnicode(info->Entries[info->EntriesNum].File.Name,buff,strlen(buff));
924 break;
925 case 0xAE:
926 while (file->Buffer[pos+i]!=0x00) i++;
927 break;
928 case 0xC0:
929 i++;
930 i++;
931 buff[0] = 0;
932 smfprintf(di, " SMIL CID : ");
933 while (file->Buffer[pos+i]!=0x00) {
934 buff[strlen(buff)+1] = 0;
935 buff[strlen(buff)] = file->Buffer[pos+i];
936 i++;
938 smfprintf(di, "%s\n",buff);
939 EncodeUnicode(info->Entries[info->EntriesNum].SMIL,buff,strlen(buff));
940 break;
941 default:
942 smfprintf(di, "unknown3 %02x\n",file->Buffer[pos+i]);
944 i++;
946 pos+=i;
948 /* data */
949 info->Entries[info->EntriesNum].File.Buffer = (unsigned char *)realloc(info->Entries[info->EntriesNum].File.Buffer,len3);
950 info->Entries[info->EntriesNum].File.Used = len3;
951 memcpy(info->Entries[info->EntriesNum].File.Buffer,file->Buffer+pos,len3);
953 info->EntriesNum++;
954 pos+=len3;
956 return ERR_NONE;
959 /* How should editor hadle tabs in this file? Add editor commands here.
960 * vim: noexpandtab sw=8 ts=8 sts=8: