4afa1432ff
* src/account.c * src/account.h * src/action.c * src/action.h * src/adbookbase.h * src/addr_compl.c * src/addr_compl.h * src/addrbook.c * src/addrcache.c * src/addrcache.h * src/addrcindex.c * src/addrcindex.h * src/addrclip.c * src/addrclip.h * src/addrdefs.h * src/addressadd.c * src/addressadd.h * src/addressbook.c * src/addressbook.h * src/addrgather.c * src/addrgather.h * src/addrharvest.c * src/addrharvest.h * src/addrindex.c * src/addrindex.h * src/addritem.c * src/addritem.h * src/addrquery.c * src/addrquery.h * src/addrselect.c * src/addrselect.h * src/alertpanel.c * src/alertpanel.h * src/browseldap.c * src/browseldap.h * src/codeconv.c * src/codeconv.h * src/compose.c * src/compose.h * src/customheader.c * src/customheader.h * src/displayheader.c * src/displayheader.h * src/editaddress.c * src/editaddress.h * src/editbook.c * src/editbook.h * src/editgroup.c * src/editgroup.h * src/editjpilot.c * src/editjpilot.h * src/editldap.c * src/editldap.h * src/editldap_basedn.c * src/editldap_basedn.h * src/editvcard.c * src/editvcard.h * src/exphtmldlg.c * src/exphtmldlg.h * src/expldifdlg.c * src/expldifdlg.h * src/export.h * src/exporthtml.c * src/exporthtml.h * src/exportldif.c * src/exportldif.h * src/filtering.c * src/filtering.h * src/folder.c * src/folder.h * src/folder_item_prefs.c * src/folder_item_prefs.h * src/foldersel.c * src/foldersel.h * src/folderutils.c * src/folderutils.h * src/folderview.c * src/folderview.h * src/grouplistdialog.c * src/grouplistdialog.h * src/headerview.c * src/html.c * src/html.h * src/image_viewer.c * src/image_viewer.h * src/imap.c * src/imap.h * src/imap_gtk.c * src/imap_gtk.h * src/import.h * src/importldif.c * src/importldif.h * src/importmutt.c * src/importmutt.h * src/importpine.c * src/importpine.h * src/inc.c * src/inc.h * src/jpilot.c * src/jpilot.h * src/ldapctrl.c * src/ldapctrl.h * src/ldaplocate.c * src/ldaplocate.h * src/ldapquery.c * src/ldapquery.h * src/ldapserver.c * src/ldapserver.h * src/ldaputil.c * src/ldaputil.h * src/ldif.c * src/ldif.h * src/main.c * src/main.h * src/mainwindow.c * src/mainwindow.h * src/manual.c * src/manual.h * src/mbox.c * src/mbox.h * src/message_search.c * src/message_search.h * src/messageview.c * src/messageview.h * src/mh.c * src/mh.h * src/mh_gtk.c * src/mh_gtk.h * src/mimeview.c * src/mimeview.h * src/msgcache.c * src/msgcache.h * src/mutt.c * src/mutt.h * src/news.c * src/news.h * src/news_gtk.c * src/news_gtk.h * src/partial_download.c * src/partial_download.h * src/pine.c * src/pine.h * src/pop.c * src/pop.h * src/prefs_account.c * src/prefs_account.h * src/prefs_actions.c * src/prefs_actions.h * src/prefs_common.c * src/prefs_common.h * src/prefs_compose_writing.c * src/prefs_compose_writing.h * src/prefs_customheader.c * src/prefs_customheader.h * src/prefs_display_header.c * src/prefs_display_header.h * src/prefs_filtering.c * src/prefs_filtering.h * src/prefs_filtering_action.c * src/prefs_filtering_action.h * src/prefs_folder_column.c * src/prefs_folder_column.h * src/prefs_folder_item.c * src/prefs_folder_item.h * src/prefs_fonts.c * src/prefs_fonts.h * src/prefs_gtk.c * src/prefs_gtk.h * src/prefs_image_viewer.c * src/prefs_image_viewer.h * src/prefs_matcher.c * src/prefs_matcher.h * src/prefs_message.c * src/prefs_msg_colors.c * src/prefs_msg_colors.h * src/prefs_other.c * src/prefs_quote.c * src/prefs_receive.c * src/prefs_send.c * src/prefs_spelling.c * src/prefs_spelling.h * src/prefs_summaries.c * src/prefs_summaries.h * src/prefs_summary_column.c * src/prefs_summary_column.h * src/prefs_template.c * src/prefs_template.h * src/prefs_themes.c * src/prefs_themes.h * src/prefs_toolbar.c * src/prefs_toolbar.h * src/prefs_wrapping.c * src/prefs_wrapping.h * src/privacy.c * src/privacy.h * src/procheader.c * src/procheader.h * src/procmime.c * src/procmime.h * src/procmsg.c * src/procmsg.h * src/quote_fmt.c * src/quote_fmt_parse.y * src/recv.c * src/recv.h * src/remotefolder.c * src/remotefolder.h * src/send_message.c * src/send_message.h * src/setup.c * src/setup.h * src/sourcewindow.c * src/sourcewindow.h * src/ssl_manager.c * src/ssl_manager.h * src/statusbar.c * src/statusbar.h * src/stock_pixmap.c * src/stock_pixmap.h * src/summary_search.c * src/summary_search.h * src/summaryview.c * src/summaryview.h * src/syldap.c * src/syldap.h * src/textview.c * src/textview.h * src/toolbar.c * src/toolbar.h * src/undo.c * src/undo.h * src/unmime.c * src/unmime.h * src/vcard.c * src/vcard.h * src/wizard.c * src/wizard.h * src/common/base64.c * src/common/base64.h * src/common/defs.h * src/common/hooks.c * src/common/hooks.h * src/common/log.c * src/common/log.h * src/common/mgutils.c * src/common/mgutils.h * src/common/nntp.c * src/common/nntp.h * src/common/passcrypt.c * src/common/passcrypt.h.in * src/common/plugin.c * src/common/plugin.h * src/common/prefs.c * src/common/prefs.h * src/common/progressindicator.c * src/common/progressindicator.h * src/common/quoted-printable.c * src/common/quoted-printable.h * src/common/session.c * src/common/session.h * src/common/smtp.c * src/common/smtp.h * src/common/socket.c * src/common/socket.h * src/common/ssl.c * src/common/ssl.h * src/common/ssl_certificate.c * src/common/ssl_certificate.h * src/common/stringtable.c * src/common/stringtable.h * src/common/sylpheed.c * src/common/sylpheed.h * src/common/template.c * src/common/template.h * src/common/timing.h * src/common/utils.c * src/common/utils.h * src/common/version.h.in * src/common/xml.c * src/common/xml.h * src/common/xmlprops.c * src/common/xmlprops.h * src/gtk/colorlabel.c * src/gtk/colorsel.c * src/gtk/colorsel.h * src/gtk/description_window.c * src/gtk/description_window.h * src/gtk/filesel.c * src/gtk/filesel.h * src/gtk/foldersort.c * src/gtk/foldersort.h * src/gtk/gtkutils.c * src/gtk/gtkutils.h * src/gtk/inputdialog.c * src/gtk/inputdialog.h * src/gtk/logwindow.c * src/gtk/logwindow.h * src/gtk/manage_window.c * src/gtk/manage_window.h * src/gtk/menu.c * src/gtk/menu.h * src/gtk/pluginwindow.c * src/gtk/pluginwindow.h * src/gtk/prefswindow.c * src/gtk/prefswindow.h * src/gtk/progressdialog.c * src/gtk/progressdialog.h * src/gtk/sslcertwindow.c * src/gtk/sslcertwindow.h * src/plugins/clamav/clamav_plugin.c * src/plugins/clamav/clamav_plugin.h * src/plugins/clamav/clamav_plugin_gtk.c * src/plugins/demo/demo.c * src/plugins/dillo_viewer/dillo_prefs.c * src/plugins/dillo_viewer/dillo_prefs.h * src/plugins/dillo_viewer/dillo_viewer.c * src/plugins/pgpcore/passphrase.c * src/plugins/pgpcore/passphrase.h * src/plugins/pgpcore/plugin.c * src/plugins/pgpcore/select-keys.c * src/plugins/pgpcore/select-keys.h * src/plugins/pgpcore/sgpgme.c * src/plugins/pgpcore/sgpgme.h * src/plugins/pgpinline/pgpinline.c * src/plugins/pgpinline/pgpinline.h * src/plugins/pgpinline/plugin.c * src/plugins/pgpmime/pgpmime.c * src/plugins/pgpmime/pgpmime.h * src/plugins/pgpmime/plugin.c * src/plugins/spamassassin/spamassassin.c * src/plugins/spamassassin/spamassassin.h * src/plugins/spamassassin/spamassassin_gtk.c * src/plugins/trayicon/trayicon.c update copyright header
694 lines
15 KiB
C
694 lines
15 KiB
C
/*
|
|
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
|
|
* Copyright (C) 2002-2006 Match Grun and the Sylpheed-Claws team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
/*
|
|
* Functions necessary to access Pine address book file.
|
|
*/
|
|
|
|
#include <sys/stat.h>
|
|
#include <glib.h>
|
|
#include <string.h>
|
|
|
|
#include "utils.h"
|
|
#include "mgutils.h"
|
|
#include "pine.h"
|
|
#include "addritem.h"
|
|
#include "addrcache.h"
|
|
|
|
#define PINE_HOME_FILE ".addressbook"
|
|
#define PINEBUFSIZE 2048
|
|
#define CHAR_QUOTE '\"'
|
|
#define CHAR_APOS '\''
|
|
#define CHAR_COMMA ','
|
|
#define CHAR_AT '@'
|
|
|
|
/*
|
|
* Create new object.
|
|
*/
|
|
PineFile *pine_create() {
|
|
PineFile *pineFile;
|
|
pineFile = g_new0( PineFile, 1 );
|
|
pineFile->path = NULL;
|
|
pineFile->file = NULL;
|
|
pineFile->retVal = MGU_SUCCESS;
|
|
pineFile->uniqTable = g_hash_table_new( g_str_hash, g_str_equal );
|
|
pineFile->cbProgress = NULL;
|
|
return pineFile;
|
|
}
|
|
|
|
/*
|
|
* Properties...
|
|
*/
|
|
void pine_set_file( PineFile* pineFile, const gchar *value ) {
|
|
g_return_if_fail( pineFile != NULL );
|
|
pineFile->path = mgu_replace_string( pineFile->path, value );
|
|
g_strstrip( pineFile->path );
|
|
}
|
|
|
|
/*
|
|
* Register a callback function. When called, the function will be passed
|
|
* the following arguments:
|
|
* PineFile object,
|
|
* File size (long),
|
|
* Current position (long)
|
|
* This can be used for a progress indicator.
|
|
*/
|
|
void pine_set_callback( PineFile *pineFile, void *func ) {
|
|
pineFile->cbProgress = func;
|
|
}
|
|
|
|
/*
|
|
* Free key in table.
|
|
*/
|
|
static gint pine_free_table_vis( gpointer key, gpointer value, gpointer data ) {
|
|
g_free( key );
|
|
key = NULL;
|
|
value = NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Free up object by releasing internal memory.
|
|
*/
|
|
void pine_free( PineFile *pineFile ) {
|
|
g_return_if_fail( pineFile != NULL );
|
|
|
|
/* Close file */
|
|
if( pineFile->file ) fclose( pineFile->file );
|
|
|
|
/* Free internal stuff */
|
|
g_free( pineFile->path );
|
|
|
|
/* Free unique address table */
|
|
g_hash_table_foreach_remove( pineFile->uniqTable, pine_free_table_vis, NULL );
|
|
g_hash_table_destroy( pineFile->uniqTable );
|
|
|
|
/* Clear pointers */
|
|
pineFile->file = NULL;
|
|
pineFile->path = NULL;
|
|
pineFile->retVal = MGU_SUCCESS;
|
|
pineFile->uniqTable = NULL;
|
|
pineFile->cbProgress = NULL;
|
|
|
|
/* Now release file object */
|
|
g_free( pineFile );
|
|
}
|
|
|
|
/*
|
|
* Display object to specified stream.
|
|
* Enter: pineFile File object.
|
|
* stream File..
|
|
*/
|
|
void pine_print_file( PineFile *pineFile, FILE *stream ) {
|
|
g_return_if_fail( pineFile != NULL );
|
|
fprintf( stream, "Pine File:\n" );
|
|
fprintf( stream, "file spec: '%s'\n", pineFile->path );
|
|
fprintf( stream, " ret val: %d\n", pineFile->retVal );
|
|
}
|
|
|
|
/*
|
|
* Open file for read.
|
|
* Enter: pineFile File object.
|
|
* return: TRUE if file opened successfully.
|
|
*/
|
|
static gint pine_open_file( PineFile* pineFile ) {
|
|
if( pineFile->path ) {
|
|
pineFile->file = g_fopen( pineFile->path, "rb" );
|
|
if( ! pineFile->file ) {
|
|
pineFile->retVal = MGU_OPEN_FILE;
|
|
return pineFile->retVal;
|
|
}
|
|
}
|
|
else {
|
|
/* printf( "file not specified\n" ); */
|
|
pineFile->retVal = MGU_NO_FILE;
|
|
return pineFile->retVal;
|
|
}
|
|
|
|
/* Setup a buffer area */
|
|
pineFile->retVal = MGU_SUCCESS;
|
|
return pineFile->retVal;
|
|
}
|
|
|
|
/*
|
|
* Close file.
|
|
* Enter: pineFile File object.
|
|
*/
|
|
static void pine_close_file( PineFile *pineFile ) {
|
|
g_return_if_fail( pineFile != NULL );
|
|
if( pineFile->file ) fclose( pineFile->file );
|
|
pineFile->file = NULL;
|
|
}
|
|
|
|
/*
|
|
* Read line of text from file.
|
|
* Enter: pineFile File object.
|
|
* Return: Copy of buffer. Should be g_free'd when done.
|
|
*/
|
|
static gchar *pine_read_line( PineFile *pineFile ) {
|
|
gchar buf[ PINEBUFSIZE ];
|
|
int c, i = 0;
|
|
gchar ch;
|
|
|
|
if( feof( pineFile->file ) )
|
|
return NULL;
|
|
|
|
while( i < PINEBUFSIZE-1 ) {
|
|
c = fgetc( pineFile->file );
|
|
if( c == EOF ) {
|
|
if( i == 0 )
|
|
return NULL;
|
|
break;
|
|
}
|
|
ch = (gchar) c;
|
|
if( ch == '\0' ) {
|
|
if( i == 0 )
|
|
return NULL;
|
|
break;
|
|
}
|
|
if( ch == '\n' ) {
|
|
break;
|
|
}
|
|
buf[i] = ch;
|
|
i++;
|
|
}
|
|
buf[i] = '\0';
|
|
|
|
/* Copy into private buffer */
|
|
return g_strdup( buf );
|
|
}
|
|
|
|
/*
|
|
* Parsed address data.
|
|
*/
|
|
typedef struct _Pine_ParsedRec_ Pine_ParsedRec;
|
|
struct _Pine_ParsedRec_ {
|
|
gchar *nickName;
|
|
gchar *name;
|
|
gchar *address;
|
|
gchar *fcc;
|
|
gchar *comments;
|
|
gboolean isGroup;
|
|
GSList *listName;
|
|
GSList *listAddr;
|
|
};
|
|
|
|
/*
|
|
* Free data record.
|
|
* Enter: rec Data record.
|
|
*/
|
|
static void pine_free_rec( Pine_ParsedRec *rec ) {
|
|
if( rec ) {
|
|
g_free( rec->nickName );
|
|
g_free( rec->name );
|
|
g_free( rec->address );
|
|
g_free( rec->fcc );
|
|
g_free( rec->comments );
|
|
mgu_clear_slist( rec->listName );
|
|
mgu_clear_slist( rec->listAddr );
|
|
g_slist_free( rec->listName );
|
|
g_slist_free( rec->listAddr );
|
|
rec->nickName = NULL;
|
|
rec->name = NULL;
|
|
rec->address = NULL;
|
|
rec->fcc = NULL;
|
|
rec->comments = NULL;
|
|
rec->isGroup = FALSE;
|
|
g_free( rec );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Clean name.
|
|
*/
|
|
static void pine_clean_name( Pine_ParsedRec *rec ) {
|
|
gchar *p;
|
|
|
|
p = rec->name;
|
|
if( p == NULL ) return;
|
|
if( *p == '\0' ) return;
|
|
|
|
g_strstrip( rec->name );
|
|
if( *p == CHAR_APOS || *p == CHAR_QUOTE ) {
|
|
return;
|
|
}
|
|
|
|
/* If embedded comma present, surround match with quotes */
|
|
while( *p ) {
|
|
if( *p == CHAR_COMMA ) {
|
|
p = g_strdup_printf( "\"%s\"", rec->name );
|
|
g_free( rec->name );
|
|
rec->name = p;
|
|
return;
|
|
}
|
|
p++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Parse pine address record.
|
|
* Enter: buf Address record buffer.
|
|
* Return: Data record.
|
|
*/
|
|
static Pine_ParsedRec *pine_parse_record( gchar *buf ) {
|
|
Pine_ParsedRec *rec;
|
|
gchar *p, *f;
|
|
gint pos, len, i;
|
|
gchar *tmp[5];
|
|
|
|
for( i = 0; i < 5; i++ )
|
|
tmp[i] = NULL;
|
|
|
|
/* Extract tab separated values */
|
|
rec = NULL;
|
|
pos = 0;
|
|
p = f = buf;
|
|
while( *p ) {
|
|
if( *p == '\t' ) {
|
|
len = p - f;
|
|
if( len > 0 ) {
|
|
tmp[ pos ] = g_strndup( f, len );
|
|
f = p;
|
|
f++;
|
|
}
|
|
pos++;
|
|
}
|
|
p++;
|
|
}
|
|
|
|
/* Extract last value */
|
|
len = p - f;
|
|
if( len > 0 ) {
|
|
tmp[ pos++ ] = g_strndup( f, len );
|
|
}
|
|
|
|
/* Populate record */
|
|
if( pos > 0 ) {
|
|
rec = g_new0( Pine_ParsedRec, 1 );
|
|
rec->isGroup = FALSE;
|
|
for( i = 0; i < pos; i++ ) {
|
|
f = tmp[i];
|
|
if( f ) {
|
|
g_strstrip( f );
|
|
}
|
|
if( i == 0 ) rec->nickName = f;
|
|
else if( i == 1 ) rec->name = f;
|
|
else if( i == 2 ) rec->address = f;
|
|
else if( i == 3 ) rec->fcc = f;
|
|
else if( i == 4 ) rec->comments = f;
|
|
tmp[i] = NULL;
|
|
}
|
|
|
|
if( rec->address != NULL ) {
|
|
/* Strip leading/trailing parens */
|
|
p = rec->address;
|
|
if( *p == '(' ) {
|
|
len = strlen( p ) - 1;
|
|
*p = ' ';
|
|
*(p + len) = ' ';
|
|
rec->isGroup = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return rec;
|
|
}
|
|
|
|
/*
|
|
* Parse name from email address string.
|
|
* Enter: buf Start address of buffer to process (not modified).
|
|
* atp Pointer to email at (@) character.
|
|
* ap Pointer to start of email address returned.
|
|
* ep Pointer to end of email address returned.
|
|
* Return: Parsed name or NULL if not present. This should be g_free'd
|
|
* when done.
|
|
*/
|
|
static gchar *pine_parse_name(
|
|
const gchar *buf, const gchar *atp, const gchar **ap,
|
|
const gchar **ep )
|
|
{
|
|
gchar *name;
|
|
const gchar *pos;
|
|
const gchar *tmp;
|
|
const gchar *bp;
|
|
gint ilen;
|
|
|
|
name = NULL;
|
|
*ap = NULL;
|
|
*ep = NULL;
|
|
|
|
/* Find first non-separator char */
|
|
bp = buf;
|
|
while( TRUE ) {
|
|
if( strchr( ",; \n\r", *bp ) == NULL ) break;
|
|
bp++;
|
|
}
|
|
|
|
/* Search back for start of name */
|
|
tmp = atp;
|
|
pos = atp;
|
|
while( pos >= bp ) {
|
|
tmp = pos;
|
|
if( *pos == '<' ) {
|
|
/* Found start of address/end of name part */
|
|
ilen = -1 + ( size_t ) ( pos - bp );
|
|
name = g_strndup( bp, ilen + 1 );
|
|
*(name + ilen + 1) = '\0';
|
|
|
|
/* Remove leading trailing quotes and spaces */
|
|
mgu_str_ltc2space( name, '\"', '\"' );
|
|
mgu_str_ltc2space( name, '\'', '\'' );
|
|
mgu_str_ltc2space( name, '\"', '\"' );
|
|
mgu_str_unescape( name );
|
|
g_strstrip( name );
|
|
break;
|
|
}
|
|
pos--;
|
|
}
|
|
*ap = tmp;
|
|
|
|
/* Search forward for end of address */
|
|
pos = atp + 1;
|
|
while( TRUE ) {
|
|
if( *pos == '>' ) {
|
|
pos++;
|
|
break;
|
|
}
|
|
if( strchr( ",; \'\n\r", *pos ) ) break;
|
|
pos++;
|
|
}
|
|
*ep = pos;
|
|
|
|
return name;
|
|
}
|
|
|
|
/*
|
|
* Parse address list.
|
|
* Enter: pineFile Pine control data.
|
|
* cache Address cache.
|
|
* rec Data record.
|
|
*/
|
|
static void pine_parse_address( PineFile *pineFile, AddressCache *cache, Pine_ParsedRec *rec ) {
|
|
const gchar *buf;
|
|
gchar addr[ PINEBUFSIZE ];
|
|
const gchar *bp;
|
|
const gchar *ep;
|
|
gchar *atCh;
|
|
gchar *name;
|
|
gint len;
|
|
|
|
g_return_if_fail( rec->address != NULL );
|
|
|
|
buf = rec->address;
|
|
while((atCh = strchr( buf, CHAR_AT )) != NULL) {
|
|
name = pine_parse_name( buf, atCh, &bp, &ep );
|
|
len = ( size_t ) ( ep - bp );
|
|
strncpy( addr, bp, len );
|
|
addr[ len ] = '\0';
|
|
extract_address( addr );
|
|
|
|
if( name == NULL ) name = g_strdup( "" );
|
|
rec->listName = g_slist_append( rec->listName, name );
|
|
rec->listAddr = g_slist_append( rec->listAddr, g_strdup( addr ) );
|
|
|
|
buf = ep;
|
|
if( atCh == ep ) {
|
|
buf++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Insert person and address into address cache.
|
|
* Enter: pineFile Pine control data.
|
|
* cache Address cache.
|
|
* address E-Mail address.
|
|
* name Name.
|
|
* remarks Remarks.
|
|
* Return: E-Mail object, either inserted or found in hash table.
|
|
*/
|
|
static ItemEMail *pine_insert_table(
|
|
PineFile *pineFile, AddressCache *cache, gchar *address,
|
|
gchar *name, gchar *remarks )
|
|
{
|
|
ItemPerson *person;
|
|
ItemEMail *email;
|
|
gchar *key;
|
|
|
|
g_return_val_if_fail( address != NULL, NULL );
|
|
|
|
/* create an entry with empty name if needed */
|
|
if ( name == NULL )
|
|
name = "";
|
|
|
|
/* Test whether address already in hash table */
|
|
key = g_strdup( address );
|
|
g_strdown( key );
|
|
email = g_hash_table_lookup( pineFile->uniqTable, key );
|
|
|
|
if( email == NULL ) {
|
|
/* No - create person */
|
|
person = addritem_create_item_person();
|
|
addritem_person_set_common_name( person, name );
|
|
addrcache_id_person( cache, person );
|
|
addrcache_add_person( cache, person );
|
|
|
|
/* Add email for person */
|
|
email = addritem_create_item_email();
|
|
addritem_email_set_address( email, address );
|
|
addritem_email_set_remarks( email, remarks );
|
|
addrcache_id_email( cache, email );
|
|
addrcache_person_add_email( cache, person, email );
|
|
|
|
/* Insert entry */
|
|
g_hash_table_insert( pineFile->uniqTable, key, email );
|
|
}
|
|
else {
|
|
/* Yes - update person with longest name */
|
|
person = ( ItemPerson * ) ADDRITEM_PARENT(email);
|
|
if( strlen( name ) > strlen( ADDRITEM_NAME(person) ) ) {
|
|
addritem_person_set_common_name( person, name );
|
|
}
|
|
|
|
/* Free up */
|
|
g_free( key );
|
|
}
|
|
|
|
return email;
|
|
}
|
|
|
|
/*
|
|
* Parse address line adn build address items.
|
|
* Enter: pineFile Pine control data.
|
|
* cache Address cache to load.
|
|
* line Address record.
|
|
*/
|
|
static void pine_build_items( PineFile *pineFile, AddressCache *cache, gchar *line ) {
|
|
Pine_ParsedRec *rec;
|
|
GSList *nodeAddr, *nodeName;
|
|
ItemGroup *group;
|
|
ItemEMail *email;
|
|
|
|
rec = pine_parse_record( line );
|
|
if( rec ) {
|
|
pine_clean_name( rec );
|
|
pine_parse_address( pineFile, cache, rec );
|
|
/* pine_print_rec( rec, stdout ); */
|
|
/* printf( "=========\n" ); */
|
|
|
|
if( rec->isGroup ) {
|
|
/* Create group */
|
|
group = addritem_create_item_group();
|
|
addritem_group_set_name( group, rec->nickName );
|
|
addrcache_id_group( cache, group );
|
|
addrcache_add_group( cache, group );
|
|
|
|
/* Add email to group */
|
|
nodeName = rec->listName;
|
|
nodeAddr = rec->listAddr;
|
|
while( nodeAddr ) {
|
|
email = pine_insert_table(
|
|
pineFile, cache, nodeAddr->data,
|
|
nodeName->data, "" );
|
|
|
|
/* Add email to group */
|
|
addritem_group_add_email( group, email );
|
|
|
|
nodeAddr = g_slist_next( nodeAddr );
|
|
nodeName = g_slist_next( nodeName );
|
|
}
|
|
}
|
|
else {
|
|
email = pine_insert_table(
|
|
pineFile, cache, rec->address,
|
|
rec->name, rec->comments );
|
|
}
|
|
|
|
pine_free_rec( rec );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Read file data into address cache.
|
|
* Enter: pineFile Pine control data.
|
|
* cache Address cache to load.
|
|
*/
|
|
static void pine_read_file( PineFile *pineFile, AddressCache *cache ) {
|
|
GSList *listValue = NULL;
|
|
gboolean flagEOF = FALSE, flagProc = FALSE, flagDone = FALSE;
|
|
gchar *line = NULL, *lineValue = NULL;
|
|
long posEnd = 0L;
|
|
long posCur = 0L;
|
|
|
|
/* Find EOF for progress indicator */
|
|
fseek( pineFile->file, 0L, SEEK_END );
|
|
posEnd = ftell( pineFile->file );
|
|
fseek( pineFile->file, 0L, SEEK_SET );
|
|
|
|
flagProc = FALSE;
|
|
while( ! flagDone ) {
|
|
if( flagEOF ) {
|
|
flagDone = TRUE;
|
|
flagProc = TRUE;
|
|
}
|
|
else {
|
|
line = pine_read_line( pineFile );
|
|
}
|
|
|
|
posCur = ftell( pineFile->file );
|
|
if( pineFile->cbProgress ) {
|
|
/* Call progress indicator */
|
|
( pineFile->cbProgress ) ( pineFile, & posEnd, & posCur );
|
|
}
|
|
|
|
/* Add line to list */
|
|
if( line == NULL ) {
|
|
flagEOF = TRUE;
|
|
}
|
|
else {
|
|
/* Check for continuation line (1 space only) */
|
|
if( *line == ' ' ) {
|
|
g_strchug( line );
|
|
listValue = g_slist_append(
|
|
listValue, g_strdup( line ) );
|
|
flagProc = FALSE;
|
|
}
|
|
else {
|
|
flagProc = TRUE;
|
|
}
|
|
}
|
|
|
|
if( flagProc ) {
|
|
if( listValue != NULL ) {
|
|
/* Process list */
|
|
lineValue = mgu_list_coalesce( listValue );
|
|
if( lineValue ) {
|
|
pine_build_items(
|
|
pineFile, cache, lineValue );
|
|
}
|
|
g_free( lineValue );
|
|
lineValue = NULL;
|
|
mgu_free_list( listValue );
|
|
listValue = NULL;
|
|
}
|
|
if( line != NULL ) {
|
|
/* Append to list */
|
|
listValue = g_slist_append(
|
|
listValue, g_strdup( line ) );
|
|
}
|
|
}
|
|
|
|
g_free( line );
|
|
line = NULL;
|
|
}
|
|
|
|
/* Release data */
|
|
mgu_free_list( listValue );
|
|
listValue = NULL;
|
|
}
|
|
|
|
/*
|
|
* ============================================================================================
|
|
* Read file into list. Main entry point
|
|
* Enter: pineFile Pine control data.
|
|
* cache Address cache to load.
|
|
* Return: Status code.
|
|
* ============================================================================================
|
|
*/
|
|
gint pine_import_data( PineFile *pineFile, AddressCache *cache ) {
|
|
g_return_val_if_fail( pineFile != NULL, MGU_BAD_ARGS );
|
|
g_return_val_if_fail( cache != NULL, MGU_BAD_ARGS );
|
|
|
|
pineFile->retVal = MGU_SUCCESS;
|
|
addrcache_clear( cache );
|
|
cache->dataRead = FALSE;
|
|
pine_open_file( pineFile );
|
|
if( pineFile->retVal == MGU_SUCCESS ) {
|
|
/* Read data into the cache */
|
|
pine_read_file( pineFile, cache );
|
|
pine_close_file( pineFile );
|
|
|
|
/* Mark cache */
|
|
cache->modified = FALSE;
|
|
cache->dataRead = TRUE;
|
|
}
|
|
return pineFile->retVal;
|
|
}
|
|
|
|
#define WORK_BUFLEN 1024
|
|
|
|
/*
|
|
* Attempt to find a Pine addressbook file.
|
|
* Return: Filename, or home directory if not found, or empty string if
|
|
* no home. Filename should be g_free() when done.
|
|
*/
|
|
gchar *pine_find_file( void ) {
|
|
const gchar *homedir;
|
|
gchar str[ WORK_BUFLEN ];
|
|
gint len;
|
|
FILE *fp;
|
|
|
|
homedir = g_get_home_dir();
|
|
if( ! homedir ) return g_strdup( "" );
|
|
|
|
strcpy( str, homedir );
|
|
len = strlen( str );
|
|
if( len > 0 ) {
|
|
if( str[ len-1 ] != G_DIR_SEPARATOR ) {
|
|
str[ len ] = G_DIR_SEPARATOR;
|
|
str[ ++len ] = '\0';
|
|
}
|
|
}
|
|
strcat( str, PINE_HOME_FILE );
|
|
|
|
/* Attempt to open */
|
|
if( ( fp = g_fopen( str, "rb" ) ) != NULL ) {
|
|
fclose( fp );
|
|
}
|
|
else {
|
|
/* Truncate filename */
|
|
str[ len ] = '\0';
|
|
}
|
|
return g_strdup( str );
|
|
}
|
|
|
|
/*
|
|
* End of Source.
|
|
*/
|
|
|