Statistics
| Revision:

root / src / jpilot.c @ 123

History | View | Annotate | Download (41.5 kB)

1 1 hiro
/*
2 1 hiro
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 1 hiro
 * Copyright (C) 2001 Match Grun
4 1 hiro
 *
5 1 hiro
 * This program is free software; you can redistribute it and/or modify
6 1 hiro
 * it under the terms of the GNU General Public License as published by
7 1 hiro
 * the Free Software Foundation; either version 2 of the License, or
8 1 hiro
 * (at your option) any later version.
9 1 hiro
 *
10 1 hiro
 * This program is distributed in the hope that it will be useful,
11 1 hiro
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 1 hiro
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 1 hiro
 * GNU General Public License for more details.
14 1 hiro
 *
15 1 hiro
 * You should have received a copy of the GNU General Public License
16 1 hiro
 * along with this program; if not, write to the Free Software
17 1 hiro
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 1 hiro
 */
19 1 hiro
20 1 hiro
/*
21 1 hiro
 * Functions necessary to access JPilot database files.
22 1 hiro
 * JPilot is Copyright(c) by Judd Montgomery.
23 1 hiro
 * Visit http://www.jpilot.org for more details.
24 1 hiro
 */
25 1 hiro
26 1 hiro
#ifdef HAVE_CONFIG_H
27 1 hiro
#  include "config.h"
28 1 hiro
#endif
29 1 hiro
30 1 hiro
#ifdef USE_JPILOT
31 1 hiro
32 1 hiro
#include <glib.h>
33 1 hiro
#include <time.h>
34 1 hiro
#include <stdio.h>
35 1 hiro
#include <stdlib.h>
36 1 hiro
#include <string.h>
37 1 hiro
#include <sys/stat.h>
38 1 hiro
/* #include <dlfcn.h> */
39 1 hiro
#include <netinet/in.h>
40 1 hiro
41 1 hiro
#ifdef HAVE_LIBPISOCK_PI_ARGS_H
42 1 hiro
#  include <libpisock/pi-args.h>
43 1 hiro
#  include <libpisock/pi-appinfo.h>
44 1 hiro
#  include <libpisock/pi-address.h>
45 1 hiro
#else
46 1 hiro
#  include <pi-args.h>
47 1 hiro
#  include <pi-appinfo.h>
48 1 hiro
#  include <pi-address.h>
49 1 hiro
#endif
50 1 hiro
51 1 hiro
#include "mgutils.h"
52 1 hiro
#include "addritem.h"
53 1 hiro
#include "addrcache.h"
54 1 hiro
#include "jpilot.h"
55 1 hiro
#include "codeconv.h"
56 42 hiro
#include "utils.h"
57 1 hiro
58 1 hiro
#define JPILOT_DBHOME_DIR   ".jpilot"
59 1 hiro
#define JPILOT_DBHOME_FILE  "AddressDB.pdb"
60 1 hiro
#define PILOT_LINK_LIB_NAME "libpisock.so"
61 1 hiro
62 1 hiro
#define IND_LABEL_LASTNAME  0         /* Index of last name in address data */
63 1 hiro
#define IND_LABEL_FIRSTNAME 1         /* Index of first name in address data */
64 1 hiro
#define IND_PHONE_EMAIL     4         /* Index of E-Mail address in phone labels */
65 1 hiro
#define OFFSET_PHONE_LABEL  3         /* Offset to phone data in address data */
66 1 hiro
#define IND_CUSTOM_LABEL    14        /* Offset to custom label names */
67 1 hiro
#define NUM_CUSTOM_LABEL    4         /* Number of custom labels */
68 1 hiro
69 1 hiro
/* Shamelessly copied from JPilot (libplugin.h) */
70 1 hiro
typedef struct {
71 1 hiro
        unsigned char db_name[32];
72 1 hiro
        unsigned char flags[2];
73 1 hiro
        unsigned char version[2];
74 1 hiro
        unsigned char creation_time[4];
75 1 hiro
        unsigned char modification_time[4];
76 1 hiro
        unsigned char backup_time[4];
77 1 hiro
        unsigned char modification_number[4];
78 1 hiro
        unsigned char app_info_offset[4];
79 1 hiro
        unsigned char sort_info_offset[4];
80 1 hiro
        unsigned char type[4];/*Database ID */
81 1 hiro
        unsigned char creator_id[4];/*Application ID */
82 1 hiro
        unsigned char unique_id_seed[4];
83 1 hiro
        unsigned char next_record_list_id[4];
84 1 hiro
        unsigned char number_of_records[2];
85 1 hiro
} RawDBHeader;
86 1 hiro
87 1 hiro
/* Shamelessly copied from JPilot (libplugin.h) */
88 1 hiro
typedef struct {
89 1 hiro
        char db_name[32];
90 1 hiro
        unsigned int flags;
91 1 hiro
        unsigned int version;
92 1 hiro
        time_t creation_time;
93 1 hiro
        time_t modification_time;
94 1 hiro
        time_t backup_time;
95 1 hiro
        unsigned int modification_number;
96 1 hiro
        unsigned int app_info_offset;
97 1 hiro
        unsigned int sort_info_offset;
98 1 hiro
        char type[5];/*Database ID */
99 1 hiro
        char creator_id[5];/*Application ID */
100 1 hiro
        char unique_id_seed[5];
101 1 hiro
        unsigned int next_record_list_id;
102 1 hiro
        unsigned int number_of_records;
103 1 hiro
} DBHeader;
104 1 hiro
105 1 hiro
/* Shamelessly copied from JPilot (libplugin.h) */
106 1 hiro
typedef struct {
107 1 hiro
        unsigned char Offset[4];  /*4 bytes offset from BOF to record */
108 1 hiro
        unsigned char attrib;
109 1 hiro
        unsigned char unique_ID[3];
110 1 hiro
} record_header;
111 1 hiro
112 1 hiro
/* Shamelessly copied from JPilot (libplugin.h) */
113 1 hiro
typedef struct mem_rec_header_s {
114 1 hiro
        unsigned int rec_num;
115 1 hiro
        unsigned int offset;
116 1 hiro
        unsigned int unique_id;
117 1 hiro
        unsigned char attrib;
118 1 hiro
        struct mem_rec_header_s *next;
119 1 hiro
} mem_rec_header;
120 1 hiro
121 1 hiro
/* Shamelessly copied from JPilot (libplugin.h) */
122 1 hiro
#define SPENT_PC_RECORD_BIT        256
123 1 hiro
124 1 hiro
typedef enum {
125 1 hiro
        PALM_REC = 100L,
126 1 hiro
        MODIFIED_PALM_REC = 101L,
127 1 hiro
        DELETED_PALM_REC = 102L,
128 1 hiro
        NEW_PC_REC = 103L,
129 1 hiro
        DELETED_PC_REC = SPENT_PC_RECORD_BIT + 104L,
130 1 hiro
        DELETED_DELETED_PALM_REC = SPENT_PC_RECORD_BIT + 105L
131 1 hiro
} PCRecType;
132 1 hiro
133 1 hiro
/* Shamelessly copied from JPilot (libplugin.h) */
134 1 hiro
typedef struct {
135 1 hiro
        PCRecType rt;
136 1 hiro
        unsigned int unique_id;
137 1 hiro
        unsigned char attrib;
138 1 hiro
        void *buf;
139 1 hiro
        int size;
140 1 hiro
} buf_rec;
141 1 hiro
142 1 hiro
/* Shamelessly copied from JPilot (libplugin.h) */
143 1 hiro
typedef struct {
144 1 hiro
        unsigned long header_len;
145 1 hiro
        unsigned long header_version;
146 1 hiro
        unsigned long rec_len;
147 1 hiro
        unsigned long unique_id;
148 1 hiro
        unsigned long rt; /* Record Type */
149 1 hiro
        unsigned char attrib;
150 1 hiro
} PC3RecordHeader;
151 1 hiro
152 1 hiro
enum {
153 1 hiro
        FAMILY_LAST = 0,
154 1 hiro
        FAMILY_FIRST = 1
155 1 hiro
} name_order;
156 1 hiro
157 1 hiro
gboolean convert_charcode;
158 1 hiro
159 1 hiro
/*
160 1 hiro
* Create new pilot file object.
161 1 hiro
*/
162 1 hiro
JPilotFile *jpilot_create() {
163 1 hiro
        JPilotFile *pilotFile;
164 1 hiro
        pilotFile = g_new0( JPilotFile, 1 );
165 1 hiro
        pilotFile->name = NULL;
166 1 hiro
        pilotFile->file = NULL;
167 1 hiro
        pilotFile->path = NULL;
168 1 hiro
        pilotFile->addressCache = addrcache_create();
169 1 hiro
        pilotFile->readMetadata = FALSE;
170 1 hiro
        pilotFile->customLabels = NULL;
171 1 hiro
        pilotFile->labelInd = NULL;
172 1 hiro
        pilotFile->retVal = MGU_SUCCESS;
173 1 hiro
        pilotFile->accessFlag = FALSE;
174 1 hiro
        pilotFile->havePC3 = FALSE;
175 1 hiro
        pilotFile->pc3ModifyTime = 0;
176 1 hiro
        return pilotFile;
177 1 hiro
}
178 1 hiro
179 1 hiro
/*
180 1 hiro
* Create new pilot file object for specified file.
181 1 hiro
*/
182 1 hiro
JPilotFile *jpilot_create_path( const gchar *path ) {
183 1 hiro
        JPilotFile *pilotFile;
184 1 hiro
        pilotFile = jpilot_create();
185 1 hiro
        jpilot_set_file( pilotFile, path );
186 1 hiro
        return pilotFile;
187 1 hiro
}
188 1 hiro
189 1 hiro
/*
190 1 hiro
* Properties...
191 1 hiro
*/
192 1 hiro
void jpilot_set_name( JPilotFile* pilotFile, const gchar *value ) {
193 1 hiro
        g_return_if_fail( pilotFile != NULL );
194 1 hiro
        pilotFile->name = mgu_replace_string( pilotFile->name, value );
195 1 hiro
}
196 1 hiro
void jpilot_set_file( JPilotFile* pilotFile, const gchar *value ) {
197 1 hiro
        g_return_if_fail( pilotFile != NULL );
198 1 hiro
        addrcache_refresh( pilotFile->addressCache );
199 1 hiro
        pilotFile->readMetadata = FALSE;
200 1 hiro
        pilotFile->path = mgu_replace_string( pilotFile->path, value );
201 1 hiro
}
202 1 hiro
void jpilot_set_accessed( JPilotFile *pilotFile, const gboolean value ) {
203 1 hiro
        g_return_if_fail( pilotFile != NULL );
204 1 hiro
        pilotFile->accessFlag = value;
205 1 hiro
}
206 1 hiro
207 1 hiro
gint jpilot_get_status( JPilotFile *pilotFile ) {
208 1 hiro
        g_return_val_if_fail( pilotFile != NULL, -1 );
209 1 hiro
        return pilotFile->retVal;
210 1 hiro
}
211 1 hiro
ItemFolder *jpilot_get_root_folder( JPilotFile *pilotFile ) {
212 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
213 1 hiro
        return addrcache_get_root_folder( pilotFile->addressCache );
214 1 hiro
}
215 1 hiro
gchar *jpilot_get_name( JPilotFile *pilotFile ) {
216 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
217 1 hiro
        return pilotFile->name;
218 1 hiro
}
219 1 hiro
220 1 hiro
/*
221 1 hiro
* Test whether file was read.
222 1 hiro
* Return: TRUE if file was read.
223 1 hiro
*/
224 1 hiro
gboolean jpilot_get_read_flag( JPilotFile *pilotFile ) {
225 1 hiro
        g_return_val_if_fail( pilotFile != NULL, FALSE );
226 1 hiro
        return pilotFile->addressCache->dataRead;
227 1 hiro
}
228 1 hiro
229 1 hiro
/*
230 1 hiro
* Free up custom label list.
231 1 hiro
*/
232 1 hiro
void jpilot_clear_custom_labels( JPilotFile *pilotFile ) {
233 1 hiro
        GList *node;
234 1 hiro
235 1 hiro
        g_return_if_fail( pilotFile != NULL );
236 1 hiro
237 1 hiro
        /* Release custom labels */
238 1 hiro
        mgu_free_dlist( pilotFile->customLabels );
239 1 hiro
        pilotFile->customLabels = NULL;
240 1 hiro
241 1 hiro
        /* Release indexes */
242 1 hiro
        node = pilotFile->labelInd;
243 1 hiro
        while( node ) {
244 1 hiro
                node->data = NULL;
245 1 hiro
                node = g_list_next( node );
246 1 hiro
        }
247 1 hiro
        g_list_free( pilotFile->labelInd );
248 1 hiro
        pilotFile->labelInd = NULL;
249 1 hiro
250 1 hiro
        /* Force a fresh read */
251 1 hiro
        addrcache_refresh( pilotFile->addressCache );
252 1 hiro
}
253 1 hiro
254 1 hiro
/*
255 1 hiro
* Append a custom label, representing an E-Mail address field to the
256 1 hiro
* custom label list.
257 1 hiro
*/
258 1 hiro
void jpilot_add_custom_label( JPilotFile *pilotFile, const gchar *labelName ) {
259 1 hiro
        g_return_if_fail( pilotFile != NULL );
260 1 hiro
261 1 hiro
        if( labelName ) {
262 1 hiro
                gchar *labelCopy = g_strdup( labelName );
263 1 hiro
                g_strstrip( labelCopy );
264 1 hiro
                if( *labelCopy == '\0' ) {
265 1 hiro
                        g_free( labelCopy );
266 1 hiro
                }
267 1 hiro
                else {
268 1 hiro
                        pilotFile->customLabels = g_list_append( pilotFile->customLabels, labelCopy );
269 1 hiro
                        /* Force a fresh read */
270 1 hiro
                        addrcache_refresh( pilotFile->addressCache );
271 1 hiro
                }
272 1 hiro
        }
273 1 hiro
}
274 1 hiro
275 1 hiro
/*
276 1 hiro
* Get list of custom labels.
277 1 hiro
* Return: List of labels. Must use g_free() when done.
278 1 hiro
*/
279 1 hiro
GList *jpilot_get_custom_labels( JPilotFile *pilotFile ) {
280 1 hiro
        GList *retVal = NULL;
281 1 hiro
        GList *node;
282 1 hiro
283 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
284 1 hiro
285 1 hiro
        node = pilotFile->customLabels;
286 1 hiro
        while( node ) {
287 1 hiro
                retVal = g_list_append( retVal, g_strdup( node->data ) );
288 1 hiro
                node = g_list_next( node );
289 1 hiro
        }
290 1 hiro
        return retVal;
291 1 hiro
}
292 1 hiro
293 1 hiro
/*
294 1 hiro
* Return filespec of PC3 file corresponding to JPilot PDB file.
295 1 hiro
* Note: Filespec should be g_free() when done.
296 1 hiro
*/
297 1 hiro
static gchar *jpilot_get_pc3_file( JPilotFile *pilotFile ) {
298 1 hiro
        gchar *fileSpec, *r;
299 1 hiro
        gint i, len, pos;
300 1 hiro
301 1 hiro
        if( pilotFile == NULL ) return NULL;
302 1 hiro
        if( pilotFile->path == NULL ) return NULL;
303 1 hiro
304 1 hiro
        fileSpec = g_strdup( pilotFile->path );
305 1 hiro
        len = strlen( fileSpec );
306 1 hiro
        pos = -1;
307 1 hiro
        r = NULL;
308 1 hiro
        for( i = len; i > 0; i-- ) {
309 1 hiro
                if( *(fileSpec + i) == '.' ) {
310 1 hiro
                        pos = i + 1;
311 1 hiro
                        r = fileSpec + pos;
312 1 hiro
                        break;
313 1 hiro
                }
314 1 hiro
        }
315 1 hiro
        if( r ) {
316 1 hiro
                if( len - pos == 3 ) {
317 1 hiro
                        *r++ = 'p'; *r++ = 'c'; *r = '3';
318 1 hiro
                        return fileSpec;
319 1 hiro
                }
320 1 hiro
        }
321 1 hiro
        g_free( fileSpec );
322 1 hiro
        return NULL;
323 1 hiro
}
324 1 hiro
325 1 hiro
/*
326 1 hiro
* Save PC3 file time to cache.
327 1 hiro
* return: TRUE if time marked.
328 1 hiro
*/
329 1 hiro
static gboolean jpilot_mark_files( JPilotFile *pilotFile ) {
330 1 hiro
        gboolean retVal = FALSE;
331 1 hiro
        struct stat filestat;
332 1 hiro
        gchar *pcFile;
333 1 hiro
334 1 hiro
        /* Mark PDB file cache */
335 1 hiro
        retVal = addrcache_mark_file( pilotFile->addressCache, pilotFile->path );
336 1 hiro
337 1 hiro
        /* Now mark PC3 file */
338 1 hiro
        pilotFile->havePC3 = FALSE;
339 1 hiro
        pilotFile->pc3ModifyTime = 0;
340 1 hiro
        pcFile = jpilot_get_pc3_file( pilotFile );
341 1 hiro
        if( pcFile == NULL ) return retVal;
342 1 hiro
        if( 0 == lstat( pcFile, &filestat ) ) {
343 1 hiro
                pilotFile->havePC3 = TRUE;
344 1 hiro
                pilotFile->pc3ModifyTime = filestat.st_mtime;
345 1 hiro
                retVal = TRUE;
346 1 hiro
        }
347 1 hiro
        g_free( pcFile );
348 1 hiro
        return retVal;
349 1 hiro
}
350 1 hiro
351 1 hiro
/*
352 1 hiro
* Check whether JPilot PDB or PC3 file has changed by comparing
353 1 hiro
* with cached data.
354 1 hiro
* return: TRUE if file has changed.
355 1 hiro
*/
356 1 hiro
static gboolean jpilot_check_files( JPilotFile *pilotFile ) {
357 1 hiro
        gboolean retVal = TRUE;
358 1 hiro
        struct stat filestat;
359 1 hiro
        gchar *pcFile;
360 1 hiro
361 1 hiro
        /* Check main file */
362 1 hiro
        if( addrcache_check_file( pilotFile->addressCache, pilotFile->path ) )
363 1 hiro
                return TRUE;
364 1 hiro
365 1 hiro
        /* Test PC3 file */
366 1 hiro
        if( ! pilotFile->havePC3 ) return FALSE;
367 1 hiro
        pcFile = jpilot_get_pc3_file( pilotFile );
368 1 hiro
        if( pcFile == NULL ) return FALSE;
369 1 hiro
370 1 hiro
        if( 0 == lstat( pcFile, &filestat ) ) {
371 1 hiro
                if( filestat.st_mtime == pilotFile->pc3ModifyTime ) retVal = FALSE;
372 1 hiro
        }
373 1 hiro
        g_free( pcFile );
374 1 hiro
        return retVal;
375 1 hiro
}
376 1 hiro
377 1 hiro
/*
378 1 hiro
* Test whether file was modified since last access.
379 1 hiro
* Return: TRUE if file was modified.
380 1 hiro
*/
381 1 hiro
gboolean jpilot_get_modified( JPilotFile *pilotFile ) {
382 1 hiro
        g_return_val_if_fail( pilotFile != NULL, FALSE );
383 1 hiro
        return jpilot_check_files( pilotFile );
384 1 hiro
}
385 1 hiro
gboolean jpilot_get_accessed( JPilotFile *pilotFile ) {
386 1 hiro
        g_return_val_if_fail( pilotFile != NULL, FALSE );
387 1 hiro
        return pilotFile->accessFlag;
388 1 hiro
}
389 1 hiro
390 1 hiro
/*
391 1 hiro
* Free up pilot file object by releasing internal memory.
392 1 hiro
*/
393 1 hiro
void jpilot_free( JPilotFile *pilotFile ) {
394 1 hiro
        g_return_if_fail( pilotFile != NULL );
395 1 hiro
396 1 hiro
        /* Free internal stuff */
397 1 hiro
        g_free( pilotFile->path );
398 1 hiro
399 1 hiro
        /* Release custom labels */
400 1 hiro
        jpilot_clear_custom_labels( pilotFile );
401 1 hiro
402 1 hiro
        /* Clear cache */
403 1 hiro
        addrcache_clear( pilotFile->addressCache );
404 1 hiro
        addrcache_free( pilotFile->addressCache );
405 1 hiro
        pilotFile->addressCache = NULL;
406 1 hiro
        pilotFile->readMetadata = FALSE;
407 1 hiro
        pilotFile->accessFlag = FALSE;
408 1 hiro
        pilotFile->havePC3 = FALSE;
409 1 hiro
        pilotFile->pc3ModifyTime = 0;
410 1 hiro
411 1 hiro
        /* Now release file object */
412 1 hiro
        g_free( pilotFile );
413 1 hiro
}
414 1 hiro
415 1 hiro
/*
416 1 hiro
* Refresh internal variables to force a file read.
417 1 hiro
*/
418 1 hiro
void jpilot_force_refresh( JPilotFile *pilotFile ) {
419 1 hiro
        addrcache_refresh( pilotFile->addressCache );
420 1 hiro
}
421 1 hiro
422 1 hiro
/*
423 1 hiro
* Print object to specified stream.
424 1 hiro
*/
425 1 hiro
void jpilot_print_file( JPilotFile *pilotFile, FILE *stream ) {
426 1 hiro
        GList *node;
427 1 hiro
428 1 hiro
        g_return_if_fail( pilotFile != NULL );
429 1 hiro
430 1 hiro
        fprintf( stream, "JPilotFile:\n" );
431 1 hiro
        fprintf( stream, "file spec: '%s'\n", pilotFile->path );
432 1 hiro
        fprintf( stream, " metadata: %s\n", pilotFile->readMetadata ? "yes" : "no" );
433 1 hiro
        fprintf( stream, "  ret val: %d\n", pilotFile->retVal );
434 1 hiro
435 1 hiro
        node = pilotFile->customLabels;
436 1 hiro
        while( node ) {
437 1 hiro
                fprintf( stream, "  c label: %s\n", (gchar *)node->data );
438 1 hiro
                node = g_list_next( node );
439 1 hiro
        }
440 1 hiro
441 1 hiro
        node = pilotFile->labelInd;
442 1 hiro
        while( node ) {
443 1 hiro
                fprintf( stream, " labelind: %d\n", GPOINTER_TO_INT(node->data) );
444 1 hiro
                node = g_list_next( node );
445 1 hiro
        }
446 1 hiro
447 1 hiro
        addrcache_print( pilotFile->addressCache, stream );
448 1 hiro
        fprintf( stream, "  ret val: %d\n", pilotFile->retVal );
449 1 hiro
        fprintf( stream, " have pc3: %s\n", pilotFile->havePC3 ? "yes" : "no" );
450 1 hiro
        fprintf( stream, " pc3 time: %lu\n", pilotFile->pc3ModifyTime );
451 1 hiro
        addritem_print_item_folder( pilotFile->addressCache->rootFolder, stream );
452 1 hiro
}
453 1 hiro
454 1 hiro
/*
455 1 hiro
* Print summary of object to specified stream.
456 1 hiro
*/
457 1 hiro
void jpilot_print_short( JPilotFile *pilotFile, FILE *stream ) {
458 1 hiro
        GList *node;
459 1 hiro
        g_return_if_fail( pilotFile != NULL );
460 1 hiro
        fprintf( stream, "JPilotFile:\n" );
461 1 hiro
        fprintf( stream, "file spec: '%s'\n", pilotFile->path );
462 1 hiro
        fprintf( stream, " metadata: %s\n", pilotFile->readMetadata ? "yes" : "no" );
463 1 hiro
        fprintf( stream, "  ret val: %d\n", pilotFile->retVal );
464 1 hiro
465 1 hiro
        node = pilotFile->customLabels;
466 1 hiro
        while( node ) {
467 1 hiro
                fprintf( stream, "  c label: %s\n", (gchar *)node->data );
468 1 hiro
                node = g_list_next( node );
469 1 hiro
        }
470 1 hiro
471 1 hiro
        node = pilotFile->labelInd;
472 1 hiro
        while( node ) {
473 1 hiro
                fprintf( stream, " labelind: %d\n", GPOINTER_TO_INT(node->data) );
474 1 hiro
                node = g_list_next( node );
475 1 hiro
        }
476 1 hiro
        addrcache_print( pilotFile->addressCache, stream );
477 1 hiro
        fprintf( stream, " have pc3: %s\n", pilotFile->havePC3 ? "yes" : "no" );
478 1 hiro
        fprintf( stream, " pc3 time: %lu\n", pilotFile->pc3ModifyTime );
479 1 hiro
}
480 1 hiro
481 1 hiro
/* Shamelessly copied from JPilot (libplugin.c) */
482 1 hiro
static unsigned int bytes_to_bin(unsigned char *bytes, unsigned int num_bytes) {
483 1 hiro
unsigned int i, n;
484 1 hiro
        n=0;
485 1 hiro
        for (i=0;i<num_bytes;i++) {
486 1 hiro
                n = n*256+bytes[i];
487 1 hiro
        }
488 1 hiro
        return n;
489 1 hiro
}
490 1 hiro
491 1 hiro
/* Shamelessly copied from JPilot (utils.c) */
492 1 hiro
/* These next 2 functions were copied from pi-file.c in the pilot-link app */
493 1 hiro
/* Exact value of "Jan 1, 1970 0:00:00 GMT" - "Jan 1, 1904 0:00:00 GMT" */
494 1 hiro
#define PILOT_TIME_DELTA (unsigned)(2082844800)
495 1 hiro
496 1 hiro
time_t pilot_time_to_unix_time ( unsigned long raw_time ) {
497 1 hiro
   return (time_t)(raw_time - PILOT_TIME_DELTA);
498 1 hiro
}
499 1 hiro
500 1 hiro
/* Shamelessly copied from JPilot (libplugin.c) */
501 1 hiro
static int raw_header_to_header(RawDBHeader *rdbh, DBHeader *dbh) {
502 1 hiro
        unsigned long temp;
503 1 hiro
504 1 hiro
        strncpy(dbh->db_name, rdbh->db_name, 31);
505 1 hiro
        dbh->db_name[31] = '\0';
506 1 hiro
        dbh->flags = bytes_to_bin(rdbh->flags, 2);
507 1 hiro
        dbh->version = bytes_to_bin(rdbh->version, 2);
508 1 hiro
        temp = bytes_to_bin(rdbh->creation_time, 4);
509 1 hiro
        dbh->creation_time = pilot_time_to_unix_time(temp);
510 1 hiro
        temp = bytes_to_bin(rdbh->modification_time, 4);
511 1 hiro
        dbh->modification_time = pilot_time_to_unix_time(temp);
512 1 hiro
        temp = bytes_to_bin(rdbh->backup_time, 4);
513 1 hiro
        dbh->backup_time = pilot_time_to_unix_time(temp);
514 1 hiro
        dbh->modification_number = bytes_to_bin(rdbh->modification_number, 4);
515 1 hiro
        dbh->app_info_offset = bytes_to_bin(rdbh->app_info_offset, 4);
516 1 hiro
        dbh->sort_info_offset = bytes_to_bin(rdbh->sort_info_offset, 4);
517 1 hiro
        strncpy(dbh->type, rdbh->type, 4);
518 1 hiro
        dbh->type[4] = '\0';
519 1 hiro
        strncpy(dbh->creator_id, rdbh->creator_id, 4);
520 1 hiro
        dbh->creator_id[4] = '\0';
521 1 hiro
        strncpy(dbh->unique_id_seed, rdbh->unique_id_seed, 4);
522 1 hiro
        dbh->unique_id_seed[4] = '\0';
523 1 hiro
        dbh->next_record_list_id = bytes_to_bin(rdbh->next_record_list_id, 4);
524 1 hiro
        dbh->number_of_records = bytes_to_bin(rdbh->number_of_records, 2);
525 1 hiro
        return 0;
526 1 hiro
}
527 1 hiro
528 1 hiro
/* Shamelessly copied from JPilot (libplugin.c) */
529 1 hiro
/* returns 1 if found */
530 1 hiro
/*         0 if eof */
531 1 hiro
static int find_next_offset( mem_rec_header *mem_rh, long fpos,
532 1 hiro
        unsigned int *next_offset, unsigned char *attrib, unsigned int *unique_id )
533 1 hiro
{
534 1 hiro
        mem_rec_header *temp_mem_rh;
535 1 hiro
        unsigned char found = 0;
536 1 hiro
        unsigned long found_at;
537 1 hiro
538 1 hiro
        found_at=0xFFFFFF;
539 1 hiro
        for (temp_mem_rh=mem_rh; temp_mem_rh; temp_mem_rh = temp_mem_rh->next) {
540 1 hiro
                if ((temp_mem_rh->offset > fpos) && (temp_mem_rh->offset < found_at)) {
541 1 hiro
                        found_at = temp_mem_rh->offset;
542 1 hiro
                        /* *attrib = temp_mem_rh->attrib; */
543 1 hiro
                        /* *unique_id = temp_mem_rh->unique_id; */
544 1 hiro
                }
545 1 hiro
                if ((temp_mem_rh->offset == fpos)) {
546 1 hiro
                        found = 1;
547 1 hiro
                        *attrib = temp_mem_rh->attrib;
548 1 hiro
                        *unique_id = temp_mem_rh->unique_id;
549 1 hiro
                }
550 1 hiro
        }
551 1 hiro
        *next_offset = found_at;
552 1 hiro
        return found;
553 1 hiro
}
554 1 hiro
555 1 hiro
/* Shamelessly copied from JPilot (libplugin.c) */
556 1 hiro
static void free_mem_rec_header(mem_rec_header **mem_rh) {
557 1 hiro
        mem_rec_header *h, *next_h;
558 1 hiro
        for (h=*mem_rh; h; h=next_h) {
559 1 hiro
                next_h=h->next;
560 1 hiro
                free(h);
561 1 hiro
        }
562 1 hiro
        *mem_rh = NULL;
563 1 hiro
}
564 1 hiro
565 1 hiro
#if 0
566 1 hiro
/* Shamelessly copied from JPilot (libplugin.c) */
567 1 hiro
static int jpilot_free_db_list( GList **br_list ) {
568 1 hiro
        GList *temp_list, *first;
569 1 hiro
        buf_rec *br;
570 1 hiro
571 1 hiro
        /* Go to first entry in the list */
572 1 hiro
        first=NULL;
573 1 hiro
        for( temp_list = *br_list; temp_list; temp_list = temp_list->prev ) {
574 1 hiro
                first = temp_list;
575 1 hiro
        }
576 1 hiro
        for (temp_list = first; temp_list; temp_list = temp_list->next) {
577 1 hiro
                if (temp_list->data) {
578 1 hiro
                        br=temp_list->data;
579 1 hiro
                        if (br->buf) {
580 1 hiro
                                free(br->buf);
581 1 hiro
                                temp_list->data=NULL;
582 1 hiro
                        }
583 1 hiro
                        free(br);
584 1 hiro
                }
585 1 hiro
        }
586 1 hiro
        g_list_free(*br_list);
587 1 hiro
        *br_list=NULL;
588 1 hiro
        return 0;
589 1 hiro
}
590 1 hiro
#endif
591 1 hiro
592 1 hiro
/* Shamelessly copied from JPilot (libplugin.c) */
593 1 hiro
/* Read file size */
594 1 hiro
static int jpilot_get_info_size( FILE *in, int *size ) {
595 1 hiro
        RawDBHeader rdbh;
596 1 hiro
        DBHeader dbh;
597 1 hiro
        unsigned int offset;
598 1 hiro
        record_header rh;
599 1 hiro
600 1 hiro
        fseek(in, 0, SEEK_SET);
601 1 hiro
        fread(&rdbh, sizeof(RawDBHeader), 1, in);
602 1 hiro
        if (feof(in)) {
603 1 hiro
                return MGU_EOF;
604 1 hiro
        }
605 1 hiro
606 1 hiro
        raw_header_to_header(&rdbh, &dbh);
607 1 hiro
        if (dbh.app_info_offset==0) {
608 1 hiro
                *size=0;
609 1 hiro
                return MGU_SUCCESS;
610 1 hiro
        }
611 1 hiro
        if (dbh.sort_info_offset!=0) {
612 1 hiro
                *size = dbh.sort_info_offset - dbh.app_info_offset;
613 1 hiro
                return MGU_SUCCESS;
614 1 hiro
        }
615 1 hiro
        if (dbh.number_of_records==0) {
616 1 hiro
                fseek(in, 0, SEEK_END);
617 1 hiro
                *size=ftell(in) - dbh.app_info_offset;
618 1 hiro
                return MGU_SUCCESS;
619 1 hiro
        }
620 1 hiro
621 1 hiro
        fread(&rh, sizeof(record_header), 1, in);
622 1 hiro
        offset = ((rh.Offset[0]*256+rh.Offset[1])*256+rh.Offset[2])*256+rh.Offset[3];
623 1 hiro
        *size=offset - dbh.app_info_offset;
624 1 hiro
625 1 hiro
        return MGU_SUCCESS;
626 1 hiro
}
627 1 hiro
628 1 hiro
/*
629 1 hiro
 * Read address file into address list. Based on JPilot's
630 1 hiro
 * libplugin.c (jp_get_app_info)
631 1 hiro
 */
632 1 hiro
static gint jpilot_get_file_info( JPilotFile *pilotFile, unsigned char **buf, int *buf_size ) {
633 1 hiro
        FILE *in;
634 1 hiro
         int num;
635 1 hiro
        unsigned int rec_size;
636 1 hiro
        RawDBHeader rdbh;
637 1 hiro
        DBHeader dbh;
638 1 hiro
639 1 hiro
        if( ( !buf_size ) || ( ! buf ) ) {
640 1 hiro
                return MGU_BAD_ARGS;
641 1 hiro
        }
642 1 hiro
643 1 hiro
        *buf = NULL;
644 1 hiro
        *buf_size=0;
645 1 hiro
646 1 hiro
        if( pilotFile->path ) {
647 1 hiro
                in = fopen( pilotFile->path, "rb" );
648 1 hiro
                if( !in ) {
649 1 hiro
                        return MGU_OPEN_FILE;
650 1 hiro
                }
651 1 hiro
        }
652 1 hiro
        else {
653 1 hiro
                return MGU_NO_FILE;
654 1 hiro
        }
655 1 hiro
656 1 hiro
        num = fread( &rdbh, sizeof( RawDBHeader ), 1, in );
657 1 hiro
        if( num != 1 ) {
658 1 hiro
                  if( ferror(in) ) {
659 1 hiro
                        fclose(in);
660 1 hiro
                        return MGU_ERROR_READ;
661 1 hiro
                }
662 1 hiro
        }
663 1 hiro
        if (feof(in)) {
664 1 hiro
                fclose(in);
665 1 hiro
                return MGU_EOF;
666 1 hiro
        }
667 1 hiro
668 1 hiro
        /* Convert header into something recognizable */
669 1 hiro
        raw_header_to_header(&rdbh, &dbh);
670 1 hiro
671 1 hiro
        num = jpilot_get_info_size(in, &rec_size);
672 1 hiro
        if (num) {
673 1 hiro
                fclose(in);
674 1 hiro
                return MGU_ERROR_READ;
675 1 hiro
        }
676 1 hiro
677 1 hiro
        fseek(in, dbh.app_info_offset, SEEK_SET);
678 1 hiro
        *buf = ( char * ) malloc(rec_size);
679 1 hiro
        if (!(*buf)) {
680 1 hiro
                fclose(in);
681 1 hiro
                return MGU_OO_MEMORY;
682 1 hiro
        }
683 1 hiro
        num = fread(*buf, rec_size, 1, in);
684 1 hiro
        if (num != 1) {
685 1 hiro
                if (ferror(in)) {
686 1 hiro
                        fclose(in);
687 1 hiro
                        free(*buf);
688 1 hiro
                        return MGU_ERROR_READ;
689 1 hiro
                }
690 1 hiro
        }
691 1 hiro
        fclose(in);
692 1 hiro
693 1 hiro
        *buf_size = rec_size;
694 1 hiro
695 1 hiro
        return MGU_SUCCESS;
696 1 hiro
}
697 1 hiro
698 1 hiro
/* Shamelessly copied from JPilot (libplugin.c) */
699 1 hiro
static int unpack_header(PC3RecordHeader *header, unsigned char *packed_header) {
700 1 hiro
        unsigned char *p;
701 1 hiro
        unsigned long l;
702 1 hiro
703 1 hiro
        p = packed_header;
704 1 hiro
705 1 hiro
        memcpy(&l, p, sizeof(l));
706 1 hiro
        header->header_len=ntohl(l);
707 1 hiro
        p+=sizeof(l);
708 1 hiro
709 1 hiro
        memcpy(&l, p, sizeof(l));
710 1 hiro
        header->header_version=ntohl(l);
711 1 hiro
        p+=sizeof(l);
712 1 hiro
713 1 hiro
        memcpy(&l, p, sizeof(l));
714 1 hiro
        header->rec_len=ntohl(l);
715 1 hiro
        p+=sizeof(l);
716 1 hiro
717 1 hiro
        memcpy(&l, p, sizeof(l));
718 1 hiro
        header->unique_id=ntohl(l);
719 1 hiro
        p+=sizeof(l);
720 1 hiro
721 1 hiro
        memcpy(&l, p, sizeof(l));
722 1 hiro
        header->rt=ntohl(l);
723 1 hiro
        p+=sizeof(l);
724 1 hiro
725 1 hiro
        memcpy(&(header->attrib), p, sizeof(unsigned char));
726 1 hiro
        p+=sizeof(unsigned char);
727 1 hiro
728 1 hiro
        return 0;
729 1 hiro
}
730 1 hiro
731 1 hiro
/* Shamelessly copied from JPilot (libplugin.c) */
732 1 hiro
static int read_header(FILE *pc_in, PC3RecordHeader *header) {
733 1 hiro
        unsigned long l, len;
734 1 hiro
        unsigned char packed_header[256];
735 1 hiro
        int num;
736 1 hiro
737 1 hiro
        num = fread(&l, sizeof(l), 1, pc_in);
738 1 hiro
        if (feof(pc_in)) {
739 1 hiro
                return -1;
740 1 hiro
        }
741 1 hiro
        if (num!=1) {
742 1 hiro
                return num;
743 1 hiro
        }
744 1 hiro
        memcpy(packed_header, &l, sizeof(l));
745 1 hiro
        len=ntohl(l);
746 1 hiro
        if (len > 255) {
747 1 hiro
                return -1;
748 1 hiro
        }
749 1 hiro
        num = fread(packed_header+sizeof(l), len-sizeof(l), 1, pc_in);
750 1 hiro
        if (feof(pc_in)) {
751 1 hiro
                return -1;
752 1 hiro
        }
753 1 hiro
        if (num!=1) {
754 1 hiro
                return num;
755 1 hiro
        }
756 1 hiro
        unpack_header(header, packed_header);
757 1 hiro
        return 1;
758 1 hiro
}
759 1 hiro
760 1 hiro
/* Read next record from PC3 file. Based on JPilot's
761 1 hiro
 * pc_read_next_rec (libplugin.c) */
762 1 hiro
static gint jpilot_read_next_pc( FILE *in, buf_rec *br ) {
763 1 hiro
        PC3RecordHeader header;
764 1 hiro
        int rec_len, num;
765 1 hiro
        char *record;
766 1 hiro
767 1 hiro
        if(feof(in)) {
768 1 hiro
                return MGU_EOF;
769 1 hiro
        }
770 1 hiro
        num = read_header(in, &header);
771 1 hiro
        if (num < 1) {
772 1 hiro
                if (ferror(in)) {
773 1 hiro
                        return MGU_ERROR_READ;
774 1 hiro
                }
775 1 hiro
                if (feof(in)) {
776 1 hiro
                        return MGU_EOF;
777 1 hiro
                }
778 1 hiro
        }
779 1 hiro
        rec_len = header.rec_len;
780 1 hiro
        record = malloc(rec_len);
781 1 hiro
        if (!record) {
782 1 hiro
                return MGU_OO_MEMORY;
783 1 hiro
        }
784 1 hiro
        num = fread(record, rec_len, 1, in);
785 1 hiro
        if (num != 1) {
786 1 hiro
                if (ferror(in)) {
787 1 hiro
                        free(record);
788 1 hiro
                        return MGU_ERROR_READ;
789 1 hiro
                }
790 1 hiro
        }
791 1 hiro
        br->rt = header.rt;
792 1 hiro
        br->unique_id = header.unique_id;
793 1 hiro
        br->attrib = header.attrib;
794 1 hiro
        br->buf = record;
795 1 hiro
        br->size = rec_len;
796 1 hiro
797 1 hiro
        return MGU_SUCCESS;
798 1 hiro
}
799 1 hiro
800 1 hiro
/*
801 1 hiro
 * Read address file into a linked list. Based on JPilot's
802 1 hiro
 * jp_read_DB_files (from libplugin.c)
803 1 hiro
 */
804 1 hiro
static gint jpilot_read_db_files( JPilotFile *pilotFile, GList **records ) {
805 1 hiro
        FILE *in, *pc_in;
806 1 hiro
        char *buf;
807 1 hiro
        GList *temp_list;
808 1 hiro
        int num_records, recs_returned, i, num, r;
809 1 hiro
        unsigned int offset, prev_offset, next_offset, rec_size;
810 1 hiro
        int out_of_order;
811 1 hiro
        long fpos;  /*file position indicator */
812 1 hiro
        unsigned char attrib;
813 1 hiro
        unsigned int unique_id;
814 1 hiro
        mem_rec_header *mem_rh, *temp_mem_rh, *last_mem_rh;
815 1 hiro
        record_header rh;
816 1 hiro
        RawDBHeader rdbh;
817 1 hiro
        DBHeader dbh;
818 1 hiro
        buf_rec *temp_br;
819 1 hiro
        gchar *pcFile;
820 1 hiro
821 1 hiro
        mem_rh = last_mem_rh = NULL;
822 1 hiro
        *records = NULL;
823 1 hiro
        recs_returned = 0;
824 1 hiro
825 1 hiro
        if( pilotFile->path == NULL ) {
826 1 hiro
                return MGU_BAD_ARGS;
827 1 hiro
        }
828 1 hiro
829 1 hiro
        in = fopen( pilotFile->path, "rb" );
830 1 hiro
        if (!in) {
831 1 hiro
                return MGU_OPEN_FILE;
832 1 hiro
        }
833 1 hiro
834 1 hiro
        /* Read the database header */
835 1 hiro
        num = fread(&rdbh, sizeof(RawDBHeader), 1, in);
836 1 hiro
        if (num != 1) {
837 1 hiro
                if (ferror(in)) {
838 1 hiro
                        fclose(in);
839 1 hiro
                        return MGU_ERROR_READ;
840 1 hiro
                }
841 1 hiro
                if (feof(in)) {
842 1 hiro
                        return MGU_EOF;
843 1 hiro
                }
844 1 hiro
        }
845 1 hiro
        raw_header_to_header(&rdbh, &dbh);
846 1 hiro
847 1 hiro
        /* Read each record entry header */
848 1 hiro
        num_records = dbh.number_of_records;
849 1 hiro
        out_of_order = 0;
850 1 hiro
        prev_offset = 0;
851 1 hiro
852 1 hiro
        for (i = 1; i < num_records + 1; i++) {
853 1 hiro
                num = fread(&rh, sizeof(record_header), 1, in);
854 1 hiro
                if (num != 1) {
855 1 hiro
                        if (ferror(in)) {
856 1 hiro
                                break;
857 1 hiro
                        }
858 1 hiro
                        if (feof(in)) {
859 1 hiro
                                return MGU_EOF;
860 1 hiro
                        }
861 1 hiro
                }
862 1 hiro
863 1 hiro
                offset = ((rh.Offset[0]*256+rh.Offset[1])*256+rh.Offset[2])*256+rh.Offset[3];
864 1 hiro
                if (offset < prev_offset) {
865 1 hiro
                        out_of_order = 1;
866 1 hiro
                }
867 1 hiro
                prev_offset = offset;
868 1 hiro
                temp_mem_rh = (mem_rec_header *)malloc(sizeof(mem_rec_header));
869 1 hiro
                if (!temp_mem_rh) {
870 1 hiro
                        break;
871 1 hiro
                }
872 1 hiro
                temp_mem_rh->next = NULL;
873 1 hiro
                temp_mem_rh->rec_num = i;
874 1 hiro
                temp_mem_rh->offset = offset;
875 1 hiro
                temp_mem_rh->attrib = rh.attrib;
876 1 hiro
                temp_mem_rh->unique_id = (rh.unique_ID[0]*256+rh.unique_ID[1])*256+rh.unique_ID[2];
877 1 hiro
                if (mem_rh == NULL) {
878 1 hiro
                        mem_rh = temp_mem_rh;
879 1 hiro
                        last_mem_rh = temp_mem_rh;
880 1 hiro
                } else {
881 1 hiro
                        last_mem_rh->next = temp_mem_rh;
882 1 hiro
                        last_mem_rh = temp_mem_rh;
883 1 hiro
                }
884 1 hiro
        }
885 1 hiro
886 1 hiro
        temp_mem_rh = mem_rh;
887 1 hiro
888 1 hiro
        if (num_records) {
889 1 hiro
                if (out_of_order) {
890 1 hiro
                        find_next_offset(mem_rh, 0, &next_offset, &attrib, &unique_id);
891 1 hiro
                } else {
892 1 hiro
                        if (mem_rh) {
893 1 hiro
                                next_offset = mem_rh->offset;
894 1 hiro
                                attrib = mem_rh->attrib;
895 1 hiro
                                unique_id = mem_rh->unique_id;
896 1 hiro
                        }
897 1 hiro
                }
898 1 hiro
                fseek(in, next_offset, SEEK_SET);
899 1 hiro
                while(!feof(in)) {
900 1 hiro
                        fpos = ftell(in);
901 1 hiro
                        if (out_of_order) {
902 1 hiro
                                find_next_offset(mem_rh, fpos, &next_offset, &attrib, &unique_id);
903 1 hiro
                        } else {
904 1 hiro
                                next_offset = 0xFFFFFF;
905 1 hiro
                                if (temp_mem_rh) {
906 1 hiro
                                        attrib = temp_mem_rh->attrib;
907 1 hiro
                                        unique_id = temp_mem_rh->unique_id;
908 1 hiro
                                        if (temp_mem_rh->next) {
909 1 hiro
                                                temp_mem_rh = temp_mem_rh->next;
910 1 hiro
                                                next_offset = temp_mem_rh->offset;
911 1 hiro
                                        }
912 1 hiro
                                }
913 1 hiro
                        }
914 1 hiro
                        rec_size = next_offset - fpos;
915 1 hiro
                        buf = malloc(rec_size);
916 1 hiro
                        if (!buf) break;
917 1 hiro
                        num = fread(buf, rec_size, 1, in);
918 1 hiro
                        if ((num != 1)) {
919 1 hiro
                                if (ferror(in)) {
920 1 hiro
                                        free(buf);
921 1 hiro
                                        break;
922 1 hiro
                                }
923 1 hiro
                        }
924 1 hiro
925 1 hiro
                        temp_br = malloc(sizeof(buf_rec));
926 1 hiro
                        if (!temp_br) {
927 1 hiro
                                break;
928 1 hiro
                        }
929 1 hiro
                        temp_br->rt = PALM_REC;
930 1 hiro
                        temp_br->unique_id = unique_id;
931 1 hiro
                        temp_br->attrib = attrib;
932 1 hiro
                        temp_br->buf = buf;
933 1 hiro
                        temp_br->size = rec_size;
934 1 hiro
935 1 hiro
                        *records = g_list_append(*records, temp_br);
936 1 hiro
937 1 hiro
                        recs_returned++;
938 1 hiro
                }
939 1 hiro
        }
940 1 hiro
        fclose(in);
941 1 hiro
        free_mem_rec_header(&mem_rh);
942 1 hiro
943 1 hiro
        /* Read the PC3 file, if present */
944 1 hiro
        pcFile = jpilot_get_pc3_file( pilotFile );
945 1 hiro
        if( pcFile == NULL ) return MGU_SUCCESS;
946 1 hiro
        pc_in = fopen( pcFile, "rb");
947 1 hiro
        g_free( pcFile );
948 1 hiro
949 1 hiro
        if( pc_in == NULL ) {
950 1 hiro
                return MGU_SUCCESS;
951 1 hiro
        }
952 1 hiro
953 1 hiro
        while( ! feof( pc_in ) ) {
954 1 hiro
                temp_br = malloc(sizeof(buf_rec));
955 1 hiro
                if (!temp_br) {
956 1 hiro
                        break;
957 1 hiro
                }
958 1 hiro
                r = jpilot_read_next_pc( pc_in, temp_br );
959 1 hiro
                if ( r != MGU_SUCCESS ) {
960 1 hiro
                        free(temp_br);
961 1 hiro
                        break;
962 1 hiro
                }
963 1 hiro
                if ((temp_br->rt!=DELETED_PC_REC)
964 1 hiro
                        &&(temp_br->rt!=DELETED_PALM_REC)
965 1 hiro
                        &&(temp_br->rt!=MODIFIED_PALM_REC)
966 1 hiro
                        &&(temp_br->rt!=DELETED_DELETED_PALM_REC)) {
967 1 hiro
                                *records = g_list_append(*records, temp_br);
968 1 hiro
                                recs_returned++;
969 1 hiro
                }
970 1 hiro
                if ((temp_br->rt==DELETED_PALM_REC) || (temp_br->rt==MODIFIED_PALM_REC)) {
971 1 hiro
                        temp_list=*records;
972 1 hiro
                        if (*records) {
973 1 hiro
                                while(temp_list->next) {
974 1 hiro
                                        temp_list=temp_list->next;
975 1 hiro
                                }
976 1 hiro
                        }
977 1 hiro
                        for (; temp_list; temp_list=temp_list->prev) {
978 1 hiro
                                if (((buf_rec *)temp_list->data)->unique_id == temp_br->unique_id) {
979 1 hiro
                                        ((buf_rec *)temp_list->data)->rt = temp_br->rt;
980 1 hiro
                                }
981 1 hiro
                        }
982 1 hiro
                }
983 1 hiro
        }
984 1 hiro
        fclose(pc_in);
985 1 hiro
986 1 hiro
        return MGU_SUCCESS;
987 1 hiro
}
988 1 hiro
989 1 hiro
#define FULLNAME_BUFSIZE        256
990 1 hiro
#define EMAIL_BUFSIZE                256
991 1 hiro
/*
992 1 hiro
 * Unpack address, building new data inside cache.
993 1 hiro
 */
994 1 hiro
static void jpilot_load_address( JPilotFile *pilotFile, buf_rec *buf, ItemFolder *folderInd[] ) {
995 1 hiro
        struct Address addr;
996 1 hiro
        gchar **addrEnt;
997 1 hiro
        gint num, k;
998 1 hiro
        gint cat_id = 0;
999 1 hiro
        guint unique_id;
1000 1 hiro
        guchar attrib;
1001 1 hiro
        gchar fullName[ FULLNAME_BUFSIZE ];
1002 1 hiro
        gchar bufEMail[ EMAIL_BUFSIZE ];
1003 1 hiro
        ItemPerson *person;
1004 1 hiro
        ItemEMail *email;
1005 1 hiro
        gint *indPhoneLbl;
1006 1 hiro
        gchar *labelEntry;
1007 1 hiro
        GList *node;
1008 1 hiro
        gchar* extID;
1009 1 hiro
        struct AddressAppInfo *ai;
1010 1 hiro
        gchar **firstName = NULL;
1011 1 hiro
        gchar **lastName = NULL;
1012 1 hiro
1013 1 hiro
        /* Retrieve address */
1014 1 hiro
        num = unpack_Address( & addr, buf->buf, buf->size );
1015 1 hiro
        if( num > 0 ) {
1016 1 hiro
                addrEnt = addr.entry;
1017 1 hiro
                attrib = buf->attrib;
1018 1 hiro
                unique_id = buf->unique_id;
1019 1 hiro
                cat_id = attrib & 0x0F;
1020 1 hiro
1021 1 hiro
                *fullName = *bufEMail = '\0';
1022 1 hiro
1023 1 hiro
                if( addrEnt[ IND_LABEL_FIRSTNAME ] ) {
1024 1 hiro
                        firstName = g_strsplit( addrEnt[ IND_LABEL_FIRSTNAME ], "\01", 2 );
1025 1 hiro
                }
1026 1 hiro
                if( addrEnt[ IND_LABEL_LASTNAME ] ) {
1027 1 hiro
                        lastName = g_strsplit( addrEnt[ IND_LABEL_LASTNAME ], "\01", 2 );
1028 1 hiro
                }
1029 1 hiro
1030 1 hiro
                if( name_order == FAMILY_LAST ) {
1031 1 hiro
                        g_snprintf( fullName, FULLNAME_BUFSIZE, "%s %s",
1032 1 hiro
                                    firstName ? firstName[0] : "",
1033 1 hiro
                                    lastName ? lastName[0] : "" );
1034 1 hiro
                }
1035 1 hiro
                else {
1036 1 hiro
                        g_snprintf( fullName, FULLNAME_BUFSIZE, "%s %s",
1037 1 hiro
                                    lastName ? lastName[0] : "",
1038 1 hiro
                                    firstName ? firstName[0] : "" );
1039 1 hiro
                }
1040 1 hiro
1041 1 hiro
                if( firstName ) {
1042 1 hiro
                        g_strfreev( firstName );
1043 1 hiro
                }
1044 1 hiro
                if( lastName ) {
1045 1 hiro
                        g_strfreev( lastName );
1046 1 hiro
                }
1047 1 hiro
1048 1 hiro
                g_strstrip( fullName );
1049 1 hiro
1050 1 hiro
                if( convert_charcode ) {
1051 1 hiro
                        gchar *nameConv;
1052 42 hiro
                        nameConv = conv_codeset_strdup( fullName, CS_SHIFT_JIS, CS_INTERNAL );
1053 42 hiro
                        strncpy2( fullName, nameConv, FULLNAME_BUFSIZE );
1054 1 hiro
                        g_free( nameConv );
1055 1 hiro
                }
1056 1 hiro
1057 1 hiro
                person = addritem_create_item_person();
1058 1 hiro
                addritem_person_set_common_name( person, fullName );
1059 1 hiro
                addritem_person_set_first_name( person, addrEnt[ IND_LABEL_FIRSTNAME ] );
1060 1 hiro
                addritem_person_set_last_name( person, addrEnt[ IND_LABEL_LASTNAME ] );
1061 1 hiro
                addrcache_id_person( pilotFile->addressCache, person );
1062 1 hiro
1063 1 hiro
                extID = g_strdup_printf( "%d", unique_id );
1064 1 hiro
                addritem_person_set_external_id( person, extID );
1065 1 hiro
                g_free( extID );
1066 1 hiro
                extID = NULL;
1067 1 hiro
1068 1 hiro
                /* Pointer to address metadata. */
1069 1 hiro
                ai = & pilotFile->addrInfo;
1070 1 hiro
1071 1 hiro
                /* Add entry for each email address listed under phone labels. */
1072 1 hiro
                indPhoneLbl = addr.phoneLabel;
1073 1 hiro
                for( k = 0; k < JPILOT_NUM_ADDR_PHONE; k++ ) {
1074 1 hiro
                        gint ind;
1075 1 hiro
1076 1 hiro
                        ind = indPhoneLbl[k];
1077 1 hiro
                        /*
1078 1 hiro
                        * fprintf( stdout, "%d : %d : %20s : %s\n", k, ind,
1079 1 hiro
                        * ai->phoneLabels[ind], addrEnt[3+k] );
1080 1 hiro
                        */
1081 1 hiro
                        if( indPhoneLbl[k] == IND_PHONE_EMAIL ) {
1082 1 hiro
                                labelEntry = addrEnt[ OFFSET_PHONE_LABEL + k ];
1083 1 hiro
                                if( labelEntry ) {
1084 1 hiro
                                        strcpy( bufEMail, labelEntry );
1085 1 hiro
                                        g_strchug( bufEMail );
1086 1 hiro
                                        g_strchomp( bufEMail );
1087 1 hiro
1088 1 hiro
                                        email = addritem_create_item_email();
1089 1 hiro
                                        addritem_email_set_address( email, bufEMail );
1090 1 hiro
                                        addrcache_id_email( pilotFile->addressCache, email );
1091 1 hiro
                                        addrcache_person_add_email
1092 1 hiro
                                                ( pilotFile->addressCache, person, email );
1093 1 hiro
                                }
1094 1 hiro
                        }
1095 1 hiro
                }
1096 1 hiro
1097 1 hiro
                /* Add entry for each custom label */
1098 1 hiro
                node = pilotFile->labelInd;
1099 1 hiro
                while( node ) {
1100 1 hiro
                        gint ind;
1101 1 hiro
1102 1 hiro
                        ind = GPOINTER_TO_INT( node->data );
1103 1 hiro
                        if( ind > -1 ) {
1104 1 hiro
                                /*
1105 1 hiro
                                * fprintf( stdout, "%d : %20s : %s\n", ind, ai->labels[ind],
1106 1 hiro
                                * addrEnt[ind] );
1107 1 hiro
                                */
1108 1 hiro
                                labelEntry = addrEnt[ind];
1109 1 hiro
                                if( labelEntry ) {
1110 1 hiro
                                        strcpy( bufEMail, labelEntry );
1111 1 hiro
                                        g_strchug( bufEMail );
1112 1 hiro
                                        g_strchomp( bufEMail );
1113 1 hiro
1114 1 hiro
                                        email = addritem_create_item_email();
1115 1 hiro
                                        addritem_email_set_address( email, bufEMail );
1116 1 hiro
1117 1 hiro
                                        if( convert_charcode ) {
1118 42 hiro
                                                gchar *convertBuff;
1119 42 hiro
                                                convertBuff = conv_codeset_strdup( ai->labels[ind], CS_SHIFT_JIS, CS_INTERNAL );
1120 1 hiro
                                                addritem_email_set_remarks( email, convertBuff );
1121 42 hiro
                                                g_free( convertBuff );
1122 1 hiro
                                        }
1123 1 hiro
                                        else {
1124 1 hiro
                                                addritem_email_set_remarks( email, ai->labels[ind] );
1125 1 hiro
                                        }
1126 1 hiro
1127 1 hiro
                                        addrcache_id_email( pilotFile->addressCache, email );
1128 1 hiro
                                        addrcache_person_add_email
1129 1 hiro
                                                ( pilotFile->addressCache, person, email );
1130 1 hiro
                                }
1131 1 hiro
                        }
1132 1 hiro
1133 1 hiro
                        node = g_list_next( node );
1134 1 hiro
                }
1135 1 hiro
1136 1 hiro
                if( person->listEMail ) {
1137 1 hiro
                        if( cat_id > -1 && cat_id < JPILOT_NUM_CATEG ) {
1138 1 hiro
                                /* Add to specified category */
1139 1 hiro
                                addrcache_folder_add_person
1140 1 hiro
                                        ( pilotFile->addressCache, folderInd[cat_id], person );
1141 1 hiro
                        }
1142 1 hiro
                        else {
1143 1 hiro
                                /* Add to root folder */
1144 1 hiro
                                addrcache_add_person( pilotFile->addressCache, person );
1145 1 hiro
                        }
1146 1 hiro
                }
1147 1 hiro
                else {
1148 1 hiro
                        addritem_free_item_person( person );
1149 1 hiro
                        person = NULL;
1150 1 hiro
                }
1151 1 hiro
        }
1152 1 hiro
}
1153 1 hiro
1154 1 hiro
/*
1155 1 hiro
 * Free up address list.
1156 1 hiro
 */
1157 1 hiro
static void jpilot_free_addrlist( GList *records ) {
1158 1 hiro
        GList *node;
1159 1 hiro
        buf_rec *br;
1160 1 hiro
1161 1 hiro
        node = records;
1162 1 hiro
        while( node ) {
1163 1 hiro
                br = node->data;
1164 1 hiro
                free( br );
1165 1 hiro
                node->data = NULL;
1166 1 hiro
                node = g_list_next( node );
1167 1 hiro
        }
1168 1 hiro
1169 1 hiro
        /* Free up list */
1170 1 hiro
        g_list_free( records );
1171 1 hiro
}
1172 1 hiro
1173 1 hiro
/*
1174 1 hiro
 * Read address file into address cache.
1175 1 hiro
 */
1176 1 hiro
static gint jpilot_read_file( JPilotFile *pilotFile ) {
1177 1 hiro
        gint retVal, i;
1178 1 hiro
        GList *records = NULL;
1179 1 hiro
        GList *node;
1180 1 hiro
        buf_rec *br;
1181 1 hiro
        ItemFolder *folderInd[ JPILOT_NUM_CATEG ];
1182 1 hiro
1183 1 hiro
        retVal = jpilot_read_db_files( pilotFile, &records );
1184 1 hiro
        if( retVal != MGU_SUCCESS ) {
1185 1 hiro
                jpilot_free_addrlist( records );
1186 1 hiro
                return retVal;
1187 1 hiro
        }
1188 1 hiro
1189 1 hiro
        /* Build array of pointers to categories */
1190 1 hiro
        i = 0;
1191 1 hiro
        node = addrcache_get_list_folder( pilotFile->addressCache );
1192 1 hiro
        while( node ) {
1193 1 hiro
                if( i < JPILOT_NUM_CATEG ) {
1194 1 hiro
                        folderInd[i] = node->data;
1195 1 hiro
                }
1196 1 hiro
                node = g_list_next( node );
1197 1 hiro
                i++;
1198 1 hiro
        }
1199 1 hiro
1200 1 hiro
        /* Load all addresses, free up old stuff as we go */
1201 1 hiro
        node = records;
1202 1 hiro
        while( node ) {
1203 1 hiro
                br = node->data;
1204 1 hiro
                if( ( br->rt != DELETED_PC_REC ) &&
1205 1 hiro
                    ( br->rt != DELETED_PALM_REC ) &&
1206 1 hiro
                    ( br->rt != MODIFIED_PALM_REC ) &&
1207 1 hiro
                    ( br->rt != DELETED_DELETED_PALM_REC ) ) {
1208 1 hiro
                        jpilot_load_address( pilotFile, br, folderInd );
1209 1 hiro
                }
1210 1 hiro
                free( br );
1211 1 hiro
                node->data = NULL;
1212 1 hiro
                node = g_list_next( node );
1213 1 hiro
        }
1214 1 hiro
1215 1 hiro
        /* Free up list */
1216 1 hiro
        g_list_free( records );
1217 1 hiro
1218 1 hiro
        return retVal;
1219 1 hiro
}
1220 1 hiro
1221 1 hiro
1222 1 hiro
/*
1223 1 hiro
* Read metadata from file.
1224 1 hiro
*/
1225 1 hiro
static gint jpilot_read_metadata( JPilotFile *pilotFile ) {
1226 1 hiro
        gint retVal;
1227 1 hiro
        unsigned int rec_size;
1228 1 hiro
        unsigned char *buf;
1229 1 hiro
        int num;
1230 1 hiro
1231 1 hiro
        g_return_val_if_fail( pilotFile != NULL, -1 );
1232 1 hiro
1233 1 hiro
        pilotFile->readMetadata = FALSE;
1234 1 hiro
        addrcache_clear( pilotFile->addressCache );
1235 1 hiro
1236 1 hiro
        /* Read file info */
1237 1 hiro
        retVal = jpilot_get_file_info( pilotFile, &buf, &rec_size);
1238 1 hiro
        if( retVal != MGU_SUCCESS ) {
1239 1 hiro
                pilotFile->retVal = retVal;
1240 1 hiro
                return pilotFile->retVal;
1241 1 hiro
        }
1242 1 hiro
1243 1 hiro
        num = unpack_AddressAppInfo( &pilotFile->addrInfo, buf, rec_size );
1244 1 hiro
        if( buf ) {
1245 1 hiro
                free(buf);
1246 1 hiro
        }
1247 1 hiro
        if( num <= 0 ) {
1248 1 hiro
                pilotFile->retVal = MGU_ERROR_READ;
1249 1 hiro
                return pilotFile->retVal;
1250 1 hiro
        }
1251 1 hiro
1252 1 hiro
        pilotFile->readMetadata = TRUE;
1253 1 hiro
        pilotFile->retVal = MGU_SUCCESS;
1254 1 hiro
        return pilotFile->retVal;
1255 1 hiro
}
1256 1 hiro
1257 1 hiro
/*
1258 1 hiro
* Setup labels and indexes from metadata.
1259 1 hiro
* Return: TRUE is setup successfully.
1260 1 hiro
*/
1261 1 hiro
static gboolean jpilot_setup_labels( JPilotFile *pilotFile ) {
1262 1 hiro
        gboolean retVal = FALSE;
1263 1 hiro
        struct AddressAppInfo *ai;
1264 1 hiro
        GList *node;
1265 1 hiro
1266 1 hiro
        g_return_val_if_fail( pilotFile != NULL, -1 );
1267 1 hiro
1268 1 hiro
        /* Release indexes */
1269 1 hiro
        node = pilotFile->labelInd;
1270 1 hiro
        while( node ) {
1271 1 hiro
                node->data = NULL;
1272 1 hiro
                node = g_list_next( node );
1273 1 hiro
        }
1274 1 hiro
        pilotFile->labelInd = NULL;
1275 1 hiro
1276 1 hiro
        if( pilotFile->readMetadata ) {
1277 1 hiro
                ai = & pilotFile->addrInfo;
1278 1 hiro
                node = pilotFile->customLabels;
1279 1 hiro
                while( node ) {
1280 1 hiro
                        gchar *lbl = node->data;
1281 1 hiro
                        gint ind = -1;
1282 1 hiro
                        gint i;
1283 1 hiro
                        for( i = 0; i < JPILOT_NUM_LABELS; i++ ) {
1284 1 hiro
                                gchar *labelName = ai->labels[i];
1285 1 hiro
                                gchar convertBuff[ JPILOT_LEN_LABEL ];
1286 1 hiro
1287 1 hiro
                                if( convert_charcode ) {
1288 42 hiro
                                        labelName = conv_codeset_strdup( labelName, CS_SHIFT_JIS, CS_INTERNAL );
1289 42 hiro
                                        strncpy2( convertBuff, labelName, JPILOT_LEN_LABEL );
1290 42 hiro
                                        g_free( labelName );
1291 1 hiro
                                        labelName = convertBuff;
1292 1 hiro
                                }
1293 1 hiro
1294 1 hiro
                                if( g_strcasecmp( labelName, lbl ) == 0 ) {
1295 1 hiro
                                        ind = i;
1296 1 hiro
                                        break;
1297 1 hiro
                                }
1298 1 hiro
                        }
1299 1 hiro
                        pilotFile->labelInd = g_list_append( pilotFile->labelInd, GINT_TO_POINTER(ind) );
1300 1 hiro
                        node = g_list_next( node );
1301 1 hiro
                }
1302 1 hiro
                retVal = TRUE;
1303 1 hiro
        }
1304 1 hiro
        return retVal;
1305 1 hiro
}
1306 1 hiro
1307 1 hiro
/*
1308 1 hiro
* Load list with character strings of label names.
1309 1 hiro
*/
1310 1 hiro
GList *jpilot_load_label( JPilotFile *pilotFile, GList *labelList ) {
1311 1 hiro
        int i;
1312 1 hiro
1313 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
1314 1 hiro
1315 1 hiro
        if( pilotFile->readMetadata ) {
1316 1 hiro
                struct AddressAppInfo *ai = & pilotFile->addrInfo;
1317 1 hiro
                for( i = 0; i < JPILOT_NUM_LABELS; i++ ) {
1318 1 hiro
                        gchar *labelName = ai->labels[i];
1319 1 hiro
1320 1 hiro
                        if( labelName ) {
1321 1 hiro
                                if( convert_charcode ) {
1322 42 hiro
                                        labelName = conv_codeset_strdup( labelName, CS_SHIFT_JIS, CS_INTERNAL );
1323 1 hiro
                                }
1324 42 hiro
                                else {
1325 42 hiro
                                        labelName = g_strdup( labelName );
1326 42 hiro
                                }
1327 42 hiro
                                labelList = g_list_append( labelList, labelName );
1328 1 hiro
                        }
1329 1 hiro
                        else {
1330 1 hiro
                                labelList = g_list_append( labelList, g_strdup( "" ) );
1331 1 hiro
                        }
1332 1 hiro
                }
1333 1 hiro
        }
1334 1 hiro
        return labelList;
1335 1 hiro
}
1336 1 hiro
1337 1 hiro
/*
1338 1 hiro
* Return category name for specified category ID.
1339 1 hiro
* Enter:  Category ID.
1340 1 hiro
* Return: Name, or empty string if not invalid ID. Name should be g_free() when done.
1341 1 hiro
*/
1342 1 hiro
gchar *jpilot_get_category_name( JPilotFile *pilotFile, gint catID ) {
1343 1 hiro
        gchar *catName = NULL;
1344 1 hiro
1345 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
1346 1 hiro
1347 1 hiro
        if( pilotFile->readMetadata ) {
1348 1 hiro
                struct AddressAppInfo *ai = & pilotFile->addrInfo;
1349 1 hiro
                struct CategoryAppInfo *cat = &        ai->category;
1350 1 hiro
                if( catID < 0 || catID > JPILOT_NUM_CATEG ) {
1351 1 hiro
                }
1352 1 hiro
                else {
1353 1 hiro
                        catName = g_strdup( cat->name[catID] );
1354 1 hiro
                }
1355 1 hiro
        }
1356 1 hiro
        if( ! catName ) catName = g_strdup( "" );
1357 1 hiro
        return catName;
1358 1 hiro
}
1359 1 hiro
1360 1 hiro
/*
1361 1 hiro
* Load list with character strings of phone label names.
1362 1 hiro
*/
1363 1 hiro
GList *jpilot_load_phone_label( JPilotFile *pilotFile, GList *labelList ) {
1364 1 hiro
        gint i;
1365 1 hiro
1366 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
1367 1 hiro
1368 1 hiro
        if( pilotFile->readMetadata ) {
1369 1 hiro
                struct AddressAppInfo *ai = & pilotFile->addrInfo;
1370 1 hiro
                for( i = 0; i < JPILOT_NUM_PHONELABELS; i++ ) {
1371 1 hiro
                        gchar        *labelName = ai->phoneLabels[i];
1372 1 hiro
                        if( labelName ) {
1373 1 hiro
                                labelList = g_list_append( labelList, g_strdup( labelName ) );
1374 1 hiro
                        }
1375 1 hiro
                        else {
1376 1 hiro
                                labelList = g_list_append( labelList, g_strdup( "" ) );
1377 1 hiro
                        }
1378 1 hiro
                }
1379 1 hiro
        }
1380 1 hiro
        return labelList;
1381 1 hiro
}
1382 1 hiro
1383 1 hiro
/*
1384 1 hiro
* Load list with character strings of label names. Only none blank names
1385 1 hiro
* are loaded.
1386 1 hiro
*/
1387 1 hiro
GList *jpilot_load_custom_label( JPilotFile *pilotFile, GList *labelList ) {
1388 1 hiro
        gint i;
1389 1 hiro
1390 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
1391 1 hiro
1392 1 hiro
        if( pilotFile->readMetadata ) {
1393 1 hiro
                struct AddressAppInfo *ai = & pilotFile->addrInfo;
1394 1 hiro
                for( i = 0; i < NUM_CUSTOM_LABEL; i++ ) {
1395 1 hiro
                        gchar *labelName = ai->labels[i+IND_CUSTOM_LABEL];
1396 1 hiro
                        if( labelName ) {
1397 1 hiro
                                g_strchomp( labelName );
1398 1 hiro
                                g_strchug( labelName );
1399 1 hiro
                                if( *labelName != '\0' ) {
1400 1 hiro
                                        if( convert_charcode ) {
1401 42 hiro
                                                labelName = conv_codeset_strdup( labelName, CS_SHIFT_JIS, CS_INTERNAL );
1402 1 hiro
                                        }
1403 42 hiro
                                        else {
1404 42 hiro
                                                labelName = g_strdup( labelName );
1405 42 hiro
                                        }
1406 42 hiro
                                        labelList = g_list_append( labelList, labelName );
1407 1 hiro
                                }
1408 1 hiro
                        }
1409 1 hiro
                }
1410 1 hiro
        }
1411 1 hiro
        return labelList;
1412 1 hiro
}
1413 1 hiro
1414 1 hiro
/*
1415 1 hiro
* Load list with character strings of category names.
1416 1 hiro
*/
1417 1 hiro
GList *jpilot_get_category_list( JPilotFile *pilotFile ) {
1418 1 hiro
        GList *catList = NULL;
1419 1 hiro
        gint i;
1420 1 hiro
1421 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
1422 1 hiro
1423 1 hiro
        if( pilotFile->readMetadata ) {
1424 1 hiro
                struct AddressAppInfo *ai = & pilotFile->addrInfo;
1425 1 hiro
                struct CategoryAppInfo *cat = &        ai->category;
1426 1 hiro
                for( i = 0; i < JPILOT_NUM_CATEG; i++ ) {
1427 1 hiro
                        gchar *catName = cat->name[i];
1428 1 hiro
                        if( catName ) {
1429 1 hiro
                                catList = g_list_append( catList, g_strdup( catName ) );
1430 1 hiro
                        }
1431 1 hiro
                        else {
1432 1 hiro
                                catList = g_list_append( catList, g_strdup( "" ) );
1433 1 hiro
                        }
1434 1 hiro
                }
1435 1 hiro
        }
1436 1 hiro
        return catList;
1437 1 hiro
}
1438 1 hiro
1439 1 hiro
/*
1440 1 hiro
* Build folder for each category.
1441 1 hiro
*/
1442 1 hiro
static void jpilot_build_category_list( JPilotFile *pilotFile ) {
1443 1 hiro
        struct AddressAppInfo *ai = & pilotFile->addrInfo;
1444 1 hiro
        struct CategoryAppInfo *cat = &        ai->category;
1445 1 hiro
        gint i;
1446 1 hiro
1447 1 hiro
        for( i = 0; i < JPILOT_NUM_CATEG; i++ ) {
1448 1 hiro
                ItemFolder *folder = addritem_create_item_folder();
1449 1 hiro
1450 1 hiro
                if( convert_charcode ) {
1451 42 hiro
                        gchar *catName;
1452 42 hiro
                        catName = conv_codeset_strdup( cat->name[i], CS_SHIFT_JIS, CS_INTERNAL );
1453 1 hiro
                        addritem_folder_set_name( folder, catName );
1454 42 hiro
                        g_free( catName );
1455 1 hiro
                }
1456 1 hiro
                else {
1457 1 hiro
                        addritem_folder_set_name( folder, cat->name[i] );
1458 1 hiro
                }
1459 1 hiro
1460 1 hiro
                addrcache_id_folder( pilotFile->addressCache, folder );
1461 1 hiro
                addrcache_add_folder( pilotFile->addressCache, folder );
1462 1 hiro
        }
1463 1 hiro
}
1464 1 hiro
1465 1 hiro
/*
1466 1 hiro
* Remove empty folders (categories).
1467 1 hiro
*/
1468 1 hiro
static void jpilot_remove_empty( JPilotFile *pilotFile ) {
1469 1 hiro
        GList *listFolder;
1470 1 hiro
        GList *remList;
1471 1 hiro
        GList *node;
1472 1 hiro
        gint i = 0;
1473 1 hiro
1474 1 hiro
        listFolder = addrcache_get_list_folder( pilotFile->addressCache );
1475 1 hiro
        node = listFolder;
1476 1 hiro
        remList = NULL;
1477 1 hiro
        while( node ) {
1478 1 hiro
                ItemFolder *folder = node->data;
1479 1 hiro
                if( ADDRITEM_NAME(folder) == NULL || *ADDRITEM_NAME(folder) == '\0' ) {
1480 1 hiro
                        if( folder->listPerson ) {
1481 1 hiro
                                /* Give name to folder */
1482 1 hiro
                                gchar name[20];
1483 1 hiro
                                sprintf( name, "? %d", i );
1484 1 hiro
                                addritem_folder_set_name( folder, name );
1485 1 hiro
                        }
1486 1 hiro
                        else {
1487 1 hiro
                                /* Mark for removal */
1488 1 hiro
                                remList = g_list_append( remList, folder );
1489 1 hiro
                        }
1490 1 hiro
                }
1491 1 hiro
                node = g_list_next( node );
1492 1 hiro
                i++;
1493 1 hiro
        }
1494 1 hiro
        node = remList;
1495 1 hiro
        while( node ) {
1496 1 hiro
                ItemFolder *folder = node->data;
1497 1 hiro
                addrcache_remove_folder( pilotFile->addressCache, folder );
1498 1 hiro
                node = g_list_next( node );
1499 1 hiro
        }
1500 1 hiro
        g_list_free( remList );
1501 1 hiro
}
1502 1 hiro
1503 1 hiro
/*
1504 1 hiro
* ============================================================================================
1505 1 hiro
* Read file into list. Main entry point
1506 1 hiro
* Return: TRUE if file read successfully.
1507 1 hiro
* ============================================================================================
1508 1 hiro
*/
1509 1 hiro
gint jpilot_read_data( JPilotFile *pilotFile ) {
1510 1 hiro
        const gchar *cur_locale;
1511 1 hiro
1512 1 hiro
        name_order = FAMILY_LAST;
1513 1 hiro
        convert_charcode = FALSE;
1514 1 hiro
1515 1 hiro
        cur_locale = conv_get_current_locale();
1516 1 hiro
1517 1 hiro
        if( g_strncasecmp( cur_locale, "ja", 2 ) == 0 ) {
1518 1 hiro
                name_order = FAMILY_FIRST;
1519 1 hiro
        }
1520 1 hiro
1521 1 hiro
        if( conv_get_locale_charset() == C_EUC_JP ) {
1522 1 hiro
                convert_charcode = TRUE;
1523 1 hiro
        }
1524 1 hiro
1525 1 hiro
        g_return_val_if_fail( pilotFile != NULL, -1 );
1526 1 hiro
1527 1 hiro
        pilotFile->retVal = MGU_SUCCESS;
1528 1 hiro
        pilotFile->accessFlag = FALSE;
1529 1 hiro
1530 1 hiro
        if( jpilot_check_files( pilotFile ) ) {
1531 1 hiro
                addrcache_clear( pilotFile->addressCache );
1532 1 hiro
                jpilot_read_metadata( pilotFile );
1533 1 hiro
                if( pilotFile->retVal == MGU_SUCCESS ) {
1534 1 hiro
                        jpilot_setup_labels( pilotFile );
1535 1 hiro
                        jpilot_build_category_list( pilotFile );
1536 1 hiro
                        pilotFile->retVal = jpilot_read_file( pilotFile );
1537 1 hiro
                        if( pilotFile->retVal == MGU_SUCCESS ) {
1538 1 hiro
                                jpilot_remove_empty( pilotFile );
1539 1 hiro
                                jpilot_mark_files( pilotFile );
1540 1 hiro
                                pilotFile->addressCache->modified = FALSE;
1541 1 hiro
                                pilotFile->addressCache->dataRead = TRUE;
1542 1 hiro
                        }
1543 1 hiro
                }
1544 1 hiro
        }
1545 1 hiro
        return pilotFile->retVal;
1546 1 hiro
}
1547 1 hiro
1548 1 hiro
/*
1549 1 hiro
* Return link list of persons.
1550 1 hiro
*/
1551 1 hiro
GList *jpilot_get_list_person( JPilotFile *pilotFile ) {
1552 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
1553 1 hiro
        return addrcache_get_list_person( pilotFile->addressCache );
1554 1 hiro
}
1555 1 hiro
1556 1 hiro
/*
1557 1 hiro
* Return link list of folders. This is always NULL since there are
1558 1 hiro
* no folders in GnomeCard.
1559 1 hiro
* Return: NULL.
1560 1 hiro
*/
1561 1 hiro
GList *jpilot_get_list_folder( JPilotFile *pilotFile ) {
1562 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
1563 1 hiro
        return addrcache_get_list_folder( pilotFile->addressCache );
1564 1 hiro
}
1565 1 hiro
1566 1 hiro
/*
1567 1 hiro
* Return link list of all persons. Note that the list contains references
1568 1 hiro
* to items. Do *NOT* attempt to use the addrbook_free_xxx() functions...
1569 1 hiro
* this will destroy the addressbook data!
1570 1 hiro
* Return: List of items, or NULL if none.
1571 1 hiro
*/
1572 1 hiro
GList *jpilot_get_all_persons( JPilotFile *pilotFile ) {
1573 1 hiro
        g_return_val_if_fail( pilotFile != NULL, NULL );
1574 1 hiro
        return addrcache_get_all_persons( pilotFile->addressCache );
1575 1 hiro
}
1576 1 hiro
1577 1 hiro
/*
1578 1 hiro
* Check label list for specified label.
1579 1 hiro
*/
1580 1 hiro
gint jpilot_check_label( struct AddressAppInfo *ai, gchar *lblCheck ) {
1581 1 hiro
        gint i;
1582 1 hiro
        gchar *lblName;
1583 1 hiro
1584 1 hiro
        if( lblCheck == NULL ) return -1;
1585 1 hiro
        if( strlen( lblCheck ) < 1 ) return -1;
1586 1 hiro
        for( i = 0; i < JPILOT_NUM_LABELS; i++ ) {
1587 1 hiro
                lblName = ai->labels[i];
1588 1 hiro
                if( lblName ) {
1589 1 hiro
                        if( strlen( lblName ) ) {
1590 1 hiro
                                if( g_strcasecmp( lblName, lblCheck ) == 0 ) return i;
1591 1 hiro
                        }
1592 1 hiro
                }
1593 1 hiro
        }
1594 1 hiro
        return -2;
1595 1 hiro
}
1596 1 hiro
1597 1 hiro
/*
1598 1 hiro
* Validate that all parameters specified.
1599 1 hiro
* Return: TRUE if data is good.
1600 1 hiro
*/
1601 1 hiro
gboolean jpilot_validate( const JPilotFile *pilotFile ) {
1602 1 hiro
        gboolean retVal;
1603 1 hiro
1604 1 hiro
        g_return_val_if_fail( pilotFile != NULL, FALSE );
1605 1 hiro
1606 1 hiro
        retVal = TRUE;
1607 1 hiro
        if( pilotFile->path ) {
1608 1 hiro
                if( strlen( pilotFile->path ) < 1 ) retVal = FALSE;
1609 1 hiro
        }
1610 1 hiro
        else {
1611 1 hiro
                retVal = FALSE;
1612 1 hiro
        }
1613 1 hiro
        if( pilotFile->name ) {
1614 1 hiro
                if( strlen( pilotFile->name ) < 1 ) retVal = FALSE;
1615 1 hiro
        }
1616 1 hiro
        else {
1617 1 hiro
                retVal = FALSE;
1618 1 hiro
        }
1619 1 hiro
        return retVal;
1620 1 hiro
}
1621 1 hiro
1622 1 hiro
#define WORK_BUFLEN 1024
1623 1 hiro
1624 1 hiro
/*
1625 1 hiro
* Attempt to find a valid JPilot file.
1626 1 hiro
* Return: Filename, or home directory if not found, or empty string if
1627 1 hiro
* no home. Filename should be g_free() when done.
1628 1 hiro
*/
1629 1 hiro
gchar *jpilot_find_pilotdb( void ) {
1630 22 hiro
        const gchar *homedir;
1631 1 hiro
        gchar str[ WORK_BUFLEN ];
1632 1 hiro
        gint len;
1633 1 hiro
        FILE *fp;
1634 1 hiro
1635 1 hiro
        homedir = g_get_home_dir();
1636 1 hiro
        if( ! homedir ) return g_strdup( "" );
1637 1 hiro
1638 1 hiro
        strcpy( str, homedir );
1639 1 hiro
        len = strlen( str );
1640 1 hiro
        if( len > 0 ) {
1641 1 hiro
                if( str[ len-1 ] != G_DIR_SEPARATOR ) {
1642 1 hiro
                        str[ len ] = G_DIR_SEPARATOR;
1643 1 hiro
                        str[ ++len ] = '\0';
1644 1 hiro
                }
1645 1 hiro
        }
1646 1 hiro
        strcat( str, JPILOT_DBHOME_DIR );
1647 1 hiro
        strcat( str, G_DIR_SEPARATOR_S );
1648 1 hiro
        strcat( str, JPILOT_DBHOME_FILE );
1649 1 hiro
1650 1 hiro
        /* Attempt to open */
1651 1 hiro
        if( ( fp = fopen( str, "rb" ) ) != NULL ) {
1652 1 hiro
                fclose( fp );
1653 1 hiro
        }
1654 1 hiro
        else {
1655 1 hiro
                /* Truncate filename */
1656 1 hiro
                str[ len ] = '\0';
1657 1 hiro
        }
1658 1 hiro
        return g_strdup( str );
1659 1 hiro
}
1660 1 hiro
1661 1 hiro
/*
1662 1 hiro
* Attempt to read file, testing for valid JPilot format.
1663 1 hiro
* Return: TRUE if file appears to be valid format.
1664 1 hiro
*/
1665 1 hiro
gint jpilot_test_read_file( const gchar *fileSpec ) {
1666 1 hiro
        JPilotFile *pilotFile;
1667 1 hiro
        gint retVal;
1668 1 hiro
1669 1 hiro
        if( fileSpec ) {
1670 1 hiro
                pilotFile = jpilot_create_path( fileSpec );
1671 1 hiro
                retVal = jpilot_read_metadata( pilotFile );
1672 1 hiro
                jpilot_free( pilotFile );
1673 1 hiro
                pilotFile = NULL;
1674 1 hiro
        }
1675 1 hiro
        else {
1676 1 hiro
                retVal = MGU_NO_FILE;
1677 1 hiro
        }
1678 1 hiro
        return retVal;
1679 1 hiro
}
1680 1 hiro
1681 1 hiro
/*
1682 1 hiro
* Check whether label is in custom labels.
1683 1 hiro
* Return: TRUE if found.
1684 1 hiro
*/
1685 1 hiro
gboolean jpilot_test_custom_label( JPilotFile *pilotFile, const gchar *labelName ) {
1686 1 hiro
        gboolean retVal;
1687 1 hiro
        GList *node;
1688 1 hiro
1689 1 hiro
        g_return_val_if_fail( pilotFile != NULL, FALSE );
1690 1 hiro
1691 1 hiro
        retVal = FALSE;
1692 1 hiro
        if( labelName ) {
1693 1 hiro
                node = pilotFile->customLabels;
1694 1 hiro
                while( node ) {
1695 1 hiro
                        if( g_strcasecmp( labelName, node->data ) == 0 ) {
1696 1 hiro
                                retVal = TRUE;
1697 1 hiro
                                break;
1698 1 hiro
                        }
1699 1 hiro
                        node = g_list_next( node );
1700 1 hiro
                }
1701 1 hiro
        }
1702 1 hiro
        return retVal;
1703 1 hiro
}
1704 1 hiro
1705 1 hiro
/*
1706 1 hiro
* Test whether pilot link library installed.
1707 1 hiro
* Return: TRUE if library available.
1708 1 hiro
*/
1709 1 hiro
#if 0
1710 1 hiro
gboolean jpilot_test_pilot_lib( void ) {
1711 1 hiro
        void *handle, *fun;
1712 1 hiro
1713 1 hiro
        handle = dlopen( PILOT_LINK_LIB_NAME, RTLD_LAZY );
1714 1 hiro
        if( ! handle ) {
1715 1 hiro
                return FALSE;
1716 1 hiro
        }
1717 1 hiro
1718 1 hiro
        /* Test for symbols we need */
1719 1 hiro
        fun = dlsym( handle, "unpack_Address" );
1720 1 hiro
        if( ! fun ) {
1721 1 hiro
                dlclose( handle );
1722 1 hiro
                return FALSE;
1723 1 hiro
        }
1724 1 hiro
1725 1 hiro
        fun = dlsym( handle, "unpack_AddressAppInfo" );
1726 1 hiro
        if( ! fun ) {
1727 1 hiro
                dlclose( handle );
1728 1 hiro
                return FALSE;
1729 1 hiro
        }
1730 1 hiro
        dlclose( handle );
1731 1 hiro
        return TRUE;
1732 1 hiro
}
1733 1 hiro
#endif /* 0 */
1734 1 hiro
1735 1 hiro
#endif        /* USE_JPILOT */
1736 1 hiro
1737 1 hiro
/*
1738 1 hiro
* End of Source.
1739 1 hiro
*/