You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
379 lines
7.1 KiB
379 lines
7.1 KiB
4 years ago
|
/*
|
||
|
* contactsdb-test.c: Playing around with palmOne's ContactsDB-PAdd
|
||
|
*
|
||
|
* Written by T. Joseph Carter <knghtbrd@bluecherry.net>
|
||
|
*
|
||
|
* This program is released to the public domain where allowed by law. Some
|
||
|
* countries (eg, the United States) lack legal provision for releasing
|
||
|
* Copyright claims. In such jurisdictions you are licensed to use, modify,
|
||
|
* and distribute this program as you see fit. This program is released
|
||
|
* WITHOUT ANY WARRANTY, including the implied warranties of MERCHANTABILITY
|
||
|
* or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
*
|
||
|
* These terms do NOT apply to libpisock, which is covered by the GNU Library
|
||
|
* General Public License. Please see the GNU LGPL for details.
|
||
|
*/
|
||
|
|
||
|
#include <config.h>
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#ifdef HAVE_STDINT_H
|
||
|
#include <stdint.h>
|
||
|
#endif
|
||
|
#include <unistd.h>
|
||
|
#include <string.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#include "popt.h"
|
||
|
#include "pi-socket.h"
|
||
|
#include "pi-dlp.h"
|
||
|
#include "pi-header.h"
|
||
|
#include "pi-appinfo.h"
|
||
|
#include "pi-contact.h"
|
||
|
|
||
|
#undef PRINT_USELESS_INFO
|
||
|
#undef SAVE_PICTURES
|
||
|
|
||
|
#define hi(x) (((x) >> 4) & 0x0f)
|
||
|
#define lo(x) ((x) & 0x0f)
|
||
|
|
||
|
char *contacts_fields[] =
|
||
|
{
|
||
|
"Last name",
|
||
|
"First name",
|
||
|
"Company",
|
||
|
"Title",
|
||
|
"Phone 1",
|
||
|
"Phone 2",
|
||
|
"Phone 3",
|
||
|
"Phone 4",
|
||
|
"Phone 5",
|
||
|
"Phone 6",
|
||
|
"Phone 7",
|
||
|
"Messaging 1",
|
||
|
"Messaging 2",
|
||
|
"Website",
|
||
|
"Custom 1",
|
||
|
"Custom 2",
|
||
|
"Custom 3",
|
||
|
"Custom 4",
|
||
|
"Custom 5",
|
||
|
"Custom 6",
|
||
|
"Custom 7",
|
||
|
"Custom 8",
|
||
|
"Custom 9",
|
||
|
"Address 1",
|
||
|
"City",
|
||
|
"State",
|
||
|
"Zip",
|
||
|
"Country",
|
||
|
"Address 2",
|
||
|
"City",
|
||
|
"State",
|
||
|
"Zip",
|
||
|
"Country",
|
||
|
"Address 3",
|
||
|
"City",
|
||
|
"State",
|
||
|
"Zip",
|
||
|
"Country",
|
||
|
"Note"
|
||
|
};
|
||
|
|
||
|
char *contacts_phones[] =
|
||
|
{
|
||
|
"Phone (Work)",
|
||
|
"Phone (Home)",
|
||
|
"Phone (Fax)",
|
||
|
"Phone (Other)",
|
||
|
"Email",
|
||
|
"Phone (Main)",
|
||
|
"Phone (Pager)",
|
||
|
"Phone (Mobile)"
|
||
|
};
|
||
|
|
||
|
char *contacts_ims[] =
|
||
|
{
|
||
|
"IM",
|
||
|
"AIM",
|
||
|
"MSN IM",
|
||
|
"Yahoo IM",
|
||
|
"ICQ"
|
||
|
};
|
||
|
|
||
|
char *contacts_addrs[] =
|
||
|
{
|
||
|
"Addr (Work)",
|
||
|
"Addr (Home)",
|
||
|
"Addr (Other)"
|
||
|
};
|
||
|
|
||
|
/* This is ugly, but it works */
|
||
|
void
|
||
|
hexprint (unsigned char *data, size_t len, size_t ofs, int ascii)
|
||
|
{
|
||
|
int i, j;
|
||
|
int line;
|
||
|
|
||
|
line = ofs;
|
||
|
i = 0;
|
||
|
|
||
|
while (i < len)
|
||
|
{
|
||
|
printf (" %08X:", line);
|
||
|
for (j = 0; j < 16; j++, i++)
|
||
|
{
|
||
|
if (i < len)
|
||
|
printf (" %02X", data[i]);
|
||
|
else
|
||
|
printf (" ");
|
||
|
if (j == 7)
|
||
|
printf (" ");
|
||
|
}
|
||
|
if (ascii)
|
||
|
{
|
||
|
printf (" |");
|
||
|
i -= 16;
|
||
|
for (j = 0; j < 16; j++, i++)
|
||
|
{
|
||
|
if (i < len)
|
||
|
{
|
||
|
if (isprint(data[i]))
|
||
|
printf ("%c", data[i]);
|
||
|
else
|
||
|
printf (".");
|
||
|
}
|
||
|
else
|
||
|
printf (" ");
|
||
|
}
|
||
|
printf ("|\n");
|
||
|
}
|
||
|
else
|
||
|
printf ("\n");
|
||
|
line += 16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
print_appblock (int sd, int db, struct ContactAppInfo *cai)
|
||
|
{
|
||
|
int i;
|
||
|
size_t j;
|
||
|
pi_buffer_t *appblock = pi_buffer_new(0xffff);
|
||
|
|
||
|
if (dlp_ReadAppBlock(sd, db, 0, -1, appblock) <= 0)
|
||
|
goto error;
|
||
|
|
||
|
if (unpack_ContactAppInfo (cai, appblock) < 0)
|
||
|
goto error;
|
||
|
|
||
|
pi_buffer_free (appblock);
|
||
|
|
||
|
printf ("Categories:\n");
|
||
|
for (i = 0; i < 16; i++)
|
||
|
{
|
||
|
if (strlen(cai->category.name[i]) > 0)
|
||
|
printf (" Category %i: %s\n",
|
||
|
cai->category.ID[i], cai->category.name[i]);
|
||
|
}
|
||
|
printf (" Last Unique ID: %i\n", cai->category.lastUniqueID);
|
||
|
|
||
|
printf ("\nCustom labels");
|
||
|
for (i = 0; i < cai->numCustoms; i++)
|
||
|
{
|
||
|
if (i%4 == 0)
|
||
|
printf ("\n ");
|
||
|
printf ("%02i:%-16s ", i, cai->customLabels[i]);
|
||
|
}
|
||
|
if (i%4 != 0)
|
||
|
printf ("\n");
|
||
|
|
||
|
/* Fair enough for a test to print opaque data.. */
|
||
|
if (cai->internal != NULL) {
|
||
|
printf ("\nInternal data (opaque)\n");
|
||
|
hexprint ((unsigned char *)cai->internal, sizeof(cai->internal), 0, 0);
|
||
|
}
|
||
|
|
||
|
printf ("\nField labels");
|
||
|
i = 0;
|
||
|
for (j = 0; j < cai->num_labels; j++)
|
||
|
{
|
||
|
if (i%4 == 0)
|
||
|
printf ("\n ");
|
||
|
printf ("%02i:%-16s ", i++, cai->labels[j]);
|
||
|
}
|
||
|
if (i%4 != 0)
|
||
|
printf ("\n");
|
||
|
|
||
|
printf ("\nCountry: %i\n", cai->country);
|
||
|
|
||
|
printf ("Sorting: %s\n\n", cai->sortByCompany ? "By company" : "By name");
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
error:
|
||
|
pi_buffer_free(appblock);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
print_records (int sd, int db, struct ContactAppInfo *cai)
|
||
|
{
|
||
|
char *l;
|
||
|
struct Contact c;
|
||
|
int i, idx, attr, category;
|
||
|
recordid_t recid;
|
||
|
pi_buffer_t *buf;
|
||
|
|
||
|
buf = pi_buffer_new (0xffff);
|
||
|
|
||
|
for (idx = 0; /**/; idx++) {
|
||
|
if (dlp_ReadRecordByIndex (sd, db, idx, buf,
|
||
|
&recid, &attr, &category) < 0)
|
||
|
break;
|
||
|
|
||
|
printf ("\nRecord 0x%04x\n", (unsigned int)recid);
|
||
|
printf (" Category : %i\n", category);
|
||
|
printf (" Attributes : %c%c%c%c%c\n",
|
||
|
attr & dlpRecAttrDeleted ? 'X' : '-',
|
||
|
attr & dlpRecAttrArchived ? 'A' : '-',
|
||
|
attr & dlpRecAttrSecret ? 'S' : '-',
|
||
|
attr & dlpRecAttrBusy ? 'B' : '-',
|
||
|
attr & dlpRecAttrDirty ? 'd' : '-');
|
||
|
printf (" Length : %zu\n", buf->used);
|
||
|
|
||
|
if (buf->used == 0)
|
||
|
/* Empty records are legal */
|
||
|
continue;
|
||
|
|
||
|
if (unpack_Contact (&c, buf, cai->type) < 0) {
|
||
|
printf (" [Broken record]\n");
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
#if PRINT_USELESS_INFO
|
||
|
printf (" Phone labels: { %i, %i, %i, %i, %i, %i, %i }"
|
||
|
" (showing [%i])\n",
|
||
|
c.phoneLabel[0],
|
||
|
c.phoneLabel[1],
|
||
|
c.phoneLabel[2],
|
||
|
c.phoneLabel[3],
|
||
|
c.phoneLabel[4],
|
||
|
c.phoneLabel[5],
|
||
|
c.phoneLabel[6],
|
||
|
c.showPhone);
|
||
|
printf (" Address labels: { %i, %i, %i }\n",
|
||
|
c.addressLabel[0],
|
||
|
c.addressLabel[1],
|
||
|
c.addressLabel[2]);
|
||
|
printf (" IM labels: { %i, %i }\n",
|
||
|
c.IMLabel[0],
|
||
|
c.IMLabel[1]);
|
||
|
#endif /* PRINT_USELESS_INFO */
|
||
|
|
||
|
for (i = 0; i < NUM_CONTACT_ENTRIES; i++) {
|
||
|
if (c.entry[i] != NULL) {
|
||
|
/* Special cases are annoying.. */
|
||
|
if (i > 3 && i < 11)
|
||
|
l = contacts_phones[c.phoneLabel[i - 4]];
|
||
|
else if (i == 11 || i == 12)
|
||
|
l = contacts_ims[c.IMLabel[i - 11]];
|
||
|
else if (i == 23)
|
||
|
l = contacts_addrs[c.addressLabel[0]];
|
||
|
else if (i == 28)
|
||
|
l = contacts_addrs[c.addressLabel[1]];
|
||
|
else if (i == 33)
|
||
|
l = contacts_addrs[c.addressLabel[2]];
|
||
|
else
|
||
|
l = contacts_fields[i];
|
||
|
|
||
|
printf (" %-15s: %s\n", l, c.entry[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (c.birthdayFlag) {
|
||
|
printf (" Birthday : %i-%02i-%02i",
|
||
|
c.birthday.tm_year + 1900,
|
||
|
c.birthday.tm_mon + 1,
|
||
|
c.birthday.tm_mday);
|
||
|
|
||
|
if (c.reminder)
|
||
|
printf (" (%i day reminder)", c.advance);
|
||
|
puts ("");
|
||
|
}
|
||
|
|
||
|
if (c.picture != NULL) {
|
||
|
#ifdef SAVE_PICTURES
|
||
|
char fname[25];
|
||
|
FILE *f;
|
||
|
|
||
|
snprintf (fname, 24, "rec-%lu.jpeg",
|
||
|
(uint32_t)recid);
|
||
|
printf (" Picture : %s\n", fname);
|
||
|
f = fopen (fname, "wb");
|
||
|
if (f) {
|
||
|
fwrite (c.picture->data, c.picture->length, 1, f);
|
||
|
fclose (f);
|
||
|
}
|
||
|
#else
|
||
|
printf (" Picture : JPEG (%zu bytes)\n",
|
||
|
c.picture->length);
|
||
|
#endif /* SAVE_PICTURES */
|
||
|
}
|
||
|
|
||
|
free_Contact (&c);
|
||
|
}
|
||
|
pi_buffer_free (buf);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
main (const int argc, const char **argv)
|
||
|
{
|
||
|
int sd = -1;
|
||
|
int db;
|
||
|
struct ContactAppInfo cai;
|
||
|
|
||
|
if (argc != 2)
|
||
|
{
|
||
|
fprintf (stderr, "Usage: contactsdb-test <port>\n");
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
sd = pilot_connect (argv[1]);
|
||
|
|
||
|
if (sd < 0)
|
||
|
goto error;
|
||
|
|
||
|
if (dlp_OpenConduit (sd) < 0)
|
||
|
goto error;
|
||
|
|
||
|
if (dlp_OpenDB(sd, 0, dlpOpenRead, "ContactsDB-PAdd", &db) < 0)
|
||
|
{
|
||
|
fprintf (stderr, "Unable to open Contacts database\n");
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
if (print_appblock (sd, db, &cai) < 0) {
|
||
|
fprintf (stderr, "Failed read/print appblock\n");
|
||
|
goto error;
|
||
|
} else {
|
||
|
print_records (sd, db, &cai);
|
||
|
}
|
||
|
free_ContactAppInfo (&cai);
|
||
|
|
||
|
dlp_CloseDB(sd, db);
|
||
|
dlp_EndOfSync (sd, 0);
|
||
|
pi_close (sd);
|
||
|
|
||
|
error:
|
||
|
if (sd != -1)
|
||
|
pi_close (sd);
|
||
|
return 1;
|
||
|
}
|