Beispiel #1
0
/*
* 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;
}
Beispiel #2
0
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;
}