+2002-04-07 [match] 0.7.4claws72
+
+ * src/addrharvest.[ch]
+ fixed to read all addresses in header, regardless
+ of header size. improved name parsing. accommodate
+ harvest from folders and selected message.
+ * src/addritem.[ch]
+ included new address parsing function.
+ * src/addrgather.[ch]
+ * src/addressbook.[ch]
+ * src/summaryview.[ch]
+ * src/mainwindow.c
+ allow address harvest of folder as well as selected
+ messages.
+
2002-04-07 [paul] 0.7.4claws71
* src/esmtp.[ch]
MICRO_VERSION=4
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=claws71
+EXTRA_VERSION=claws72
VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
dnl set $target
}
/*
-* Gather addresses.
-* Enter: folderItem Folder to import.
-*/
-void addressbook_gather( FolderItem *folderItem ) {
+ * Gather addresses.
+ * Enter: folderItem Folder to import.
+ * msgList List of message numbers, or NULL to process folder.
+ */
+void addressbook_gather( FolderItem *folderItem, GList *msgList ) {
AddressDataSource *ds = NULL;
AdapterDSource *ads = NULL;
AddressBookFile *abf = NULL;
AdapterInterface *adapter;
GtkCTreeNode *newNode;
- abf = addrgather_dlg_execute( folderItem, _addressIndex_ );
+ abf = addrgather_dlg_execute( folderItem, _addressIndex_, msgList );
if( abf ) {
ds = addrindex_index_add_datasource(
_addressIndex_, ADDR_IF_BOOK, abf );
gboolean addressbook_load_completion ( gint (*callBackFunc) ( const gchar *, const gchar *, const gchar * ) );
-void addressbook_gather ( FolderItem *folderItem );
+void addressbook_gather ( FolderItem *folderItem,
+ GList *msgList );
#endif /* __ADDRESSBOOK_H__ */
HEADER_CC,
HEADER_ERRORS_TO
};
+static GList *_harv_messageList_;
void addrgather_dlg_status_show( gchar *msg ) {
if( addrgather_dlg.statusbar != NULL ) {
g_free( name );
/* Harvest addresses */
- addrharvest_harvest( harvester, abf->addressCache );
+ addrharvest_harvest(
+ harvester, abf->addressCache, _harv_messageList_ );
addrbook_save_data( abf );
_harv_addressBook_ = abf;
window = gtk_window_new( GTK_WINDOW_DIALOG );
gtk_widget_set_usize( window, 380, -1 );
gtk_container_set_border_width(GTK_CONTAINER(window), 0);
- gtk_window_set_title( GTK_WINDOW(window), _("Gather E-Mail Addresses") );
gtk_window_set_position( GTK_WINDOW(window), GTK_WIN_POS_CENTER );
gtk_window_set_modal( GTK_WINDOW(window), TRUE );
gtk_signal_connect( GTK_OBJECT(window), "delete_event",
}
/*
-* Gather addresses main window.
-* Enter: folderItem Source folder.
-* addrIndex Address index.
-* Return: Populated address book file, or NULL if none created.
-*/
-AddressBookFile *addrgather_dlg_execute( FolderItem *folderItem, AddressIndex *addrIndex ) {
+ * Gather addresses main window.
+ * Enter: folderItem Source folder.
+ * addrIndex Address index.
+ * msgList List of message numbers, or NULL to process folder.
+ * Return: Populated address book file, or NULL if none created.
+ */
+AddressBookFile *addrgather_dlg_execute(
+ FolderItem *folderItem, AddressIndex *addrIndex, GList *msgList )
+{
gboolean errFlag;
gint i;
_harv_addressIndex_ = addrIndex;
_harv_addressBook_ = NULL;
+ _harv_messageList_ = msgList;
/* Create dialog */
if( ! addrgather_dlg.window ) {
gtk_widget_grab_default( addrgather_dlg.btnCancel );
}
+ if( msgList ) {
+ gtk_window_set_title( GTK_WINDOW(addrgather_dlg.window),
+ _("Gather E-Mail Addresses - from Selected Messages") );
+ }
+ else {
+ gtk_window_set_title( GTK_WINDOW(addrgather_dlg.window),
+ _("Gather E-Mail Addresses - from Folder") );
+ }
addrgather_dlg_status_show( "" );
gtk_widget_show( addrgather_dlg.window );
/* Function prototypes */
AddressBookFile *addrgather_dlg_execute( FolderItem *folderItem,
- AddressIndex *addrIndex );
+ AddressIndex *addrIndex,
+ GList *msgList );
#endif /* __ADDR_GATHER_H__ */
static gchar *_headerTo_ = HEADER_TO;
#define ADDR_BUFFSIZE 1024
-#define MSG_BUFFSIZE 16384
+#define MSG_BUFFSIZE 2048
+#define MSGNUM_BUFFSIZE 32
#define DFL_FOLDER_SIZE 20
/* Noise strings included by some other E-Mail clients */
newFolder = TRUE; /* Folder is full */
}
- if( newFolder ) {
- cnt = 1 + ( entry->count / harvester->folderSize );
- folderName = g_strdup_printf( "%s (%d)", entry->header, cnt );
- folder = addritem_create_item_folder();
- addritem_folder_set_name( folder, folderName );
- addritem_folder_set_remarks( folder, "" );
- addrcache_id_folder( cache, folder );
- addrcache_add_folder( cache, folder );
- entry->folder = folder;
- g_free( folderName );
- }
-
/* Insert address */
key = g_strdup( address );
g_strdown( key );
person = g_hash_table_lookup( harvester->dupTable, key );
if( person ) {
- /* Use longest name */
+ /* Update existing person to use longest name */
value = ADDRITEM_NAME(person);
if( strlen( name ) > strlen( value ) ) {
addritem_person_set_common_name( person, name );
g_free( key );
}
else {
+ /* Folder if required */
+ if( newFolder ) {
+ cnt = 1 + ( entry->count / harvester->folderSize );
+ folderName =g_strdup_printf( "%s (%d)",
+ entry->header, cnt );
+ folder = addritem_create_item_folder();
+ addritem_folder_set_name( folder, folderName );
+ addritem_folder_set_remarks( folder, "" );
+ addrcache_id_folder( cache, folder );
+ addrcache_add_folder( cache, folder );
+ entry->folder = folder;
+ g_free( folderName );
+ }
+
/* Insert entry */
person = addrcache_add_contact(
cache, folder, name, address, "" );
g_hash_table_insert( harvester->dupTable, key, person );
entry->count++;
}
+ addritem_parse_first_last( person );
}
/*
* Remove specified string from name.
* Enter: name Name.
- * em String to remove.
+ * str String to remove.
*/
-static void addrharvest_del_email( gchar *name, gchar *em ) {
+static void addrharvest_del_email( gchar *name, gchar *str ) {
gchar *p;
- gint ilen;
+ gint lenn, lenr;
- ilen = strlen( em );
- while( p = strcasestr( name, em ) ) {
- memmove( p, p + ilen, ilen + 1 );
+ lenr = strlen( str );
+ while( p = strcasestr( name, str ) ) {
+ lenn = strlen( p );
+ memmove( p, p + lenr, lenn );
}
}
gchar buffer[ ADDR_BUFFSIZE + 2 ];
const gchar *bp;
const gchar *ep;
- gchar *atCh, *email, *p;
+ gchar *atCh, *email, *name;
gint bufLen;
/* Search for an address */
buffer[ bufLen + 1 ] = '\0';
buffer[ bufLen + 2 ] = '\0';
- /* Make whitespace */
- p = buffer;
- while( *p ) {
- if( *p == '\r' || *p == '\n' || *p == '\t' ) *p = ' ';
- p++;
- }
-
/* Extract address from buffer */
email = addrharvest_extract_address( buffer );
if( email ) {
mgu_str_ltc2space( buffer, '(', ')' );
g_strstrip( buffer );
+ if( g_strcasecmp( buffer, email ) == 0 ) {
+ name = "";
+ }
+ else {
+ name = buffer;
+ }
+
/* Insert into address book */
addrharvest_insert_cache(
- harvester, entry, cache, buffer, email );
+ harvester, entry, cache, name, email );
g_free( email );
}
hdrBuf = ep;
}
}
+/*
+ * Test whether buffer contains a header that appears in header list.
+ * Enter: listHdr Header list.
+ * buf Header buffer.
+ * Return: TRUE if header in list.
+ */
+static gboolean addrharvest_check_hdr( GList *listHdr, gchar *buf ) {
+ gboolean retVal;
+ GList *node;
+ gchar *p, *hdr, *nhdr;
+ gint len;
+
+ retVal = FALSE;
+ p = strchr( buf, ':' );
+ if( p ) {
+ len = ( size_t ) ( p - buf );
+ hdr = g_strndup( buf, len );
+ node = listHdr;
+ while( node ) {
+ nhdr = node->data;
+ if( g_strcasecmp( nhdr, hdr ) == 0 ) {
+ retVal = TRUE;
+ break;
+ }
+ node = g_list_next( node );
+ }
+ g_free( hdr );
+ }
+ return retVal;
+}
+
+/*
+ * Read header into a linked list of lines.
+ * Enter: fp File to read.
+ * listHdr List of header lines of interest.
+ * done End of headers or end of file reached.
+ * Return: Linked list of lines.
+ */
+static GSList *addrharvest_get_header( FILE *fp, GList *listHdr, gboolean *done ) {
+ GSList *list;
+ gchar buf[ MSG_BUFFSIZE + 2 ];
+ gint ch;
+ gboolean foundHdr;
+
+ list = NULL;
+
+ /* Read line */
+ if( fgets( buf, MSG_BUFFSIZE, fp ) == NULL ) {
+ *done = TRUE;
+ return list;
+ }
+
+ /* Test for end of headers */
+ if( buf[0] == '\r' || buf[0] == '\n' ) {
+ *done = TRUE;
+ return list;
+ }
+
+ /* Test whether required header */
+ foundHdr = addrharvest_check_hdr( listHdr, buf );
+
+ /* Read all header lines. Only add reqd ones to list */
+ while( TRUE ) {
+ gchar *p;
+
+ if( foundHdr ) {
+ p = g_strdup( buf );
+ list = g_slist_append( list, p );
+ }
+
+ /* Read first character */
+ ch = fgetc( fp );
+ if( ch == ' ' || ch == '\t' ) {
+ /* Continuation character - read into buffer */
+ if( fgets( buf, MSG_BUFFSIZE, fp ) == NULL ) {
+ break;
+ }
+ }
+ else {
+ if( ch == EOF ) {
+ *done = TRUE;
+ }
+ else {
+ /* Push back character for next header */
+ ungetc( ch, fp );
+ }
+ break;
+ }
+ }
+
+ return list;
+}
+
/*
* Read specified file into address book.
* Enter: harvester Harvester object.
*/
static gint addrharvest_readfile(
AddressHarvester *harvester, const gchar *fileName,
- AddressCache *cache )
+ AddressCache *cache, GList *listHdr )
{
gint retVal;
FILE *msgFile;
- gchar buf[ MSG_BUFFSIZE ], tmp[ MSG_BUFFSIZE ];
+ gchar *buf, *addr, *p;
HeaderEntry *entry;
+ GSList *list;
+ gboolean done;
msgFile = fopen( fileName, "rb" );
if( ! msgFile ) {
return retVal;
}
- for( ;; ) {
- gint val;
- gchar *p;
+ done = FALSE;
+ while( TRUE ) {
+ list = addrharvest_get_header( msgFile, listHdr, &done );
+ if( done ) break;
- val = procheader_get_one_field(
- buf, sizeof(buf), msgFile, NULL );
- if( val == -1 ) {
- break;
+ if( list == NULL ) {
+ continue;
}
- conv_unmime_header( tmp, sizeof(tmp), buf, NULL );
- if(( p = strchr( tmp, ':' ) ) != NULL ) {
- const gchar *hdr;
+ buf = mgu_list_coalesce( list );
+ mgu_free_list( list );
+
+ if(( p = strchr( buf, ':' ) ) != NULL ) {
+ addr = p + 1;
*p = '\0';
- hdr = p + 1;
- entry = addrharvest_find( harvester, tmp );
+
+ entry = addrharvest_find( harvester, buf );
if( entry && entry->selected ) {
+ /* Sanitize control characters */
+ p = addr;
+ while( *p ) {
+ if( *p == '\r' || *p == '\n' || *p == '\t' )
+ *p = ' ';
+ p++;
+ }
addrharvest_parse_address(
- harvester, entry, cache, hdr );
+ harvester, entry, cache, addr );
}
}
+ g_free( buf );
}
fclose( msgFile );
* Read all files in specified directory into address book.
* Enter: harvester Harvester object.
* cache Address cache to load.
+ * msgList List of message numbers, or NULL to process folder.
* Return: Status.
* ============================================================================
*/
-gint addrharvest_harvest( AddressHarvester *harvester, AddressCache *cache ) {
+gint addrharvest_harvest(
+ AddressHarvester *harvester, AddressCache *cache, GList *msgList )
+{
gint retVal;
DIR *dp;
struct dirent *d;
struct stat s;
gint num;
+ GList *node;
+ GList *listHdr;
+ gchar msgNum[ MSGNUM_BUFFSIZE ];
retVal = MGU_BAD_ARGS;
g_return_val_if_fail( harvester != NULL, retVal );
return retVal;
}
- while( ( d = readdir( dp ) ) != NULL ) {
- stat( d->d_name, &s );
- if( S_ISREG( s.st_mode ) ) {
- if( ( num = to_number( d->d_name ) ) >= 0 ) {
- addrharvest_readfile(
- harvester, d->d_name, cache );
+ /* Build list of headers of interest */
+ listHdr = NULL;
+ node = harvester->headerTable;
+ while( node ) {
+ HeaderEntry *entry;
+
+ entry = node->data;
+ if( entry->selected ) {
+ gchar *p;
+
+ p = g_strdup( entry->header );
+ g_strdown( p );
+ listHdr = g_list_append( listHdr, p );
+ }
+ node = g_list_next( node );
+ }
+
+ if( msgList == NULL ) {
+ /* Process directory */
+ while( ( d = readdir( dp ) ) != NULL ) {
+ stat( d->d_name, &s );
+ if( S_ISREG( s.st_mode ) ) {
+ if( ( num = to_number( d->d_name ) ) >= 0 ) {
+ addrharvest_readfile(
+ harvester, d->d_name, cache, listHdr );
+ }
}
}
}
+ else {
+ /* Process message list */
+ node = msgList;
+ while( node ) {
+ num = GPOINTER_TO_UINT( node->data );
+ sprintf( msgNum, "%d", num );
+ addrharvest_readfile(
+ harvester, msgNum, cache, listHdr );
+ node = g_list_next( node );
+ }
+ }
+ mgu_free_dlist( listHdr );
closedir( dp );
void addrharvest_print ( AddressHarvester *harvester,
FILE *stream );
gint addrharvest_harvest ( AddressHarvester *harvester,
- AddressCache *cache );
+ AddressCache *cache,
+ GList *msgList );
gboolean addrharvest_check_header ( AddressHarvester *harvester );
#endif /* __ADDRHARVEST_H__ */
return itemMove;
}
+/**
+ * Parse first and last names for person from common name.
+ * Enter: person Person to process.
+ */
+void addritem_parse_first_last( ItemPerson *person ) {
+ gchar *name;
+ gchar *fName, *lName;
+ gchar *p;
+ gint len, i;
+
+ g_return_if_fail( person != NULL );
+
+ name = ADDRITEM_NAME(person);
+ if( name == NULL ) return;
+
+ fName = NULL;
+ lName = NULL;
+ p = strchr( name, ',' );
+ if( p ) {
+ len = ( size_t ) ( p - name );
+ lName = g_strndup( name, len );
+ fName = g_strdup( p + 1 );
+ }
+ else {
+ /* Other way around */
+ i = strlen( name );
+ while( i >= 0 ) {
+ if( name[i] == ' ' ) {
+ fName = g_strndup( name, i );
+ lName = g_strdup( &name[i] );
+ break;
+ }
+ i--;
+ }
+ if( fName == NULL ) {
+ fName = g_strdup( name );
+ }
+ }
+
+ if( person->firstName ) {
+ g_free( person->firstName );
+ }
+ person->firstName = fName;
+ if( person->firstName )
+ g_strstrip( person->firstName );
+
+ if( person->lastName ) {
+ g_free( person->lastName );
+ }
+ person->lastName = lName;
+ if( person->lastName )
+ g_strstrip( person->lastName );
+}
+
/*
* End of Source.
*/
ItemEMail *addritem_move_email_before ( ItemPerson *person, ItemEMail *itemMove, ItemEMail *itemTarget );
ItemEMail *addritem_move_email_after ( ItemPerson *person, ItemEMail *itemMove, ItemEMail *itemTarget );
+void addritem_parse_first_last ( ItemPerson *person );
+
#endif /* __ADDRITEM_H__ */
guint action,
GtkWidget *widget );
+static void addr_gather_msg_cb ( MainWindow *mainwin,
+ guint action,
+ GtkWidget *widget );
+
#define SEPARATE_ACTION 667
static GtkItemFactoryEntry mainwin_entries[] =
{N_("/_Tools/_Address book..."), "<shift><control>A", addressbook_open_cb, 0, NULL},
{N_("/_Tools/Add sender to address boo_k"),
NULL, add_address_cb, 0, NULL},
- {N_("/_Tools/_Gather addresses..."), NULL, addr_gather_cb, 0, NULL},
+ {N_("/_Tools/_Gather addresses"), NULL, NULL, 0, "<Branch>"},
+ {N_("/_Tools/_Gather addresses/from _Folder..."), NULL, addr_gather_cb, 0, NULL},
+ {N_("/_Tools/_Gather addresses/from _Messages..."), NULL, addr_gather_msg_cb, 0, NULL},
{N_("/_Tools/---"), NULL, NULL, 0, "<Separator>"},
{N_("/_Tools/_Filter messages"), NULL, filter_cb, 0, NULL},
{N_("/_Tools/_Create filter rule"), NULL, NULL, 0, "<Branch>"},
{"/Tools/Selective download..." , M_HAVE_ACCOUNT|M_UNLOCKED},
{"/Tools/Add sender to address book", M_SINGLE_TARGET_EXIST},
- {"/Tools/Gather addresses..." , M_SINGLE_TARGET_EXIST|M_UNLOCKED},
+ {"/Tools/Gather addresses" , M_TARGET_EXIST|M_UNLOCKED},
{"/Tools/Filter messages" , M_MSG_EXIST|M_EXEC|M_UNLOCKED},
{"/Tools/Create filter rule" , M_SINGLE_TARGET_EXIST|M_UNLOCKED},
{"/Tools/Execute" , M_MSG_EXIST|M_EXEC|M_UNLOCKED},
}
}
+/*
+ * Gather addresses for selected folder.
+ */
static void addr_gather_cb( MainWindow *mainwin,
guint action,
GtkWidget *widget )
{
- addressbook_gather( mainwin->summaryview->folder_item );
+ addressbook_gather( mainwin->summaryview->folder_item, NULL );
+}
+
+/*
+ * Gather addresses for selected messages in summary view.
+ */
+static void addr_gather_msg_cb( MainWindow *mainwin,
+ guint action,
+ GtkWidget *widget )
+{
+ summary_gather_address( mainwin->summaryview );
}
/*
folderview_select(summaryview->folderview, summaryview->folder_item);
}
+/*
+ * Gather addresses for selected messages in summary view.
+ */
+void summary_gather_address( SummaryView *summaryview ) {
+ GtkCTree *ctree = GTK_CTREE( summaryview->ctree );
+ GList *cur;
+ GList *msgList;
+ MsgInfo *msginfo;
+
+ msgList = NULL;
+ for( cur = GTK_CLIST(ctree)->selection; cur != NULL; cur = cur->next ) {
+ msginfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(cur->data) );
+ msgList = g_list_append( msgList, GUINT_TO_POINTER( msginfo->msgnum ) );
+ }
+ addressbook_gather( summaryview->folder_item, msgList );
+ g_list_free( msgList );
+}
/*
* End of Source.
void summary_toggle_view_real (SummaryView *summaryview);
void summary_reflect_prefs_pixmap_theme(SummaryView *summaryview);
+
+void summary_gather_address ( SummaryView *summaryview );
+
#endif /* __SUMMARY_H__ */