~ubuntu-branches/ubuntu/trusty/modem-manager-gui/trusty-backports

« back to all changes in this revision

Viewing changes to src/smsdb.c

  • Committer: Package Import Robot
  • Author(s): Graham Inggs
  • Date: 2013-07-30 12:51:59 UTC
  • Revision ID: package-import@ubuntu.com-20130730125159-flzv882fhuzhmfmi
Tags: upstream-0.0.16
ImportĀ upstreamĀ versionĀ 0.0.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      smsdb.c
 
3
 *      
 
4
 *      Copyright 2012-2013 Alex <alex@linuxonly.ru>
 
5
 *      
 
6
 *      This program is free software: you can redistribute it and/or modify
 
7
 *      it under the terms of the GNU General Public License as published by
 
8
 *      the Free Software Foundation; either version 3 of the License, or
 
9
 *      (at your option) any later version.
 
10
 *      
 
11
 *      This program is distributed in the hope that it will be useful,
 
12
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *      GNU General Public License for more details.
 
15
 *      
 
16
 *      You should have received a copy of the GNU General Public License
 
17
 *      along with this program. If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <stdlib.h>
 
21
#include <glib.h>
 
22
#include <glib/gprintf.h>
 
23
#include <string.h>
 
24
#include <gdbm.h>
 
25
#include <ctype.h>
 
26
#include <sys/stat.h>
 
27
#include <sys/types.h>
 
28
 
 
29
#include "encoding.h"
 
30
#include "smsdb.h"
 
31
 
 
32
#define MMGUI_SMSDB_SMS_MESSAGE_XML "<sms>\n\t<number>%s</number>\n\t<time>%lu</time>\n\t<binary>%u</binary>\n\t<servicenumber>%s</servicenumber>\n\t<text>%s</text>\n\t<read>%u</read>\n\t<folder>%u</folder>\n</sms>\n\n"
 
33
 
 
34
#define MMGUI_SMSDB_READ_TAG        "\n\t<read>"
 
35
#define MMGUI_SMSDB_TRAILER_TAG     "\n</sms>\n\n"
 
36
#define MMGUI_SMSDB_TRAILER_PARAMS  "\n\t<read>%u</read>\n\t<folder>%u</folder>\n</sms>\n\n"
 
37
 
 
38
#define MMGUI_SMSDB_ACCESS_MASK     0755
 
39
 
 
40
enum _mmgui_smsdb_xml_elements {
 
41
        MMGUI_SMSDB_XML_PARAM_NUMBER = 0,
 
42
        MMGUI_SMSDB_XML_PARAM_TIME,
 
43
        MMGUI_SMSDB_XML_PARAM_BINARY,
 
44
        MMGUI_SMSDB_XML_PARAM_SERVICENUMBER,
 
45
        MMGUI_SMSDB_XML_PARAM_TEXT,
 
46
        MMGUI_SMSDB_XML_PARAM_READ,
 
47
        MMGUI_SMSDB_XML_PARAM_FOLDER,
 
48
        MMGUI_SMSDB_XML_PARAM_NULL
 
49
};
 
50
 
 
51
static gint mmgui_smsdb_xml_parameter = MMGUI_SMSDB_XML_PARAM_NULL;
 
52
 
 
53
static gint mmgui_smsdb_sms_message_sort_compare(gconstpointer a, gconstpointer b);
 
54
static void mmgui_smsdb_free_sms_list_foreach(gpointer data, gpointer user_data);
 
55
static mmgui_sms_message_t mmgui_smsdb_xml_parse(gchar *xml, gsize size);
 
56
static void mmgui_smsdb_xml_get_element(GMarkupParseContext *context, const gchar *element, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error);
 
57
static void mmgui_smsdb_xml_get_value(GMarkupParseContext *context, const gchar *text, gsize size, gpointer data, GError **error);
 
58
static void mmgui_smsdb_xml_end_element(GMarkupParseContext *context, const gchar *element, gpointer data, GError **error);
 
59
 
 
60
smsdb_t mmgui_smsdb_open(const gchar *persistentid, const gchar *internalid)
 
61
{
 
62
        smsdb_t smsdb;
 
63
        const gchar *newfilepath;
 
64
        const gchar *newfilename;
 
65
        gchar filename[64];
 
66
        const gchar *oldfilename;
 
67
        
 
68
        if (persistentid == NULL) return NULL;
 
69
        
 
70
        //Form path using XDG standard
 
71
        newfilepath = g_build_path(G_DIR_SEPARATOR_S, g_get_user_data_dir(), "modem-manager-gui", "devices", persistentid, NULL);
 
72
        
 
73
        if (newfilepath == NULL) return NULL;
 
74
        
 
75
        //If directory structure not exists, create it
 
76
        if (!g_file_test(newfilepath, G_FILE_TEST_IS_DIR)) {
 
77
                if (g_mkdir_with_parents(newfilepath, S_IRUSR|S_IWUSR|S_IXUSR|S_IXGRP|S_IXOTH) == -1) {
 
78
                        g_warning("Failed to make XDG data directory: %s", newfilepath);
 
79
                }
 
80
        }
 
81
        
 
82
        //Form file name
 
83
        newfilename = g_build_filename(newfilepath, "sms.gdbm", NULL);
 
84
        
 
85
        g_free((gchar *)newfilepath);
 
86
        
 
87
        if (newfilename == NULL) return NULL;
 
88
        
 
89
        //If file already exists, just work with it
 
90
        if ((!g_file_test(newfilename, G_FILE_TEST_EXISTS)) && (internalid != NULL)) {
 
91
                //Form old-style file path
 
92
                memset(filename, 0, sizeof(filename));
 
93
                g_snprintf(filename, sizeof(filename), "sms-%s.gdbm", internalid);
 
94
                
 
95
                oldfilename = g_build_filename(g_get_home_dir(), ".config", "modem-manager-gui", filename, NULL);       
 
96
                
 
97
                if (oldfilename != NULL) {
 
98
                        //If file exists in old location, move it
 
99
                        if (g_file_test(oldfilename, G_FILE_TEST_EXISTS)) {
 
100
                                if (g_rename(oldfilename, newfilename) == -1) {
 
101
                                        g_warning("Failed to move file into XDG data directory: %s -> %s", oldfilename, newfilename);
 
102
                                }
 
103
                        }
 
104
                }
 
105
                
 
106
                g_free((gchar *)oldfilename);
 
107
        }
 
108
        
 
109
        smsdb = g_new(struct _smsdb, 1);
 
110
        
 
111
        smsdb->filepath = newfilename;
 
112
        smsdb->unreadmessages = 0;
 
113
        
 
114
        return smsdb;
 
115
}
 
116
 
 
117
gboolean mmgui_smsdb_close(smsdb_t smsdb)
 
118
{
 
119
        if (smsdb == NULL) return FALSE;
 
120
        
 
121
        if (smsdb->filepath != NULL) {
 
122
                g_free((gchar *)smsdb->filepath);
 
123
        }
 
124
        smsdb->unreadmessages = 0;
 
125
        
 
126
        g_free(smsdb);
 
127
        
 
128
        return TRUE;
 
129
}
 
130
 
 
131
mmgui_sms_message_t mmgui_smsdb_message_create(void)
 
132
{
 
133
        mmgui_sms_message_t message;
 
134
        
 
135
        message = g_new(struct _mmgui_sms_message, 1);
 
136
        message->timestamp = time(NULL);
 
137
        message->read = FALSE;
 
138
        message->binary = FALSE;
 
139
        message->folder = MMGUI_SMSDB_SMS_FOLDER_INCOMING;
 
140
        message->number = NULL;
 
141
        message->svcnumber = NULL;
 
142
        message->idents = NULL;
 
143
        message->text = NULL;
 
144
        
 
145
        return message;
 
146
}
 
147
 
 
148
void mmgui_smsdb_message_free(mmgui_sms_message_t message)
 
149
{
 
150
        if (message == NULL) return;
 
151
        
 
152
        if (message->number != NULL) {
 
153
                g_free(message->number);
 
154
        }
 
155
        
 
156
        if (message->svcnumber != NULL) {
 
157
                g_free(message->svcnumber);
 
158
        }
 
159
        
 
160
        if (message->idents != NULL) {
 
161
                g_array_free(message->idents, TRUE);
 
162
        }
 
163
        
 
164
        if (message->text != NULL) {
 
165
                g_string_free(message->text, TRUE);
 
166
        }
 
167
                
 
168
        g_free(message);
 
169
}
 
170
 
 
171
static gchar *mmgui_smsdb_message_escape_number(const gchar *number)
 
172
{
 
173
        size_t srclen, numlen;
 
174
        gchar *bcdnumber, *escnumber;
 
175
        
 
176
        if (number == NULL) return NULL;
 
177
        
 
178
        srclen = strlen(number);
 
179
        
 
180
        if (srclen == 0) return NULL;
 
181
        
 
182
        bcdnumber = bcd_to_utf8_ascii_part(number, srclen, &numlen);
 
183
        
 
184
        if (bcdnumber != NULL) {
 
185
                escnumber = encoding_clear_special_symbols(bcdnumber, numlen);
 
186
        } else {
 
187
                escnumber = encoding_clear_special_symbols(g_strdup(number), srclen);
 
188
        }
 
189
        
 
190
        return escnumber;
 
191
}
 
192
 
 
193
gboolean mmgui_smsdb_message_set_number(mmgui_sms_message_t message, const gchar *number)
 
194
{
 
195
        gchar *escnumber;
 
196
        
 
197
        if ((message == NULL) || (number == NULL)) return FALSE;
 
198
        
 
199
        escnumber = mmgui_smsdb_message_escape_number(number);
 
200
        
 
201
        if (escnumber != NULL) {
 
202
                if (message->number != NULL) {
 
203
                        g_free(message->number);
 
204
                }
 
205
                message->number = escnumber;
 
206
                return TRUE;
 
207
        } else {
 
208
                return FALSE;
 
209
        }
 
210
}
 
211
 
 
212
const gchar *mmgui_smsdb_message_get_number(mmgui_sms_message_t message)
 
213
{
 
214
        if (message == NULL) return NULL;
 
215
        
 
216
        return message->number;
 
217
}
 
218
 
 
219
gboolean mmgui_smsdb_message_set_service_number(mmgui_sms_message_t message, const gchar *number)
 
220
{
 
221
        gchar *escnumber;
 
222
        
 
223
        if ((message == NULL) || (number == NULL)) return FALSE;
 
224
        
 
225
        escnumber = mmgui_smsdb_message_escape_number(number);
 
226
        
 
227
        if (escnumber != NULL) {
 
228
                if (message->svcnumber != NULL) {
 
229
                        g_free(message->svcnumber);
 
230
                }
 
231
                message->svcnumber = escnumber;
 
232
                return TRUE;
 
233
        } else {
 
234
                return FALSE;
 
235
        }
 
236
}
 
237
 
 
238
const gchar *mmgui_smsdb_message_get_service_number(mmgui_sms_message_t message)
 
239
{
 
240
        if (message == NULL) return NULL;
 
241
        
 
242
        return message->svcnumber;
 
243
}
 
244
 
 
245
gboolean mmgui_smsdb_message_set_text(mmgui_sms_message_t message, const gchar *text, gboolean append)
 
246
{
 
247
        if ((message == NULL) || (text == NULL)) return FALSE;
 
248
        
 
249
        if (message->binary) return FALSE;
 
250
        
 
251
        if (!append) {
 
252
                if (message->text != NULL) {
 
253
                        g_string_free(message->text, TRUE);
 
254
                }
 
255
                message->text = g_string_new(text);
 
256
        } else {
 
257
                if (message->text != NULL) {
 
258
                        message->text = g_string_append_c(message->text, ' ');
 
259
                        message->text = g_string_append(message->text, text);
 
260
                } else {
 
261
                        message->text = g_string_new(text);
 
262
                }
 
263
        }
 
264
        
 
265
        return TRUE;
 
266
}
 
267
 
 
268
const gchar *mmgui_smsdb_message_get_text(mmgui_sms_message_t message)
 
269
{
 
270
        if (message == NULL) return NULL;
 
271
        
 
272
        if (message->text != NULL) {
 
273
                return message->text->str;
 
274
        } else {
 
275
                return NULL;
 
276
        }
 
277
}
 
278
 
 
279
gboolean mmgui_smsdb_message_set_data(mmgui_sms_message_t message, const gchar *data, gsize len, gboolean append)
 
280
{
 
281
        guint srclen, index;
 
282
        
 
283
        if ((message == NULL) || (data == NULL) || (len == 0)) return FALSE;
 
284
        
 
285
        if (!message->binary) return FALSE;
 
286
        
 
287
        if (!append) {
 
288
                if (message->text != NULL) {
 
289
                        g_string_free(message->text, TRUE);
 
290
                }
 
291
                message->text = g_string_new_len(NULL, len*2+1);
 
292
                for (index=0; index<len; index++) {
 
293
                        if ((guchar)data[index] < 0x10) {
 
294
                                g_sprintf(message->text->str+(index*2), "0%1x", (guchar)data[index]);
 
295
                        } else {
 
296
                                g_sprintf(message->text->str+(index*2), "%2x", (guchar)data[index]);
 
297
                        }
 
298
                }
 
299
                message->text->str[len*2] = '\0';
 
300
        } else {
 
301
                if (message->text != NULL) {
 
302
                        message->text = g_string_append(message->text, "00");
 
303
                        srclen = message->text->len-1;
 
304
                        message->text = g_string_set_size(message->text, srclen+len*2+1);
 
305
                        for (index=0; index<len; index++) {
 
306
                                if ((guchar)data[index] < 0x10) {
 
307
                                        g_sprintf(message->text->str+(srclen+index*2), "0%1x", (guchar)data[index]);
 
308
                                } else {
 
309
                                        g_sprintf(message->text->str+(srclen+index*2), "%2x", (guchar)data[index]);
 
310
                                }
 
311
                        }
 
312
                        message->text->str[srclen+len*2] = '\0';
 
313
                } else {
 
314
                        message->text = g_string_new_len(NULL, len*2+1);
 
315
                        for (index=0; index<len; index++) {
 
316
                                if ((guchar)data[index] < 0x10) {
 
317
                                        g_sprintf(message->text->str+(index*2), "0%1x", (guchar)data[index]);
 
318
                                } else {
 
319
                                        g_sprintf(message->text->str+(index*2), "%2x", (guchar)data[index]);
 
320
                                }
 
321
                        }
 
322
                        message->text->str[len*2] = '\0';
 
323
                }
 
324
        }
 
325
        
 
326
        return TRUE;
 
327
}
 
328
 
 
329
gboolean mmgui_smsdb_message_set_identifier(mmgui_sms_message_t message, guint ident, gboolean append)
 
330
{
 
331
        if (message == NULL) return FALSE;
 
332
        
 
333
        if (!append) {
 
334
                if (message->idents != NULL) {
 
335
                        g_array_free(message->idents, TRUE);
 
336
                }
 
337
                message->idents = g_array_new(FALSE, TRUE, sizeof(guint));
 
338
                g_array_append_val(message->idents, ident);
 
339
        } else {
 
340
                if (message->idents != NULL) {
 
341
                        g_array_append_val(message->idents, ident);
 
342
                } else {
 
343
                        message->idents = g_array_new(FALSE, TRUE, sizeof(guint));
 
344
                        g_array_append_val(message->idents, ident);
 
345
                }
 
346
        }
 
347
        
 
348
        return TRUE;
 
349
}
 
350
 
 
351
guint mmgui_smsdb_message_get_identifier(mmgui_sms_message_t message)
 
352
{
 
353
        guint ident;
 
354
        
 
355
        if (message == NULL) return 0;
 
356
        
 
357
        if (message->idents != NULL) {
 
358
                ident = g_array_index(message->idents, guint, 0);
 
359
        } else {
 
360
                ident = 0;
 
361
        }
 
362
        
 
363
        return ident;
 
364
}
 
365
 
 
366
gboolean mmgui_smsdb_message_set_timestamp(mmgui_sms_message_t message, time_t timestamp)
 
367
{
 
368
        if (message == NULL) return FALSE;
 
369
        
 
370
        message->timestamp = timestamp;
 
371
        
 
372
        return TRUE;
 
373
}
 
374
 
 
375
time_t mmgui_smsdb_message_get_timestamp(mmgui_sms_message_t message)
 
376
{
 
377
        if (message == NULL) return 0;
 
378
        
 
379
        return message->timestamp;
 
380
}
 
381
 
 
382
gboolean mmgui_smsdb_message_set_read(mmgui_sms_message_t message, gboolean read)
 
383
{
 
384
        if (message == NULL) return FALSE;
 
385
        
 
386
        message->read = read;
 
387
        
 
388
        return TRUE;
 
389
}
 
390
 
 
391
gboolean mmgui_smsdb_message_get_read(mmgui_sms_message_t message)
 
392
{
 
393
        if (message == NULL) return FALSE;
 
394
        
 
395
        return message->read;
 
396
}
 
397
 
 
398
gboolean mmgui_smsdb_message_set_folder(mmgui_sms_message_t message, enum _mmgui_smsdb_sms_folder folder)
 
399
{
 
400
        if (message == NULL) return FALSE;
 
401
        
 
402
        switch (folder) {
 
403
                case MMGUI_SMSDB_SMS_FOLDER_INCOMING:
 
404
                        message->folder = MMGUI_SMSDB_SMS_FOLDER_INCOMING;
 
405
                        break;
 
406
                case MMGUI_SMSDB_SMS_FOLDER_SENT:
 
407
                        message->folder = MMGUI_SMSDB_SMS_FOLDER_SENT;
 
408
                        break;
 
409
                case MMGUI_SMSDB_SMS_FOLDER_DRAFTS:
 
410
                        message->folder = MMGUI_SMSDB_SMS_FOLDER_DRAFTS;
 
411
                        break;
 
412
                default:
 
413
                        message->folder = MMGUI_SMSDB_SMS_FOLDER_INCOMING;
 
414
                        break;
 
415
        }
 
416
        
 
417
        return TRUE;
 
418
}
 
419
 
 
420
enum _mmgui_smsdb_sms_folder mmgui_smsdb_message_get_folder(mmgui_sms_message_t message)
 
421
{
 
422
        if (message == NULL) return MMGUI_SMSDB_SMS_FOLDER_INCOMING;
 
423
        
 
424
        return message->folder;
 
425
}
 
426
 
 
427
gboolean mmgui_smsdb_message_set_binary(mmgui_sms_message_t message, gboolean binary)
 
428
{
 
429
        if (message == NULL) return FALSE;
 
430
        
 
431
        message->binary = binary;
 
432
        
 
433
        return TRUE;
 
434
}
 
435
 
 
436
gboolean mmgui_smsdb_message_get_binary(mmgui_sms_message_t message)
 
437
{
 
438
        if (message == NULL) return FALSE;
 
439
        
 
440
        return message->binary;
 
441
}
 
442
 
 
443
gulong mmgui_smsdb_message_get_db_identifier(mmgui_sms_message_t message)
 
444
{
 
445
        if (message == NULL) return 0;
 
446
        
 
447
        return message->dbid;
 
448
}
 
449
 
 
450
guint mmgui_smsdb_get_unread_messages(smsdb_t smsdb)
 
451
{
 
452
        if (smsdb == NULL) return 0;
 
453
        
 
454
        return smsdb->unreadmessages;
 
455
}
 
456
 
 
457
gboolean mmgui_smsdb_add_sms(smsdb_t smsdb, mmgui_sms_message_t message)
 
458
{
 
459
        GDBM_FILE db;
 
460
        gchar smsid[64];
 
461
        gulong idvalue;
 
462
        gint idlen;
 
463
        datum key, data;
 
464
        gchar *smsnumber;
 
465
        gchar *smstext;
 
466
        gchar *smsxml;
 
467
        
 
468
        if ((smsdb == NULL) || (message == NULL)) return FALSE;
 
469
        if (smsdb->filepath == NULL) return FALSE;
 
470
        if ((message->number == NULL) || ((message->text->str == NULL))) return FALSE;
 
471
                
 
472
        db = gdbm_open((gchar *)smsdb->filepath, 0, GDBM_WRCREAT, MMGUI_SMSDB_ACCESS_MASK, 0);
 
473
        
 
474
        if (db == NULL) return FALSE;
 
475
        
 
476
        do {
 
477
                idvalue = (gulong)random();
 
478
                memset(smsid, 0, sizeof(smsid));
 
479
                idlen = snprintf(smsid, sizeof(smsid), "%lu", idvalue);
 
480
                key.dptr = (gchar *)smsid;
 
481
                key.dsize = idlen;
 
482
        } while (gdbm_exists(db, key));
 
483
        
 
484
        message->dbid = idvalue;
 
485
        
 
486
        smsnumber = g_markup_escape_text(message->number, -1);
 
487
        
 
488
        if (smsnumber == NULL) {
 
489
                g_warning("Unable to convert SMS number string");
 
490
                gdbm_close(db);
 
491
                return FALSE;
 
492
        }
 
493
        
 
494
        smstext = g_markup_escape_text(message->text->str, -1);
 
495
        
 
496
        if (smstext == NULL) {
 
497
                g_warning("Unable to convert SMS text string");
 
498
                g_free(smsnumber);
 
499
                gdbm_close(db);
 
500
                return FALSE;
 
501
        }
 
502
        
 
503
        smsxml = g_strdup_printf(MMGUI_SMSDB_SMS_MESSAGE_XML,
 
504
                                                                smsnumber,
 
505
                                                                message->timestamp,
 
506
                                                                message->binary,
 
507
                                                                message->svcnumber,
 
508
                                                                smstext,
 
509
                                                                message->read,
 
510
                                                                message->folder);
 
511
        
 
512
        data.dptr = smsxml;
 
513
        data.dsize = strlen(smsxml);
 
514
        
 
515
        if (gdbm_store(db, key, data, GDBM_REPLACE) == -1) {
 
516
                g_warning("Unable to write to database");
 
517
                gdbm_close(db);
 
518
                g_free(smsxml);
 
519
                return FALSE;
 
520
        }
 
521
        
 
522
        gdbm_sync(db);
 
523
        gdbm_close(db);
 
524
        
 
525
        if (!message->read) {
 
526
                smsdb->unreadmessages++;
 
527
        }
 
528
        
 
529
        g_free(smsxml);
 
530
        g_free(smsnumber);
 
531
        g_free(smstext);
 
532
        
 
533
        return TRUE;
 
534
}
 
535
 
 
536
static gint mmgui_smsdb_sms_message_sort_compare(gconstpointer a, gconstpointer b)
 
537
{
 
538
        mmgui_sms_message_t sms1, sms2;
 
539
                
 
540
        sms1 = (mmgui_sms_message_t)a;
 
541
        sms2 = (mmgui_sms_message_t)b;
 
542
        
 
543
        if (sms1->timestamp < sms2->timestamp) {
 
544
                return -1;
 
545
        } else if (sms1->timestamp > sms2->timestamp) {
 
546
                return 1;
 
547
        } else {
 
548
                return 0;
 
549
        }
 
550
}
 
551
 
 
552
GSList *mmgui_smsdb_read_sms_list(smsdb_t smsdb)
 
553
{
 
554
        GDBM_FILE db;
 
555
        GSList *list;
 
556
        mmgui_sms_message_t message;
 
557
        datum key, data;
 
558
        gchar smsid[64];
 
559
        
 
560
        if (smsdb == NULL) return NULL;
 
561
        if (smsdb->filepath == NULL) return NULL;
 
562
        
 
563
        db = gdbm_open((gchar *)smsdb->filepath, 0, GDBM_READER, MMGUI_SMSDB_ACCESS_MASK, 0);
 
564
        
 
565
        if (db == NULL) return NULL;
 
566
        
 
567
        smsdb->unreadmessages = 0;
 
568
        
 
569
        list = NULL;
 
570
        
 
571
        key = gdbm_firstkey(db);
 
572
        
 
573
        if (key.dptr != NULL) {
 
574
                do {
 
575
                        data = gdbm_fetch(db, key);
 
576
                        if (data.dptr != NULL) {
 
577
                                message = mmgui_smsdb_xml_parse(data.dptr, data.dsize);
 
578
                                if (message != NULL) {
 
579
                                        if (!message->read) {
 
580
                                                smsdb->unreadmessages++;
 
581
                                        }
 
582
                                        memset(smsid, 0, sizeof(smsid));
 
583
                                        strncpy(smsid, key.dptr, key.dsize);
 
584
                                        message->dbid = strtoul(smsid, NULL, 0);
 
585
                                        list = g_slist_prepend(list, message);
 
586
                                }
 
587
                        }
 
588
                        key = gdbm_nextkey(db, key);
 
589
                } while (key.dptr != NULL);
 
590
        }
 
591
        
 
592
        gdbm_close(db);
 
593
        
 
594
        if (list != NULL) {
 
595
                list = g_slist_sort(list, mmgui_smsdb_sms_message_sort_compare);
 
596
        } 
 
597
        
 
598
        return list;
 
599
}
 
600
 
 
601
static void mmgui_smsdb_free_sms_list_foreach(gpointer data, gpointer user_data)
 
602
{
 
603
        mmgui_sms_message_t message;
 
604
        
 
605
        if (data != NULL) return;
 
606
        
 
607
        message = (mmgui_sms_message_t)data;
 
608
        
 
609
        if (message->number != NULL) {
 
610
                g_free(message->number);
 
611
        }
 
612
        
 
613
        if (message->svcnumber != NULL) {
 
614
                g_free(message->svcnumber);
 
615
        }
 
616
        
 
617
        if (message->idents != NULL) {
 
618
                g_array_free(message->idents, TRUE);
 
619
        }
 
620
        
 
621
        if (message->text != NULL) {
 
622
                g_string_free(message->text, TRUE);
 
623
        }
 
624
}
 
625
 
 
626
void mmgui_smsdb_message_free_list(GSList *smslist)
 
627
{
 
628
        if (smslist == NULL) return;
 
629
        
 
630
        g_slist_foreach(smslist, mmgui_smsdb_free_sms_list_foreach, NULL);
 
631
        g_slist_free(smslist);
 
632
}
 
633
 
 
634
mmgui_sms_message_t mmgui_smsdb_read_sms_message(smsdb_t smsdb, gulong idvalue)
 
635
{
 
636
        GDBM_FILE db;
 
637
        gchar smsid[64];
 
638
        gint idlen;
 
639
        datum key, data;
 
640
        mmgui_sms_message_t message;
 
641
                
 
642
        if (smsdb == NULL) return NULL;
 
643
        if (smsdb->filepath == NULL) return NULL;
 
644
        
 
645
        db = gdbm_open((gchar *)smsdb->filepath, 0, GDBM_READER, MMGUI_SMSDB_ACCESS_MASK, 0);
 
646
        
 
647
        if (db == NULL) return NULL;
 
648
        
 
649
        message = NULL;
 
650
        
 
651
        memset(smsid, 0, sizeof(smsid));
 
652
        idlen = snprintf(smsid, sizeof(smsid), "%lu", idvalue);
 
653
        key.dptr = (gchar *)smsid;
 
654
        key.dsize = idlen;
 
655
        
 
656
        if (gdbm_exists(db, key)) {
 
657
                data = gdbm_fetch(db, key);
 
658
                if (data.dptr != NULL) {
 
659
                        message = mmgui_smsdb_xml_parse(data.dptr, data.dsize);
 
660
                        message->dbid = idvalue;
 
661
                }
 
662
        }
 
663
        
 
664
        gdbm_close(db);
 
665
        
 
666
        return message;
 
667
}
 
668
 
 
669
gboolean mmgui_smsdb_remove_sms_message(smsdb_t smsdb, gulong idvalue)
 
670
{
 
671
        GDBM_FILE db;
 
672
        gchar smsid[64];
 
673
        gint idlen, unreaddelta;
 
674
        datum key, data;
 
675
        gchar *node;
 
676
        
 
677
        if (smsdb == NULL) return FALSE;
 
678
        if (smsdb->filepath == NULL) return FALSE;
 
679
        
 
680
        db = gdbm_open((gchar *)smsdb->filepath, 0, GDBM_WRCREAT, MMGUI_SMSDB_ACCESS_MASK, 0);
 
681
        
 
682
        if (db == NULL) return FALSE;
 
683
        
 
684
        memset(smsid, 0, sizeof(smsid));
 
685
        idlen = g_snprintf(smsid, sizeof(smsid), "%lu", idvalue);
 
686
        key.dptr = (gchar *)smsid;
 
687
        key.dsize = idlen;
 
688
        
 
689
        unreaddelta = 0;
 
690
        
 
691
        if (gdbm_exists(db, key)) {
 
692
                data = gdbm_fetch(db, key);
 
693
                if (data.dptr != NULL) {
 
694
                        node = strstr(data.dptr, MMGUI_SMSDB_READ_TAG);
 
695
                        if (node != NULL) {
 
696
                                if ((node-data.dptr > 8) && (isdigit(node[8]))) {
 
697
                                        if (node[8] == '0') {
 
698
                                                unreaddelta = -1;
 
699
                                        } else {
 
700
                                                unreaddelta = 0;
 
701
                                        }
 
702
                                }
 
703
                        } else {
 
704
                                unreaddelta = -1;
 
705
                        }
 
706
                        free(data.dptr);
 
707
                }
 
708
                
 
709
                if (gdbm_delete(db, key) == 0) {
 
710
                        smsdb->unreadmessages += unreaddelta;
 
711
                        gdbm_sync(db);
 
712
                        gdbm_close(db);
 
713
                        return TRUE;
 
714
                }
 
715
        }
 
716
        
 
717
        gdbm_close(db);
 
718
        
 
719
        return FALSE;
 
720
}
 
721
 
 
722
gboolean mmgui_smsdb_set_message_read_status(smsdb_t smsdb, gulong idvalue, gboolean readflag)
 
723
{
 
724
        GDBM_FILE db;
 
725
        gint unreaddelta;
 
726
        gchar smsid[64];
 
727
        gint idlen;
 
728
        datum key, data;
 
729
        gchar *node, *trailer, *newmsg;
 
730
        gchar newtrailer[64];
 
731
        gint newtrailerlen;
 
732
        gboolean res;
 
733
                        
 
734
        if (smsdb == NULL) return FALSE;
 
735
        if (smsdb->filepath == NULL) return FALSE;
 
736
        
 
737
        db = gdbm_open((gchar *)smsdb->filepath, 0, GDBM_WRITER, MMGUI_SMSDB_ACCESS_MASK, 0);
 
738
        
 
739
        if (db == NULL) return FALSE;
 
740
        
 
741
        memset(smsid, 0, sizeof(smsid));
 
742
        idlen = snprintf(smsid, sizeof(smsid), "%lu", idvalue);
 
743
        key.dptr = (gchar *)smsid;
 
744
        key.dsize = idlen;
 
745
        
 
746
        res = FALSE;
 
747
        
 
748
        unreaddelta = 0;
 
749
        
 
750
        if (gdbm_exists(db, key)) {
 
751
                data = gdbm_fetch(db, key);
 
752
                if (data.dptr != NULL) {
 
753
                        node = strstr(data.dptr, MMGUI_SMSDB_READ_TAG);
 
754
                        if (node != NULL) {
 
755
                                if ((node-data.dptr > 8) && (isdigit(node[8]))) {
 
756
                                        if ((readflag) && (node[8] == '0')) {
 
757
                                                unreaddelta = -1;
 
758
                                                node[8] = '1';
 
759
                                        } else if ((!readflag) && (node[8] == '1')) {
 
760
                                                unreaddelta = 1;
 
761
                                                node[8] = '0';
 
762
                                        }
 
763
                                        
 
764
                                        if (gdbm_store(db, key, data, GDBM_REPLACE) == 0) {
 
765
                                                smsdb->unreadmessages += unreaddelta;
 
766
                                                res = TRUE;
 
767
                                        }
 
768
                                        
 
769
                                        free(data.dptr);
 
770
                                }
 
771
                        } else {
 
772
                                if (strstr(data.dptr, MMGUI_SMSDB_TRAILER_TAG) != NULL) {
 
773
                                        memset(newtrailer, 0, sizeof(newtrailer));
 
774
                                        newtrailerlen = g_snprintf(newtrailer, sizeof(newtrailer), MMGUI_SMSDB_TRAILER_PARAMS, readflag, MMGUI_SMSDB_SMS_FOLDER_INCOMING);
 
775
                                        
 
776
                                        newmsg = g_malloc0(data.dsize-9+newtrailerlen+1);
 
777
                                        memcpy(newmsg, data.dptr, data.dsize-9);
 
778
                                        memcpy(newmsg+data.dsize-9, newtrailer, newtrailerlen);
 
779
                                        
 
780
                                        free(data.dptr);
 
781
                                        
 
782
                                        data.dptr = newmsg;
 
783
                                        data.dsize = data.dsize-9+newtrailerlen;
 
784
                                        
 
785
                                        if (readflag) {
 
786
                                                unreaddelta = -1;
 
787
                                        } else {
 
788
                                                unreaddelta = 0;
 
789
                                        }
 
790
                                        
 
791
                                        if (gdbm_store(db, key, data, GDBM_REPLACE) == 0) {
 
792
                                                smsdb->unreadmessages += unreaddelta;
 
793
                                                res = TRUE;
 
794
                                        }
 
795
                                        
 
796
                                        g_free(newmsg);
 
797
                                }
 
798
                        }
 
799
                }
 
800
        }
 
801
        
 
802
        gdbm_close(db);
 
803
        
 
804
        return res;
 
805
}
 
806
 
 
807
static mmgui_sms_message_t mmgui_smsdb_xml_parse(gchar *xml, gsize size)
 
808
{
 
809
        mmgui_sms_message_t message;
 
810
        GMarkupParser mp;
 
811
        GMarkupParseContext *mpc;
 
812
        GError *error = NULL;
 
813
        
 
814
        message = g_new(struct _mmgui_sms_message, 1);
 
815
        
 
816
        message->timestamp = time(NULL);
 
817
        message->read = FALSE;
 
818
        message->folder = MMGUI_SMSDB_SMS_FOLDER_INCOMING;
 
819
        message->binary = FALSE;
 
820
        message->number = NULL;
 
821
        message->svcnumber = NULL;
 
822
        message->idents = NULL;
 
823
        message->text = NULL;
 
824
                
 
825
        mp.start_element = mmgui_smsdb_xml_get_element;
 
826
        mp.end_element = mmgui_smsdb_xml_end_element;
 
827
        mp.text = mmgui_smsdb_xml_get_value;
 
828
        mp.passthrough = NULL;
 
829
        mp.error = NULL;
 
830
        
 
831
        mpc = g_markup_parse_context_new(&mp, 0, (gpointer)message, NULL);
 
832
        g_markup_parse_context_parse(mpc, xml, size, &error);
 
833
        if (error != NULL) {
 
834
                //g_warning(error->message);
 
835
                g_error_free(error);
 
836
                g_markup_parse_context_free(mpc);
 
837
                return NULL;
 
838
        }
 
839
        g_markup_parse_context_free(mpc);
 
840
        
 
841
        return message;
 
842
}
 
843
 
 
844
static void mmgui_smsdb_xml_get_element(GMarkupParseContext *context, const gchar *element, const gchar **attr_names, const gchar **attr_values, gpointer data, GError **error)
 
845
{
 
846
        if (g_str_equal(element, "number")) {
 
847
                mmgui_smsdb_xml_parameter = MMGUI_SMSDB_XML_PARAM_NUMBER;
 
848
        } else if (g_str_equal(element, "time")) {
 
849
                mmgui_smsdb_xml_parameter = MMGUI_SMSDB_XML_PARAM_TIME;
 
850
        } else if (g_str_equal(element, "binary")) {
 
851
                mmgui_smsdb_xml_parameter = MMGUI_SMSDB_XML_PARAM_BINARY;
 
852
        } else if (g_str_equal(element, "servicenumber")) {
 
853
                mmgui_smsdb_xml_parameter = MMGUI_SMSDB_XML_PARAM_SERVICENUMBER;
 
854
        } else if (g_str_equal(element, "text")) {
 
855
                mmgui_smsdb_xml_parameter = MMGUI_SMSDB_XML_PARAM_TEXT;
 
856
        } else if (g_str_equal(element, "read")) {
 
857
                mmgui_smsdb_xml_parameter = MMGUI_SMSDB_XML_PARAM_READ;
 
858
        } else if (g_str_equal(element, "folder")) {
 
859
                mmgui_smsdb_xml_parameter = MMGUI_SMSDB_XML_PARAM_FOLDER;
 
860
        } else {
 
861
                mmgui_smsdb_xml_parameter = MMGUI_SMSDB_XML_PARAM_NULL;
 
862
        }
 
863
}
 
864
 
 
865
static void mmgui_smsdb_xml_get_value(GMarkupParseContext *context, const gchar *text, gsize size, gpointer data, GError **error)
 
866
{
 
867
        mmgui_sms_message_t message;
 
868
        gchar *numescstr, *textescstr;
 
869
        gsize numlen;
 
870
        
 
871
        message = (mmgui_sms_message_t)data;
 
872
        
 
873
        if (mmgui_smsdb_xml_parameter == MMGUI_SMSDB_XML_PARAM_NULL) return;
 
874
        
 
875
        switch (mmgui_smsdb_xml_parameter) {
 
876
                case MMGUI_SMSDB_XML_PARAM_NUMBER:
 
877
                        numescstr = encoding_unescape_xml_markup(text, size);
 
878
                        if (numescstr != NULL) {
 
879
                                message->number = bcd_to_utf8_ascii_part(numescstr, strlen(numescstr), &numlen);
 
880
                                g_free(numescstr);
 
881
                        } else {
 
882
                                message->number = bcd_to_utf8_ascii_part(text, size, &numlen);
 
883
                        }
 
884
                        if (message->number != NULL) {
 
885
                                message->number = encoding_clear_special_symbols(message->number, numlen);
 
886
                        } else {
 
887
                                message->number = encoding_clear_special_symbols(g_strdup(text), size);
 
888
                        }
 
889
                        break;
 
890
                case MMGUI_SMSDB_XML_PARAM_TIME:
 
891
                        message->timestamp = (time_t)atol(text);
 
892
                        break;
 
893
                case MMGUI_SMSDB_XML_PARAM_BINARY:
 
894
                        if (atoi(text)) {
 
895
                                message->binary = TRUE;
 
896
                        } else {
 
897
                                message->binary = FALSE;
 
898
                        }
 
899
                        break;
 
900
                case MMGUI_SMSDB_XML_PARAM_SERVICENUMBER:
 
901
                        message->svcnumber = g_strdup(text);
 
902
                        break;
 
903
                case MMGUI_SMSDB_XML_PARAM_TEXT:
 
904
                        textescstr = encoding_unescape_xml_markup(text, size);
 
905
                        if (textescstr != NULL) {
 
906
                                message->text = g_string_new(textescstr);
 
907
                                g_free(textescstr);
 
908
                        } else {
 
909
                                message->text = g_string_new(text);
 
910
                        }
 
911
                        break;
 
912
                case MMGUI_SMSDB_XML_PARAM_READ:
 
913
                        if (atoi(text)) {
 
914
                                message->read = TRUE;
 
915
                        } else {
 
916
                                message->read = FALSE;
 
917
                        }
 
918
                        break;
 
919
                case MMGUI_SMSDB_XML_PARAM_FOLDER:
 
920
                        message->folder = atoi(text);
 
921
                        break;
 
922
                default:
 
923
                        break;
 
924
        }
 
925
}
 
926
 
 
927
static void mmgui_smsdb_xml_end_element(GMarkupParseContext *context, const gchar *element, gpointer data, GError **error)
 
928
{
 
929
        if (!g_str_equal(element, "sms")) {
 
930
                mmgui_smsdb_xml_parameter = MMGUI_SMSDB_XML_PARAM_NULL;
 
931
        }
 
932
}