home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
back2roots/padua
/
padua.7z
/
padua
/
ftp.vapor.com
/
microdot-1
/
md1_src_02.lzx
/
mail.c
< prev
next >
Wrap
C/C++ Source or Header
|
2014-05-19
|
15KB
|
725 lines
/* MicroDot-MsgBase-System */
#define RBSIZE MAILBFSIZE
#include "microdot.h"
#include "asyncio.h"
struct ixcache
{
struct MinNode n;
ULONG puffID;
BPTR ixfile;
struct AsyncFile *datafile;
};
static struct MinList ixlist;
static void *ixcachepool;
void ixc_flush( void )
{
struct ixcache *ixc;
while( ( ixc = ( struct ixcache * ) RemHead( ( struct List * ) &ixlist ) ) )
{
if( ixc->ixfile )
Close( ixc->ixfile );
if( ixc->datafile )
CloseAsync( ixc->datafile );
LibFreePooled( ixcachepool, ixc, sizeof( *ixc ) );
}
}
void ixc_init( void )
{
ixcachepool = LibCreatePool( MEMF_CLEAR, sizeof( struct ixcache ) * 10, sizeof( struct ixcache ) * 5 );
NewList( ( struct List * ) &ixlist );
}
void ixc_exit( void )
{
ixc_flush();
LibDeletePool( ixcachepool );
}
static struct ixcache *getixc( ULONG pID )
{
struct ixcache *ixc = ( struct ixcache * ) ixlist.mlh_Head;
// Printf( "getixc %ld\n", pID );
while( ixc->n.mln_Succ )
{
if( ixc->puffID == pID )
{
// Printf("getixc: found\n" );
return( ixc );
}
ixc = ( struct ixcache * ) ixc->n.mln_Succ;
}
// Printf("getixc: numentries %ld\n",GetNumEntries( ( struct List * ) &ixlist ) );
if( GetNumEntries( ( struct List * ) &ixlist ) > 10 || AvailMem( MEMF_LARGEST | MEMF_FAST ) < (256*1024) )
ixc_flush();
ixc = LibAllocPooled( ixcachepool, sizeof( *ixc ) );
ixc->puffID = pID;
AddTail( ( struct List * ) &ixlist, ( struct Node * ) ixc );
return( ixc );
}
static BPTR ixc_getix( ULONG pID )
{
struct ixcache *ixc = getixc( pID );
char buf[á128 ];
if( !ixc->ixfile )
{
sprintf( buf, "%sMD_%lx.Index", prefs.datadir, pID );
ixc->ixfile = Open( buf, MODE_OLDFILE );
}
return( ixc->ixfile );
}
static struct AsyncFile *ixc_getdata( ULONG pID )
{
struct ixcache *ixc = getixc( pID );
char buf[á128 ];
if( !ixc->datafile )
{
sprintf( buf, "%sMD_%lx.Data", prefs.datadir, pID );
ixc->datafile = OpenAsync( buf, MODE_READ, 8192 );
}
return( ixc->datafile );
}
struct msghandle *msg_open( ULONG pufID, ULONG mID )
{
BPTR ixfile;
struct msghandle *new;
char buf[á256 ];
int rc;
ixfile = ixc_getix( pufID );
if( !ixfile )
{
sprintf( buf, "%sMD_%lx.Data", prefs.datadir, pufID );
askreq( "Fehler beim Datenbankzugriff auf Nachricht %ld:%ld\nDatei %s lΣ▀t sich nicht ÷ffnen!", "Abbruch",
pufID, mID, buf
);
return( NULL );
}
rc = Seek( ixfile, mID * sizeof( struct pindex ), OFFSET_BEGINNING );
if( rc < 0 )
{
askreq( "Fehler (%ld) beim Datenbankzugriff auf Nachricht %ld:%ld\nIndexeintrag fehlend oder fehlerhaft.", "Abbruch",
IoErr(), pufID, mID
);
return( NULL );
}
new = LibAllocPooled( miscmempool, sizeof( *new ) );
if( !new )
{
return( NULL );
}
Read( ixfile, &new->pix, sizeof( struct pindex ) );
new->file = ixc_getdata( pufID );
// Printf( "pix.offset %ld, realoffset %ld\n", new->pix.offset, FtellAsync( new->file ) );
if( !new->file )
{
askreq( "Fehler beim Datenbankzugriff auf Nachricht %ld:%ld\nDatei %s lΣ▀t sich nicht ÷ffnen!", "Abbruch",
pufID, mID, buf
);
return( NULL );
}
return( new );
}
void msg_close( struct msghandle *msg )
{
if( msg )
{
LibFreePooled( miscmempool, msg, sizeof( *msg ) );
/*if( msg->file )
CloseAsync( msg->file );*/
}
}
static int copyfh( struct AsyncFile *from, BPTR to, int bytes, int packed )
{
void *bufmem;
int rc;
struct pfhandle *pfh;
int bs;
if( bytes < 1 )
return( 0 );
pfh = pf_open( from, FALSE, packed, &bytes );
bufmem = allocbuffmem( bytes, &bs );
while( bytes )
{
rc = pf_read( pfh, bufmem, min( bs, bytes ) );
if( rc )
Write( to, bufmem, rc );
bytes -= rc;
}
pf_close( pfh );
freebuffmem();
return( 0 );
}
int copyfh2p( struct AsyncFile *from, FILE *to, int bytes, int packed )
{
void *bufmem;
int rc;
struct pfhandle *pfh;
int bs;
if( bytes < 1 )
return( 0 );
pfh = pf_open( from, FALSE, packed, &bytes );
bufmem = allocbuffmem( bytes, &bs );
while( bytes )
{
rc = pf_read( pfh, bufmem, min( bs, bytes ) );
if( rc )
fwrite( bufmem, rc, 1, to );
bytes -= rc;
}
pf_close( pfh );
freebuffmem();
return( 0 );
}
/* Nachricht rauskopieren */
int msg_copyfh( struct msghandle *msg, BPTR tofile, ULONG flags )
{
if( !msg || !msg->file )
return( -1 );
if( flags & MC_HEADER )
{
SeekAsync( msg->file, msg->pix.offset, OFFSET_BEGINNING );
copyfh( msg->file, tofile, msg->pix.headersize, msg->pix.flags & ( PIF_PACKED | PIF_XPK ) );
}
if( msg->pix.commentsize )
{
if( flags & MC_COMMENT )
{
SeekAsync( msg->file, msg->pix.offset + msg->pix.headersize, OFFSET_BEGINNING );
copyfh( msg->file, tofile, msg->pix.commentsize, msg->pix.flags & ( PIF_PACKED | PIF_XPK ) );
}
}
if( msg->pix.datasize )
{
if( flags & MC_DATA )
{
SeekAsync( msg->file, msg->pix.offset + msg->pix.headersize + msg->pix.commentsize, OFFSET_BEGINNING );
copyfh( msg->file, tofile, msg->pix.datasize, msg->pix.flags & ( PIF_PACKED | PIF_XPK ) );
}
}
return( 0 );
}
int msg_copyfp( struct msghandle *msg, FILE *tofile, ULONG flags )
{
if( !msg || !msg->file )
return( -1 );
if( flags & MC_HEADER )
{
SeekAsync( msg->file, msg->pix.offset, OFFSET_BEGINNING );
copyfh2p( msg->file, tofile, msg->pix.headersize, msg->pix.flags & ( PIF_PACKED | PIF_XPK ) );
}
if( msg->pix.commentsize )
{
if( flags & MC_COMMENT )
{
SeekAsync( msg->file, msg->pix.offset + msg->pix.headersize, OFFSET_BEGINNING );
copyfh2p( msg->file, tofile, msg->pix.commentsize, msg->pix.flags & ( PIF_PACKED | PIF_XPK ) );
}
}
if( msg->pix.datasize )
{
if( flags & MC_DATA )
{
SeekAsync( msg->file, msg->pix.offset + msg->pix.headersize + msg->pix.commentsize, OFFSET_BEGINNING );
copyfh2p( msg->file, tofile, msg->pix.datasize, msg->pix.flags & ( PIF_PACKED | PIF_XPK ) );
}
}
return( 0 );
}
int msg_copy( struct msghandle *msg, char *to, ULONG flags )
{
BPTR tofile;
int rc;
tofile = Open( to, MODE_NEWFILE );
if( !tofile )
return( -1 );
rc = msg_copyfh( msg, tofile, flags );
Close( tofile );
return( rc );
}
/* Header einer Nachricht laden */
struct hlist *msg_loadheader( struct msghandle *msg )
{
char *buffer, *bp;
struct hlist *hlist;
struct pfhandle *pfh;
int len = msg->pix.headersize;
char *p, *p2;
if( SeekAsync( msg->file, msg->pix.offset, MODE_START ) < 0 )
{
return( NULL );
}
pfh = pf_open( msg->file, FALSE, msg->pix.flags & ( PIF_PACKED | PIF_XPK ), &len );
bp = buffer = myAllocVec( len + 1, MEMF_CLEAR );
if( !buffer )
{
pf_close( pfh );
return( NULL );
}
pf_read( pfh, buffer, len );
pf_close( pfh );
hlist = hl_initheader();
while( ( p = strchr( buffer, '\n'á) ) )
{
*p++ = 0;
p2 = strchr( buffer, ':' );
if( !p2 )
break;
else
*p2++ = 0;
hl_addheader( hlist, buffer, stpblk( p2 ) );
buffer = p;
}
myFreeVec( bp );
return( hlist );
}
int msg_initread( struct msghandle *msg, int readwhat )
{
switch( readwhat )
{
case MC_HEADER:
msg->readmode = 1;
msg->readremain = msg->pix.headersize;
if( !msg->readremain )
return( 0 );
SeekAsync( msg->file, msg->pix.offset, MODE_START );
break;
case MC_COMMENT:
msg->readmode = 1;
msg->readremain = msg->pix.commentsize;
if( !msg->readremain )
return( 0 );
SeekAsync( msg->file, msg->pix.offset + msg->pix.headersize, MODE_START );
break;
case MC_DATA:
msg->readmode = 1;
msg->readremain = msg->pix.datasize;
if( !msg->readremain )
return( 0 );
SeekAsync( msg->file, msg->pix.offset + msg->pix.headersize + msg->pix.commentsize, MODE_START );
break;
default: /* tja... */
return( -1 );
}
msg->pfh = pf_open( msg->file, FALSE, msg->pix.flags & ( PIF_PACKED | PIF_XPK ), ( int * ) &msg->readremain );
return( 0 );
}
void msg_endread( struct msghandle *msg )
{
msg->readmode = msg->readremain = 0;
if( msg->pfh )
{
pf_close( msg->pfh );
msg->pfh = NULL;
}
}
/* Nachricht zeilenweise lesen; null bei ende/fehler */
int msg_read( struct msghandle *msg, UBYTE *buffer, int size )
{
int count = 0;
int ch;
if( !msg->readmode || !msg->readremain )
return( 0 );
while( size-- )
{
ch = pf_readch( msg->pfh );
if( ch < 0 )
break;
if( ch == 13 )
continue;
if( ch == 10 )
break;
buffer[ácount++ ]á= ch;
}
buffer[ count ] = 0;
return( ( ch == 10 ) ? 1 : ( count ? 2 : 0 ) );
}
/* Nummer des Userpuffers zurⁿckgeben */
static ULONG getmypuffer( void )
{
ULONG c = ~0;
char buff[á64 ];
int pl;
pushdir( prefs.datadir );
while( c )
{
sprintf( buff, "MD_%lx.Data", c );
pl = getfilelen( buff );
if( pl < 256000 )
break;
c--;
}
popdir();
return( c );
}
static int copypack( BPTR fromfile, struct AsyncFile *tofile, int size )
{
struct pfhandle *pfh = pf_open( tofile, TRUE, prefs.do_packmsg, 0 );
char buffer[á2048 ];
int rc;
while( size )
{
rc = Read( fromfile, buffer, min( size, 2048 ) );
if( rc )
pf_write( pfh, buffer, rc );
size -= rc;
}
return( pf_close( pfh ) );
}
static int copymempack( struct AsyncFile *tofile, UBYTE *data, int size )
{
struct pfhandle *pfh = pf_open( tofile, TRUE, prefs.do_packmsg, 0 );
pf_write( pfh, data, size );
return( pf_close( pfh ) );
}
ULONG msg_getsize( struct msghandle *msg, int what )
{
ULONG size = 0;
if( ! ( msg->pix.flags & ( PIF_PACKED ) ) )
{
switch( what )
{
case MC_HEADER:
return( msg->pix.headersize );
case MC_COMMENT:
return( msg->pix.commentsize );
case MC_DATA:
return( msg->pix.datasize );
}
}
else switch( what )
{
case MC_HEADER:
if( msg->pix.headersize )
{
SeekAsync( msg->file, msg->pix.offset, MODE_START );
ReadAsync( msg->file, &size, 4 );
}
break;
case MC_COMMENT:
if( msg->pix.commentsize )
{
SeekAsync( msg->file, msg->pix.offset + msg->pix.headersize, MODE_START );
ReadAsync( msg->file, &size, 4 );
}
break;
case MC_DATA:
if( msg->pix.datasize )
{
SeekAsync( msg->file, msg->pix.offset + msg->pix.headersize + msg->pix.commentsize, MODE_START );
ReadAsync( msg->file, &size, 4 );
}
break;
}
return( size );
}
/* Nachricht speichern; header in header... */
struct pindex *msg_store( char *comment, LONG commentsize,
char *data, LONG datasize,
ULONG *pID, ULONG *mID, struct hlist *hlist )
{
BPTR commentfile = NULL, datafile = NULL;
BPTR ixfile;
struct AsyncFile *outfile;
static struct pindex pix;
ULONG p;
int c;
char buff[á128 ];
ixc_flush();
memset( &pix, 0, sizeof( pix ) );
if( prefs.do_packmsg )
pix.flags |= PIF_PACKED;
if( prefs.do_packmsg >= PACKMODE_XPK )
pix.flags |= PIF_XPK;
/* Comment ist Datei */
if( commentsize < 0 )
{
commentsize = getfilelen( comment );
commentfile = Open( comment, MODE_OLDFILE );
if( !commentfile )
{
if( commentsize > 0 )
return( NULL );
commentsize = 0;
}
}
/* Data ist Datei */
if( datasize < 0 )
{
datasize = getfilelen( data );
datafile = Open( data, MODE_OLDFILE );
if( !datafile )
{
if( datasize > 0 )
return( NULL );
datasize = 0;
}
}
/* Gut... */
p = getmypuffer();
sprintf( buff, "%sMD_%lx.Data", prefs.datadir, p );
c = getfilelen( buff );
if( c < 0 )
c = 0;
outfile = OpenAsync( buff, MODE_APPEND, 32768 );
if( !outfile )
return( NULL );
// WriteAsync( outfile, "Test0\n", 6 );
*pID = p;
pix.offset = c;
pix.headersize = hl_dumpheaderpf( hlist, outfile );
// WriteAsync( outfile, "Test1\n", 6 );
if( commentsize )
{
if( commentfile )
pix.commentsize = copypack( commentfile, outfile, commentsize );
else
pix.commentsize = copymempack( outfile, comment, commentsize );
}
// WriteAsync( outfile, "Test2\n", 6 );
if( datasize )
{
if( datafile )
pix.datasize = copypack( datafile, outfile, datasize );
else
pix.datasize = copymempack( outfile, data, datasize );
}
// WriteAsync( outfile, "Test3\n", 6 );
CloseAsync( outfile );
if( datafile )
Close( datafile );
if( commentfile )
Close( commentfile );
/* Index schreiben */
sprintf( buff, "%sMD_%lx.Index", prefs.datadir, p );
ixfile = OpenAppend( buff );
if( !ixfile )
return( NULL );
*mID = Seek( ixfile, 0, OFFSET_CURRENT ) / sizeof( pix );
Write( ixfile, &pix, sizeof( pix ) );
Close( ixfile );
/* Alles k.o. */
return( &pix );
}
/* Nachricht ersetzen (!) */
struct pindex *msg_replace( char *comment, LONG commentsize,
char *data, LONG datasize,
ULONG pID, ULONG mID, struct hlist *hlist )
{
BPTR commentfile = NULL, datafile = NULL;
BPTR ixfile;
struct AsyncFile *outfile;
static struct pindex pix;
char buff[á128 ];
ixc_flush();
memset( &pix, 0, sizeof( pix ) );
if( prefs.do_packmsg )
pix.flags |= PIF_PACKED;
if( prefs.do_packmsg >= PACKMODE_XPK )
pix.flags |= PIF_XPK;
/* Comment ist Datei */
if( commentsize < 0 )
{
commentsize = getfilelen( comment );
commentfile = Open( comment, MODE_OLDFILE );
if( !commentfile )
{
if( commentsize > 0 )
return( NULL );
commentsize = 0;
}
}
/* Data ist Datei */
if( datasize < 0 )
{
datasize = getfilelen( data );
datafile = Open( data, MODE_OLDFILE );
if( !datafile )
{
if( datasize > 0 )
return( NULL );
datasize = 0;
}
}
/* Gut... */
sprintf( buff, "%sMD_%lx.Data", prefs.datadir, pID );
outfile = OpenAsync( buff, MODE_APPEND, 32768 );
if( !outfile )
return( NULL );
pix.offset = FtellAsync( outfile );
pix.headersize = hl_dumpheaderpf( hlist, outfile );
if( commentsize )
{
if( commentfile )
pix.commentsize = copypack( commentfile, outfile, commentsize );
else
pix.commentsize = copymempack( outfile, comment, commentsize );
}
if( datasize )
{
if( datafile )
pix.datasize = copypack( datafile, outfile, datasize );
else
pix.datasize = copymempack( outfile, data, datasize );
}
CloseAsync( outfile );
if( datafile )
Close( datafile );
if( commentfile )
Close( commentfile );
/* Index schreiben */
sprintf( buff, "%sMD_%lx.Index", prefs.datadir, pID );
ixfile = OpenAppend( buff );
if( !outfile )
return( NULL );
Seek( ixfile, sizeof( pix ) * mID, OFFSET_BEGINNING );
Write( ixfile, &pix, sizeof( pix ) );
Close( ixfile );
/* Alles k.o. */
return( &pix );
}
/*
Format gecrunchter Daten:
ULONG decrunchlen Entpackte LΣnge des gesammten Parts
dann ein oder mehrere
UWORD chunksize Gepackte Gr÷▀e dieses Chunks; 0 = Ende
UWORD chunkreal Entpackte Gr÷▀e dieses Chunks; 0 = ungepackt
UBYTE data[ xxx ] Gepackte Daten
*/