1 /*
2
3 S M S D
4
5 A Linux/Unix tool for the mobile phones.
6
7 This file is part of gnokii.
8
9 Gnokii is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 Gnokii is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with gnokii; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 Copyright (C) 2002-2011 Jan Derfinak
24
25 This file is a module to smsd for file access.
26
27 */
28
29 #include "config.h"
30
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <dirent.h>
35 #include <string.h>
36 #include <glib.h>
37 #include "smsd.h"
38 #include "gnokii.h"
39 #include "compat.h"
40 #include "utils.h"
41
42 static gchar *action;
43 static gchar *spool;
44
DB_Bye(void)45 GNOKII_API void DB_Bye (void)
46 {
47 return;
48 }
49
50
DB_ConnectInbox(DBConfig connect)51 GNOKII_API gint DB_ConnectInbox (DBConfig connect)
52 {
53 struct stat status;
54
55 if (connect.user[0] != '\0')
56 {
57 if ((stat (connect.user, &status)) != 0)
58 {
59 g_print (_("Cannot stat file %s!\n"), connect.user);
60 return (1);
61 }
62
63 if (!((S_IFREG & status.st_mode) &&
64 (((status.st_uid == geteuid ()) && (S_IXUSR & status.st_mode)) ||
65 ((status.st_gid == getegid ()) && (S_IXGRP & status.st_mode)) ||
66 (S_IXGRP & status.st_mode))))
67 {
68 g_print (_("File %s is not regular file or\nyou have not executable permission to this file!\n"),
69 connect.user);
70 return (2);
71 }
72 }
73
74 action = connect.user;
75
76 return (0);
77 }
78
79
DB_ConnectOutbox(DBConfig connect)80 GNOKII_API gint DB_ConnectOutbox (DBConfig connect)
81 {
82 struct stat status;
83
84 if (connect.host[0] == '\0')
85 g_print (_("You have not set spool directory, sms sending is disabled!\n"));
86 else
87 {
88 if ((stat (connect.host, &status)) != 0)
89 {
90 g_print (_("Cannot stat file %s!\n"), connect.host);
91 return (1);
92 }
93
94 if (!((S_IFDIR & status.st_mode) &&
95 (((status.st_uid == geteuid ()) && (S_IRUSR & status.st_mode) && (S_IWUSR & status.st_mode)) ||
96 ((status.st_gid == getegid ()) && (S_IRGRP & status.st_mode) && (S_IWGRP & status.st_mode)) ||
97 ((S_IROTH & status.st_mode) && (S_IWOTH & status.st_mode)))))
98 {
99 g_print (_("File %s is not directory or\nyou have not read and write permissions to this directory,\nsms sending is disabled!\n!"),
100 connect.host);
101 return (2);
102 }
103 }
104
105 spool = connect.host;
106
107 return (0);
108 }
109
110
DB_InsertSMS(const gn_sms * const data,const gchar * const phone)111 GNOKII_API gint DB_InsertSMS (const gn_sms * const data, const gchar * const phone)
112 {
113 FILE *p;
114 GString *buf;
115 gchar *text;
116
117 text = strEscape ((gchar *) data->user_data[0].u.text);
118
119 if (action[0] == '\0')
120 g_print ("Number: %s, Date: %02d-%02d-%02d %02d:%02d:%02d\nText:\n%s\n", \
121 data->remote.number, data->smsc_time.year, data->smsc_time.month, \
122 data->smsc_time.day, data->smsc_time.hour, data->smsc_time.minute, \
123 data->smsc_time.second, text);
124 else
125 {
126 buf = g_string_sized_new (256);
127 g_string_printf (buf, "%s %s \"%02d-%02d-%02d %02d:%02d:%02d\"", \
128 action, data->remote.number, data->smsc_time.year, \
129 data->smsc_time.month, data->smsc_time.day, \
130 data->smsc_time.hour, data->smsc_time.minute, \
131 data->smsc_time.second);
132 if ((p = popen (buf->str, "w")) == NULL)
133 {
134 g_free (text);
135 g_string_free (buf, TRUE);
136 return (1);
137 }
138
139 g_string_free (buf, TRUE);
140
141 fprintf (p, "%s", text);
142 pclose (p);
143 }
144
145 g_free (text);
146
147 return (0);
148 }
149
150
DB_Look(const gchar * const phone)151 GNOKII_API gint DB_Look (const gchar * const phone)
152 {
153 DIR *dir;
154 struct dirent *dirent;
155 FILE *smsFile;
156 GString *buf;
157 gint numError, error;
158 gint empty = 1;
159
160
161 if (spool[0] == '\0') // if user don't set spool dir, sending is disabled
162 return (SMSD_NOK);
163
164 if ((dir = opendir (spool)) == NULL)
165 {
166 g_print (_("Cannot open directory %s\n"), spool);
167 return (SMSD_NOK);
168 }
169
170 buf = g_string_sized_new (64);
171
172 while ((dirent = readdir (dir)))
173 {
174 gn_sms sms;
175 gint slen = 0;
176
177 if (strcmp (dirent->d_name, ".") == 0 || strcmp (dirent->d_name, "..") == 0 ||
178 strncmp (dirent->d_name, "ERR.", 4) == 0)
179 continue;
180
181 g_string_printf (buf, "%s/%s", spool, dirent->d_name);
182
183 if ((smsFile = fopen (buf->str, "r")) == NULL)
184 {
185 g_print (_("Can't open file %s for reading!\n"), buf->str);
186 continue;
187 }
188
189 empty = 0;
190 gn_sms_default_submit (&sms);
191 memset (&sms.remote.number, 0, sizeof (sms.remote.number));
192
193 if (fgets (sms.remote.number, sizeof (sms.remote.number), smsFile))
194 slen = strlen (sms.remote.number);
195 if (slen < 1)
196 {
197 error = -1;
198 fclose (smsFile);
199 g_print (_("Remote number is empty in %s!\n"), buf->str);
200 goto handle_file;
201 }
202
203 if (sms.remote.number[slen - 1] == '\n')
204 sms.remote.number[slen - 1] = '\0';
205
206 /* Initialize SMS text */
207 memset (&sms.user_data[0].u.text, 0, sizeof (sms.user_data[0].u.text));
208
209 slen = fread ((gchar *) sms.user_data[0].u.text, 1, GN_SMS_MAX_LENGTH, smsFile);
210 if (slen > 0 && sms.user_data[0].u.text[slen - 1] == '\n')
211 sms.user_data[0].u.text[slen - 1] = '\0';
212
213 fclose (smsFile);
214
215 // sms.delivery_report = (smsdConfig.smsSets & SMSD_READ_REPORTS);
216
217 if (sms.remote.number[0] == '+')
218 sms.remote.type = GN_GSM_NUMBER_International;
219 else
220 sms.remote.type = GN_GSM_NUMBER_Unknown;
221
222 sms.user_data[0].length = strlen ((gchar *) sms.user_data[0].u.text);
223 sms.user_data[0].type = GN_SMS_DATA_Text;
224 sms.user_data[1].type = GN_SMS_DATA_None;
225 if (!gn_char_def_alphabet (sms.user_data[0].u.text))
226 sms.dcs.u.general.alphabet = GN_SMS_DCS_UCS2;
227
228
229 gn_log_xdebug ("Sending SMS: %s, %s\n", sms.remote.number, sms.user_data[0].u.text);
230
231 numError = 0;
232 do
233 {
234 error = WriteSMS (&sms);
235 sleep (1);
236 }
237 while ((error == GN_ERR_TIMEOUT || error == GN_ERR_FAILED) && numError++ < 3);
238
239 handle_file:
240 if (error == GN_ERR_NONE)
241 {
242 if (unlink (buf->str))
243 g_print (_("Cannot unlink %s."), buf->str);
244 }
245 else
246 {
247 GString *buf2;
248
249 buf2 = g_string_sized_new (64);
250 g_string_printf (buf2, "%s/ERR.%s", spool, dirent->d_name);
251
252 g_print (_("Cannot send sms from file %s\n"), buf->str);
253 if (rename (buf->str, buf2->str))
254 {
255 g_print (_("Cannot rename file %s to %s. Trying to unlink it.\n"),
256 buf->str, buf2->str);
257 if (unlink (buf->str))
258 g_print (_("Cannot unlink %s."), buf->str);
259 }
260 g_string_free (buf2, TRUE);
261 }
262 }
263
264 g_string_free (buf, TRUE);
265 closedir (dir);
266
267 if (empty)
268 return (SMSD_OUTBOXEMPTY);
269 else
270 return (SMSD_OK);
271 }
272