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