Fix bug 3793: segfault when autocompletion asks for master passphrase
[claws.git] / src / addrindex.c
index 433a736753a2a235563dea9980d5b2b1da6c77b3..282281f6224b2b9c33663124965000868222177f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2001-2007 Match Grun and the Claws Mail team
+ * Copyright (C) 2001-2012 Match Grun and the Claws Mail 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
@@ -23,6 +23,7 @@
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
+#include "claws-features.h"
 #endif
 
 #include "defs.h"
@@ -41,6 +42,7 @@
 #include "addr_compl.h"
 #include "utils.h"
 #include "alertpanel.h"
+#include "passwordstore.h"
 
 #ifndef DEV_STANDALONE
 #include "prefs_gtk.h"
 #include "ldaputil.h"
 #endif
 
+#ifdef G_OS_WIN32
+#undef interface
+#endif
+
 #define TAG_ADDRESS_INDEX    "addressbook"
 
 #define TAG_IF_ADDRESS_BOOK  "book_list"
@@ -398,7 +404,7 @@ AddressDataSource *addrindex_create_datasource( AddressIfType ifType ) {
 void addrindex_free_datasource( AddressDataSource *ds ) {
        AddressInterface *iface;
 
-       g_return_if_fail( ds != NULL );
+       cm_return_if_fail( ds != NULL );
 
        iface = ds->interface;
        if( ds->rawDataSource != NULL ) {
@@ -512,8 +518,8 @@ gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds )
        AddrBookBase *adbase;
        AddressCache *cache;
 
-       g_return_val_if_fail( addrIndex != NULL, NULL );
-       g_return_val_if_fail( ds != NULL, NULL );
+       cm_return_val_if_fail( addrIndex != NULL, NULL );
+       cm_return_val_if_fail( ds != NULL, NULL );
 
        adbase = ( AddrBookBase * ) ds->rawDataSource;
        if( adbase ) {
@@ -535,8 +541,8 @@ gchar *addrindex_get_cache_id( AddressIndex *addrIndex, AddressDataSource *ds )
 static AddressDataSource *addrindex_get_datasource(
                AddressIndex *addrIndex, const gchar *cacheID )
 {
-       g_return_val_if_fail( addrIndex != NULL, NULL );
-       g_return_val_if_fail( cacheID != NULL, NULL );
+       cm_return_val_if_fail( addrIndex != NULL, NULL );
+       cm_return_val_if_fail( cacheID != NULL, NULL );
        return ( AddressDataSource * ) g_hash_table_lookup( addrIndex->hashCache, cacheID );
 }
 
@@ -551,8 +557,8 @@ AddressCache *addrindex_get_cache( AddressIndex *addrIndex, const gchar *cacheID
        AddrBookBase *adbase;
        AddressCache *cache;
 
-       g_return_val_if_fail( addrIndex != NULL, NULL );
-       g_return_val_if_fail( cacheID != NULL, NULL );
+       cm_return_val_if_fail( addrIndex != NULL, NULL );
+       cm_return_val_if_fail( cacheID != NULL, NULL );
 
        cache = NULL;
        ds = addrindex_get_datasource( addrIndex, cacheID );
@@ -653,7 +659,7 @@ AddressIndex *addrindex_create_index( void ) {
  * \param value Path to index file.
  */
 void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
-       g_return_if_fail( addrIndex != NULL );
+       cm_return_if_fail( addrIndex != NULL );
        addrIndex->filePath = mgu_replace_string( addrIndex->filePath, value );
 }
 
@@ -663,7 +669,7 @@ void addrindex_set_file_path( AddressIndex *addrIndex, const gchar *value ) {
  * \param value File name.
  */
 void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
-       g_return_if_fail( addrIndex != NULL );
+       cm_return_if_fail( addrIndex != NULL );
        addrIndex->fileName = mgu_replace_string( addrIndex->fileName, value );
 }
 
@@ -673,7 +679,7 @@ void addrindex_set_file_name( AddressIndex *addrIndex, const gchar *value ) {
  * \return List of address interfaces.
  */
 GList *addrindex_get_interface_list( AddressIndex *addrIndex ) {
-       g_return_val_if_fail( addrIndex != NULL, NULL );
+       cm_return_val_if_fail( addrIndex != NULL, NULL );
        return addrIndex->interfaceList;
 }
 
@@ -700,7 +706,7 @@ void addrindex_teardown( void ) {
 void addrindex_free_index( AddressIndex *addrIndex ) {
        GList *node;
 
-       g_return_if_fail( addrIndex != NULL );
+       cm_return_if_fail( addrIndex != NULL );
 
        /* Search stuff */
        g_list_free( addrIndex->searchOrder );
@@ -754,7 +760,7 @@ void addrindex_free_index( AddressIndex *addrIndex ) {
  * \parem stream    Stream to print.
 */
 void addrindex_print_index( AddressIndex *addrIndex, FILE *stream ) {
-       g_return_if_fail( addrIndex != NULL );
+       cm_return_if_fail( addrIndex != NULL );
        fprintf( stream, "AddressIndex:\n" );
        fprintf( stream, "\tfile path: '%s'\n", addrIndex->filePath );
        fprintf( stream, "\tfile name: '%s'\n", addrIndex->fileName );
@@ -778,7 +784,7 @@ static AddressInterface *addrindex_get_interface(
        AddressInterface *retVal = NULL;
        GList *node;
 
-       g_return_val_if_fail( addrIndex != NULL, NULL );
+       cm_return_val_if_fail( addrIndex != NULL, NULL );
 
        node = addrIndex->interfaceList;
        while( node ) {
@@ -808,8 +814,8 @@ AddressDataSource *addrindex_index_add_datasource(
        AddressInterface *iface;
        AddressDataSource *ds = NULL;
 
-       g_return_val_if_fail( addrIndex != NULL, NULL );
-       g_return_val_if_fail( dataSource != NULL, NULL );
+       cm_return_val_if_fail( addrIndex != NULL, NULL );
+       cm_return_val_if_fail( dataSource != NULL, NULL );
 
        iface = addrindex_get_interface( addrIndex, ifType );
        if( iface ) {
@@ -839,8 +845,8 @@ AddressDataSource *addrindex_index_remove_datasource(
        AddressDataSource *retVal = FALSE;
        AddressInterface *iface;
 
-       g_return_val_if_fail( addrIndex != NULL, NULL );
-       g_return_val_if_fail( dataSource != NULL, NULL );
+       cm_return_val_if_fail( addrIndex != NULL, NULL );
+       cm_return_val_if_fail( dataSource != NULL, NULL );
 
        iface = addrindex_get_interface( addrIndex, dataSource->type );
        if( iface ) {
@@ -979,6 +985,7 @@ static int addrindex_write_attr( FILE *fp, const gchar *name, const gchar *value
        return 0;
 }
 
+#if !defined(USE_LDAP) || !defined(USE_JPILOT)
 /**
  * Return DOM fragment for current XML tag from file.
  * \param  file XML file being processed.
@@ -1087,7 +1094,7 @@ static int addrindex_write_fragment(
        
        return 0;
 }
-
+#endif
 /**
  * Read/parse address index file, creating a data source for a regular
  * intrinsic XML addressbook.
@@ -1315,7 +1322,6 @@ static void addrindex_parse_ldap_attrlist( XMLFile *file, LdapControl *ctl ) {
                                break;
                        }
                }
-               xtag = xtagPrev;
        }
 
        /* Build list of search attributes */
@@ -1348,6 +1354,7 @@ static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
        gboolean bDynSearch;
        gboolean bTLS, bSSL;
        gint iMatch;
+       gchar *password = NULL;
 
        /* g_print( "addrindex_parse_ldap\n" ); */
        /* Set up some defaults */
@@ -1381,7 +1388,7 @@ static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
                        ldapctl_set_bind_dn( ctl, value );
                }
                else if( strcmp( name, ATTAG_LDAP_BIND_PASS ) == 0 ) {
-                       ldapctl_set_bind_password( ctl, value );
+                       password = value;
                }
                else if( strcmp( name, ATTAG_LDAP_CRITERIA ) == 0 ) {
                        g_free( criteria );
@@ -1424,14 +1431,15 @@ static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
                attr = g_list_next( attr );
        }
 
+       if (password != NULL)
+               passwd_store_set(PWS_CORE, "LDAP", ctl->hostName, password, TRUE);
+
        server = ldapsvr_create_noctl();
        ldapsvr_set_name( server, serverName );
        ldapsvr_set_search_flag( server, bDynSearch );
        ldapctl_set_matching_option( ctl, iMatch );
-#ifdef USE_LDAP_TLS
        ldapctl_set_tls( ctl, bTLS );
        ldapctl_set_ssl( ctl, bSSL );
-#endif
        g_free( serverName );
        ldapsvr_set_control( server, ctl );
        ds->rawDataSource = server;
@@ -1480,8 +1488,6 @@ static int addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
                return -1;
        if (addrindex_write_attr( fp, ATTAG_LDAP_BIND_DN, ctl->bindDN ) < 0)
                return -1;
-       if (addrindex_write_attr( fp, ATTAG_LDAP_BIND_PASS, ctl->bindPass ) < 0)
-               return -1;
 
        sprintf( value, "%d", ctl->maxEntries );
        if (addrindex_write_attr( fp, ATTAG_LDAP_MAX_ENTRY, value ) < 0)
@@ -1568,7 +1574,6 @@ static int addrindex_write_ldap( FILE *fp, AddressDataSource *ds, gint lvl ) {
  * \param  file Address index file.
  */
 static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
-       guint prev_level;
        XMLTag *xtag;
        AddressInterface *iface = NULL, *dsIFace = NULL;
        AddressDataSource *ds;
@@ -1576,9 +1581,8 @@ static void addrindex_read_index( AddressIndex *addrIndex, XMLFile *file ) {
 
        addrIndex->loadedFlag = FALSE;
        for (;;) {
-               prev_level = file->level;
                rc = xml_parse_next_tag( file );
-               if( file->level == 0 ) return;
+               if( rc < 0 || file->level == 0 ) return;
 
                xtag = xml_get_current_tag( file );
 
@@ -1661,7 +1665,7 @@ static gint addrindex_read_file( AddressIndex *addrIndex ) {
        XMLFile *file = NULL;
        gchar *fileSpec = NULL;
 
-       g_return_val_if_fail( addrIndex != NULL, -1 );
+       cm_return_val_if_fail( addrIndex != NULL, -1 );
 
        fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, addrIndex->fileName, NULL );
        addrIndex->retVal = MGU_NO_FILE;
@@ -1749,7 +1753,7 @@ static gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile )
        PrefFile *pfile;
 #endif
 
-       g_return_val_if_fail( addrIndex != NULL, -1 );
+       cm_return_val_if_fail( addrIndex != NULL, -1 );
 
        fileSpec = g_strconcat( addrIndex->filePath, G_DIR_SEPARATOR_S, newFile, NULL );
        addrIndex->retVal = MGU_OPEN_FILE;
@@ -1789,7 +1793,7 @@ static gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile )
        fileSpec = NULL;
        return addrIndex->retVal;
 fail:
-       g_warning("error writing AB index\n");
+       g_warning("error writing AB index");
        addrIndex->retVal = MGU_ERROR_WRITE;
        if (pfile)
                prefs_file_close_revert( pfile );
@@ -1806,7 +1810,7 @@ gint addrindex_save_data( AddressIndex *addrIndex ) {
        GList *nodeDS;
 #endif
        
-       g_return_val_if_fail( addrIndex != NULL, -1 );
+       cm_return_val_if_fail( addrIndex != NULL, -1 );
 
 #ifdef USE_LDAP
        nodeIf = addrIndex->interfaceList;
@@ -2002,8 +2006,7 @@ static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
                        node->list = g_list_append( node->list, newNode );
                }
                else {
-                       /* g_print( "invalid: !!! \n" ); */
-                       attr = xml_get_current_tag_attr( file );
+                       g_warning("Invalid tag");
                }
        }
 }
@@ -2013,47 +2016,17 @@ static void addrindex_add_obj( XMLFile *file, AddressCvtNode *node ) {
 */
 static void addrindex_consume_tree( XMLFile *file ) {
        guint prev_level;
-       gchar *element;
-       GList *attr;
-       XMLTag *xtag;
 
        for (;;) {
                prev_level = file->level;
                xml_parse_next_tag( file );
-               if (file->level < prev_level) return;
+               if (file->level < prev_level)
+                       return;
 
-               xtag = xml_get_current_tag( file );
-               /* g_print( "tag : %s\n", xtag->tag ); */
-               element = xml_get_element( file );
-               attr = xml_get_current_tag_attr( file );
-               /* show_attribs( attr ); */
-               /* g_print( "\ttag  value : %s :\n", element ); */
                addrindex_consume_tree( file );
        }
 }
 
-/*
-* Print temporary tree.
-*/
-static void addrindex_print_node( AddressCvtNode *node, FILE *stream  ) {
-       GList *list;
-
-       fprintf( stream, "Node:\ttype :%d:\n", node->type );
-       fprintf( stream, "\tname :%s:\n", node->name );
-       fprintf( stream, "\taddr :%s:\n", node->address );
-       fprintf( stream, "\trems :%s:\n", node->remarks );
-       if( node->list ) {
-               fprintf( stream, "\t--list----\n" );
-       }
-       list = node->list;
-       while( list ) {
-               AddressCvtNode *lNode = list->data;
-               list = g_list_next( list );
-               addrindex_print_node( lNode, stream );
-       }
-       fprintf( stream, "\t==list-%d==\n", node->type );
-}
-
 /*
 * Free up temporary tree.
 */
@@ -2217,8 +2190,6 @@ static gboolean addrindex_process_book( AddressIndex *addrIndex, XMLFile *file,
 */
 static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
        guint prev_level;
-       gchar *element;
-       GList *attr;
        XMLTag *xtag;
 
        /* Process file */
@@ -2245,10 +2216,6 @@ static void addrindex_convert_tree( AddressIndex *addrIndex, XMLFile *file ) {
                        }
                        return;
                }
-               element = xml_get_element( file );
-               attr = xml_get_current_tag_attr( file );
-               /* show_attribs( attr ); */
-               /* g_print( "\ttag  value : %s :\n", element ); */
                addrindex_consume_tree( file );
        }
 }
@@ -2336,18 +2303,16 @@ static gboolean addrindex_create_new_book( AddressIndex *addrIndex, gchar *displ
 *      "Gathered addresses" - a new address book.
 */
 gint addrindex_read_data( AddressIndex *addrIndex ) {
-       g_return_val_if_fail( addrIndex != NULL, -1 );
+       cm_return_val_if_fail( addrIndex != NULL, -1 );
 
        addrIndex->conversionError = FALSE;
        addrindex_read_file( addrIndex );
        if( addrIndex->retVal == MGU_SUCCESS ) {
                if( addrIndex->needsConversion ) {
-                       if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS ) {
+                       if( addrindex_convert_data( addrIndex ) == MGU_SUCCESS )
+                               addrIndex->conversionError = FALSE;
+                       else
                                addrIndex->conversionError = TRUE;
-                       }
-                       else {
-                               addrIndex->conversionError = TRUE;
-                       }
                }
                addrIndex->dirtyFlag = TRUE;
        }
@@ -2367,7 +2332,7 @@ gint addrindex_read_data( AddressIndex *addrIndex ) {
 gint addrindex_create_new_books( AddressIndex *addrIndex ) {
        gboolean flg;
 
-       g_return_val_if_fail( addrIndex != NULL, -1 );
+       cm_return_val_if_fail( addrIndex != NULL, -1 );
 
        flg = addrindex_create_new_book( addrIndex, DISP_NEW_COMMON );
        if( flg ) {
@@ -2813,7 +2778,6 @@ gboolean addrindex_start_search( const gint queryID ) {
  */
 void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
        AddrBookBase *adbase;
-       AddressCache *cache;
        gint queryID = 0;
 
        /* g_print( "addrindex_remove_results/start\n" ); */
@@ -2823,7 +2787,6 @@ void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
        /* g_print( "folder name ::%s::\n", ADDRITEM_NAME(folder) ); */
        adbase = ( AddrBookBase * ) ds->rawDataSource;
        if( adbase == NULL ) return;
-       cache = adbase->addressCache;
 
        /* Hide folder to prevent re-display */
        addritem_folder_set_hidden( folder, TRUE );
@@ -2957,7 +2920,7 @@ gboolean addrindex_load_completion(
                   folderpath must not be empty or NULL */
                
                if( ! addressbook_peek_folder_exists( folderpath, &book, &folder ) ) {
-                       g_warning("addrindex_load_completion: folder path '%s' doesn't exist\n", folderpath);
+                       g_warning("addrindex_load_completion: folder path '%s' doesn't exist", folderpath);
                        return FALSE;
                }
 
@@ -3011,7 +2974,7 @@ gboolean addrindex_load_completion(
                                return TRUE;
 
                        } else {
-                               g_warning("addrindex_load_completion: book/folder path is valid but got no pointer\n");
+                               g_warning("addrindex_load_completion: book/folder path is valid but got no pointer");
                        }
                }
                return FALSE;
@@ -3116,6 +3079,173 @@ gboolean addrindex_load_person_attribute(
        return TRUE;
 }
 
+/**
+ * This function can be used to collect information about
+ * addressbook entries
+ *
+ * \param callBackFunc Function to be called for each ItemPerson
+ * \return <i>TRUE</i>
+ */
+gboolean addrindex_load_person_ds( gint (*callBackFunc)
+                       ( ItemPerson *, AddressDataSource * ) )
+{
+       AddressDataSource *ds;
+       GList *nodeIf, *nodeDS;
+       GList *listP, *nodeP;
+
+       nodeIf = addrindex_get_interface_list( _addressIndex_ );
+       while( nodeIf ) {
+               AddressInterface *iface = nodeIf->data;
+
+               nodeIf = g_list_next( nodeIf );
+
+               if( ! iface->useInterface || iface->externalQuery )
+                       continue;
+
+               nodeDS = iface->listSource;
+               while( nodeDS ) {
+                       ds = nodeDS->data;
+
+                       /* Read address book */
+                       if( addrindex_ds_get_modify_flag( ds ) ) {
+                               addrindex_ds_read_data( ds );
+                       }
+
+                       if( ! addrindex_ds_get_read_flag( ds ) ) {
+                               addrindex_ds_read_data( ds );
+                       }
+
+                       /* Get all persons */
+                       listP = addrindex_ds_get_all_persons( ds );
+                       nodeP = listP;
+                       while( nodeP ) {
+                               ItemPerson *person = nodeP->data;
+
+                               callBackFunc(person, ds);
+                               nodeP = g_list_next( nodeP );
+                       }
+                       /* Free up the list */
+                       g_list_free( listP );
+
+                       nodeDS = g_list_next( nodeDS );
+               }
+       }
+       return TRUE;
+}
+
+gchar *addrindex_get_picture_file(const gchar *emailaddr)
+{
+       AddressDataSource *ds;
+       GList *nodeIf, *nodeDS;
+       GList *listP, *nodeP;
+       gboolean found = FALSE;
+       gchar *filename = NULL;
+       gchar *raw_addr = NULL;
+       
+       if (!emailaddr)
+               return NULL;
+
+       Xstrdup_a(raw_addr, emailaddr, return NULL);
+       extract_address(raw_addr);
+
+       nodeIf = addrindex_get_interface_list( _addressIndex_ );
+       while( nodeIf ) {
+               AddressInterface *iface = nodeIf->data;
+
+               nodeIf = g_list_next( nodeIf );
+
+               if( ! iface->useInterface || iface->externalQuery )
+                       continue;
+
+               nodeDS = iface->listSource;
+               while( nodeDS && !found) {
+                       ds = nodeDS->data;
+
+                       /* Read address book */
+                       if( addrindex_ds_get_modify_flag( ds ) ) {
+                               addrindex_ds_read_data( ds );
+                       }
+
+                       if( ! addrindex_ds_get_read_flag( ds ) ) {
+                               addrindex_ds_read_data( ds );
+                       }
+
+                       /* Get all persons */
+                       listP = addrindex_ds_get_all_persons( ds );
+                       nodeP = listP;
+                       while( nodeP ) {
+                               GList *nodeM;
+                               ItemPerson *person = nodeP->data;
+                               nodeM = person->listEMail;
+                               while(nodeM) {
+                                       ItemEMail *email = nodeM->data;
+                                       if (email->address && !strcasecmp(raw_addr, email->address)) {
+                                               found = TRUE;
+                                               filename = g_strconcat( get_rc_dir(), G_DIR_SEPARATOR_S, 
+                                                       ADDRBOOK_DIR, G_DIR_SEPARATOR_S, 
+                                                       person->picture, ".png", NULL );
+                                               break;
+                                       }
+                                       nodeM = nodeM->next;
+                               }
+                               nodeP = g_list_next( nodeP );
+                       }
+                       /* Free up the list */
+                       g_list_free( listP );
+
+                       nodeDS = g_list_next( nodeDS );
+               }
+       }
+
+       return filename;
+}
+
+#ifdef USE_LDAP
+GSList *addrindex_get_password_protected_ldap_servers()
+{
+       AddressInterface *iface;
+       AddressDataSource *ds;
+       GList *nodeIf;
+       GList *nodeDS;
+       GSList *list = NULL;
+       LdapServer *server;
+       LdapControl *ctl;
+
+       nodeIf = _addressIndex_->searchOrder;
+       while (nodeIf) {
+               iface = nodeIf->data;
+               nodeIf = g_list_next(nodeIf);
+
+               if (!iface->useInterface)
+                       continue;
+               if (!iface->externalQuery)
+                       continue;
+               if (iface->type != ADDR_IF_LDAP)
+                       continue;
+
+               nodeDS = iface->listSource;
+               while (nodeDS) {
+                       ds = nodeDS->data;
+                       nodeDS = g_list_next(nodeDS);
+                       server = ds->rawDataSource;
+                       if (!server->searchFlag)
+                               continue;
+
+                       ctl = server->control;
+
+                       if (!ctl)
+                               continue;
+
+                       if (ctl->bindDN != NULL && strlen(ctl->bindDN)) {
+                               list = g_slist_append(list, server);
+                       }
+               }
+       }
+
+       return list;
+}
+#endif /* USE_LDAP */
+
 /*
  * End of Source.
  */