Translated using Weblate.
[gammu.git] / gammu / message.c
blob2f5d98317d180603b8bcca608afcdea3d6a5daeb
1 #define _GNU_SOURCE /* For strcasestr */
2 #include <string.h>
3 #include <stdarg.h>
4 #include <signal.h>
5 #include <stdlib.h>
6 #include <ctype.h>
7 #ifdef WIN32
8 # include <io.h>
9 #else
10 # include <unistd.h>
11 #endif
13 #include "../helper/locales.h"
15 #include "common.h"
16 #include "message.h"
17 #include "memory.h"
18 #include "../helper/formats.h"
19 #include "calendar.h"
20 #include "misc.h"
21 #include "backup.h"
23 #include "../helper/message-display.h"
24 #include "../helper/memory-display.h"
25 #include "../helper/message-cmdline.h"
26 #include "../helper/printing.h"
27 #include "../helper/string.h"
28 #include "../helper/cmdline.h"
30 volatile gboolean wasincomingsms = FALSE;
31 volatile int num_replies = 0;
33 GSM_MultiSMSMessage IncomingSMSData;
35 void IncomingSMS(GSM_StateMachine *sm UNUSED, GSM_SMSMessage *sms, void *user_data)
37 printf("%s\n", _("SMS message received"));
38 fflush(stdout);
40 if (wasincomingsms) {
41 printf("%s\n", _("We already have one pending, ignoring this one!"));
42 fflush(stdout);
43 return;
45 wasincomingsms = TRUE;
46 IncomingSMSData.SMS[0] = *sms;
47 IncomingSMSData.Number = 1;
50 void DisplayIncomingSMS(void)
52 GSM_SMSFolders folders;
53 GSM_Error error;
55 if (IncomingSMSData.SMS[0].State == 0) {
56 error=GSM_GetSMSFolders(gsm, &folders);
57 Print_Error(error);
59 error=GSM_GetSMS(gsm, &IncomingSMSData);
61 switch (error) {
62 case ERR_EMPTY:
63 printf(_("Location %i\n"),IncomingSMSData.SMS[0].Location);
64 printf("%s\n", _("Empty"));
65 fflush(stdout);
66 break;
67 default:
68 Print_Error(error);
69 PrintSMSLocation(&IncomingSMSData.SMS[0], &folders);
72 DisplayMultiSMSInfo(&IncomingSMSData,FALSE,FALSE,NULL, gsm);
73 wasincomingsms = FALSE;
76 void IncomingCB(GSM_StateMachine *sm UNUSED, GSM_CBMessage *CB, void *user_data)
78 printf("%s\n", _("CB message received"));
79 printf(_("Channel %i, text \"%s\"\n"),CB->Channel,DecodeUnicodeConsole(CB->Text));
80 fflush(stdout);
83 void IncomingUSSD(GSM_StateMachine *sm UNUSED, GSM_USSDMessage *ussd, void *user_data)
85 printf("%s\n", _("USSD received"));
86 printf(LISTFORMAT, _("Status"));
88 switch(ussd->Status) {
89 case USSD_NoActionNeeded:
90 printf("%s\n", _("No action needed"));
91 break;
92 case USSD_ActionNeeded:
93 printf("%s\n", _("Action needed"));
94 break;
95 case USSD_Terminated:
96 printf("%s\n", _("Terminated"));
97 break;
98 case USSD_AnotherClient:
99 printf("%s\n", _("Another client replied"));
100 break;
101 case USSD_NotSupported:
102 printf("%s\n", _("Not supported"));
103 break;
104 case USSD_Timeout:
105 printf("%s\n", _("Timeout"));
106 break;
107 #ifndef CHECK_CASES
108 default:
109 #endif
110 case USSD_Unknown:
111 printf("%s\n", _("Unknown"));
112 break;
114 printf(LISTFORMAT "\"%s\"\n", _("Service reply"), DecodeUnicodeConsole(ussd->Text));
115 fflush(stdout);
118 void IncomingUSSD2(GSM_StateMachine *sm, GSM_USSDMessage *ussd, void * user_data)
120 IncomingUSSD(sm, ussd, user_data);
121 num_replies++;
124 void GetUSSD(int argc UNUSED, char *argv[])
126 GSM_Error error;
127 int last_replies;
128 time_t last_reply;
130 GSM_Init(TRUE);
132 signal(SIGINT, interrupt);
133 fprintf(stderr, "%s\n", _("Press Ctrl+C to break..."));
134 fflush(stderr);
136 GSM_SetIncomingUSSDCallback(gsm, IncomingUSSD2, NULL);
138 error=GSM_SetIncomingUSSD(gsm,TRUE);
139 Print_Error(error);
141 error=GSM_DialService(gsm, argv[2]);
142 /* Fallback to voice call, it can work with some phones */
143 if (error == ERR_NOTIMPLEMENTED || error == ERR_NOTSUPPORTED) {
144 error=GSM_DialVoice(gsm, argv[2], GSM_CALL_DefaultNumberPresence);
146 Print_Error(error);
148 num_replies = 0;
149 last_replies = 0;
150 last_reply = time(NULL);
151 while (!gshutdown) {
152 if (num_replies != last_replies) {
153 last_replies = num_replies;
154 last_reply = time(NULL);
155 } else if (num_replies == 0 && difftime(time(NULL), last_reply) > 60) {
156 /* Wait one minute for reply */
157 gshutdown = TRUE;
158 } else if (num_replies > 0 && difftime(time(NULL), last_reply) > 30) {
159 /* Wait for consequent replies for 30 seconds */
160 gshutdown = TRUE;
162 GSM_ReadDevice(gsm, FALSE);
165 error=GSM_SetIncomingUSSD(gsm, FALSE);
166 Print_Error(error);
168 GSM_Terminate();
171 void SetSMSC(int argc, char *argv[])
173 GSM_Error error;
174 GSM_SMSC smsc;
176 smsc.Location = GetInt(argv[2]);
177 if (smsc.Location < 1) {
178 printf_err(_("Invalid SMSC location: %s\n"), argv[2]);
179 return;
181 GSM_Init(TRUE);
183 error = GSM_GetSMSC(gsm, &smsc);
184 Print_Error(error);
186 EncodeUnicode(smsc.Number, argv[3], strlen(argv[3]));
188 error = GSM_SetSMSC(gsm, &smsc);
189 Print_Error(error);
191 GSM_Terminate();
194 void GetSMSC(int argc, char *argv[])
196 GSM_SMSC smsc;
197 GSM_Error error;
198 int start=0, stop=0, i=0;
200 if (argc == 2) {
201 start = 1;
202 stop = 1;
203 } else {
204 GetStartStop(&start, &stop, 2, argc, argv);
207 GSM_Init(TRUE);
209 for (i=start;i<=stop;i++) {
210 smsc.Location=i;
212 error=GSM_GetSMSC(gsm, &smsc);
213 Print_Error(error);
215 printf(LISTFORMAT "%d\n", _("Location"), smsc.Location);
217 if (UnicodeLength(smsc.Name) != 0) {
218 printf(LISTFORMAT "\"%s\"\n", _("Name"),DecodeUnicodeConsole(smsc.Name));
220 printf(LISTFORMAT "\"%s\"\n", _("Number"),DecodeUnicodeConsole(smsc.Number));
221 printf(LISTFORMAT "\"%s\"\n", _("Default number"),DecodeUnicodeConsole(smsc.DefaultNumber));
223 printf(LISTFORMAT, _("Format"));
224 switch (smsc.Format) {
225 case SMS_FORMAT_Text : printf("%s", _("Text")); break;
226 case SMS_FORMAT_Fax : printf("%s", _("Fax")); break;
227 case SMS_FORMAT_Email : printf("%s", _("Email")); break;
228 case SMS_FORMAT_Pager : printf("%s", _("Pager")); break;
230 printf("\n");
232 printf(LISTFORMAT, _("Validity"));
234 switch (smsc.Validity.Relative) {
235 case SMS_VALID_1_Hour :
236 PRINTHOURS(1);
237 break;
238 case SMS_VALID_6_Hours :
239 PRINTHOURS(6);
240 break;
241 case SMS_VALID_1_Day :
242 PRINTDAYS(1);
243 break;
244 case SMS_VALID_3_Days :
245 PRINTDAYS(3);
246 break;
247 case SMS_VALID_1_Week :
248 PRINTWEEKS(1);
249 break;
250 case SMS_VALID_Max_Time :
251 printf("%s", _("Maximum time"));
252 break;
253 default:
254 /* Typecasting is here needed to silent GCC warning.
255 * Validity usually fits in some unsigned type so it is always >= 0 */
256 if ((int)smsc.Validity.Relative >= 0 && smsc.Validity.Relative <= 143) {
257 PRINTMINUTES((smsc.Validity.Relative + 1) * 5);
258 } else if (smsc.Validity.Relative >= 144 && smsc.Validity.Relative <= 167) {
259 PRINTMINUTES(12 * 60 + (smsc.Validity.Relative - 143) * 30);
260 } else if (smsc.Validity.Relative >= 168 && smsc.Validity.Relative <= 196) {
261 PRINTDAYS(smsc.Validity.Relative - 166);
262 } else if (smsc.Validity.Relative >= 197 && smsc.Validity.Relative <= 255) {
263 PRINTWEEKS(smsc.Validity.Relative - 192);
266 printf("\n");
267 fflush(stdout);
269 GSM_Terminate();
272 void GetSMS(int argc, char *argv[])
274 GSM_Error error;
275 GSM_MultiSMSMessage sms;
276 GSM_SMSFolders folders;
277 int start=0, stop=0, j=0;
278 long int folder;
280 GetStartStop(&start, &stop, 3, argc, argv);
281 folder = GetInt(argv[2]);
283 GSM_Init(TRUE);
285 error=GSM_GetSMSFolders(gsm, &folders);
286 Print_Error(error);
288 for (j = start; j <= stop; j++) {
289 sms.SMS[0].Folder = folder;
290 sms.SMS[0].Location = j;
291 sms.Number = 0;
292 error=GSM_GetSMS(gsm, &sms);
293 switch (error) {
294 case ERR_EMPTY:
295 printf(_("Location %i\n"),sms.SMS[0].Location);
296 printf("%s\n", _("Empty"));
297 break;
298 default:
299 Print_Error(error);
300 PrintSMSLocation(&sms.SMS[0], &folders);
301 DisplayMultiSMSInfo(&sms,FALSE,FALSE,NULL, gsm);
304 fflush(stdout);
305 GSM_Terminate();
308 void DeleteSMS(int argc, char *argv[])
310 GSM_Error error;
311 GSM_SMSMessage sms;
312 int start=0, stop=0, i=0;
314 sms.Folder = GetInt(argv[2]);
316 GetStartStop(&start, &stop, 3, argc, argv);
318 GSM_Init(TRUE);
320 for (i=start;i<=stop;i++) {
321 sms.Location = i;
322 error=GSM_DeleteSMS(gsm, &sms);
323 Print_Error(error);
325 GSM_Terminate();
328 void GetAllSMS(int argc, char *argv[])
330 GSM_Error error;
331 GSM_MultiSMSMessage sms;
332 GSM_SMSFolders folders;
333 gboolean start = TRUE;
334 int smsnum=0,smspos=0;
335 #ifndef GSM_ENABLE_BACKUP
336 void *BackupPtr = NULL;
337 #else
338 GSM_Backup *BackupPtr = NULL;
339 GSM_Backup Backup;
341 GSM_ClearBackup(&Backup);
342 BackupPtr = &Backup;
343 #endif
345 sms.Number = 0;
346 sms.SMS[0].Location = 0;
348 GSM_Init(TRUE);
350 #ifdef GSM_ENABLE_BACKUP
351 if (argc == 3 && strcasecmp(argv[2],"-pbk") == 0) {
352 ReadPhonebook(Backup.PhonePhonebook, MEM_ME, NULL, GSM_BACKUP_MAX_PHONEPHONEBOOK, NULL, TRUE);
353 ReadPhonebook(Backup.SIMPhonebook, MEM_SM, NULL, GSM_BACKUP_MAX_SIMPHONEBOOK, NULL, TRUE);
355 #endif
357 error=GSM_GetSMSFolders(gsm, &folders);
358 Print_Error(error);
360 while (error == ERR_NONE) {
361 sms.SMS[0].Folder=0x00;
362 error=GSM_GetNextSMS(gsm, &sms, start);
364 switch (error) {
365 case ERR_EMPTY:
366 break;
367 case ERR_CORRUPTED:
368 fprintf(stderr, "\n%s\n", _("Corrupted message, skipping"));
369 fflush(stderr);
370 error = ERR_NONE;
371 continue;
372 default:
373 Print_Error(error);
374 PrintSMSLocation(&sms.SMS[0], &folders);
375 smspos++;
376 smsnum+=sms.Number;
377 DisplayMultiSMSInfo(&sms, FALSE, FALSE, BackupPtr, gsm);
379 start=FALSE;
381 printf("\n\n");
382 printf(_("%i SMS parts in %i SMS sequences"),smsnum,smspos);
383 printf("\n");
384 fflush(stdout);
386 #ifdef GSM_ENABLE_BACKUP
387 GSM_FreeBackup(&Backup);
388 #endif
389 GSM_Terminate();
392 void GetEachSMS(int argc, char *argv[])
394 GSM_Error error;
395 GSM_MultiSMSMessage *GetSMSData[GSM_PHONE_MAXSMSINFOLDER],*SortedSMS[GSM_PHONE_MAXSMSINFOLDER],sms;
396 GSM_SMSFolders folders;
397 gboolean start=TRUE, ems=TRUE;
398 int GetSMSNumber=0,i=0,j=0,smsnum=0,smspos=0;
399 #ifndef GSM_ENABLE_BACKUP
400 void *BackupPtr = NULL;
401 #else
402 GSM_Backup *BackupPtr = NULL;
403 GSM_Backup Backup;
405 GSM_ClearBackup(&Backup);
406 BackupPtr = &Backup;
407 #endif
409 sms.Number = 0;
410 sms.SMS[0].Location = 0;
412 GetSMSData[0] = NULL;
414 GSM_Init(TRUE);
416 #ifdef GSM_ENABLE_BACKUP
417 if (argc == 3 && strcasecmp(argv[2],"-pbk") == 0) {
418 ReadPhonebook(Backup.PhonePhonebook, MEM_ME, NULL, GSM_BACKUP_MAX_PHONEPHONEBOOK, NULL, TRUE);
419 ReadPhonebook(Backup.SIMPhonebook, MEM_SM, NULL, GSM_BACKUP_MAX_SIMPHONEBOOK, NULL, TRUE);
421 #endif
423 error=GSM_GetSMSFolders(gsm, &folders);
424 Print_Error(error);
426 fprintf(stderr, LISTFORMAT, _("Reading"));
428 while (error == ERR_NONE) {
429 if (GetSMSNumber==GSM_PHONE_MAXSMSINFOLDER-1) {
430 fprintf(stderr, "\n%s\n", _("SMS counter overflow"));
431 break;
433 sms.SMS[0].Folder=0x00;
434 error=GSM_GetNextSMS(gsm, &sms, start);
436 switch (error) {
437 case ERR_EMPTY:
438 break;
439 case ERR_CORRUPTED:
440 fprintf(stderr, "\n%s\n", _("Corrupted message, skipping"));
441 error = ERR_NONE;
442 continue;
443 default:
444 Print_Error(error);
445 GetSMSData[GetSMSNumber] = malloc(sizeof(GSM_MultiSMSMessage));
447 if (GetSMSData[GetSMSNumber] == NULL) Print_Error(ERR_MOREMEMORY);
448 GetSMSData[GetSMSNumber+1] = NULL;
449 memcpy(GetSMSData[GetSMSNumber],&sms,sizeof(GSM_MultiSMSMessage));
450 GetSMSNumber++;
452 fprintf(stderr,"*");
453 fflush(stderr);
454 start=FALSE;
456 fprintf(stderr,"\n");
457 fflush(stderr);
459 error = GSM_LinkSMS(GSM_GetDebug(gsm), GetSMSData, SortedSMS, ems);
460 Print_Error(error);
462 i=0;
464 while(GetSMSData[i] != NULL) {
465 free(GetSMSData[i]);
466 GetSMSData[i] = NULL;
467 i++;
470 i=0;
472 while(SortedSMS[i] != NULL) {
473 smspos++;
475 for (j=0;j<SortedSMS[i]->Number;j++) {
476 smsnum++;
478 if ((j==0) || (j!=0 && SortedSMS[i]->SMS[j].Location != SortedSMS[i]->SMS[j-1].Location)) {
479 PrintSMSLocation(&SortedSMS[i]->SMS[j], &folders);
482 DisplayMultiSMSInfo(SortedSMS[i], TRUE, ems, BackupPtr, gsm);
484 free(SortedSMS[i]);
485 SortedSMS[i] = NULL;
486 i++;
489 #ifdef GSM_ENABLE_BACKUP
490 GSM_FreeBackup(&Backup);
491 #endif
493 printf("\n");
494 printf(_("%i SMS parts in %i SMS sequences"),smsnum,smspos);
495 printf("\n");
496 fflush(stdout);
497 GSM_Terminate();
500 void GetSMSFolders(int argc UNUSED, char *argv[] UNUSED)
502 GSM_Error error;
503 GSM_SMSFolders folders;
504 int i=0;
506 GSM_Init(TRUE);
508 error=GSM_GetSMSFolders(gsm,&folders);
509 Print_Error(error);
511 for (i=0;i<folders.Number;i++) {
512 printf("%i. \"%30s\"",i+1,DecodeUnicodeConsole(folders.Folder[i].Name));
514 switch(folders.Folder[i].Memory) {
515 case MEM_SM: printf("%s", _(", SIM memory")); break;
516 case MEM_ME: printf("%s", _(", phone memory")); break;
517 case MEM_MT: printf("%s", _(", phone or SIM memory")); break;
518 default : break;
520 if (folders.Folder[i].InboxFolder) printf("%s", _(", Inbox folder"));
521 if (folders.Folder[i].OutboxFolder) printf("%s", _(", Outbox folder"));
522 printf("\n");
524 fflush(stdout);
525 GSM_Terminate();
528 #define SEND_SAVE_SMS_BUFFER_SIZE 10000
530 GSM_Error SMSStatus;
532 void SendSMSStatus (GSM_StateMachine *sm, int status, int MessageReference, void *user_data)
534 smprintf(gsm, "Sent SMS on device: \"%s\"\n", GSM_GetConfig(sm, -1)->Device);
536 printf("..");
537 if (status==0) {
538 printf("%s", _("OK"));
539 SMSStatus = ERR_NONE;
540 } else {
541 printf(_("error %i"),status);
542 SMSStatus = ERR_UNKNOWN;
544 printf(_(", message reference=%d"),MessageReference);
545 printf("\n");
546 fflush(stdout);
549 void SendSaveDisplaySMS(int argc, char *argv[])
551 GSM_Error error;
552 GSM_MultiSMSMessage sms;
553 GSM_Message_Type type;
554 GSM_SMSFolders folders;
555 int i=0;
557 if (strcasestr(argv[1], "savesms") != NULL) {
558 type = SMS_Save;
559 } else if (strcasestr(argv[1], "sendsmsdsms") != NULL) {
560 type = SMS_SMSD;
561 } else if (strcasestr(argv[1], "sendsms") != NULL) {
562 type = SMS_Send;
563 } else if (strcasestr(argv[1], "displaysms") != NULL) {
564 type = SMS_Display;
565 } else {
566 return;
569 GSM_Init(TRUE);
571 error = CreateMessage(&type, &sms, argc, 2, argv, gsm);
572 Print_Error(error);
574 switch (type) {
575 case SMS_Display:
576 for (i = 0; i < sms.Number; i++) {
577 printf(LISTFORMAT "%i\n", _("Message number"), i);
578 error = DisplaySMSFrame(&sms.SMS[i], gsm);
579 Print_Error(error);
582 printf(LISTFORMAT "%i\n", _("Number of messages"), sms.Number);
583 break;
584 case SMS_Save:
585 case SMS_SendSaved:
586 error = GSM_GetSMSFolders(gsm, &folders);
587 Print_Error(error);
589 if (type == SMS_SendSaved) {
590 GSM_SetSendSMSStatusCallback(gsm, SendSMSStatus, NULL);
592 signal(SIGINT, interrupt);
593 fprintf(stderr, "%s\n", _("If you want break, press Ctrl+C..."));
594 fflush(stderr);
597 for (i=0;i<sms.Number;i++) {
598 printf(_("Saving SMS %i/%i\n"),i+1,sms.Number);
599 error = GSM_AddSMS(gsm, &sms.SMS[i]);
600 Print_Error(error);
601 printf(_("Saved in folder number %d \"%s\", location %i"),
602 sms.SMS[i].Folder,
603 DecodeUnicodeConsole(folders.Folder[sms.SMS[i].Folder-1].Name),
604 sms.SMS[i].Location);
605 if (sms.SMS[i].Memory == MEM_SM) {
606 printf(", %s\n", _("SIM"));
607 } else {
608 printf(", %s\n", _("phone"));
611 if (type == SMS_SendSaved) {
612 printf(_("Sending sms from folder \"%s\", location %i\n"),
613 DecodeUnicodeString(folders.Folder[sms.SMS[i].Folder-1].Name),sms.SMS[i].Location);
614 fflush(stdout);
615 SMSStatus = ERR_TIMEOUT;
616 error = GSM_SendSavedSMS(gsm, 0, sms.SMS[i].Location);
617 Print_Error(error);
618 printf("%s", _("....waiting for network answer"));
619 fflush(stdout);
621 while (!gshutdown) {
622 GSM_ReadDevice(gsm,TRUE);
623 if (SMSStatus == ERR_UNKNOWN) {
624 Print_Error(SMSStatus);
626 if (SMSStatus == ERR_NONE) break;
630 break;
631 case SMS_Send:
632 signal(SIGINT, interrupt);
633 fprintf(stderr, "%s\n", _("If you want break, press Ctrl+C..."));
634 fflush(stderr);
636 GSM_SetSendSMSStatusCallback(gsm, SendSMSStatus, NULL);
638 for (i=0;i<sms.Number;i++) {
639 printf(_("Sending SMS %i/%i"),i+1,sms.Number);
640 fflush(stdout);
641 SMSStatus = ERR_TIMEOUT;
642 error=GSM_SendSMS(gsm, &sms.SMS[i]);
643 Print_Error(error);
644 printf("%s", _("....waiting for network answer"));
645 fflush(stdout);
647 while (!gshutdown) {
648 GSM_ReadDevice(gsm,TRUE);
650 if (SMSStatus == ERR_UNKNOWN) {
651 Print_Error(SMSStatus);
653 if (SMSStatus == ERR_NONE) break;
656 break;
657 default:
658 printf_err("%s", _("Something went wrong, uknown message operation!\n"));
661 GSM_Terminate();
664 void AddSMSFolder(int argc UNUSED, char *argv[])
666 unsigned char buffer[200];
667 GSM_Error error;
669 GSM_Init(TRUE);
671 EncodeUnicode(buffer,argv[2],strlen(argv[2]));
672 error=GSM_AddSMSFolder(gsm,buffer);
673 Print_Error(error);
675 GSM_Terminate();
678 void DeleteAllSMS(int argc, char *argv[])
680 GSM_MultiSMSMessage sms;
681 GSM_SMSFolders folders;
682 int foldernum;
683 gboolean start = TRUE;
684 GSM_Error error;
686 GSM_Init(TRUE);
688 error=GSM_GetSMSFolders(gsm, &folders);
689 Print_Error(error);
691 GetStartStop(&foldernum, NULL, 2, argc, argv);
693 if (foldernum > folders.Number) {
694 printf(_("Too high folder number (max. %i)\n"),folders.Number);
695 fflush(stdout);
696 GSM_Terminate();
697 Terminate(2);
700 printf(_("Deleting SMS from \"%s\" folder: "),DecodeUnicodeConsole(folders.Folder[foldernum-1].Name));
701 fflush(stdout);
703 while (error == ERR_NONE) {
704 sms.SMS[0].Folder=0x00;
705 error=GSM_GetNextSMS(gsm, &sms, start);
707 switch (error) {
708 case ERR_EMPTY:
709 break;
710 case ERR_CORRUPTED:
711 fprintf(stderr, "\n%s\n", _("Corrupted message, skipping"));
712 error = ERR_NONE;
713 continue;
714 default:
715 Print_Error(error);
716 if (sms.SMS[0].Folder == foldernum) {
717 sms.SMS[0].Folder=0x00;
718 error=GSM_DeleteSMS(gsm, &sms.SMS[0]);
719 Print_Error(error);
720 printf("*");
723 start=FALSE;
726 printf("\n");
727 fflush(stdout);
729 GSM_Terminate();
732 /* How should editor hadle tabs in this file? Add editor commands here.
733 * vim: noexpandtab sw=8 ts=8 sts=8: