/* * Read metadata from file. */ static gint jpilot_read_metadata( JPilotFile *pilotFile ) { gint retVal; unsigned int rec_size; unsigned char *buf; int num; g_return_val_if_fail( pilotFile != NULL, -1 ); pilotFile->readMetadata = FALSE; addrcache_clear( pilotFile->addressCache ); /* Read file info */ retVal = jpilot_get_file_info( pilotFile, &buf, &rec_size); if( retVal != MGU_SUCCESS ) { pilotFile->retVal = retVal; return pilotFile->retVal; } num = unpack_AddressAppInfo( &pilotFile->addrInfo, buf, rec_size ); if( buf ) { free(buf); } if( num <= 0 ) { pilotFile->retVal = MGU_ERROR_READ; return pilotFile->retVal; } pilotFile->readMetadata = TRUE; pilotFile->retVal = MGU_SUCCESS; return pilotFile->retVal; }
int main(int argc, const char *argv[]) { int c, /* switch */ db, l, sd = -1; enum { mode_none, mode_read, mode_write, mode_delete_all, mode_delete } run_mode = mode_none; const char *progname = argv[0]; char *defaultcategoryname = 0, *deletecategory = 0, *wrFilename = NULL, *rdFilename = NULL, buf[0xffff]; int writehuman = 0; pi_buffer_t *appblock; struct AddressAppInfo aai; struct PilotUser User; struct SysInfo info; poptContext po; struct poptOption options[] = { USERLAND_RESERVED_OPTIONS {"delete-all", 0 , POPT_ARG_NONE, NULL, mode_delete_all, "Delete all Palm records in all categories", NULL}, {"delimiter", 't', POPT_ARG_INT, &tabledelim, 0, "Include category, use delimiter (3=tab, 2=;, 1=,)", "<delimeter>"}, {"delete-category", 'd', POPT_ARG_STRING, &deletecategory,'d', "Delete old Palm records in <category>", "category"}, {"category", 'c', POPT_ARG_STRING, &defaultcategoryname, 0, "Category to install to", "category"}, {"augment", 'a', POPT_ARG_NONE, &augment, 0, "Augment records with additional information", NULL}, {"read", 'r', POPT_ARG_STRING, &rdFilename, 'r', "Read records from <file> and install them to Palm", "file"}, {"write", 'w', POPT_ARG_STRING, &wrFilename, 'w', "Get records from Palm and write them to <file>", "file"}, {"human-readable",'C', POPT_ARG_NONE, &writehuman, 0, "Write generic human-readable output instead of CSV", NULL}, POPT_TABLEEND }; const char *mode_error = " ERROR: Specify exactly one of read, write, delete or delete all.\n"; po = poptGetContext("pilot-addresses", argc, argv, options, 0); poptSetOtherOptionHelp(po,"\n\n" " Reads addresses from a file and installs on the Palm, or\n" " writes addresses from the Palm to a file.\n\n" " Provide exactly one of --read or --write.\n\n"); plu_popt_alias(po,"delall",0,"--bad-option --delete-all"); plu_popt_alias(po,"delcat",0,"--bad-option --delete-category"); plu_popt_alias(po,"install",0,"--bad-option --category"); /* Useful alias */ plu_popt_alias(po,"no-csv",0,"--human-readable"); if (argc < 2) { poptPrintUsage(po,stderr,0); return 1; } while ((c = poptGetNextOpt(po)) >= 0) { switch (c) { /* These are the mode-setters. delete-all does it through * popt hooks, since it doesn't take an argument. * * Special case is that you can mix -w and -d to write the * file and then delete a category. */ case mode_delete_all : if (run_mode != mode_none) { fprintf(stderr,"%s",mode_error); return 1; } run_mode = mode_delete_all; break; case 'r': if (run_mode != mode_none) { fprintf(stderr,"%s",mode_error); return 1; } run_mode = mode_read; break; case 'w': if ((run_mode != mode_none) && (run_mode != mode_delete)) { fprintf(stderr,"%s",mode_error); return 1; } run_mode = mode_write; break; case 'd': if ((run_mode != mode_none) && (run_mode != mode_write)) { fprintf(stderr,"%s",mode_error); return 1; } run_mode = mode_delete; break; default: fprintf(stderr," ERROR: Unhandled option %d.\n",c); return 1; } } if (c < -1) plu_badoption(po,c); if (mode_none == run_mode) { fprintf(stderr,"%s",mode_error); return 1; } /* The first implies that -t was given; the second that it wasn't, so use default, and the third if handles weird values. */ if ((tabledelim < 0) || (tabledelim > sizeof(tabledelim))) { fprintf(stderr," ERROR: Invalid delimiter number %d (use 0-%d).\n", tabledelim,(int)(sizeof(tabledelim))); return 1; } sd = plu_connect(); if (sd < 0) goto error; if (dlp_ReadUserInfo(sd, &User) < 0) goto error_close; if (dlp_ReadSysInfo(sd,&info) < 0) { fprintf(stderr," ERROR: Could not read Palm System Information.\n"); return -1; } if (info.romVersion > 0x05003000) { printf(" PalmOS 5.x (Garnet) and later devices are not currently supported by this\n" " tool. The data format of the AddressBook has changed. The legacy format\n" " is called \"Classic\" and PalmOS 5.x and later uses \"Extended\" databases\n" " with a different structure. Your Palm has \"Contacts\", and this tool reads\n" " the \"AddressBook\" database. (Found OS version: %x)\n\n" " Due to this change, pilot-addresses and other tools must be rewritten to\n" " compensate. Sorry about the inconvenience.\n\n", info.romVersion); /* return -1; FIXME: Need to adjust this to clealy detect OS version and rewrite */ } /* Open the AddressDB.pdb database, store access handle in db */ if (dlp_OpenDB(sd, 0, 0x80 | 0x40, "AddressDB", &db) < 0) { puts("Unable to open AddressDB"); dlp_AddSyncLogEntry(sd, "Unable to open AddressDB.\n"); goto error_close; } appblock = pi_buffer_new(0xffff); l = dlp_ReadAppBlock(sd, db, 0, 0xffff, appblock); unpack_AddressAppInfo(&aai, appblock->data, l); pi_buffer_free(appblock); if (defaultcategoryname) { defaultcategory = plu_findcategory(&aai.category,defaultcategoryname, PLU_CAT_CASE_INSENSITIVE | PLU_CAT_DEFAULT_UNFILED); } else { defaultcategory = 0; /* Unfiled */ } switch(run_mode) { FILE *f; int i; int old_quiet; case mode_none: /* impossible */ fprintf(stderr,"%s",mode_error); break; case mode_write: /* FIXME - Must test for existing file first! DD 2002/03/18 */ if (strcmp(wrFilename,"-") == 0) { f = stdout; old_quiet = plu_quiet; plu_quiet = 1; } else { f = fopen(wrFilename, "w"); } if (f == NULL) { sprintf(buf, "%s: %s", progname, wrFilename); perror(buf); goto error_close; } write_file(f, sd, db, &aai, writehuman); if (f == stdout) { plu_quiet = old_quiet; } if (deletecategory) { dlp_DeleteCategory(sd, db, plu_findcategory(&aai.category,deletecategory,PLU_CAT_CASE_INSENSITIVE | PLU_CAT_WARN_UNKNOWN)); } if (f != stdout) { fclose(f); } break; case mode_read: f = fopen(rdFilename, "r"); if (f == NULL) { fprintf(stderr, "Unable to open input file"); fprintf(stderr, " '%s' (%s)\n\n", rdFilename, strerror(errno)); fprintf(stderr, "Please make sure the file"); fprintf(stderr, "'%s' exists, and that\n", rdFilename); fprintf(stderr, "it is readable by this user"); fprintf(stderr, " before launching.\n\n"); goto error_close; } read_file(f, sd, db, &aai); fclose(f); break; case mode_delete: i = plu_findcategory (&aai.category,deletecategory,PLU_CAT_CASE_INSENSITIVE | PLU_CAT_WARN_UNKNOWN); if (i>=0) { dlp_DeleteCategory(sd, db, i); } break; case mode_delete_all: for (i = 0; i < 16; i++) if (aai.category.name[i][0]) dlp_DeleteCategory(sd, db, i); break; } /* Close the database */ dlp_CloseDB(sd, db); /* Tell the user who it is, with a different PC id. */ User.lastSyncPC = 0x00010000; User.successfulSyncDate = time(NULL); User.lastSyncDate = User.successfulSyncDate; dlp_WriteUserInfo(sd, &User); if (run_mode == mode_read) { dlp_AddSyncLogEntry(sd, "Wrote entries to Palm Address Book.\n"); } else if (run_mode == mode_write) { dlp_AddSyncLogEntry(sd, "Successfully read Address Book from Palm.\n"); } dlp_EndOfSync(sd, 0); pi_close(sd); return 0; error_close: pi_close(sd); error: return -1; }
/* Pilot syncing callbacks */ static gint pre_sync (GnomePilotConduit *conduit, GnomePilotDBInfo *dbi, EAddrConduitContext *ctxt) { GnomePilotConduitSyncAbs *abs_conduit; EBookQuery *query; GList *l; int len; char *filename; char *change_id; char *auth; gint num_records, add_records = 0, mod_records = 0, del_records = 0; #ifdef PILOT_LINK_0_12 pi_buffer_t *buffer; #else unsigned char *buf; #endif abs_conduit = GNOME_PILOT_CONDUIT_SYNC_ABS (conduit); LOG (g_message ( "---------------------------------------------------------\n" )); LOG (g_message ( "pre_sync: Addressbook Conduit v.%s", CONDUIT_VERSION )); /* g_message ("Addressbook Conduit v.%s", CONDUIT_VERSION); */ ctxt->dbi = dbi; if (ctxt->cfg->source) { ctxt->ebook = e_book_new (ctxt->cfg->source, NULL); } else { ctxt->ebook = e_book_new_default_addressbook (NULL); } auth = (gchar *)e_source_get_property (ctxt->cfg->source, "auth"); if (auth) { LOG (g_message ("contacts needs authentication\n")); g_signal_connect (ctxt->ebook, "auth_required", G_CALLBACK (addressbook_authenticate), ctxt->cfg->source); } if (!ctxt->ebook || !e_book_open (ctxt->ebook, TRUE, NULL)) { WARN(_("Could not load addressbook")); gnome_pilot_conduit_error (conduit, _("Could not load addressbook")); return -1; } /* Load the uid <--> pilot id mappings */ filename = map_name (ctxt); e_pilot_map_read (filename, &ctxt->map); g_free (filename); /* Get a list of all contacts */ if (!(query = e_book_query_any_field_contains (""))) { LOG (g_warning ("Failed to get EBookQuery")); return -1; } if (!e_book_get_contacts (ctxt->ebook, query, &ctxt->cards, NULL)) { LOG (g_warning ("Failed to get Contacts")); e_book_query_unref (query); return -1; } e_book_query_unref (query); /* Count and hash the changes */ change_id = g_strdup_printf ("pilot-sync-evolution-addressbook-%d", ctxt->cfg->pilot_id); if (!e_book_get_changes (ctxt->ebook, change_id, &ctxt->changed, NULL)) return -1; ctxt->changed_hash = g_hash_table_new (g_str_hash, g_str_equal); g_free (change_id); for (l = ctxt->changed; l != NULL; l = l->next) { EBookChange *ebc = l->data; const char *uid; uid = e_contact_get_const (ebc->contact, E_CONTACT_UID); if (!e_pilot_map_uid_is_archived (ctxt->map, uid)) { g_hash_table_insert (ctxt->changed_hash, g_strdup (uid), ebc); switch (ebc->change_type) { case E_BOOK_CHANGE_CARD_ADDED: add_records++; break; case E_BOOK_CHANGE_CARD_MODIFIED: mod_records++; break; case E_BOOK_CHANGE_CARD_DELETED: del_records++; break; } } else if (ebc->change_type == E_BOOK_CHANGE_CARD_DELETED) { e_pilot_map_remove_by_uid (ctxt->map, uid); } } /* Set the count information */ num_records = g_list_length (ctxt->cards); gnome_pilot_conduit_sync_abs_set_num_local_records(abs_conduit, num_records); gnome_pilot_conduit_sync_abs_set_num_new_local_records (abs_conduit, add_records); gnome_pilot_conduit_sync_abs_set_num_updated_local_records (abs_conduit, mod_records); gnome_pilot_conduit_sync_abs_set_num_deleted_local_records(abs_conduit, del_records); #ifdef PILOT_LINK_0_12 buffer = pi_buffer_new(DLP_BUF_SIZE); if(buffer == NULL){ return pi_set_error(dbi->pilot_socket, PI_ERR_GENERIC_MEMORY); } len = dlp_ReadAppBlock (dbi->pilot_socket, dbi->db_handle, 0, DLP_BUF_SIZE, buffer); #else buf = (unsigned char*)g_malloc (0xffff); len = dlp_ReadAppBlock (dbi->pilot_socket, dbi->db_handle, 0, (unsigned char *)buf, 0xffff); #endif if (len < 0) { WARN (_("Could not read pilot's Address application block")); WARN ("dlp_ReadAppBlock(...) = %d", len); gnome_pilot_conduit_error (conduit, _("Could not read pilot's Address application block")); return -1; } #ifdef PILOT_LINK_0_12 unpack_AddressAppInfo (&(ctxt->ai), buffer->data, len); pi_buffer_free (buffer); #else unpack_AddressAppInfo (&(ctxt->ai), buf, len); g_free (buf); #endif check_for_slow_setting (conduit, ctxt); if (ctxt->cfg->sync_type == GnomePilotConduitSyncTypeCopyToPilot || ctxt->cfg->sync_type == GnomePilotConduitSyncTypeCopyFromPilot) ctxt->map->write_touched_only = TRUE; return 0; }