ic35link/src/dataio.c

429 lines
11 KiB
C

/************************************************************************
* Copyright (C) 2000 Thomas Schulz *
* */
static char rcsid[] =
"$Id: dataio.c,v 1.33 2001/03/02 02:09:59 tsch Rel $"; /*
* *
* IC35 synchronize data import/export *
* *
*************************************************************************
* *
* ??? is "fixme" mark: sections of code needing fixes *
* *
* backup_and_openwr backup and open output file for write *
* revised date+time on IC35 *
* clr_newic35dt clear new IC35 revised to get it fresh *
* get_newic35dt new revised date+time to IC35 string *
* set_oldic35dt IC35 string to old revised date+time *
* *
* PIM format
* pimfmt2bin local: PIM format text to binary
* set_pim_format set PIM format
* pim_format report current PIM format
* pimop[] functions table of format-specific ops
* PIM file access
* pim_open open PIMfile(s) and read if present
* pim_openinp open PIMfile(s) for input and read
* pim_openout note PIMfile(s) for output
* pim_close close and flush to PIMfile(s)
* PIM record operations
* pim_rewind rewind PIM record list
* pim_getrec get next PIM record for fileid
* pim_getrec_byID get PIM record by rec-ID (and fileid)
* pim_updic35rec update IC35 record with PIM record
* pim_cmpic35rec compare IC35 record with PIM record
* pim_putic35rec put IC35 record to (new) PIM record
* pim_putrec output (new) PIM record
* pim_delrec delete PIM record
* PIM record IC35-recID and status
* pim_recid report IC35 record-ID from PIM record
* pim_set_recid set IC35 record-ID to PIM record
* pim_recstat report PIM record changeflag
* pim_set_recstat set PIM record changeflag
* *
************************************************************************/
#include <stdio.h> /* fprintf(), .. */
#include <string.h> /* strcpy(), .. */
#include <ctype.h> /* isprint(), .. */
#include <unistd.h> /* access() */
#include <sys/types.h> /* size_t, .. */
#include <time.h> /* struct tm, time() .. */
#include "vcc.h" /* VObject, .. */
#include "util.h" /* ERR, uchar, .. */
#include "ic35frec.h" /* IC35 record fields.. */
#include "dataio.h"
NOTUSED(rcsid);
/* backup and open output file for write
* -------------------------------------
*/
FILE *
backup_and_openwr( char * fname )
{
char * bkpfname;
FILE * fp;
if ( !( fname && *fname ) )
return NULL;
if ( strcmp( fname, "-" ) == 0 )
return stdout;
if ( (bkpfname = malloc( strlen( fname ) + 2 )) != NULL ) {
strcat( strcpy( bkpfname, fname ), "~" );
remove( bkpfname );
rename( fname, bkpfname );
free( bkpfname );
}
if ( (fp = fopen( fname, "w" )) == NULL )
error( "cannot open outfile: %s", fname );
return fp;
}
/* ============================================ */
/* revised date+time on IC35 */
/* ============================================ */
/*
* IC35 does not maintain last modified date+time per record
* instead there is a command to write date+time to IC35,
* which is used for synchronization.
* this timestamp is also used for "last modified" VObject property
*/
/* revised date+time for vCard,vCal records
* ----------------------------------------
*/
static time_t _new_ic35dtime; /* to vCard,vCal records and IC35 */
void
clr_newic35dt( void )
{
_new_ic35dtime = 0;
}
time_t
newic35dt( void )
{
if ( _new_ic35dtime == 0 )
_new_ic35dtime = time( NULL );
return _new_ic35dtime;
}
/* new revised date+time to string for IC35
* ----------------------------------------
*/
void
get_newic35dt( char * dtbuf )
{
time_t ic35dt;
struct tm * ptm;
ic35dt = newic35dt();
ptm = localtime( &ic35dt );
strftime( dtbuf, 2+2+4+2+2+2+1, "%m%d%Y%H%M%S", ptm );
}
/* string from IC35 to old revised date+time
* -----------------------------------------
* the ugly format [mmddyyyyhhmmss] (instead of pretty [yyyymmddhhmmss])
* is used for reasons of compatibility with IC35sync/Windows.
* if sysinfo string from IC35 lacks plausible year,month,day, assume
* sysinfo was never written to IC35 and use old reference date+time
* far in the past.
*/
static time_t _old_ic35dtime; /* from IC35, reference for vCard */
void
set_oldic35dt( char * dtime )
{
struct tm ic35tm;
if ( dtime == NULL )
return;
memset( &ic35tm, 0, sizeof(ic35tm) );
sscanf( dtime, "%2d%2d%4d%2d%2d%2d",
&ic35tm.tm_mon, &ic35tm.tm_mday, &ic35tm.tm_year,
&ic35tm.tm_hour, &ic35tm.tm_min, &ic35tm.tm_sec );
if ( 1970 <= ic35tm.tm_year
&& 1 <= ic35tm.tm_mon && ic35tm.tm_mon <= 12
&& 1 <= ic35tm.tm_mday && ic35tm.tm_mday <= 31 ) {
ic35tm.tm_year -= 1900;
ic35tm.tm_mon -= 1;
ic35tm.tm_isdst = -1;
_old_ic35dtime = mktime( &ic35tm );
} else
_old_ic35dtime = 1;
}
time_t
oldic35dt( void )
{
return _old_ic35dtime;
}
/* ============================================ */
/* generic PIM access */
/* ============================================ */
/* set, get format of input/output file(s)
* ---------------------------------------
*/
static int pimfmt;
static int inpfmt;
static int
pimfmt2bin( char * format )
{
if ( format ) {
if ( strcmp( format, "txt" ) == 0 ) return PIM_TXT;
else if ( strcmp( format, "bin" ) == 0 ) return PIM_BIN;
else if ( strcmp( format, "vca" ) == 0 ) return PIM_VCA;
}
return 0;
}
int
set_pim_format( char * format )
{
int newfmt;
if ( (newfmt = pimfmt2bin( format )) <= 0 )
return ERR; /* unknown format */
pimfmt = inpfmt = newfmt;
return OK;
}
int
pim_format( void )
{
return pimfmt;
}
/*
* pim_open()
* pim_close()
* pim_rewind()
*
* pim_getrec( int fileid ) -> void* / NULL
* pim_getrec_byID( ulong recid ) -> void* / NULL
* pim_cmpic35rec( IC35REC*, void* ) -> 0:same 1:differ
* pim_putic35rec( IC35REC* ) IC35REC to PIMrec
* pim_updic35rec( IC35REC*, void* ) PIMrec to IC35REC
* pim_delrec( void* )
*
* pim_recid( void* )
* pim_set_recid( void*, ulong )
* pim_recstat( void* )
* pim_set_recstat( void*, int )
*/
/* dummy null operations
* ---------------------
*/
static struct pim_oper nul_oper = {
NULL, /* NO open */
NULL, /* NO close */
NULL, /* NO rewind */
NULL, /* NO getrec */
NULL, /* NO getrec_byID */
NULL, /* NO cmpic35rec */
NULL, /* NO updic35rec */
NULL, /* NO putic35rec */
NULL, /* NO delrec */
NULL, /* NO recid */
NULL, /* NO set_recid */
NULL, /* NO recstat */
NULL, /* NO set_recstat */
};
/* table of supported PIM-formats
* ------------------------------
*/
extern struct pim_oper txt_oper; /* text output IC35 record */
extern struct pim_oper bin_oper; /* binary IC35 record format */
extern struct pim_oper vca_oper; /* vCard,vCalendar format */
static struct pim_oper *pimop[] = {
&nul_oper,
&txt_oper,
&bin_oper,
&vca_oper
};
/* open, close, rewind output file(s)
* ----------------------------------
*/
int
pim_open( char * addrfname, char * vcalfname, char * memofname )
{
LPRINTF(( L_INFO, "pim_open(%s,%s,%s) pimfmt=%d (%s)",
addrfname ? addrfname : "NULL",
vcalfname ? vcalfname : "NULL",
memofname ? memofname : "NULL",
pimfmt, pimfmt == PIM_TXT ? "txt" :
pimfmt == PIM_BIN ? "bin" :
pimfmt == PIM_VCA ? "vca" : "unknown" ));
/*??? check file(s) creatable in dirname(a_xxxxfname) ???*/
if ( pimop[pimfmt]->open )
return (*pimop[pimfmt]->open)( "r+", addrfname, vcalfname, memofname );
return ERR;
}
int
pim_openinp( char * format, char * fname )
{
int ifmt;
if ( (ifmt = pimfmt2bin( format )) <= 0
|| pimop[ifmt]->open == NULL )
return ERR;
inpfmt = ifmt;
return (*pimop[inpfmt]->open)( "r", fname, NULL, NULL );
}
int
pim_openout( char * format, char * fname )
{
int ofmt;
if ( (ofmt = pimfmt2bin( format )) <= 0
|| pimop[ofmt]->open == NULL
|| !( fname && *fname ) )
return ERR;
pimfmt = ofmt;
/*??? check file creatable in dirname(fname) ???*/
remove( fname );
return (*pimop[pimfmt]->open)( "w", fname, NULL, NULL );
}
void
pim_close( void )
{
LPRINTF(( L_INFO, "pim_close: pimfmt=%d (%s) inpfmt=%d (%s)",
pimfmt, pimfmt == PIM_TXT ? "txt" :
pimfmt == PIM_BIN ? "bin" :
pimfmt == PIM_VCA ? "vca" : "unknown",
inpfmt, inpfmt == PIM_TXT ? "txt" :
inpfmt == PIM_BIN ? "bin" :
inpfmt == PIM_VCA ? "vca" : "unknown" ));
if ( pimop[pimfmt]->close ) /* write output file and .. */
(*pimop[pimfmt]->close)(); /* release output record list */
if ( inpfmt != pimfmt /* input format is different .. */
&& *pimop[inpfmt]->close ) /* release input record list */
(*pimop[inpfmt]->close)();
}
void
pim_rewind( void )
{
if ( pimop[inpfmt]->rewind )
(*pimop[inpfmt]->rewind)();
}
/* get next PIM-record for fileid
* ------------------------------
*/
void *
pim_getrec( int fileid )
{
if ( pimop[inpfmt]->getrec )
return (*pimop[inpfmt]->getrec)( fileid );
return NULL;
}
/* get PIM-record by rec-ID for fileid
* -----------------------------------
*/
void *
pim_getrec_byID( ulong recid )
{
if ( pimop[inpfmt]->getrec_byID )
return (*pimop[inpfmt]->getrec_byID)( recid );
return NULL;
}
/* update IC35 record with PIM record
* ----------------------------------
*/
IC35REC *
pim_updic35rec( IC35REC * ic35rec, void * pimrec )
{
if ( pimop[inpfmt]->updic35rec )
return (*pimop[inpfmt]->updic35rec)( ic35rec, pimrec );
return NULL;
}
/* compare IC35 record with vCard,vCal record
* ------------------------------------------
*/
int
pim_cmpic35rec( IC35REC * ic35rec, void * pimrec )
{
if ( pimop[pimfmt]->cmpic35rec )
return (*pimop[pimfmt]->cmpic35rec)( ic35rec, pimrec );
return -1;
}
/* put IC35-record to (new) PIM-record
* -----------------------------------
*/
void *
pim_putic35rec( IC35REC * ic35rec )
{
if ( pimop[pimfmt]->putic35rec )
return (*pimop[pimfmt]->putic35rec)( ic35rec );
return NULL;
}
void
pim_putrec( void * pimrec )
{
IC35REC * ic35rec;
if ( pimop[inpfmt]->updic35rec != NULL
&& pimop[pimfmt]->putic35rec != NULL
&& (ic35rec = new_ic35rec()) != NULL ) {
(*pimop[inpfmt]->updic35rec)( ic35rec, pimrec );
(*pimop[pimfmt]->putic35rec)( ic35rec );
del_ic35rec( ic35rec );
}
}
/* delete PIM-record
* -----------------
*/
void
pim_delrec( void * pimrec )
{
if ( pimop[pimfmt]->delrec )
(*pimop[pimfmt]->delrec)( pimrec );
}
/* get,set IC35-record-ID
* ----------------------
*/
ulong
pim_recid( void * pimrec )
{
if ( pimop[pimfmt]->recid )
return (*pimop[pimfmt]->recid)( pimrec );
return 0;
}
void
pim_set_recid( void * pimrec, ulong recid )
{
if ( pimop[pimfmt]->set_recid )
(*pimop[pimfmt]->set_recid)( pimrec, recid );
}
/* get,set record-changeflag
* -------------------------
*/
int
pim_recstat( void * pimrec )
{
if ( pimop[pimfmt]->recstat )
return (*pimop[pimfmt]->recstat)( pimrec );
return PIM_DIRTY;
}
void
pim_set_recstat( void * pimrec, int stat )
{
if ( pimop[pimfmt]->set_recstat )
(*pimop[pimfmt]->set_recstat)( pimrec, stat );
}