~ubuntu-branches/ubuntu/karmic/pilot-link/karmic

« back to all changes in this revision

Viewing changes to src/pilot-memos.c

  • Committer: Bazaar Package Importer
  • Author(s): Ludovic Rousseau
  • Date: 2006-09-22 11:51:36 UTC
  • mfrom: (3.1.8 edgy)
  • Revision ID: james.westby@ubuntu.com-20060922115136-qqmy17bx8j5x0y72
Tags: 0.12.1-5
* urgency medium since libpisock-dev was not usable to build any package
* libpisock-dev now depends on libusb-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * pilot-memos.c:  Translate Palm Memos into e-mail format
 
3
 *
 
4
 * Copyright (c) 1996, Kenneth Albanowski
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify it
 
7
 * under the terms of the GNU General Public License as published by the
 
8
 * Free Software Foundation; either version 2 of the License, or (at your
 
9
 * option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 
14
 * Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License along
 
17
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
18
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
19
 *
 
20
 */
 
21
 
 
22
#include <stdio.h>
 
23
#include <sys/stat.h>
 
24
#include <regex.h>
 
25
 
 
26
#include "pi-memo.h"
 
27
#include "pi-file.h"
 
28
#include "pi-header.h"
 
29
#include "pi-userland.h"
 
30
 
 
31
/* constants to determine how to produce memos */
 
32
#define MEMO_MBOX_STDOUT 0
 
33
#define MEMO_DIRECTORY 1
 
34
#define MAXDIRNAMELEN 1024
 
35
 
 
36
void write_memo_mbox(struct Memo m, struct MemoAppInfo mai, int category);
 
37
void write_memo_in_directory(char *dirname, struct Memo m,
 
38
                             struct MemoAppInfo mai, int category,
 
39
                             int verbose, const char *progname);
 
40
 
 
41
/***********************************************************************
 
42
 *
 
43
 * Function:    write_memo_mbox
 
44
 *
 
45
 * Summary:     Write a memo entry to MailDB database
 
46
 *
 
47
 * Parameters:  None
 
48
 *
 
49
 * Returns:     Nothing
 
50
 *
 
51
 ***********************************************************************/
 
52
void write_memo_mbox(struct Memo m, struct MemoAppInfo mai, int category)
 
53
{
 
54
        int     j;
 
55
        time_t  now;
 
56
        char    *time_str;
 
57
 
 
58
        now = time( NULL );
 
59
 
 
60
        /* FIXME: might be good to get the time stamp of the memo file for
 
61
           the "Received" line */
 
62
 
 
63
        time_str = ctime(&now);
 
64
 
 
65
        printf("From Palm.Handheld %s"
 
66
               "From: pilot-link memos (MemoDB) <Palm.Handheld@your.machine>\n"
 
67
               "Received: %s"
 
68
               "To: You\n"
 
69
               "Date: %s"
 
70
               "Subject: ", time_str, time_str, time_str);
 
71
 
 
72
        /* print category name in brackets in subject field */
 
73
        printf("[%s] ", mai.category.name[category]);
 
74
 
 
75
        /* print (at least part of) first line as part of subject: */
 
76
        for (j = 0; j < 40; j++) {
 
77
                if ((!m.text[j]) || (m.text[j] == '\n'))
 
78
                        break;
 
79
                printf("%c", m.text[j]);
 
80
        }
 
81
        if (j == 40)
 
82
                printf("...\n");
 
83
        else
 
84
                printf("\n");
 
85
        printf("\n");
 
86
        puts(m.text);
 
87
}
 
88
 
 
89
/***********************************************************************
 
90
 *
 
91
 * Function:    write_memo_in_directory
 
92
 *
 
93
 * Summary:     Writes each memo into /$DIR/$CATEGORY/$FILENAME form
 
94
 *              after the user specifies the -d /dir/name argument
 
95
 *
 
96
 * Parameters:  None
 
97
 *
 
98
 * Returns:     Nothing
 
99
 *
 
100
 ***********************************************************************/
 
101
void
 
102
write_memo_in_directory(char *dirname, struct Memo m,
 
103
                        struct MemoAppInfo mai, int category, int verbose, const char *progname)
 
104
{
 
105
        int     j;
 
106
        char    pathbuffer[MAXDIRNAMELEN] = "",
 
107
                tmp[5] = "";
 
108
        FILE *fd;
 
109
 
 
110
        /* Should check if dirname exists and is a directory */
 
111
        mkdir(dirname, 0700);
 
112
 
 
113
        /* Create a directory for the category */
 
114
        strncat(pathbuffer, dirname, MAXDIRNAMELEN);
 
115
        strncat(pathbuffer, "/", 1);
 
116
 
 
117
        /* Should make sure category doesn't have slashes in it */
 
118
        strncat(pathbuffer, mai.category.name[category], 60);
 
119
 
 
120
        /* Should check if pathbuffer exists and is a directory */
 
121
        mkdir(pathbuffer, 0700);
 
122
 
 
123
        /* Should check if there were problems creating directory */
 
124
        /* open the actual file to write */
 
125
        strncat(pathbuffer, "/", 1);
 
126
        for (j = 0; j < 40; j++) {
 
127
                if ((!m.text[j]) || (m.text[j] == '\n'))
 
128
                        break;
 
129
                if (m.text[j] == '/') {
 
130
                        strncat(pathbuffer, "=2F", 3);
 
131
                        continue;
 
132
                }
 
133
                if (m.text[j] == '=') {
 
134
                        strncat(pathbuffer, "=3D", 3);
 
135
                        continue;
 
136
                }
 
137
#ifdef OS2
 
138
                if (m.text[j] == ':') {
 
139
                        strncat(pathbuffer, "=3A", 3);
 
140
                        continue;
 
141
                }
 
142
#endif
 
143
                /* escape if it's an ISO8859 control chcter (note: some
 
144
                   are printable on the Palm) */
 
145
                if ((m.text[j] | 0x7f) < ' ') {
 
146
                        tmp[0] = '\0';
 
147
                        sprintf(tmp, "=%2X", (unsigned char) m.text[j]);
 
148
                } else {
 
149
                        tmp[0] = m.text[j];
 
150
                        tmp[1] = '\0';
 
151
                }
 
152
                strcat(pathbuffer, tmp);
 
153
        }
 
154
 
 
155
        if (verbose) {
 
156
                printf("Writing %s\n", pathbuffer);
 
157
        }
 
158
 
 
159
        if (!(fd = fopen(pathbuffer, "w"))) {
 
160
                printf("%s: can't open file \"%s\" for writing\n",
 
161
                        progname, pathbuffer);
 
162
                exit(EXIT_FAILURE);
 
163
        }
 
164
        fputs(m.text, fd);
 
165
        fclose(fd);
 
166
}
 
167
 
 
168
 
 
169
int main(int argc, const char *argv[])
 
170
{
 
171
        int     attr,
 
172
                c,              /* switch */
 
173
                category,
 
174
                db,
 
175
                idx,
 
176
                ret,
 
177
                sd              = -1,
 
178
                verbose         = 0,
 
179
                delete          = 0,
 
180
                mode            = MEMO_MBOX_STDOUT,
 
181
                bufsize         = 1024,
 
182
                match_category  = -1,
 
183
                title_matching  = 0;
 
184
 
 
185
        size_t  len;
 
186
 
 
187
        pi_buffer_t     *buffer,
 
188
                *appblock;
 
189
 
 
190
        const char
 
191
                *progname       = argv[0];
 
192
 
 
193
        char    *buf = NULL,
 
194
                *dirname = NULL,
 
195
                *category_name = NULL,
 
196
                *filename = NULL,
 
197
                *regex = NULL,
 
198
                *ptr;
 
199
 
 
200
        struct  MemoAppInfo mai;
 
201
        struct  pi_file *pif = NULL;
 
202
        struct  Memo m;
 
203
 
 
204
        regex_t title_pattern;
 
205
        recordid_t id;
 
206
 
 
207
        poptContext po;
 
208
 
 
209
        struct poptOption options[] = {
 
210
                USERLAND_RESERVED_OPTIONS
 
211
                {"verbose",     'v', POPT_ARG_VAL, &verbose, 1, "Verbose, with -s, print each filename when written", NULL},
 
212
                {"delete",      'd', POPT_ARG_VAL, &delete,  1, "Delete memo named by number <num>", "<num>"},
 
213
                {"file",        'f', POPT_ARG_STRING, &filename, 0, "Use <file> as input file (instead of MemoDB.pdb)", "<file>"},
 
214
                {"save",        's', POPT_ARG_STRING, &dirname, 0, "Save memos in <dir> instead of writing to STDOUT", "<dir>"},
 
215
                {"category",    'c', POPT_ARG_STRING, &category_name, 0, "Only upload memos in this category", "<category>"},
 
216
                {"regex",       'r', POPT_ARG_STRING, &regex, 0, "Select memos saved by regular expression on title", "<regex>"},
 
217
        POPT_AUTOHELP
 
218
        POPT_TABLEEND
 
219
        };
 
220
 
 
221
        po = poptGetContext("memos", argc, argv, options, 0);
 
222
 
 
223
        poptSetOtherOptionHelp(po,"\n\n"
 
224
                "  Manipulate Memo entries from a file or your Palm device\n\n"
 
225
                "  By default, the contents of your Palm's memo database will be written to\n"
 
226
                "  standard output as a standard UNIX mailbox (mbox-format) file, with each\n"
 
227
                "  memo as a separate message.  The subject of each message will be the\n"
 
228
                "  category.\n\n"
 
229
 
 
230
                "  If '-s' is specified, than instead of being written to standard output,\n"
 
231
                "  will be saved in subdirectories of <dir>. Each subdirectory will be the\n"
 
232
                "  name of a category on the Palm, and will contain the memos in that\n"
 
233
                "  category. Each memo's filename will be the first line (up to the first 40\n"
 
234
                "  characters) of the memo. Control chcters, slashes, and equal signs that\n"
 
235
                "  would otherwise appear in filenames are converted after the fashion of\n"
 
236
                "  MIME's quoted-printable encoding. Note that if you have two memos in the\n"
 
237
                "  same category whose first lines are identical, one of them will be\n"
 
238
                "  overwritten.\n\n"
 
239
 
 
240
                "  If '-f' is specified, the specified file will be treated as a memo\n"
 
241
                "  database from which to read memos, rather than HotSyncing from the Palm.\n");
 
242
 
 
243
        if (argc < 2) {
 
244
                poptPrintUsage(po,stderr,0);
 
245
                return 1;
 
246
        }
 
247
 
 
248
        while ((c = poptGetNextOpt(po)) >= 0) {
 
249
                fprintf(stderr,"   ERROR: Unhandled option %d.\n",c);
 
250
                return -1;
 
251
        }
 
252
 
 
253
        if (dirname)
 
254
                mode = MEMO_DIRECTORY;
 
255
 
 
256
        if (c < -1)
 
257
                plu_badoption(po, c);
 
258
 
 
259
        if (regex) {
 
260
                ret = regcomp(&title_pattern, regex, REG_NOSUB);
 
261
                buf = (char *) malloc(bufsize);
 
262
                if (ret) {
 
263
                        regerror(ret, &title_pattern, buf, bufsize);
 
264
                        fprintf(stderr,"   ERROR: Regexp - %s\n", buf);
 
265
                        return 1;
 
266
                }
 
267
                title_matching = 1;
 
268
        }
 
269
 
 
270
        /* FIXME - Need to add tests here for port/filename, clean this. -DD */
 
271
        appblock = pi_buffer_new(0xffff);
 
272
        if (!filename) {
 
273
 
 
274
                sd = plu_connect();
 
275
 
 
276
                if (sd < 0)
 
277
                        goto error;
 
278
 
 
279
                if (dlp_OpenConduit(sd) < 0)
 
280
                        goto error_close;
 
281
 
 
282
                /* Open the Memo Pad's database, store access handle in db */
 
283
                if (dlp_OpenDB(sd, 0, 0x80 | 0x40, "MemoDB", &db) < 0) {
 
284
                        fprintf(stderr,"   ERROR: Unable to open MemoDB on Palm.\n");
 
285
                        dlp_AddSyncLogEntry(sd,
 
286
                                            "Unable to open MemoDB.\n");
 
287
                        goto error_close;
 
288
                }
 
289
 
 
290
                dlp_ReadAppBlock(sd, db, 0, 0xffff, appblock);
 
291
        } else {
 
292
                pif = pi_file_open(filename);
 
293
                if (!pif) {
 
294
                        fprintf(stderr,"   ERROR: pi_file_open: %s\n",strerror(errno));
 
295
                        return 1;
 
296
                }
 
297
 
 
298
                pi_file_get_app_info(pif, (void **) &ptr, &len);
 
299
                pi_buffer_append(appblock, ptr, len);
 
300
        }
 
301
 
 
302
        unpack_MemoAppInfo(&mai, appblock->data, appblock->used);
 
303
        pi_buffer_free(appblock);
 
304
 
 
305
        if (category_name && category_name[0] != '\0') {
 
306
                match_category = plu_findcategory(&mai.category,category_name, PLU_CAT_WARN_UNKNOWN);
 
307
                if (match_category < 0) {
 
308
                        goto error_close;
 
309
                };
 
310
        }
 
311
 
 
312
        buffer = pi_buffer_new (0xffff);
 
313
 
 
314
        for (idx = 0;; idx++) {
 
315
 
 
316
                if (!filename) {
 
317
                        if (match_category >= 0) {
 
318
                                ret = dlp_ReadNextRecInCategory(sd, db,
 
319
                                                                match_category,
 
320
                                                                buffer, &id,
 
321
                                                                0, &attr);
 
322
                                category = match_category;
 
323
                        } else {
 
324
                                ret = dlp_ReadRecordByIndex(sd, db, idx,
 
325
                                                            buffer, &id,
 
326
                                                            &attr,
 
327
                                                            &category);
 
328
                        }
 
329
                        if (ret < 0)
 
330
                                break;
 
331
 
 
332
                        len = (size_t)ret;
 
333
                } else {
 
334
                        if (pi_file_read_record
 
335
                            (pif, idx, (void **) &ptr, &len, &attr, &category,
 
336
                             0) < 0)
 
337
                                break;
 
338
                        memcpy(buffer->data, ptr, len);
 
339
                        buffer->used = len;
 
340
                }
 
341
 
 
342
                /* Skip deleted records */
 
343
                if ((attr & dlpRecAttrDeleted)
 
344
                    || (attr & dlpRecAttrArchived))
 
345
                        continue;
 
346
 
 
347
                /* Skip memos whose category doesn't match */
 
348
                if( match_category >= 0 ) {
 
349
                        if( match_category != category )
 
350
                                continue;
 
351
                }
 
352
 
 
353
                unpack_Memo(&m, buffer, memo_v1);
 
354
 
 
355
                /* Skip memos whose title does not match with the query */
 
356
                if (title_matching) {
 
357
                        for (len = 0; m.text[len] && m.text[len] != '\n';
 
358
                             len++);
 
359
                        if (bufsize < len + 1)
 
360
                                buf = (char *) realloc(buf, len + 1);
 
361
                        strncpy(buf, m.text, len);
 
362
                        buf[len] = '\0';
 
363
                        if (regexec(&title_pattern, buf, 0, NULL, 0) ==
 
364
                            REG_NOMATCH)
 
365
                                continue;
 
366
                }
 
367
 
 
368
                switch (mode) {
 
369
                  case MEMO_MBOX_STDOUT:
 
370
                          write_memo_mbox(m, mai, category);
 
371
                          break;
 
372
                  case MEMO_DIRECTORY:
 
373
                          write_memo_in_directory(dirname, m, mai,
 
374
                                                  category, verbose, progname);
 
375
                          break;
 
376
                }
 
377
        }
 
378
 
 
379
        pi_buffer_free (buffer);
 
380
 
 
381
        if (delete && !filename) {
 
382
                if (verbose)
 
383
                        printf("Deleting record %d.\n", (int) id);
 
384
                dlp_DeleteRecord(sd, db, 0, id);
 
385
        }
 
386
 
 
387
        if (title_matching) {
 
388
                regfree(&title_pattern);
 
389
                free(buf);
 
390
        }
 
391
 
 
392
        if (!filename) {
 
393
                /* Close the database */
 
394
                dlp_CloseDB(sd, db);
 
395
                dlp_AddSyncLogEntry(sd, "Successfully read memos from Palm.\n"
 
396
                                        "Thank you for using pilot-link.\n");
 
397
                pi_close(sd);
 
398
        } else {
 
399
                pi_file_close(pif);
 
400
        }
 
401
        return 0;
 
402
 
 
403
error_close:
 
404
        if (pif) {
 
405
                pi_file_close(pif);
 
406
        }
 
407
        if (sd >= 0) {
 
408
                pi_close(sd);
 
409
        }
 
410
 
 
411
error:
 
412
        return -1;
 
413
}