1 /***************************************************************************
2  *   copyright           : (C) 2002 by Hendrik Sattler                     *
3  *   mail                : post@hendrik-sattler.de                         *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  ***************************************************************************/
11 
12 #ifndef _GNU_SOURCE
13 # define _GNU_SOURCE
14 #endif
15 #ifndef _REENTRANT
16 # define _REENTRANT
17 #endif
18 
19 #include <smspdu.h>
20 #include "smscoding.h"
21 #include "smsudh.h"
22 
23 #include <charsets.h>
24 #include <helper.h>
25 #include <gtincl.h>
26 #include <intincl.h>
27 
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 
32 static
sms_pdu_create_submit_frame(char * number,unsigned long options,int header_present)33 struct sms_pdu_raw* sms_pdu_create_submit_frame (char* number,
34 				   unsigned long options,
35 				   int header_present)
36 {
37   uint8_t sca_len = 0;
38   struct gsm_number sca; //short message service center address
39   uint8_t pdutype; //PDU type
40   uint8_t mr; //message reference
41   uint8_t da_len = 0;
42   struct gsm_number da; //destination address
43   uint8_t pid = 0; //protocol identifier (normally 0)
44   uint8_t dcs; //data coding scheme
45   uint8_t vp_rel = 0xff; //validity period (0xff = max = 63 weeks)
46   //char vp_abs[15]; //validity period (YYMMDDhhmmssTZ)
47 
48   struct sms_pdu_raw* frame = mem_alloc(sizeof(*frame),0);
49   char* temp;
50   uint8_t* ptr;
51 
52   sms_pdu_raw_init(frame);
53 
54   /* not yet supported
55    * zero length means that the phone will use its default
56    */
57   gsm_number_init(&sca);
58   sca_len = 0;
59 
60   /* set PDU type to standard values
61    */
62   pdutype = 1; //message type SMS-SUBMIT
63   pdutype |= (1<<4); //validity period format: relative
64   if (options&SMS_CREATE_OPT_REPORT) {
65     pdutype |= (1<<5); //status report request;
66   }
67   if (header_present) {
68     pdutype |= (1<<6); //user data header indication
69   }
70 
71   /* message reference must be zero for Siemens phones!
72    */
73   mr = 0;
74 
75   /* destination number
76    */
77   if (is_telephone_number(number) == 0) {
78     fprintf(stderr,"%s: %s\n",_("Error"),_("No valid number specified."));
79     return NULL;
80   }
81   gsm_number_init(&da);
82   gsm_number_set_toa(&da,numtype(number));
83   gsm_number_set(&da,number,str_len(number));
84   temp = gsm_number_get(&da);
85   if (temp == NULL || strcmp(temp,number) != 0) {
86     fprintf(stderr,_("%s: sms number cannot have more than %lu digits.\n"),_("Error"),(unsigned long)sizeof(da.digits)-1);
87     return NULL;
88   }
89   mem_realloc(temp,0);
90   da_len = strlen(da.digits);
91 
92   /* support "flash-SMS" and unicode here
93    */
94   dcs = 0;
95   if (options&SMS_CREATE_OPT_FLASH) {
96     dcs &= 0xec; //clear all affected bits
97     dcs |= 0x10; //set class 0 message (immediate display)
98   }
99   if (options&SMS_CREATE_OPT_UNICODE) {
100     dcs &= 0xf3; //clear all affected bits
101     dcs |= 0x08; //set unicode charset
102   }
103 
104   //leave pid and vp_rel as is
105 
106   //create PDU frame
107   ptr = frame->data;
108   ptr[0] = sca_len;
109   ++ptr;
110   if (sca_len) {
111     ptr[0] = gsm_number_get_toa(&sca);
112     ptr += gsm_number_get_semioctets(&sca,ptr)+1;
113   }
114 
115   ptr[0] = pdutype;
116   ptr[1] = mr;
117   ptr += 2;
118 
119   ptr[0] = da_len;
120   ptr[1] = gsm_number_get_toa(&da);
121   ptr += 2;
122   if (da_len) ptr += gsm_number_get_semioctets(&da,ptr);
123 
124   ptr[0] = pid;
125   ptr[1] = dcs;
126   ptr[2] = vp_rel;
127   ptr += 3;
128   frame->size = ptr-frame->data;
129 
130   gsm_number_delete(&sca);
131   gsm_number_delete(&da);
132 
133   return frame;
134 }
135 
sms_pdu_create_submit(char * text,char * number,unsigned long options)136 struct sms_pdu_raw** sms_pdu_create_submit (char* text,
137 					    char* number,
138 					    unsigned long options)
139 {
140   ucs4char_t* wide_str = convert_from_system(text);
141   struct sms_pdu_raw** tpdu = NULL;
142   unsigned int i = 0;
143   struct sms_pdu_raw* frame;
144   enum sms_encoding charset = SMS_CHARSET_GSM;
145   gsmchar_t* g1 = NULL;
146   ucs2char_t* g2 = NULL;
147 
148   if (options&SMS_CREATE_OPT_UNICODE) charset = SMS_CHARSET_UCS2;
149   if (charset == SMS_CHARSET_GSM &&
150       options&SMS_CREATE_OPT_AUTOCHAR)
151   {
152     g1 = convert_to_gsm(wide_str);
153     if (gsmwidth(g1) < ucs4len(wide_str)) {
154       g2 = convert_to_ucs2(wide_str);
155       if (ucs2len(g2) == ucs4len(wide_str) ||
156 	  ucs2len(g2) > gsmwidth(g1))
157       {
158 	/* more characters from the original string can be
159 	 * encoded if UCS-2 is used instead of the default GSM character set
160 	 */
161 	fprintf(stderr,"%s: %s\n",_("Notice"),_("Selecting UCS-2 character set."));
162 	charset = SMS_CHARSET_UCS2;
163       } else {
164 	/* we do not want error messages from convert_to_gsm
165 	 * being printed twice
166 	 */
167 	mem_realloc(wide_str,0);
168 	wide_str = convert_from_gsm(g1);
169       }
170       mem_realloc(g2,0);
171     }
172     mem_realloc(g1,0);
173   }
174   tpdu = sms_data_encode(charset,NULL, wide_str);
175   mem_realloc(wide_str,0);
176 
177   if (tpdu == NULL) return NULL;
178 
179   frame = sms_pdu_create_submit_frame(number,options,
180 				      (tpdu[1] == NULL)? 0 : 1);
181   if (frame == NULL) return NULL;
182 
183   for (; tpdu[i] != NULL; ++i) {
184     memmove(tpdu[i]->data+frame->size,tpdu[i]->data,tpdu[i]->size);
185     memcpy(tpdu[i]->data,frame->data,frame->size);
186     tpdu[i]->size += frame->size;
187   }
188   mem_realloc(frame,0);
189 
190   return tpdu;
191 }
192