+2003-11-01 [match] 0.9.6claws63
+
+ * po/POTFILES.in
+ * src/Makefile.am
+ * src/addr_compl.[ch]
+ * src/addrbook.c
+ * src/addrcache.[ch]
+ * src/addrdefs.h ** NEW **
+ * src/addressbook.c
+ * src/addressitem.h
+ * src/addrindex.[ch]
+ * src/addritem.h
+ * src/addrquery.[ch]
+ * src/ldapquery.[ch]
+ * src/ldapserver.[ch]
+ refactor LDAP query mechanism.
+
+ * src/browseldap.[ch] ** NEW **
+ * src/ldaplocate.[ch] ** NEW **
+ add feature to browse LDAP entry that was retrieved using
+ an explicit LDAP search.
+
2003-11-01 [alfons] 0.9.6claws62
* src/prefs_gtk.c
MICRO_VERSION=6
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=62
+EXTRA_VERSION=63
if test $EXTRA_VERSION -eq 0; then
VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}claws
else
addrquery.c \
addrselect.c \
alertpanel.c \
+ browseldap.c \
codeconv.c \
compose.c \
crash.c \
inputdialog.c \
jpilot.c \
ldapctrl.c \
+ ldaplocate.c \
ldapquery.c \
ldapserver.c \
ldaputil.c \
addrcache.h \
addrclip.h \
addr_compl.h \
+ addrdefs.h \
addressadd.h \
addressbook.h \
addressitem.h \
addrquery.h \
addrselect.h \
alertpanel.h \
+ browseldap.h \
codeconv.h \
compose.h \
crash.h \
inputdialog.h \
jpilot.h \
ldapctrl.h \
+ ldaplocate.h \
ldapquery.h \
ldapserver.h \
ldaputil.h \
# include <wctype.h>
#endif
-#include "addressbook.h"
+#include "addrindex.h"
#include "addr_compl.h"
#include "utils.h"
#include <pthread.h>
* any of those words).
*/
-/**
- * Reference to address index.
- */
-static AddressIndex *_addressIndex_ = NULL;
-
/**
* address_entry - structure which refers to the original address entry in the
* address book .
* Read address book, creating all entries in the completion index.
*/
static void read_address_book(void) {
- addrindex_load_completion( _addressIndex_, add_address );
+ addrindex_load_completion( add_address );
g_address_list = g_list_reverse(g_address_list);
g_completion_list = g_list_reverse(g_completion_list);
}
* \param cw Window to destroy.
*/
static void addrcompl_destroy_window( CompletionWindow *cw ) {
+ /* Stop all searches currently in progress */
+ addrindex_stop_search( _queryID_ );
+
/* Remove idler function... or application may not terminate */
if( _completionIdleID_ != 0 ) {
gtk_idle_remove( _completionIdleID_ );
static gboolean addrcompl_idle( gpointer data ) {
GList *node;
gchar *address;
- CompletionWindow *cw;
/* Process all entries in display queue */
pthread_mutex_lock( & _completionMutex_ );
if( _displayQueue_ ) {
- cw = data;
node = _displayQueue_;
while( node ) {
address = node->data;
/* printf( "address ::: %s :::\n", address ); */
- addrcompl_add_entry( cw, address );
+ addrcompl_add_entry( _compWindow_, address );
g_free( address );
node = g_list_next( node );
}
/**
* Callback entry point. The background thread (if any) appends the address
* list to the display queue.
+ * \param sender Sender of query.
* \param queryID Query ID of search request.
* \param listEMail List of zero of more email objects that met search
* criteria.
- * \param target Target object to received data.
+ * \param data Query data.
*/
-static gint addrcompl_callback(
- gint queryID, GList *listEMail, gpointer target )
+static gint addrcompl_callback_entry(
+ gpointer sender, gint queryID, GList *listEMail, gpointer data )
{
GList *node;
gchar *address;
- /* printf( "addrcompl_callback::queryID=%d\n", queryID ); */
+ /* printf( "addrcompl_callback_entry::queryID=%d\n", queryID ); */
pthread_mutex_lock( & _completionMutex_ );
- if( target ) {
- if( queryID == _queryID_ ) {
- /* Append contents to end of display queue */
- node = listEMail;
- while( node ) {
- ItemEMail *email = node->data;
-
- address = addritem_format_email( email );
- /* printf( "\temail/address ::%s::\n", address ); */
- _displayQueue_ = g_list_append( _displayQueue_, address );
- node = g_list_next( node );
- }
+ if( queryID == _queryID_ ) {
+ /* Append contents to end of display queue */
+ node = listEMail;
+ while( node ) {
+ ItemEMail *email = node->data;
+
+ address = addritem_format_email( email );
+ /* printf( "\temail/address ::%s::\n", address ); */
+ _displayQueue_ = g_list_append( _displayQueue_, address );
+ node = g_list_next( node );
}
}
+ g_list_free( listEMail );
pthread_mutex_unlock( & _completionMutex_ );
- /* printf( "addrcompl_callback...done\n" ); */
return 0;
}
/**
* Load list with entries from local completion index.
- * \param cw Completion window.
*/
-static void addrcompl_load_local( CompletionWindow *cw ) {
+static void addrcompl_load_local( void ) {
guint count = 0;
for (count = 0; count < get_completion_count(); count++) {
/* Setup the search */
_queryID_ = addrindex_setup_search(
- _addressIndex_, searchTerm, _compWindow_, addrcompl_callback );
+ searchTerm, NULL, addrcompl_callback_entry );
g_free( searchTerm );
/* printf( "addrcompl_start_search::queryID=%d\n", _queryID_ ); */
/* Load local stuff */
- addrcompl_load_local( _compWindow_ );
+ addrcompl_load_local();
/* Sit back and wait until something happens */
_completionIdleID_ =
- gtk_idle_add( ( GtkFunction ) addrcompl_idle, _compWindow_ );
+ gtk_idle_add( ( GtkFunction ) addrcompl_idle, NULL );
/* printf( "addrindex_start_search::queryID=%d\n", _queryID_ ); */
- addrindex_start_search( _addressIndex_, _queryID_ );
+ addrindex_start_search( _queryID_ );
}
/**
/**
* Setup completion object.
- * \param addrIndex Address index object.
*/
-void addrcompl_initialize( AddressIndex *addrIndex ) {
- g_return_if_fail( addrIndex != NULL );
- _addressIndex_ = addrIndex;
-
+void addrcompl_initialize( void ) {
/* printf( "addrcompl_initialize...\n" ); */
if( ! _compWindow_ ) {
_compWindow_ = addrcompl_create_window();
}
_displayQueue_ = NULL;
_completionIdleID_ = 0;
- _addressIndex_ = NULL;
/* printf( "addrcompl_teardown...done\n" ); */
}
#include <gtk/gtk.h>
-#include "addrindex.h"
-
gint start_address_completion (void);
guint complete_address (const gchar *str);
-gchar *get_complete_address (gint index);
+gchar *get_complete_address (gint index);
gint invalidate_address_completion (void);
gint end_address_completion (void);
void address_completion_unregister_entry(GtkEntry *entry);
void address_completion_end (GtkWidget *mainwindow);
-void addrcompl_initialize ( AddressIndex *addrIndex );
+void addrcompl_initialize ( void );
void addrcompl_teardown ( void );
#endif /* __ADDR_COMPL_H__ */
* <code>g_free()</code> when done.
*/
ItemFolder *addrbook_add_new_folder(AddressBookFile *book, ItemFolder *parent)
+{
+ g_return_val_if_fail(book != NULL, NULL);
+ return addrcache_add_new_folder( book->addressCache, parent );
+}
+#if 0
{
ItemFolder *folder = NULL;
ItemFolder *p = parent;
}
return folder;
}
+#endif
/**
* Update address book attribute list for specified person. Note: The existing
return NULL;
}
-/*
-* Add person and address data to cache.
-* Enter: cache Cache.
-* folder Folder where to add person, or NULL for root folder.
-* name Common name.
-* address EMail address.
-* remarks Remarks.
-* Return: Person added. Do not *NOT* to use the addrbook_free_xxx() functions...
-* this will destroy the address book data.
-*/
-ItemPerson *addrcache_add_contact( AddressCache *cache, ItemFolder *folder, const gchar *name,
+/**
+ * Add person and address data to cache.
+ * \param cache Cache.
+ * \param folder Folder where to add person, or NULL for root folder.
+ * \param name Common name.
+ * \param address EMail address.
+ * \param remarks Remarks.
+ * \return Person added. Do not *NOT* to use the
+ * <code>addrbook_free_xxx()</code> functions...; this will destroy
+ * the address book data.
+ */
+ItemPerson *addrcache_add_contact(
+ AddressCache *cache, ItemFolder *folder, const gchar *name,
const gchar *address, const gchar *remarks )
{
ItemPerson *person = NULL;
return person;
}
+/**
+ * Create a new folder and add to address cache.
+ * \param cache Address cache.
+ * \param folder Parent folder where to add folder, or <i>NULL</i> for
+ * root folder.
+ * \return Folder that was created. This should <b>*NOT*</b> be
+ * <code>g_free()</code> when done.
+ */
+ItemFolder *addrcache_add_new_folder( AddressCache *cache, ItemFolder *parent )
+{
+ ItemFolder *folder;
+ ItemFolder *p = parent;
+
+ g_return_val_if_fail( cache != NULL, NULL );
+
+ if( !p ) p = cache->rootFolder;
+ folder = addritem_create_item_folder();
+ addrcache_id_folder( cache, folder );
+ if( addrcache_hash_add_folder( cache, folder ) ) {
+ p->listFolder = g_list_append( p->listFolder, folder );
+ ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(p);
+ addrcache_set_dirty( cache, TRUE );
+ }
+ else {
+ addritem_free_item_folder( folder );
+ folder = NULL;
+ }
+ return folder;
+}
+
/*
* End of Source.
*/
const gchar *address,
const gchar *remarks );
+ItemFolder *addrcache_add_new_folder ( AddressCache *cache,
+ ItemFolder *parent );
+
#endif /* __ADDRCACHE_H__ */
#define ADDRESSBOOK_LDAP_BUSYMSG "Busy"
#endif
+#include "addrquery.h"
#include "addrselect.h"
#include "addrclip.h"
#include "addrgather.h"
#include "adbookbase.h"
#include "exphtmldlg.h"
#include "expldifdlg.h"
+#include "browseldap.h"
typedef enum
{
static void addressbook_treenode_copy_cb ( void );
static void addressbook_treenode_paste_cb ( void );
+#ifdef USE_LDAP
+static void addressbook_browse_entry_cb ( void );
+#endif
+
static GtkItemFactoryEntry addressbook_entries[] =
{
{N_("/_File"), NULL, NULL, 0, "<Branch>"},
{N_("/_Copy"), NULL, addressbook_clip_copy_cb, 0, NULL},
{N_("/_Paste"), NULL, addressbook_clip_paste_cb, 0, NULL},
{N_("/---"), NULL, NULL, 0, "<Separator>"},
- {N_("/Pa_ste Address"), NULL, addressbook_clip_paste_address_cb, 0, NULL}
+#ifdef USE_LDAP
+ {N_("/Pa_ste Address"), NULL, addressbook_clip_paste_address_cb, 0, NULL},
+ {N_("/_Browse Entry"), NULL, addressbook_browse_entry_cb, 0, NULL}
+#else
+ {N_("/Pa_ste Address"), NULL, addressbook_clip_paste_address_cb, 0, NULL}
+#endif
};
/**
* Lookup table of error messages for LDAP errors.
*/
static ErrMsgTableEntry _lutErrorsLDAP_[] = {
- { MGU_SUCCESS, N_("Success") },
- { MGU_LDAP_CONNECT, N_("Error connecting to LDAP server") },
- { MGU_LDAP_INIT, N_("Error initializing LDAP") },
- { MGU_LDAP_BIND, N_("Error binding to LDAP server") },
- { MGU_LDAP_SEARCH, N_("Error searching LDAP database") },
- { MGU_LDAP_TIMEOUT, N_("Timeout performing LDAP operation") },
- { MGU_LDAP_CRITERIA, N_("Error in LDAP search criteria") },
- { MGU_LDAP_CRITERIA, N_("Error in LDAP search criteria") },
- { MGU_LDAP_NOENTRIES, N_("No LDAP entries found for search criteria") },
+ { LDAPRC_SUCCESS, N_("Success") },
+ { LDAPRC_CONNECT, N_("Error connecting to LDAP server") },
+ { LDAPRC_INIT, N_("Error initializing LDAP") },
+ { LDAPRC_BIND, N_("Error binding to LDAP server") },
+ { LDAPRC_SEARCH, N_("Error searching LDAP database") },
+ { LDAPRC_TIMEOUT, N_("Timeout performing LDAP operation") },
+ { LDAPRC_CRITERIA, N_("Error in LDAP search criteria") },
+ { LDAPRC_NOENTRIES, N_("No LDAP entries found for search criteria") },
+ { LDAPRC_STOP_FLAG, N_("LDAP search terminated on request") },
{ 0, NULL }
};
#endif
addressbook_set_target_compose(target);
}
-void addressbook_destroy() {
+/**
+ * Destroy addressbook.
+ */
+void addressbook_destroy( void ) {
/* Free up address stuff */
if( _addressSelect_ != NULL ) {
addrselect_list_free( _addressSelect_ );
}
if( _addressIndex_ != NULL ) {
addrindex_free_index( _addressIndex_ );
- addrindex_teardown( _addressIndex_ );
+ addrindex_teardown();
}
_addressSelect_ = NULL;
_clipBoard_ = NULL;
return addrbook.target_compose;
}
-void addressbook_refresh(void)
+/**
+ * Refresh addressbook and save to file(s).
+ */
+void addressbook_refresh( void )
{
if (addrbook.window) {
if (addrbook.treeSelected) {
}
+/**
+ * Close address book window and save to file(s).
+ */
static gint addressbook_close( void ) {
gtk_widget_hide(addrbook.window);
addressbook_export_to_file();
return TRUE;
}
+/**
+ * Display message in status line.
+ * \param msg Message to display.
+ */
static void addressbook_status_show( gchar *msg ) {
if( addrbook.statusbar != NULL ) {
gtk_statusbar_pop(
addressbook_list_select_clear();
}
-/*
-* Setup address list popup menu.
-* Enter: pobj Parent address object in address tree.
-* obj Address object in address list.
-*/
+/**
+ * Setup address list popup menu items. Items are enabled or disabled as
+ * required.
+ */
static void addressbook_list_menu_setup( void ) {
GtkCTree *clist = NULL;
AddressObject *pobj = NULL;
gboolean canCut = FALSE;
gboolean canCopy = FALSE;
gboolean canPaste = FALSE;
+ gboolean canBrowse = FALSE;
pobj = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), addrbook.treeSelected );
if( pobj == NULL ) return;
menu_set_insensitive_all( GTK_MENU_SHELL(addrbook.list_popup) );
if( pobj->type == ADDR_DATASOURCE ) {
+ /* Parent object is a data source */
ads = ADAPTER_DSOURCE(pobj);
ds = ads->dataSource;
iface = ds->interface;
}
}
else if( pobj->type != ADDR_INTERFACE ) {
+ /* Parent object is not an interface */
ds = addressbook_find_datasource( addrbook.treeSelected );
iface = ds->interface;
if( ! iface->readOnly ) {
+ /* Folder or group */
if( pobj->type == ADDR_ITEM_FOLDER || pobj->type == ADDR_ITEM_GROUP ) {
menu_set_sensitive( addrbook.list_factory, "/New Address", TRUE );
gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
if( obj ) canEdit = TRUE;
}
+ /* Folder */
if( pobj->type == ADDR_ITEM_FOLDER ) {
menu_set_sensitive( addrbook.list_factory, "/New Folder", TRUE );
menu_set_sensitive( addrbook.list_factory, "/New Group", TRUE );
if( ! addrclip_is_empty( _clipBoard_ ) ) canPaste = TRUE;
if( ! addrselect_test_empty( _addressSelect_ ) ) canCut = TRUE;
}
+ if( iface->type == ADDR_IF_LDAP ) {
+ if( obj ) canBrowse = TRUE;
+ }
}
if( ! addrselect_test_empty( _addressSelect_ ) ) canCopy = TRUE;
- canDelete = canEdit;
canDelete = canEdit;
/* Disable edit if more than one row selected */
if( GTK_CLIST(clist)->selection && GTK_CLIST(clist)->selection->next ) canEdit = FALSE;
+ /* Now go finalize menu items */
menu_set_sensitive( addrbook.list_factory, "/Edit", canEdit );
menu_set_sensitive( addrbook.list_factory, "/Delete", canDelete );
menu_set_sensitive( addrbook.menu_factory, "/Address/Delete", canDelete );
gtk_widget_set_sensitive( addrbook.del_btn, canDelete );
+
+#ifdef USE_LDAP
+ menu_set_sensitive( addrbook.list_factory, "/Browse Entry", canBrowse );
+#endif
}
static void addressbook_list_selected(GtkCList *clist, gint row, gint column,
}
}
-/*
+/**
* Add list of items into tree node below specified tree node.
- * Enter: treeNode Tree node.
- * ds Data source.
- * listItems List of items.
+ * \param treeNode Tree node.
+ * \param ds Data source.
+ * \param listItems List of items.
*/
static void addressbook_treenode_add_list(
GtkCTreeNode *treeNode, AddressDataSource *ds, GList *listItems )
}
}
-/*
-* Cut from address list widget.
-*/
+/**
+ * Cut from address list widget.
+ */
static void addressbook_clip_cut_cb( void ) {
_clipBoard_->cutFlag = TRUE;
addrclip_clear( _clipBoard_ );
/* addrclip_list_show( _clipBoard_, stdout ); */
}
-/*
-* Copy from address list widget.
-*/
+/**
+ * Copy from address list widget.
+ */
static void addressbook_clip_copy_cb( void ) {
_clipBoard_->cutFlag = FALSE;
addrclip_clear( _clipBoard_ );
/* addrclip_list_show( _clipBoard_, stdout ); */
}
-/*
-* Paste clipboard into address list widget.
-*/
+/**
+ * Paste clipboard into address list widget.
+ */
static void addressbook_clip_paste_cb( void ) {
GtkCTree *ctree = GTK_CTREE( addrbook.ctree );
AddressObject *pobj = NULL;
}
-/*
-* Paste clipboard email addresses only into address list widget.
-*/
+/**
+ * Paste clipboard email addresses only into address list widget.
+ */
static void addressbook_clip_paste_address_cb( void ) {
GtkCTree *clist = GTK_CTREE(addrbook.clist);
GtkCTree *ctree;
}
}
-/*
-* Add current treenode object to clipboard. Note that widget only allows
-* one entry from the tree list to be selected.
-*/
+/**
+ * Add current treenode object to clipboard. Note that widget only allows
+ * one entry from the tree list to be selected.
+ */
static void addressbook_treenode_to_clipboard( void ) {
AddressObject *obj = NULL;
AddressDataSource *ds = NULL;
}
}
-/*
-* Cut from tree widget.
-*/
+/**
+ * Cut from tree widget.
+ */
static void addressbook_treenode_cut_cb( void ) {
_clipBoard_->cutFlag = TRUE;
addressbook_treenode_to_clipboard();
/* addrclip_list_show( _clipBoard_, stdout ); */
}
-/*
-* Copy from tree widget.
-*/
+/**
+ * Copy from tree widget.
+ */
static void addressbook_treenode_copy_cb( void ) {
_clipBoard_->cutFlag = FALSE;
addressbook_treenode_to_clipboard();
/* addrclip_list_show( _clipBoard_, stdout ); */
}
-/*
-* Paste clipboard into address tree widget.
-*/
+/**
+ * Paste clipboard into address tree widget.
+ */
static void addressbook_treenode_paste_cb( void ) {
addressbook_clip_paste_cb();
}
+/**
+ * Clear selected entries in clipboard.
+ */
static void addressbook_list_select_clear( void ) {
addrselect_list_clear( _addressSelect_ );
}
AddressInterface *iface = NULL;
AddressDataSource *ds = NULL;
gboolean canEdit = FALSE;
+ gboolean canDelete = FALSE;
gboolean canCut = FALSE;
gboolean canCopy = FALSE;
gboolean canPaste = FALSE;
ds = ads->dataSource;
iface = ds->interface;
canEdit = TRUE;
+ canDelete = TRUE;
if( iface->readOnly ) {
canTreePaste = FALSE;
}
}
else {
canEdit = TRUE;
+ canDelete = TRUE;
canTreeCut = TRUE;
menu_set_sensitive( addrbook.tree_factory, "/New Address", TRUE );
menu_set_sensitive( addrbook.tree_factory, "/New Folder", TRUE );
}
canTreeCopy = TRUE;
iface = ds->interface;
- if( iface->externalQuery ) canLookup = TRUE;
+ if( iface->externalQuery ) {
+ /* Enable deletion of LDAP folder */
+ canLookup = TRUE;
+ canDelete = TRUE;
+ }
}
else if (obj->type == ADDR_ITEM_GROUP) {
ds = addressbook_find_datasource( addrbook.treeSelected );
iface = ds->interface;
if( ! iface->readOnly ) {
canEdit = TRUE;
+ canDelete = TRUE;
menu_set_sensitive( addrbook.tree_factory, "/New Address", TRUE );
gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
}
/* Enable edit */
menu_set_sensitive( addrbook.tree_factory, "/Edit", canEdit );
- menu_set_sensitive( addrbook.tree_factory, "/Delete", canEdit );
+ menu_set_sensitive( addrbook.tree_factory, "/Delete", canDelete );
menu_set_sensitive( addrbook.tree_factory, "/Cut", canTreeCut );
menu_set_sensitive( addrbook.tree_factory, "/Copy", canTreeCopy );
menu_set_sensitive( addrbook.tree_factory, "/Paste", canTreePaste );
folder = addressbook_edit_folder( abf, parentFolder, NULL );
if( folder ) {
GtkCTreeNode *nn;
- nn = addressbook_node_add_folder( addrbook.treeSelected, ds, folder, ADDR_ITEM_FOLDER );
+ nn = addressbook_node_add_folder(
+ addrbook.treeSelected, ds, folder, ADDR_ITEM_FOLDER );
gtk_ctree_expand( ctree, addrbook.treeSelected );
- if( addrbook.treeSelected == addrbook.opened ) addressbook_set_clist(obj);
+ if( addrbook.treeSelected == addrbook.opened )
+ addressbook_set_clist(obj);
}
}
GtkCTreeNode *nn;
nn = addressbook_node_add_group( addrbook.treeSelected, ds, group );
gtk_ctree_expand( ctree, addrbook.treeSelected );
- if( addrbook.treeSelected == addrbook.opened ) addressbook_set_clist(obj);
+ if( addrbook.treeSelected == addrbook.opened )
+ addressbook_set_clist(obj);
}
}
is_leaf, expanded);
}
-/*
-* Edit data source.
-* Enter: obj Address object to edit.
-* node Node in tree.
-* Return: New name of data source.
-*/
+/**
+ * Edit data source.
+ * \param obj Address object to edit.
+ * \param node Node in tree.
+ * \return New name of data source.
+ */
static gchar *addressbook_edit_datasource( AddressObject *obj, GtkCTreeNode *node ) {
gchar *newName = NULL;
AddressDataSource *ds = NULL;
}
}
-/*
-* Delete an item from the tree widget.
-*/
-static void addressbook_treenode_delete_cb(gpointer data, guint action,
- GtkWidget *widget)
+typedef enum {
+ ADDRTREE_DEL_NONE,
+ ADDRTREE_DEL_DATA,
+ ADDRTREE_DEL_FOLDER_ONLY,
+ ADDRTREE_DEL_FOLDER_ADDR
+} TreeItemDelType ;
+
+/**
+ * Delete an item from the tree widget.
+ * \param data Data passed in.
+ * \param action Action.
+ * \param widget Widget issuing callback.
+ */
+static void addressbook_treenode_delete_cb(
+ gpointer data, guint action, GtkWidget *widget )
{
GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
GtkCTreeNode *node = NULL;
AddressObject *obj;
gchar *message;
AlertValue aval;
- AddressBookFile *abf = NULL;
+ AddrBookBase *adbase;
+ AddressCache *cache;
AdapterDSource *ads = NULL;
AddressInterface *iface = NULL;
AddressDataSource *ds = NULL;
gboolean remFlag = FALSE;
+ TreeItemDelType delType;
if( ! addrbook.treeSelected ) return;
node = addrbook.treeSelected;
ds = addressbook_find_datasource( node );
if( ds == NULL ) return;
- /* Only allow deletion from non-readOnly data sources */
+ /* Only allow deletion from non-readOnly */
iface = ds->interface;
- if( iface->readOnly ) return;
+ if( iface->readOnly ) {
+ /* Allow deletion of query results */
+ if( ! iface->externalQuery ) return;
+ }
}
/* Confirm deletion */
+ delType = ADDRTREE_DEL_NONE;
if( obj->type == ADDR_ITEM_FOLDER ) {
- message = g_strdup_printf( _(
- "Do you want to delete the folder AND all addresses in `%s' ? \n" \
- "If deleting the folder only, addresses will be moved into parent folder." ),
- obj->name );
- aval = alertpanel( _("Delete"), message,
- _("Folder only"), _("Folder and Addresses"), _("Cancel") );
- g_free(message);
- if( aval == G_ALERTOTHER ) return;
+ if( iface->externalQuery ) {
+ message = g_strdup_printf( _(
+ "Do you want to delete the query " \
+ "results and addresses in `%s' ?" ),
+ obj->name );
+ aval = alertpanel( _("Delete"), message,
+ _("Yes"), _("No"), NULL );
+ g_free(message);
+ if( aval == G_ALERTDEFAULT ) {
+ delType = ADDRTREE_DEL_FOLDER_ADDR;
+ }
+ }
+ else {
+ message = g_strdup_printf( _(
+ "Do you want to delete the folder " \
+ "AND all addresses in `%s' ? \n" \
+ "If deleting the folder only, addresses " \
+ "will be moved into parent folder." ),
+ obj->name );
+ aval = alertpanel( _("Delete"), message,
+ _("Folder only"),
+ _("Folder and Addresses"),
+ _("Cancel") );
+ g_free(message);
+ if( aval == G_ALERTDEFAULT ) {
+ delType = ADDRTREE_DEL_FOLDER_ONLY;
+ }
+ else if( aval == G_ALERTALTERNATE ) {
+ delType = ADDRTREE_DEL_FOLDER_ADDR;
+ }
+ }
}
else {
message = g_strdup_printf(_("Really delete `%s' ?"), obj->name);
aval = alertpanel(_("Delete"), message, _("Yes"), _("No"), NULL);
g_free(message);
- if (aval != G_ALERTDEFAULT) return;
+ if( aval == G_ALERTDEFAULT ) delType = ADDRTREE_DEL_DATA;
}
+ if( delType == ADDRTREE_DEL_NONE ) return;
/* Proceed with deletion */
if( obj->type == ADDR_DATASOURCE ) {
+ /* Remove node from tree */
+ gtk_ctree_remove_node( ctree, node );
+
/* Remove data source. */
if( addrindex_index_remove_datasource( _addressIndex_, ds ) ) {
addrindex_free_datasource( ds );
- remFlag = TRUE;
}
+ return;
}
- else {
- abf = addressbook_get_book_file();
- if( abf == NULL ) return;
+
+ /* Get reference to cache */
+ adbase = ( AddrBookBase * ) ds->rawDataSource;
+ if( adbase == NULL ) return;
+ cache = adbase->addressCache;
+
+ /* Remove query results folder */
+ if( iface->externalQuery ) {
+ AdapterFolder *adapter = ADAPTER_FOLDER(obj);
+ ItemFolder *folder = adapter->itemFolder;
+
+ addrindex_remove_results( ds, folder );
+ gtk_ctree_remove_node( ctree, node );
+ return;
}
+ /* Code below is valid for regular address book deletion */
if( obj->type == ADDR_ITEM_FOLDER ) {
AdapterFolder *adapter = ADAPTER_FOLDER(obj);
ItemFolder *item = adapter->itemFolder;
- if( aval == G_ALERTDEFAULT ) {
+
+ if( delType == ADDRTREE_DEL_FOLDER_ONLY ) {
/* Remove folder only */
- item = addrbook_remove_folder( abf, item );
+ item = addrcache_remove_folder( cache, item );
if( item ) {
addritem_free_item_folder( item );
addressbook_move_nodes_up( ctree, node );
remFlag = TRUE;
}
}
- else if( aval == G_ALERTALTERNATE ) {
+ else if( delType == ADDRTREE_DEL_FOLDER_ADDR ) {
/* Remove folder and addresses */
- item = addrbook_remove_folder_delete( abf, item );
+ item = addrcache_remove_folder_delete( cache, item );
if( item ) {
addritem_free_item_folder( item );
remFlag = TRUE;
AdapterGroup *adapter = ADAPTER_GROUP(obj);
ItemGroup *item = adapter->itemGroup;
- item = addrbook_remove_group( abf, item );
+ item = addrcache_remove_group( cache, item );
if( item ) {
addritem_free_item_group( item );
remFlag = TRUE;
ItemPerson *person = addressbook_edit_person( abf, NULL, NULL, FALSE );
if( person && addrbook.treeSelected == addrbook.opened ) {
gtk_clist_unselect_all( GTK_CLIST(addrbook.clist) );
- addressbook_folder_refresh_one_person( GTK_CTREE(addrbook.clist), person );
+ addressbook_folder_refresh_one_person(
+ GTK_CTREE(addrbook.clist), person );
}
}
}
}
}
-/*
-* Search for specified child group node in address index tree.
-* Enter: parent Parent node.
-* group Group to find.
-*/
+/**
+ * Search for specified child group node in address index tree.
+ * \param parent Parent node.
+ * \param group Group to find.
+ */
static GtkCTreeNode *addressbook_find_group_node( GtkCTreeNode *parent, ItemGroup *group ) {
GtkCTreeNode *node = NULL;
GtkCTreeRow *currRow;
atci->iconXpmOpen, atci->maskXpmOpen,
FALSE, FALSE);
gtk_ctree_node_set_row_data(clist, nodeGroup, group );
+ gtk_sctree_sort_node(clist, NULL);
}
- gtk_sctree_sort_node(clist, NULL);
-
/* Free up the list */
mgu_clear_list( items );
g_list_free( items );
}
-/*
-* Search ctree widget callback function.
-* Enter: pA Pointer to node.
-* pB Pointer to data item being sought.
-* Return: Zero (0) if group found.
-*/
+/**
+ * Search ctree widget callback function.
+ * \param pA Pointer to node.
+ * \param pB Pointer to data item being sought.
+ * \return Zero (0) if group found.
+ */
static int addressbook_treenode_find_group_cb( gconstpointer pA, gconstpointer pB ) {
AddressObject *aoA;
return 1;
}
-/*
-* Search ctree widget callback function.
-* Enter: pA Pointer to node.
-* pB Pointer to data item being sought.
-* Return: Zero (0) if folder found.
-*/
+/**
+ * Search ctree widget callback function.
+ * \param pA Pointer to node.
+ * \param pB Pointer to data item being sought.
+ * \return Zero (0) if folder found.
+ */
static int addressbook_treenode_find_folder_cb( gconstpointer pA, gconstpointer pB ) {
AddressObject *aoA;
}
}
-/*
-* Find parent datasource for specified tree node.
-* Enter: node Node to test.
-* Return: Data source, or NULL if not found.
-*/
+/**
+ * Find parent datasource for specified tree node.
+ * \param node Node to test.
+ * \return Data source, or NULL if not found.
+ */
static AddressDataSource *addressbook_find_datasource( GtkCTreeNode *node ) {
AddressDataSource *ds = NULL;
AddressObject *ao;
return ds;
}
-/*
-* Load address list widget with children of specified object.
-* Enter: obj Parent object to be loaded.
-*/
+/**
+ * Load address list widget with children of specified object.
+ * \param obj Parent object to be loaded.
+ */
static void addressbook_set_clist( AddressObject *obj ) {
GtkCTree *ctreelist = GTK_CTREE(addrbook.clist);
GtkCList *clist = GTK_CLIST(addrbook.clist);
gtk_clist_thaw(clist);
}
-/*
-* Call back function to free adaptor. Call back is setup by function
-* gtk_ctree_node_set_row_data_full() when node is populated. This function is
-* called when the address book tree widget node is removed by calling
-* function gtk_ctree_remove_node().
-* Enter: data Tree node's row data.
-*/
+/**
+ * Call back function to free adaptor. Call back is setup by function
+ * gtk_ctree_node_set_row_data_full() when node is populated. This function is
+ * called when the address book tree widget node is removed by calling
+ * function gtk_ctree_remove_node().
+ *
+ * \param data Tree node's row data.
+ */
static void addressbook_free_treenode( gpointer data ) {
AddressObject *ao;
}
addrIndex = addrindex_create_index();
- addrindex_initialize( addrIndex );
+ addrindex_initialize();
/* Use new address book index. */
addrindex_set_file_path( addrIndex, get_rc_dir() );
return added;
}
-/*
-* Add group into the address index tree.
-* Enter: node Parent node.
-* ds Data source.
-* itemGroup Group to add.
-* Return: Inserted node.
-*/
+/**
+ * Add group into the address index tree.
+ * \param node Parent node.
+ * \param ds Data source.
+ * \param itemGroup Group to add.
+ * \return Inserted node.
+ */
static GtkCTreeNode *addressbook_node_add_group(
GtkCTreeNode *node, AddressDataSource *ds,
ItemGroup *itemGroup )
* \param queryType Query type.
* \param status Status/Error code.
*/
-static void addressbook_search_message( AddrQueryType queryType, gint sts ) {
+static void addressbook_search_message( gint queryType, gint sts ) {
gchar *desc = NULL;
*addressbook_msgbuf = '\0';
desc = addressbook_err2string( _lutErrorsLDAP_, sts );
#endif
}
- else {
- desc = NULL;
- }
+ }
+ if( desc ) {
g_snprintf( addressbook_msgbuf,
sizeof(addressbook_msgbuf), "%s", desc );
+ addressbook_status_show( addressbook_msgbuf );
+ }
+ else {
+ addressbook_status_show( "" );
}
- addressbook_status_show( addressbook_msgbuf );
}
/**
addressbook_set_clist( obj );
}
-static gchar *_tempMessage_ = N_("Busy searching...");
+/**
+ * Message that is displayed whilst a query is executing in a background
+ * thread.
+ */
+static gchar *_tempMessage_ = N_( "Busy searching..." );
/**
* Address search idle function. This function is called during UI idle time
}
/**
- * Search completion function. This removes the query from the idle list.
+ * Search completion callback function. This removes the query from the idle
+ * list.
*
- * \param queryID Query to be removed.
- * \param queryType Query type being removed.
- * \param status Search status.
+ * \param sender Sender of query.
+ * \param queryID Query ID of search request.
+ * \param status Search status.
+ * \param data Query data.
*/
-static void addressbook_search_idle_end(
- gint queryID, AddrQueryType queryType, gint status )
+static void addressbook_search_callback_end(
+ gpointer sender, gint queryID, gint status, gpointer data )
{
- gpointer data;
+ gpointer ptrQID;
+ QueryRequest *req;
+ AddrQueryObject *aqo;
- data = GINT_TO_POINTER( queryID );
- if( data ) {
- gtk_idle_remove_by_data( data );
+ /* Remove idler function */
+ ptrQID = GINT_TO_POINTER( queryID );
+ if( ptrQID ) {
+ gtk_idle_remove_by_data( ptrQID );
}
+
+ /* Refresh addressbook contents */
addressbook_refresh_current();
- addressbook_search_message( queryType, status );
+ req = qrymgr_find_request( queryID );
+ if( req != NULL ) {
+ aqo = ( AddrQueryObject * ) req->queryList->data;
+ addressbook_search_message( aqo->queryType, status );
+ }
+
+ /* Stop the search */
+ addrindex_stop_search( queryID );
}
+/**
+ * Label (a format string) that is used to name each folder.
+ */
+static gchar *_queryFolderLabel_ = N_( "Search '%s'" );
+
/**
* Perform search.
*
AddressDataSource *ds, gchar *searchTerm,
GtkCTreeNode *pNode )
{
- AddressBookFile *abf;
+ AddrBookBase *adbase;
+ AddressCache *cache;
ItemFolder *folder;
GtkCTree *ctree;
GtkCTreeNode *nNode;
guint idleID;
AddressObjectType aoType;
+ /* Setup a query */
+ if( *searchTerm == '\0' || strlen( searchTerm ) < 1 ) return;
+
if( ds->type == ADDR_IF_LDAP ) {
-#ifdef USE_LDAP
+#if USE_LDAP
aoType = ADDR_LDAP_QUERY;
#endif
}
else {
return;
}
- abf = ds->rawDataSource;
-
- /* Setup a query */
- if( *searchTerm == '\0' || strlen( searchTerm ) < 1 ) return;
+ /* Get reference to address cache */
+ adbase = ( AddrBookBase * ) ds->rawDataSource;
+ cache = adbase->addressCache;
/* Create a folder for the search results */
- folder = addrbook_add_new_folder( abf, NULL );
- name = g_strdup_printf( "Search '%s'", searchTerm );
+ folder = addrcache_add_new_folder( cache, NULL );
+ name = g_strdup_printf( _queryFolderLabel_, searchTerm );
addritem_folder_set_name( folder, name );
addritem_folder_set_remarks( folder, "" );
g_free( name );
}
/* Setup the search */
- queryID = addrindex_setup_static_search(
- ds, searchTerm, folder, addressbook_search_idle_end );
+ queryID = addrindex_setup_explicit_search(
+ ds, searchTerm, folder, addressbook_search_callback_end, NULL );
if( queryID == 0 ) return;
/* Set up idler function */
GINT_TO_POINTER( queryID ) );
/* Start search, sit back and wait for something to happen */
- addrindex_start_static_search( queryID, idleID );
+ addrindex_start_search( queryID );
addressbook_status_show( _tempMessage_ );
}
g_free( searchTerm );
}
+/**
+ * Browse address entry for highlighted entry.
+ */
+static void addressbook_browse_entry_cb( void ) {
+ GtkCTree *clist = GTK_CTREE(addrbook.clist);
+ AddressObject *obj;
+ AddressDataSource *ds;
+ AddressInterface *iface;
+ ItemPerson *person;
+ ItemEMail *email;
+
+ if( addrbook.listSelected == NULL ) return;
+ obj = gtk_ctree_node_get_row_data( clist, addrbook.listSelected );
+ g_return_if_fail(obj != NULL);
+
+ ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
+ if( ds == NULL ) return;
+ iface = ds->interface;
+ if( ! iface->haveLibrary ) return;
+
+ person = NULL;
+ if( obj->type == ADDR_ITEM_EMAIL ) {
+ email = ( ItemEMail * ) obj;
+ if( email == NULL ) return;
+ person = ( ItemPerson * ) ADDRITEM_PARENT(email);
+ }
+ else if( obj->type == ADDR_ITEM_PERSON ) {
+ person = ( ItemPerson * ) obj;
+ }
+ else {
+ /* None of these */
+ return;
+ }
+
+ if( iface->type == ADDR_IF_LDAP ) {
+#ifdef USE_LDAP
+ browseldap_entry( ds, person->externalID );
+#endif
+ }
+}
+
/* **********************************************************************
* Build lookup tables.
* ***********************************************************************
g_free( adapter );
}
-/*
+/**
* Build GUI interface list.
*/
-void addrbookctl_build_iflist() {
+void addrbookctl_build_iflist( void ) {
AddressTypeControlItem *atci;
AdapterInterface *adapter;
GList *list = NULL;
adapter->haveLibrary = interface->haveLibrary;
ADDRESS_OBJECT(adapter)->type = ADDR_INTERFACE;
ADDRESS_OBJECT_NAME(adapter) = g_strdup( atci->displayName );
- _addressInterfaceList_ = g_list_append( _addressInterfaceList_, adapter );
+ _addressInterfaceList_ =
+ g_list_append( _addressInterfaceList_, adapter );
}
list = g_list_next( list );
}
}
+#if 0
void addrbookctl_free_selection( GList *list ) {
GList *node = list;
while( node ) {
}
g_list_free( list );
}
+#endif
-/*
-* Find GUI interface type specified interface type.
-* Return: Interface item, or NULL if not found.
-*/
+/**
+ * Find GUI interface type specified interface type.
+ * \param ifType Interface type.
+ * \return Interface item, or NULL if not found.
+ */
AdapterInterface *addrbookctl_find_interface( AddressIfType ifType ) {
GList *node = _addressInterfaceList_;
while( node ) {
return NULL;
}
-/*
-* Build interface list selection.
-*/
-void addrbookctl_build_ifselect() {
+/**
+ * Build interface list selection.
+ */
+void addrbookctl_build_ifselect( void ) {
GList *newList = NULL;
gchar *selectStr;
gchar **splitStr;
newList = NULL;
}
-/* **********************************************************************
-* Add sender to address book.
-* ***********************************************************************
-*/
+/* ***********************************************************************
+ * Add sender to address book.
+ * ***********************************************************************
+ */
/*
* This function is used by the Add sender to address book function.
*/
-gboolean addressbook_add_contact( const gchar *name, const gchar *address, const gchar *remarks ) {
+gboolean addressbook_add_contact(
+ const gchar *name, const gchar *address, const gchar *remarks )
+{
debug_print( "addressbook_add_contact: name/address: %s - %s\n", name, address );
if( addressadd_selection( _addressIndex_, name, address, remarks ) ) {
debug_print( "addressbook_add_contact - added\n" );
}
/* **********************************************************************
-* Address completion support.
-* ***********************************************************************
-*/
-
-/*
-* This function is used by the address completion function to load
-* addresses.
-* Enter: callBackFunc Function to be called when an address is
-* to be loaded.
-* Return: TRUE if data loaded, FALSE if address index not loaded.
-*/
-gboolean addressbook_load_completion(
- gint (*callBackFunc) ( const gchar *, const gchar *, const gchar * ) )
-{
- debug_print( "addressbook_load_completion\n" );
- return addrindex_load_completion( _addressIndex_, callBackFunc );
-}
-
-/* **********************************************************************
-* Address Import.
-* ***********************************************************************
-*/
+ * Address Import.
+ * ***********************************************************************
+ */
-/*
-* Import LDIF file.
-*/
-static void addressbook_import_ldif_cb() {
+/**
+ * Import LDIF file.
+ */
+static void addressbook_import_ldif_cb( void ) {
AddressDataSource *ds = NULL;
AdapterDSource *ads = NULL;
AddressBookFile *abf = NULL;
}
}
-/*
-* Import MUTT file.
-*/
-static void addressbook_import_mutt_cb() {
+/**
+ * Import MUTT file.
+ */
+static void addressbook_import_mutt_cb( void ) {
AddressDataSource *ds = NULL;
AdapterDSource *ads = NULL;
AddressBookFile *abf = NULL;
}
}
-/*
-* Import Pine file.
-*/
-static void addressbook_import_pine_cb() {
+/**
+ * Import Pine file.
+ */
+static void addressbook_import_pine_cb( void ) {
AddressDataSource *ds = NULL;
AdapterDSource *ads = NULL;
AddressBookFile *abf = NULL;
}
}
-/*
+/**
* Harvest addresses.
- * Enter: folderItem Folder to import.
- * sourceInd Source indicator: FALSE - Folder, TRUE - Messages.
- * msgList List of message numbers, or NULL to process folder.
+ * \param folderItem Folder to import.
+ * \param sourceInd Source indicator: FALSE - Folder, TRUE - Messages.
+ * \param msgList List of message numbers, or NULL to process folder.
*/
void addressbook_harvest(
FolderItem *folderItem, gboolean sourceInd, GList *msgList )
}
}
-/*
-* Export HTML file.
-*/
+/**
+ * Export HTML file.
+ */
static void addressbook_export_html_cb( void ) {
GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
AddressObject *obj;
addressbook_exp_html( cache );
}
-/*
-* Export LDIF file.
-*/
+/**
+ * Export LDIF file.
+ */
static void addressbook_export_ldif_cb( void ) {
GtkCTree *ctree = GTK_CTREE(addrbook.ctree);
AddressObject *obj;
#define DISP_OLD_COMMON _("Common address")
#define DISP_OLD_PERSONAL _("Personal address")
+/**
+ * Singleton object.
+ */
+static AddressIndex *_addressIndex_ = NULL;
+
/*
* Define attribute name-value pair.
*/
g_hash_table_destroy( table );
}
-/*
+/**
* Remove data source from internal hashtable.
* \param addrIndex Address index.
* \param ds Data source to remove.
}
}
-/*
- * Create a new address index.
+/**
+ * Create a new address index. This is created as a singleton object.
* \return Initialized address index object.
*/
AddressIndex *addrindex_create_index( void ) {
- AddressIndex *addrIndex = g_new0( AddressIndex, 1 );
+ AddressIndex *index;
+
+ if( _addressIndex_ == NULL ) {
+ index = g_new0( AddressIndex, 1 );
+ ADDRITEM_TYPE(index) = ITEMTYPE_INDEX;
+ ADDRITEM_ID(index) = NULL;
+ ADDRITEM_NAME(index) = g_strdup( "Address Index" );
+ ADDRITEM_PARENT(index) = NULL;
+ ADDRITEM_SUBTYPE(index) = 0;
+ index->filePath = NULL;
+ index->fileName = NULL;
+ index->retVal = MGU_SUCCESS;
+ index->needsConversion = FALSE;
+ index->wasConverted = FALSE;
+ index->conversionError = FALSE;
+ index->interfaceList = NULL;
+ index->lastType = ADDR_IF_NONE;
+ index->dirtyFlag = FALSE;
+ index->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
+ index->loadedFlag = FALSE;
+ index->searchOrder = NULL;
+ addrindex_build_if_list( index );
+ _addressIndex_ = index;
+ }
+ return _addressIndex_;
+}
- ADDRITEM_TYPE(addrIndex) = ITEMTYPE_INDEX;
- ADDRITEM_ID(addrIndex) = NULL;
- ADDRITEM_NAME(addrIndex) = g_strdup( "Address Index" );
- ADDRITEM_PARENT(addrIndex) = NULL;
- ADDRITEM_SUBTYPE(addrIndex) = 0;
- addrIndex->filePath = NULL;
- addrIndex->fileName = NULL;
- addrIndex->retVal = MGU_SUCCESS;
- addrIndex->needsConversion = FALSE;
- addrIndex->wasConverted = FALSE;
- addrIndex->conversionError = FALSE;
- addrIndex->interfaceList = NULL;
- addrIndex->lastType = ADDR_IF_NONE;
- addrIndex->dirtyFlag = FALSE;
- addrIndex->hashCache = g_hash_table_new( g_str_hash, g_str_equal );
- addrIndex->loadedFlag = FALSE;
- addrIndex->searchOrder = NULL;
- addrindex_build_if_list( addrIndex );
- return addrIndex;
+/**
+ * Return reference to address index.
+ * \return Address index object.
+ */
+AddressIndex *addrindex_get_object( void ) {
+ return _addressIndex_;
}
/**
/**
* Perform any other initialization of address index.
- * \param addrIndex Address index.
*/
-void addrindex_initialize( AddressIndex *addrIndex ) {
+void addrindex_initialize( void ) {
qrymgr_initialize();
- addrcompl_initialize( addrIndex );
+ addrcompl_initialize();
}
/**
* Perform any other teardown of address index.
- * \param addrIndex Address index.
*/
-void addrindex_teardown( AddressIndex *addrIndex ) {
+void addrindex_teardown( void ) {
addrcompl_teardown();
qrymgr_teardown();
}
addrIndex->loadedFlag = FALSE;
g_free( addrIndex );
+ addrIndex = NULL;
+ _addressIndex_ = NULL;
}
/**
}
}
-/*
+#if 0
static void addrindex_print_fragment_r(
const AddressIfFragment *fragment, FILE *stream, gint lvl )
{
static void addrindex_print_fragment( const AddressIfFragment *fragment, FILE *stream ) {
addrindex_print_fragment_r( fragment, stream, 0 );
}
-*/
+#endif
/**
* Read/parse address index file, creating a data source for a regular
*/
/**
- * Current query ID. This is incremented for each query created.
- */
-static gint _currentQueryID_ = 0;
-
-/*
- * Variables for the search that is being performed.
- */
-static gchar *_searchTerm_ = NULL;
-static gpointer _searchTarget_ = NULL;
-static AddrSearchCallbackFunc *_searchCallback_ = NULL;
-
-/**
- * Setup or register the search that will be performed.
- * \param addrIndex Address index object.
- * \param searchTerm Search term. A private copy will be made.
- * \param target Target object that will receive data.
- * \param callBack Callback function.
+ * Setup or register the dynamic search that will be performed. The search
+ * is registered with the query manager.
+ *
+ * \param searchTerm Search term. A private copy will be made.
+ * \param callBackEntry Callback function that should be called when
+ * each entry is received.
+ * \param callBackEnd Callback function that should be called when
+ * search has finished running.
* \return ID allocated to query that will be executed.
*/
gint addrindex_setup_search(
- AddressIndex *addrIndex, const gchar *searchTerm,
- const gpointer target, AddrSearchCallbackFunc callBack )
+ const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
{
+ QueryRequest *req;
gint queryID;
- /* printf( "search term ::%s::\n", searchTerm ); */
- g_free( _searchTerm_ );
- _searchTerm_ = g_strdup( searchTerm );
+ /* Set up a dynamic address query */
+ req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
+ queryID = req->queryID;
+ qryreq_set_search_type( req, ADDRSEARCH_DYNAMIC );
- queryID = ++_currentQueryID_;
- _searchTarget_ = target;
- _searchCallback_ = callBack;
- /* printf( "query ID ::%d::\n", queryID ); */
+ /* printf( "***> query ID ::%d::\n", queryID ); */
return queryID;
}
#ifdef USE_LDAP
-/**
- * LDAP callback entry point for each address entry found.
- * \param qry LDAP query.
- * \param listEMail List of Item EMail objects found.
- */
-static void addrindex_ldap_entry_cb( LdapQuery *qry, GList *listEMail ) {
- /*
- GList *node;
-
- printf( "\naddrindex::addrindex_ldap_entry_cb ::%s::\n", qry->queryName );
- node = listEMail;
- while( node ) {
- ItemEMail *email = node->data;
- printf( "\temail ::%s::\n", email->address );
- node = g_list_next( node );
- }
- */
- if( _searchCallback_ ) {
- ( _searchCallback_ ) ( qry->queryID, listEMail, _searchTarget_ );
- }
- g_list_free( listEMail );
-}
-
-/**
- * LDAP callback entry point for completion of search.
- * \param qry LDAP query.
- */
-static void addrindex_ldap_end_cb( LdapQuery *qry ) {
- /* printf( "\naddrindex::addrindex_ldap_end_cb ::%s::\n", qry->queryName ); */
-}
-
-/**
- * Return results of previous query.
- * \param folder.
- * \return List of ItemEMail objects.
- */
-static void addrindex_ldap_use_previous(
- const ItemFolder *folder, const gint queryID )
-{
- GList *listEMail;
- GList *node;
- GList *nodeEM;
-
- listEMail = NULL;
- if( _searchCallback_ ) {
- node = folder->listPerson;
- while( node ) {
- AddrItemObject *aio = node->data;
- if( aio && aio->type == ITEMTYPE_PERSON ) {
- ItemPerson *person = node->data;
- nodeEM = person->listEMail;
- while( nodeEM ) {
- ItemEMail *email = nodeEM->data;
- nodeEM = g_list_next( nodeEM );
- listEMail = g_list_append( listEMail, email );
- }
- }
- node = g_list_next( node );
- }
- ( _searchCallback_ ) ( queryID, listEMail, _searchTarget_ );
- g_list_free( listEMail );
- }
-}
/*
- * Function prototype (not in header file or circular reference encountered!)
- */
-LdapQuery *ldapsvr_locate_query( LdapServer *server, const gchar *searchTerm );
-
-/**
- * Construct an LDAP query and initiate an LDAP dynamic search.
- * \param server LDAP server object.
- * \param queryID ID of search query to be executed.
+ * Function prototypes (not in header file or circular reference errors are
+ * encountered!)
*/
-static void addrindex_search_ldap( LdapServer *server, const gint queryID ) {
- LdapQuery *qry;
- gchar *name;
-
- if( ! server->searchFlag ) return;
-
- /* Retire any aged queries */
- ldapsvr_retire_query( server );
-
- /* Test whether any queries for the same term exist */
- qry = ldapsvr_locate_query( server, _searchTerm_ );
- if( qry ) {
- ItemFolder *folder = qry->folder;
-
- /* Touch query to ensure it hangs around for a bit longer */
- ldapqry_touch( qry );
- if( folder ) {
- addrindex_ldap_use_previous( folder, queryID );
- return;
- }
- }
-
- /* Construct a query */
- qry = ldapqry_create();
- ldapqry_set_query_id( qry, queryID );
- ldapqry_set_search_value( qry, _searchTerm_ );
- ldapqry_set_query_type( qry, LDAPQUERY_DYNAMIC );
- ldapqry_set_callback_entry( qry, addrindex_ldap_entry_cb );
- ldapqry_set_callback_end( qry, addrindex_ldap_end_cb );
-
- /* Name the query */
- name = g_strdup_printf( "Search for '%s'", _searchTerm_ );
- ldapqry_set_name( qry, name );
- g_free( name );
-
- ldapsvr_add_query( server, qry );
- ldapsvr_execute_query( server, qry );
-}
+LdapQuery *ldapsvr_new_dynamic_search(
+ LdapServer *server, QueryRequest *req );
+LdapQuery *ldapsvr_new_explicit_search(
+ LdapServer *server, QueryRequest *req, ItemFolder *folder );
#endif
/**
- * Perform the previously registered search.
- * \param addrIndex Address index object.
- * \param queryID ID of search query to be executed.
+ * Execute the previously registered dynamic search.
+ *
+ * \param req Address query object to execute.
* \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
* failed.
*/
-gboolean addrindex_start_search( AddressIndex *addrIndex, const gint queryID ) {
+static gboolean addrindex_start_dynamic( QueryRequest *req ) {
AddressInterface *iface;
AddressDataSource *ds;
GList *nodeIf;
GList *nodeDS;
gint type;
- /* printf( "addrindex_start_search::%d::\n", queryID ); */
- nodeIf = addrIndex->searchOrder;
+ /* printf( "addrindex_start_dynamic::%d::\n", req->queryID ); */
+ nodeIf = _addressIndex_->searchOrder;
while( nodeIf ) {
iface = nodeIf->data;
nodeIf = g_list_next( nodeIf );
if( ! iface->useInterface ) {
continue;
}
-
if( ! iface->externalQuery ) {
continue;
}
nodeDS = g_list_next( nodeDS );
#ifdef USE_LDAP
if( type == ADDR_IF_LDAP ) {
- LdapServer *server = ds->rawDataSource;
- addrindex_search_ldap( server, queryID );
+ LdapServer *server;
+ LdapQuery *qry;
+
+ server = ds->rawDataSource;
+ if( ! server->searchFlag ) {
+ continue;
+ }
+ if( ldapsvr_reuse_previous( server, req ) ) {
+ continue;
+ }
+
+ /* Start a new dynamic search */
+ qry = ldapsvr_new_dynamic_search( server, req );
+ if( qry ) {
+ ldapsvr_execute_query( server, qry );
+ }
}
#endif
}
/**
* Stop the previously registered search.
- * \param addrIndex Address index object.
+ *
* \param queryID ID of search query to stop.
*/
-void addrindex_stop_search( AddressIndex *addrIndex, const gint queryID ){
-#ifdef USE_LDAP
- AddressInterface *iface;
- AddressDataSource *ds;
- GList *nodeIf;
- GList *nodeDS;
- gint type;
+void addrindex_stop_search( const gint queryID ){
+ QueryRequest *req;
+ AddrQueryObject *aqo;
+ GList *node;
+ /* printf( "addrindex_stop_search/queryID=%d\n", queryID ); */
/* If query ID does not match, search has not been setup */
- /* if( queryID != _queryID_ ) return; */
-
- /* printf( "addrindex_stop_search::%d::\n", queryID ); */
- nodeIf = addrIndex->searchOrder;
- while( nodeIf ) {
- iface = nodeIf->data;
- nodeIf = g_list_next( nodeIf );
-
- if( ! iface->useInterface ) {
- continue;
- }
-
- type = iface->type;
- nodeDS = iface->listSource;
- while( nodeDS ) {
- ds = nodeDS->data;
- nodeDS = g_list_next( nodeDS );
- if( type == ADDR_IF_LDAP ) {
- LdapServer *server = ds->rawDataSource;
- ldapsvr_stop_all_query( server );
- }
- }
+ req = qrymgr_find_request( queryID );
+ if( req == NULL ) {
+ return;
}
-#endif
-}
+ /* Stop all queries that were associated with request */
+ node = req->queryList;
+ while( node ) {
+ aqo = node->data;
#ifdef USE_LDAP
-/**
- * LDAP callback entry point for completion of search.
- * \param qry LDAP query.
- */
-static void addrindex_ldap_end_static_cb( LdapQuery *qry ) {
- AddrQuery *addrQry;
- gint queryID;
- AddrQueryType queryType;
- AddrSearchStaticFunc *callBack;
-
- queryID = qry->queryID;
- queryType = qry->queryType;
- addrQry = qrymgr_find_query( queryID );
- if( addrQry == NULL ) {
- return;
+ if( aqo->queryType == ADDRQUERY_LDAP ) {
+ LdapQuery *qry = ( LdapQuery * ) aqo;
+ ldapqry_set_stop_flag( qry, TRUE );
+ }
+#endif
+ node->data = NULL;
+ node = g_list_next( node );
}
- callBack = addrQry->callBack;
-
- /* Delete query */
- qrymgr_delete_query( queryID );
- /* Execute callback function */
- callBack( queryID, queryType, qry->retVal );
+ /* Delete query request */
+ qrymgr_delete_request( queryID );
}
-#endif
/**
- * Setup the explicit search that will be performed. The search is registered with
- * the query manager.
+ * Setup or register the explicit search that will be performed. The search is
+ * registered with the query manager.
*
- * \param ds Data source to search.
- * \param searchTerm Search term to locate.
- * \param folder Folder to receive search results; may be NULL.
- * \param callbackEnd Function to call when search has terminated.
+ * \param ds Data source to search.
+ * \param searchTerm Search term to locate.
+ * \param folder Folder to receive search results; may be NULL.
+ * \param callbackEnd Function to call when search has terminated.
+ * \param callbackEntry Function to called for each entry processed.
* \return ID allocated to query that will be executed.
*/
-gint addrindex_setup_static_search(
+gint addrindex_setup_explicit_search(
AddressDataSource *ds, const gchar *searchTerm, ItemFolder *folder,
- void *callbackEnd )
+ void *callBackEnd, void *callBackEntry )
{
- AddrQuery *addrQry;
+ QueryRequest *req;
gint queryID;
gchar *name;
- queryID = ++_currentQueryID_;
-
/* Name the query */
name = g_strdup_printf( "Search '%s'", searchTerm );
- /* Set up a generic address query */
- addrQry = qrymgr_add_query( queryID, searchTerm, callbackEnd, NULL );
+ /* Set up query request */
+ req = qrymgr_add_request( searchTerm, callBackEnd, callBackEntry );
+ qryreq_set_search_type( req, ADDRSEARCH_EXPLICIT );
+ queryID = req->queryID;
if( ds->type == ADDR_IF_LDAP ) {
#ifdef USE_LDAP
LdapServer *server;
- LdapQuery *qry;
server = ds->rawDataSource;
-
- /* Construct a query */
- qry = ldapqry_create();
- ldapqry_set_query_id( qry, queryID );
- ldapqry_set_name( qry, name );
- ldapqry_set_search_value( qry, searchTerm );
- ldapqry_set_query_type( qry, LDAPQUERY_STATIC );
- ldapqry_set_callback_end( qry, addrindex_ldap_end_static_cb );
-
- /* Specify folder type and back reference */
- qry->folder = folder;
- folder->folderType = ADDRFOLDER_LDAP_QUERY;
- folder->folderData = ( gpointer ) qry;
-
- /* Setup server */
- ldapsvr_add_query( server, qry );
-
- /* Set up generic query */
- addrqry_set_query_type( addrQry, ADDRQUERY_LDAP );
- addrqry_set_server( addrQry, server );
- addrqry_set_query( addrQry, qry );
+ ldapsvr_new_explicit_search( server, req, folder );
#endif
}
else {
- qrymgr_delete_query( queryID );
+ qrymgr_delete_request( queryID );
queryID = 0;
}
-
g_free( name );
return queryID;
}
/**
- * Perform the previously registered explicit search.
- * \param queryID ID of search query to be executed.
- * \param idleID Idler ID.
+ * Execute the previously registered explicit search.
+ *
+ * \param req Address query request object to execute.
* \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
* failed.
*/
-gboolean addrindex_start_static_search( const gint queryID, const guint idleID )
-{
+static gboolean addrindex_start_explicit( QueryRequest *req ) {
gboolean retVal;
- AddrQuery *addrQry;
+ AddrQueryObject *aqo;
retVal = FALSE;
- addrQry = qrymgr_find_query( queryID );
- if( addrQry == NULL ) {
- return retVal;
- }
- if( addrQry->queryType == ADDRQUERY_LDAP ) {
+ /* Note: there should only be one query in the list. */
+ aqo = req->queryList->data;
#ifdef USE_LDAP
+ if( aqo->queryType == ADDRQUERY_LDAP ) {
LdapServer *server;
LdapQuery *qry;
- server = ( LdapServer * ) addrQry->serverObject;
- qry = ( LdapQuery * ) addrQry->queryObject;
-
- /* Retire any aged queries */
- ldapsvr_retire_query( server );
+ qry = ( LdapQuery * ) aqo;
+ server = qry->server;
/* Start the search */
- ldapsvr_execute_query( server, qry );
retVal = TRUE;
+ ldapsvr_execute_query( server, qry );
+ }
#endif
+ return retVal;
+}
+
+/**
+ * Start the previously registered search.
+ *
+ * \param queryID ID of search query to be executed.
+ * \return <i>TRUE</i> if search started successfully, or <i>FALSE</i> if
+ * failed.
+ */
+gboolean addrindex_start_search( const gint queryID ) {
+ gboolean retVal;
+ QueryRequest *req;
+ AddrSearchType searchType;
+
+ retVal = FALSE;
+ /* printf( "addrindex_start_search/queryID=%d\n", queryID ); */
+ req = qrymgr_find_request( queryID );
+ if( req == NULL ) {
+ return retVal;
}
- if( retVal ) {
- addrqry_set_idle_id( addrQry, idleID );
+ searchType = req->searchType;
+ if( searchType == ADDRSEARCH_DYNAMIC ) {
+ retVal = addrindex_start_dynamic( req );
+ }
+ else if( searchType == ADDRSEARCH_EXPLICIT ) {
+ retVal = addrindex_start_explicit( req );
}
return retVal;
}
/**
- * Read all address books that do not support dynamic queries.
- * \param addrIndex Address index object.
+ * Remove results (folder and data) for specified data source and folder.
+ * \param ds Data source to process.
+ * \param folder Results folder to remove.
*/
-void addrindex_read_all( AddressIndex *addrIndex ) {
- AddressInterface *iface;
- AddressDataSource *ds;
- GList *nodeIf;
- GList *nodeDS;
+void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
+ AddrBookBase *adbase;
+ AddressCache *cache;
+ gint queryID = 0;
- nodeIf = addrIndex->searchOrder;
- while( nodeIf ) {
- iface = nodeIf->data;
- nodeIf = g_list_next( nodeIf );
+ /* Test for folder */
+ if( folder->folderType != ADDRFOLDER_QUERY_RESULTS ) return;
+ adbase = ( AddrBookBase * ) ds->rawDataSource;
+ if( adbase == NULL ) return;
+ cache = adbase->addressCache;
- if( ! iface->useInterface ) {
- continue;
- }
- if( iface->externalQuery ) {
- continue;
- }
- nodeDS = iface->listSource;
- while( nodeDS ) {
- ds = nodeDS->data;
- nodeDS = g_list_next( nodeDS );
+ /* Hide folder to prevent re-display */
+ addritem_folder_set_hidden( folder, TRUE );
- /* Read address book */
- if( addrindex_ds_get_modify_flag( ds ) ) {
- addrindex_ds_read_data( ds );
- continue;
- }
+ if( ds->type == ADDR_IF_LDAP ) {
+#ifdef USE_LDAP
+ LdapQuery *qry;
- if( ! addrindex_ds_get_read_flag( ds ) ) {
- addrindex_ds_read_data( ds );
- continue;
- }
- }
+ qry = ( LdapQuery * ) folder->folderData;
+ queryID = ADDRQUERY_ID(qry);
+ ldapquery_remove_results( qry );
+#endif
+ }
+
+ /* Delete query request */
+ if( queryID > 0 ) {
+ qrymgr_delete_request( queryID );
}
- addrIndex->loadedFlag = TRUE;
}
+/* **********************************************************************
+* Address completion stuff.
+* ***********************************************************************
+*/
+
/**
* This function is used by the address completion function to load
* addresses for all non-external address book interfaces.
*
- * \param addrIndex Address index object.
* \param callBackFunc Function to be called when an address is
* to be loaded.
* \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
*/
gboolean addrindex_load_completion(
- AddressIndex *addrIndex,
gint (*callBackFunc) ( const gchar *, const gchar *, const gchar * ) )
{
AddressDataSource *ds;
GList *nodeM;
gchar *sName, *sAddress, *sAlias, *sFriendly;
- if( addrIndex == NULL ) return FALSE;
-
- nodeIf = addrindex_get_interface_list( addrIndex );
+ nodeIf = addrindex_get_interface_list( _addressIndex_ );
while( nodeIf ) {
AddressInterface *iface = nodeIf->data;
gpointer rawDataSource;
};
-void addrindex_initialize ( AddressIndex *addrIndex );
-void addrindex_teardown ( AddressIndex *addrIndex );
+void addrindex_initialize ( void );
+void addrindex_teardown ( void );
AddressIndex *addrindex_create_index ( void );
+AddressIndex *addrindex_get_object ( void );
void addrindex_set_file_path ( AddressIndex *addrIndex,
const gchar *value );
void addrindex_set_file_name ( AddressIndex *addrIndex,
GList *addrindex_ds_get_all_groups ( AddressDataSource *ds );
/* Search support */
-gint addrindex_setup_search ( AddressIndex *addrIndex,
- const gchar *searchTerm,
- const gpointer target,
- AddrSearchCallbackFunc callBack );
-gboolean addrindex_start_search ( AddressIndex *addrIndex,
- const gint queryID );
-void addrindex_stop_search ( AddressIndex *addrIndex,
- const gint queryID );
-
-void addrindex_read_all ( AddressIndex *addrIndex );
+gint addrindex_setup_search ( const gchar *searchTerm,
+ void *callBackEnd,
+ void *callBackEntry );
+
+gint addrindex_setup_static_search ( AddressDataSource *ds,
+ const gchar *searchTerm,
+ ItemFolder *folder,
+ void *callBackEnd,
+ void *callBackEntry );
+
+gboolean addrindex_start_search ( const gint queryID );
+void addrindex_stop_search ( const gint queryID );
+void addrindex_remove_results ( AddressDataSource *ds,
+ ItemFolder *folder );
+
gboolean addrindex_load_completion(
- AddressIndex *addrIndex,
gint (*callBackFunc)
( const gchar *, const gchar *, const gchar * ) );
ADDRFOLDER_ROOT,
ADDRFOLDER_REGULAR,
ADDRFOLDER_CATEGORY,
- ADDRFOLDER_LDAP_QUERY
+ ADDRFOLDER_QUERY_RESULTS
} AddressFolderType;
typedef struct _AddrItemObject AddrItemObject;
/**
* Query list for tracking current queries.
*/
-static GList *_queryList_ = NULL;
+static GList *_requestList_ = NULL;
/**
* Mutex to protect list from multiple threads.
*/
-static pthread_mutex_t _queryListMutex_ = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t _requestListMutex_ = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * Current query ID. This is incremented for each query request created.
+ */
+static gint _currentQueryID_ = 0;
/**
* Create new address query.
* \return Initialized address query object.
*/
-AddrQuery *addrqry_create( void ) {
- AddrQuery *qry;
-
- qry = g_new0( AddrQuery, 1 );
- qry->queryType = ADDRQUERY_NONE;
- qry->queryID = 0;
- qry->idleID = 0;
- qry->searchTerm = NULL;
- qry->callBack = NULL;
- qry->target = NULL;
- qry->serverObject = NULL;
- qry->queryObject = NULL;
- return qry;
+QueryRequest *reqreq_create( void ) {
+ QueryRequest *req;
+
+ req = g_new0( QueryRequest, 1 );
+ req->queryID = 0;
+ req->searchType = ADDRSEARCH_NONE;
+ req->searchTerm = NULL;
+ req->callBackEnd = NULL;
+ req->callBackEntry = NULL;
+ req->queryList = NULL;
+ return req;
}
/**
* Clear the query.
- * \param qry Address query object.
+ * \param req Request query object.
*/
-void addrqry_clear( AddrQuery *qry ) {
- g_return_if_fail( qry != NULL );
- g_free( qry->searchTerm );
- qry->queryType = ADDRQUERY_NONE;
- qry->queryID = 0;
- qry->idleID = 0;
- qry->searchTerm = NULL;
- qry->callBack = NULL;
- qry->target = NULL;
- qry->serverObject = NULL;
- qry->queryObject = NULL;
+void qryreq_clear( QueryRequest *req ) {
+ GList *node;
+
+ g_return_if_fail( req != NULL );
+ g_free( req->searchTerm );
+ req->queryID = 0;
+ req->searchType = ADDRSEARCH_NONE;
+ req->searchTerm = NULL;
+ req->callBackEnd = NULL;
+ req->callBackEntry = NULL;
+
+ /* Empty the list */
+ node = req->queryList;
+ while( node ) {
+ node->data = NULL;
+ node = g_list_next( node );
+ }
+ g_list_free( req->queryList );
+ req->queryList = NULL;
}
/**
* Free query.
- * \param qry Address query object.
+ * \param req Request query object.
*/
-void addrqry_free( AddrQuery *qry ) {
- g_return_if_fail( qry != NULL );
- addrqry_clear( qry );
- g_free( qry );
+void qryreq_free( QueryRequest *req ) {
+ g_return_if_fail( req != NULL );
+ qryreq_clear( req );
+ g_free( req );
}
/**
- * Specify query type.
- * \param qry Address query object.
+ * Specify search type.
+ * \param req Request query object.
* \param value Type.
*/
-void addrqry_set_query_type( AddrQuery *qry, const AddrQueryType value ) {
- g_return_if_fail( qry != NULL );
- qry->queryType = value;
-}
-
-/**
- * Specify idle ID.
- * \param qry Address query object.
- * \param value Idle ID.
- */
-void addrqry_set_idle_id( AddrQuery *qry, const guint value ) {
- g_return_if_fail( qry != NULL );
- qry->idleID = value;
+void qryreq_set_search_type( QueryRequest *req, const AddrSearchType value ) {
+ g_return_if_fail( req != NULL );
+ req->searchType = value;
}
/**
* Specify search term to be used.
- * \param qry Address query object.
+ * \param req Request query object.
* \param value Search term.
*/
-void addrqry_set_search_term( AddrQuery* qry, const gchar *value ) {
- qry->searchTerm = mgu_replace_string( qry->searchTerm, value );
- g_return_if_fail( qry != NULL );
- g_strstrip( qry->searchTerm );
-}
-
-/**
- * Specify server object to be used.
- * \param qry Address query object.
- * \param value Server object that performs the search.
- */
-void addrqry_set_server( AddrQuery* qry, const gpointer value ) {
- g_return_if_fail( qry != NULL );
- qry->serverObject = value;
+void qryreq_set_search_term( QueryRequest *req, const gchar *value ) {
+ req->searchTerm = mgu_replace_string( req->searchTerm, value );
+ g_return_if_fail( req != NULL );
+ g_strstrip( req->searchTerm );
}
/**
- * Specify query object to be used.
- * \param qry Address query object.
- * \param value Query object that performs the search.
+ * Add address query object to request.
+ * \param req Request query object.
+ * \param aqo Address query object that performs the search.
*/
-void addrqry_set_query( AddrQuery* qry, const gpointer value ) {
- g_return_if_fail( qry != NULL );
- qry->queryObject = value;
+void qryreq_add_query( QueryRequest *req, AddrQueryObject *aqo ) {
+ g_return_if_fail( req != NULL );
+ g_return_if_fail( aqo != NULL );
+ req->queryList = g_list_append( req->queryList, aqo );
}
/**
* Display object to specified stream.
- * \param qry Address query object.
+ * \param req Request query object.
* \param stream Output stream.
*/
-void addrqry_print( const AddrQuery *qry, FILE *stream ) {
- g_return_if_fail( qry != NULL );
+void qryreq_print( const QueryRequest *req, FILE *stream ) {
+ GList *node;
+ g_return_if_fail( req != NULL );
- fprintf( stream, "AddressQuery:\n" );
- fprintf( stream, " queryID: %d\n", qry->queryID );
- fprintf( stream, " idleID: %d\n", qry->idleID );
- fprintf( stream, " searchTerm: '%s'\n", qry->searchTerm );
+ fprintf( stream, "QueryRequest:\n" );
+ fprintf( stream, " queryID: %d\n", req->queryID );
+ fprintf( stream, " searchType: %d\n", req->searchType );
+ fprintf( stream, " searchTerm: '%s'\n", req->searchTerm );
+ node = req->queryList;
+ while( node ) {
+ AddrQueryObject *aqo = node->data;
+ fprintf( stream, " --- type: %d\n", aqo->queryType );
+ node = g_list_next( node );
+ }
}
/**
* Add query to list.
- * \param queryID ID of query being executed.
- * \param searchTerm Search term. A private copy will be made.
- * \param callBack Callback function.
- * \param target Target object to receive data.
+ *
+ * \param searchTerm Search term. A private copy will be made.
+ * \param callBackEnd Callback function that will be called when query
+ * terminates.
+ * \param callBackEntry Callback function that will be called after each
+ * address entry has been read.
+ * \return Initialize query request object.
*/
-AddrQuery *qrymgr_add_query(
- const gint queryID, const gchar *searchTerm, void *callBack,
- gpointer target )
+QueryRequest *qrymgr_add_request(
+ const gchar *searchTerm, void *callBackEnd, void *callBackEntry )
{
- AddrQuery *qry;
-
- qry = g_new0( AddrQuery, 1 );
- qry->queryType = ADDRQUERY_NONE;
- qry->queryID = queryID;
- qry->idleID = 0;
- qry->searchTerm = g_strdup( searchTerm );
- qry->callBack = callBack;
- qry->target = NULL;
- qry->timeStart = time( NULL );
- qry->serverObject = NULL;
- qry->queryObject = NULL;
+ QueryRequest *req;
+
+ req = g_new0( QueryRequest, 1 );
+ req->searchTerm = g_strdup( searchTerm );
+ req->callBackEnd = callBackEnd;
+ req->callBackEntry = callBackEntry;
+ req->timeStart = time( NULL );
+ req->queryList = NULL;
/* Insert in head of list */
- pthread_mutex_lock( & _queryListMutex_ );
- _queryList_ = g_list_prepend( _queryList_, qry );
- pthread_mutex_unlock( & _queryListMutex_ );
+ pthread_mutex_lock( & _requestListMutex_ );
+ req->queryID = ++_currentQueryID_;
+ _requestList_ = g_list_prepend( _requestList_, req );
+ pthread_mutex_unlock( & _requestListMutex_ );
- return qry;
+ return req;
}
/**
* \param queryID ID of query to find.
* \return Query object, or <i>NULL</i> if not found.
*/
-AddrQuery *qrymgr_find_query( const gint queryID ) {
- AddrQuery *qry;
- AddrQuery *q;
+QueryRequest *qrymgr_find_request( const gint queryID ) {
+ QueryRequest *req;
+ QueryRequest *q;
GList *node;
- pthread_mutex_lock( & _queryListMutex_ );
- qry = NULL;
- node = _queryList_;
+ pthread_mutex_lock( & _requestListMutex_ );
+ req = NULL;
+ node = _requestList_;
while( node ) {
q = node->data;
if( q->queryID == queryID ) {
- qry = q;
+ req = q;
break;
}
node = g_list_next( node );
}
- pthread_mutex_unlock( & _queryListMutex_ );
+ pthread_mutex_unlock( & _requestListMutex_ );
- return qry;
+ return req;
}
/**
* Delete specified query.
* \param queryID ID of query to retire.
*/
-void qrymgr_delete_query( const gint queryID ) {
- AddrQuery *qry;
+void qrymgr_delete_request( const gint queryID ) {
+ QueryRequest *req;
GList *node, *nf;
- pthread_mutex_lock( & _queryListMutex_ );
+ pthread_mutex_lock( & _requestListMutex_ );
/* Find node */
nf = NULL;
- node = _queryList_;
+ node = _requestList_;
while( node ) {
- qry = node->data;
- if( qry->queryID == queryID ) {
+ req = node->data;
+ if( req->queryID == queryID ) {
nf = node;
- addrqry_free( qry );
+ qryreq_free( req );
break;
}
node = g_list_next( node );
/* Free link element and associated query */
if( nf ) {
- _queryList_ = g_list_remove_link( _queryList_, nf );
+ _requestList_ = g_list_remove_link( _requestList_, nf );
g_list_free_1( nf );
}
- pthread_mutex_unlock( & _queryListMutex_ );
+ pthread_mutex_unlock( & _requestListMutex_ );
}
/**
* Initialize query manager.
*/
void qrymgr_initialize( void ) {
- _queryList_ = NULL;
+ _requestList_ = NULL;
}
/**
* Free all queries.
*/
-static void qrymgr_free_all_query( void ) {
- AddrQuery *qry;
+static void qrymgr_free_all_request( void ) {
+ QueryRequest *req;
GList *node;
- pthread_mutex_lock( & _queryListMutex_ );
- node = _queryList_;
+ pthread_mutex_lock( & _requestListMutex_ );
+ node = _requestList_;
while( node ) {
- qry = node->data;
- addrqry_free( qry );
+ req = node->data;
+ qryreq_free( req );
node->data = NULL;
node = g_list_next( node );
}
- g_list_free( _queryList_ );
- _queryList_ = NULL;
- pthread_mutex_unlock( & _queryListMutex_ );
+ g_list_free( _requestList_ );
+ _requestList_ = NULL;
+ pthread_mutex_unlock( & _requestListMutex_ );
}
/**
* Teardown query manager.
*/
void qrymgr_teardown( void ) {
- qrymgr_free_all_query();
+ qrymgr_free_all_request();
}
/**
* \param stream Output stream.
*/
void qrymgr_print( FILE *stream ) {
- AddrQuery *qry;
+ QueryRequest *req;
GList *node;
- pthread_mutex_lock( & _queryListMutex_ );
+ pthread_mutex_lock( & _requestListMutex_ );
fprintf( stream, "=== Query Manager ===\n" );
- node = _queryList_;
+ node = _requestList_;
while( node ) {
- qry = node->data;
- addrqry_print( qry, stream );
+ req = node->data;
+ qryreq_print( req, stream );
fprintf( stream, "---\n" );
node = g_list_next( node );
}
- pthread_mutex_unlock( & _queryListMutex_ );
+ pthread_mutex_unlock( & _requestListMutex_ );
}
/*
#include <glib.h>
#include <stdio.h>
#include <sys/time.h>
+#include "addritem.h"
/* Query types */
-typedef enum {
- ADDRQUERY_NONE,
- ADDRQUERY_LDAP
-} AddrQueryType;
-
-/* Address search call back function */
-typedef gint ( AddrSearchCallbackFunc ) ( gint cacheID,
- GList *listEMail,
- gpointer target );
+#define ADDRQUERY_NONE 0
+#define ADDRQUERY_LDAP 1
-typedef void ( AddrSearchStaticFunc ) ( gint qid, AddrQueryType qty, gint status );
+/* Search type */
+typedef enum {
+ ADDRSEARCH_NONE,
+ ADDRSEARCH_DYNAMIC,
+ ADDRSEARCH_EXPLICIT,
+ ADDRSEARCH_LOCATE
+} AddrSearchType;
/* Data structures */
typedef struct {
- AddrQueryType queryType;
- gint queryID;
- gint idleID;
- gchar *searchTerm;
- time_t timeStart;
- AddrSearchStaticFunc *callBack;
- gpointer target;
- gpointer serverObject;
- gpointer queryObject;
+ gint queryID;
+ AddrSearchType searchType;
+ gchar *searchTerm;
+ time_t timeStart;
+ void ( *callBackEnd ) ( void * );
+ void ( *callBackEntry ) ( void * );
+ GList *queryList;
}
-AddrQuery;
+QueryRequest;
+
+/* Some macros */
+#define ADDRQUERY_OBJECT(obj) ((AddrQueryObject *)obj)
+#define ADDRQUERY_TYPE(obj) (ADDRQUERY_OBJECT(obj)->queryType)
+#define ADDRQUERY_ID(obj) (ADDRQUERY_OBJECT(obj)->queryID)
+#define ADDRQUERY_SEARCHTYPE(obj) (ADDRQUERY_OBJECT(obj)->searchType)
+#define ADDRQUERY_NAME(obj) (ADDRQUERY_OBJECT(obj)->queryName)
+#define ADDRQUERY_RETVAL(obj) (ADDRQUERY_OBJECT(obj)->retVal)
+#define ADDRQUERY_FOLDER(obj) (ADDRQUERY_OBJECT(obj)->folder)
+#define ADDRQUERY_SEARCHVALUE(obj) (ADDRQUERY_OBJECT(obj)->searchValue)
+
+/* Generic address query (base class) */
+typedef struct _AddrQueryObject AddrQueryObject;
+struct _AddrQueryObject {
+ gint queryType;
+ gint queryID;
+ AddrSearchType searchType;
+ gchar *queryName;
+ gint retVal;
+ ItemFolder *folder; /* Reference to folder in cache */
+ gchar *searchValue;
+};
+
+/* Address search call back functions */
+typedef gint ( AddrSearchCallbackEntry ) ( gpointer sender,
+ gint queryID,
+ GList *listEMail,
+ gpointer data );
+
+typedef void ( AddrSearchCallbackEnd ) ( gpointer sender,
+ gint queryID,
+ gint status,
+ gpointer data );
/* Function prototypes */
-AddrQuery *addrqry_create ( void );
-void addrqry_clear ( AddrQuery *qry );
-void addrqry_free ( AddrQuery *qry );
-void addrqry_set_query_type ( AddrQuery *qry, const AddrQueryType value );
-void addrqry_set_idle_id ( AddrQuery *qry, const guint value );
-void addrqry_set_search_term ( AddrQuery* qry, const gchar *value );
-void addrqry_set_server ( AddrQuery* qry, const gpointer server );
-void addrqry_set_query ( AddrQuery* qry, const gpointer query );
-void addrqry_print ( const AddrQuery *qry, FILE *stream );
+QueryRequest *qryreq_create ( void );
+void qryreq_clear ( QueryRequest *req );
+void qryreq_free ( QueryRequest *req );
+void qryreq_set_search_type ( QueryRequest *req, const AddrSearchType value );
+void qryreq_set_search_term ( QueryRequest *req, const gchar *value );
+void qryreq_add_query ( QueryRequest *req, AddrQueryObject *aqo );
+void qryreq_print ( const QueryRequest *req, FILE *stream );
void qrymgr_initialize ( void );
void qrymgr_teardown ( void );
-AddrQuery *qrymgr_add_query(
- const gint queryID, const gchar *searchTerm,
- void *callBack, gpointer target );
+QueryRequest *qrymgr_add_request( const gchar *searchTerm,
+ void *callBackEnd,
+ void *callBackEntry );
-AddrQuery *qrymgr_find_query ( const gint queryID );
-void qrymgr_delete_query ( const gint queryID );
+QueryRequest *qrymgr_find_request( const gint queryID );
+void qrymgr_delete_request ( const gint queryID );
void qrymgr_print ( FILE *stream );
#endif /* __ADDRQUERY_H__ */
#include <glib.h>
#include <sys/time.h>
#include <string.h>
-#include <ldap.h>
#include <lber.h>
#include "ldapquery.h"
#include "addritem.h"
#include "addrcache.h"
+#include "ldapquery.h"
+
/*
* Key for thread specific data.
*/
LdapQuery *qry;
qry = g_new0( LdapQuery, 1 );
+ ADDRQUERY_TYPE(qry) = ADDRQUERY_LDAP;
+ ADDRQUERY_ID(qry) = 0;
+ ADDRQUERY_SEARCHTYPE(qry) = ADDRSEARCH_NONE;
+ ADDRQUERY_NAME(qry) = NULL;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
+ ADDRQUERY_FOLDER(qry) = NULL;
+ ADDRQUERY_SEARCHVALUE(qry) = NULL;
qry->control = NULL;
- qry->retVal = LDAPRC_SUCCESS;
- qry->queryType = LDAPQUERY_NONE;
- qry->queryName = NULL;
- qry->searchValue = NULL;
- qry->queryID = 0;
+ qry->server = NULL;
qry->entriesRead = 0;
qry->elapsedTime = 0;
qry->stopFlag = FALSE;
qry->agedFlag = FALSE;
qry->completed = FALSE;
qry->thread = NULL;
- qry->callBackStart = NULL;
qry->callBackEntry = NULL;
qry->callBackEnd = NULL;
- qry->folder = NULL;
- qry->server = NULL;
+ qry->ldap = NULL;
+ qry->data = NULL;
/* Mutex to protect stop and busy flags */
qry->mutexStop = g_malloc0( sizeof( pthread_mutex_t ) );
* \param value Name.
*/
void ldapqry_set_name( LdapQuery* qry, const gchar *value ) {
- qry->queryName = mgu_replace_string( qry->queryName, value );
- g_strstrip( qry->queryName );
+ ADDRQUERY_NAME(qry) = mgu_replace_string( ADDRQUERY_NAME(qry), value );
+ g_strstrip( ADDRQUERY_NAME(qry) );
}
/**
* \param value
*/
void ldapqry_set_search_value( LdapQuery *qry, const gchar *value ) {
- qry->searchValue = mgu_replace_string( qry->searchValue, value );
- g_strstrip( qry->searchValue );
+ ADDRQUERY_SEARCHVALUE(qry) = mgu_replace_string( ADDRQUERY_SEARCHVALUE(qry), value );
+ g_strstrip( ADDRQUERY_SEARCHVALUE(qry) );
}
/**
* \param value Status.
*/
void ldapqry_set_error_status( LdapQuery* qry, const gint value ) {
- qry->retVal = value;
+ ADDRQUERY_RETVAL(qry) = value;
}
/**
* <li><code>LDAPQUERY_DYNAMIC</code></li>
* </ul>
*/
+/*
void ldapqry_set_query_type( LdapQuery* qry, const gint value ) {
- qry->queryType = value;
+ ADDRQUERY_TYPE(qry) = value;
+}
+*/
+
+/**
+ * Specify search type.
+ * \param qry Query object.
+ * \param value Type.
+ */
+void ldapqry_set_search_type( LdapQuery *qry, const AddrSearchType value ) {
+ g_return_if_fail( qry != NULL );
+ ADDRQUERY_SEARCHTYPE(qry) = value;
}
/**
* \param value ID for the query.
*/
void ldapqry_set_query_id( LdapQuery* qry, const gint value ) {
- qry->queryID = value;
+ ADDRQUERY_ID(qry) = value;
}
/**
}
}
-/**
- * Register a callback function that will be executed when the search
- * starts. When called, the function will be passed this query object
- * as an argument.
- * \param qry Query object.
- * \param func Function.
- */
-void ldapqry_set_callback_start( LdapQuery *qry, void *func ) {
- qry->callBackStart = func;
-}
-
/**
* Register a callback function that will be executed when each entry
* has been read and processed. When called, the function will be passed
return qry->agedFlag;
}
+/**
+ * Specify user data for query.
+ * \param qry Query object.
+ * \param value Data to set.
+ */
+void ldapqry_set_data( LdapQuery *qry, const gpointer value ) {
+ g_return_if_fail( qry != NULL );
+ qry->data = value;
+}
+
+/**
+ * Retrieve user data associated with query.
+ * \param qry Query object.
+ * \return Data.
+ */
+gpointer ldapqry_get_data( LdapQuery *qry ) {
+ g_return_if_fail( qry != NULL );
+ return qry->data;
+}
+
/**
* Release the LDAP control data associated with the query.
* \param qry Query object to process.
g_return_if_fail( qry != NULL );
/* Free internal stuff */
- g_free( qry->queryName );
- g_free( qry->searchValue );
+ g_free( ADDRQUERY_NAME(qry) );
+ g_free( ADDRQUERY_SEARCHVALUE(qry) );
/* Clear pointers and value */
- qry->queryName = NULL;
- qry->searchValue = NULL;
- qry->retVal = LDAPRC_SUCCESS;
- qry->queryType = LDAPQUERY_NONE;
- qry->queryID = 0;
+ ADDRQUERY_NAME(qry) = NULL;
+ ADDRQUERY_SEARCHVALUE(qry) = NULL;
+ ADDRQUERY_ID(qry) = 0;
+ ADDRQUERY_SEARCHTYPE(qry) = ADDRSEARCH_NONE;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
qry->entriesRead = 0;
qry->elapsedTime = 0;
qry->stopFlag = FALSE;
qry->busyFlag = FALSE;
qry->agedFlag = FALSE;
qry->completed = FALSE;
- qry->callBackStart = NULL;
qry->callBackEntry = NULL;
qry->callBackEnd = NULL;
+ qry->ldap = NULL;
+ qry->data = NULL;
}
/**
g_return_if_fail( qry != NULL );
/* Clear out internal members */
+ ADDRQUERY_TYPE(qry) = ADDRQUERY_NONE;
ldapqry_clear( qry );
/* Free the mutex */
qry->mutexStop = NULL;
/* Do not free folder - parent server object should free */
- qry->folder = NULL;
+ ADDRQUERY_FOLDER(qry) = NULL;
/* Do not free thread - thread should be terminated before freeing */
qry->thread = NULL;
fprintf( stream, "LdapQuery:\n" );
fprintf( stream, " control?: %s\n", qry->control ? "yes" : "no" );
- fprintf( stream, "err/status: %d\n", qry->retVal );
- fprintf( stream, "query type: %d\n", qry->queryType );
- fprintf( stream, "query name: '%s'\n", qry->queryName );
- fprintf( stream, "search val: '%s'\n", qry->searchValue );
- fprintf( stream, " queryID: %d\n", qry->queryID );
+ fprintf( stream, "err/status: %d\n", ADDRQUERY_RETVAL(qry) );
+ fprintf( stream, "query type: %d\n", ADDRQUERY_TYPE(qry) );
+ fprintf( stream, "searchType: %d\n", ADDRQUERY_SEARCHTYPE(qry) );
+ fprintf( stream, "query name: '%s'\n", ADDRQUERY_NAME(qry) );
+ fprintf( stream, "search val: '%s'\n", ADDRQUERY_SEARCHVALUE(qry) );
+ fprintf( stream, " queryID: %d\n", ADDRQUERY_ID(qry) );
fprintf( stream, " entries: %d\n", qry->entriesRead );
fprintf( stream, " elapsed: %d\n", qry->elapsedTime );
fprintf( stream, " stop flag: %s\n", qry->stopFlag ? "yes" : "no" );
}
/* Create new folder for results */
- if( qry->folder == NULL ) {
+ if( ADDRQUERY_FOLDER(qry) == NULL ) {
folder = addritem_create_item_folder();
- addritem_folder_set_name( folder, qry->queryName );
+ addritem_folder_set_name( folder, ADDRQUERY_NAME(qry) );
addritem_folder_set_remarks( folder, "" );
addrcache_id_folder( cache, folder );
addrcache_add_folder( cache, folder );
- qry->folder = folder;
+ ADDRQUERY_FOLDER(qry) = folder;
/* Specify folder type and back reference */
- folder->folderType = ADDRFOLDER_LDAP_QUERY;
+ folder->folderType = ADDRFOLDER_QUERY_RESULTS;
folder->folderData = ( gpointer ) qry;
folder->isHidden = TRUE;
}
addritem_person_set_last_name( person, lastName );
addrcache_id_person( cache, person );
addritem_person_set_external_id( person, dn );
- addrcache_folder_add_person( cache, qry->folder, person );
+ addrcache_folder_add_person( cache, ADDRQUERY_FOLDER(qry), person );
qry->entriesRead++;
*/
gboolean ldapqry_check_search( LdapQuery *qry ) {
LdapControl *ctl;
- qry->retVal = LDAPRC_CRITERIA;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_CRITERIA;
/* Test for control data */
ctl = qry->control;
}
/* Test for search value */
- if( qry->searchValue == NULL ) {
+ if( ADDRQUERY_SEARCHVALUE(qry) == NULL ) {
return FALSE;
}
- if( strlen( qry->searchValue ) < 1 ) {
+ if( strlen( ADDRQUERY_SEARCHVALUE(qry) ) < 1 ) {
return FALSE;
}
-
- qry->retVal = LDAPRC_SUCCESS;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
return TRUE;
}
}
/**
- * Perform the LDAP search, reading LDAP entries into cache.
- * Note that one LDAP entry can have multiple values for many of its
- * attributes. If these attributes are E-Mail addresses; these are
- * broken out into separate address items. For any other attribute,
- * only the first occurrence is read.
- *
+ * Connect to LDAP server.
* \param qry Query object to process.
* \return Error/status code.
*/
-static gint ldapqry_perform_search( LdapQuery *qry ) {
+static gint ldapqry_connect( LdapQuery *qry ) {
LdapControl *ctl;
LDAP *ld;
- LDAPMessage *result, *e;
- char **attribs;
- gchar *criteria;
- gboolean entriesFound;
- gboolean first;
- struct timeval timeout;
gint rc;
- time_t tstart, tend;
- AddressCache *cache;
- GList *listEMail;
-
- /* Initialize some variables */
- ctl = qry->control;
- cache = qry->server->addressCache;
- timeout.tv_sec = ctl->timeOut;
- timeout.tv_usec = 0L;
- entriesFound = FALSE;
- qry->elapsedTime = -1;
- qry->retVal = LDAPRC_SUCCESS;
-
- /* Check search criteria */
- if( ! ldapqry_check_search( qry ) ) {
- return qry->retVal;
- }
/* Initialize connection */
+ ctl = qry->control;
ldapqry_touch( qry );
- tstart = qry->touchTime;
- tend = tstart - 1;
+ qry->startTime = qry->touchTime;
+ qry->elapsedTime = -1;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_INIT;
if( ( ld = ldap_init( ctl->hostName, ctl->port ) ) == NULL ) {
- qry->retVal = LDAPRC_INIT;
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
+ qry->ldap = ld;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
if( ldapqry_get_stop_flag( qry ) ) {
- qry->retVal = LDAPRC_SUCCESS;
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
ldapqry_touch( qry );
*/
/* Bind to the server, if required */
+ ADDRQUERY_RETVAL(qry) = LDAPRC_BIND;
if( ctl->bindDN ) {
if( * ctl->bindDN != '\0' ) {
/* printf( "binding...\n" ); */
printf( "LDAP Error: ldap_simple_bind_s: %s\n",
ldap_err2string( rc ) );
*/
- ldap_unbind( ld );
- qry->retVal = LDAPRC_BIND;
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
}
}
+ ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
if( ldapqry_get_stop_flag( qry ) ) {
- ldap_unbind( ld );
- qry->retVal = LDAPRC_SUCCESS;
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
ldapqry_touch( qry );
+ ADDRQUERY_RETVAL(qry) = LDAP_SUCCESS;
+
+ return ADDRQUERY_RETVAL(qry);
+}
+
+/**
+ * Connect to LDAP server.
+ * \param qry Query object to process.
+ * \return Error/status code.
+ */
+static gint ldapqry_disconnect( LdapQuery *qry ) {
+ /* Disconnect */
+ if( qry->ldap ) ldap_unbind( qry->ldap );
+ qry->ldap = NULL;
+
+ ldapqry_touch( qry );
+ qry->elapsedTime = qry->touchTime - qry->startTime;
+
+ return ADDRQUERY_RETVAL(qry);
+}
+
+/**
+ * Perform the LDAP search, reading LDAP entries into cache.
+ * Note that one LDAP entry can have multiple values for many of its
+ * attributes. If these attributes are E-Mail addresses; these are
+ * broken out into separate address items. For any other attribute,
+ * only the first occurrence is read.
+ *
+ * \param qry Query object to process.
+ * \return Error/status code.
+ */
+static gint ldapqry_search_retrieve( LdapQuery *qry ) {
+ LdapControl *ctl;
+ LDAP *ld;
+ LDAPMessage *result, *e;
+ char **attribs;
+ gchar *criteria;
+ gboolean entriesFound;
+ gboolean first;
+ struct timeval timeout;
+ gint rc;
+ AddressCache *cache;
+ GList *listEMail;
+
+ /* Initialize some variables */
+ ld = qry->ldap;
+ ctl = qry->control;
+ cache = qry->server->addressCache;
+ timeout.tv_sec = ctl->timeOut;
+ timeout.tv_usec = 0L;
+ entriesFound = FALSE;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
+
/* Define all attributes we are interested in. */
attribs = ldapctl_attribute_array( ctl );
/* Create LDAP search string */
- criteria = ldapctl_format_criteria( ctl, qry->searchValue );
+ criteria = ldapctl_format_criteria( ctl, ADDRQUERY_SEARCHVALUE(qry) );
/* printf( "Search criteria ::%s::\n", criteria ); */
/*
* Execute the search - this step may take some time to complete
* depending on network traffic and server response time.
*/
+ ADDRQUERY_RETVAL(qry) = LDAPRC_TIMEOUT;
rc = ldap_search_ext_s( ld, ctl->baseDN, LDAP_SCOPE_SUBTREE, criteria,
attribs, 0, NULL, NULL, &timeout, 0, &result );
ldapctl_free_attribute_array( attribs );
g_free( criteria );
criteria = NULL;
if( rc == LDAP_TIMEOUT ) {
- ldap_unbind( ld );
- qry->retVal = LDAPRC_TIMEOUT;
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SEARCH;
if( rc != LDAP_SUCCESS ) {
/*
printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) );
*/
- ldap_unbind( ld );
- qry->retVal = LDAPRC_SEARCH;
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
+ ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
if( ldapqry_get_stop_flag( qry ) ) {
- qry->retVal = LDAPRC_SUCCESS;
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
ldapqry_touch( qry );
printf( "Total results are: %d\n", ldap_count_entries( ld, result ) );
*/
- if( ldapqry_get_stop_flag( qry ) ) {
- qry->retVal = LDAPRC_SUCCESS;
- return qry->retVal;
- }
-
/* Process results */
first = TRUE;
while( TRUE ) {
/* Process callback */
if( qry->callBackEntry ) {
- qry->callBackEntry( qry, listEMail );
+ qry->callBackEntry( qry, ADDRQUERY_ID(qry), listEMail, qry->data );
}
else {
g_list_free( listEMail );
/* Free up and disconnect */
ldap_msgfree( result );
- ldap_unbind( ld );
- ldapqry_touch( qry );
- tend = qry->touchTime;
- qry->elapsedTime = tend - tstart;
if( entriesFound ) {
- qry->retVal = LDAPRC_SUCCESS;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
}
else {
- qry->retVal = LDAPRC_NOENTRIES;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_NOENTRIES;
}
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
+}
+
+/**
+ * Connection, perform search and disconnect.
+ * \param qry Query object to process.
+ * \return Error/status code.
+ */
+static gint ldapqry_perform_search( LdapQuery *qry ) {
+ /* Check search criteria */
+ if( ! ldapqry_check_search( qry ) ) {
+ return ADDRQUERY_RETVAL(qry);
+ }
+
+ /* Connect */
+ qry->ldap = NULL;
+ ldapqry_connect( qry );
+ if( ADDRQUERY_RETVAL(qry) == LDAPRC_SUCCESS ) {
+ /* Perform search */
+ ldapqry_search_retrieve( qry );
+ }
+ /* Disconnect */
+ ldapqry_disconnect( qry );
+ qry->ldap = NULL;
+
+ return ADDRQUERY_RETVAL(qry);
}
/**
ldapqry_touch( qry );
qry->completed = FALSE;
- /* Process callback */
- if( qry->callBackStart ) {
- qry->callBackStart( qry );
- }
-
/* Setup pointer to thread specific area */
pthread_setspecific( _queryThreadKey_, qry );
/* Now perform the search */
qry->entriesRead = 0;
- qry->retVal = LDAPRC_SUCCESS;
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
ldapqry_set_busy_flag( qry, TRUE );
ldapqry_set_stop_flag( qry, FALSE );
- retVal = ldapqry_perform_search( qry );
+ if( ADDRQUERY_SEARCHTYPE(qry) == ADDRSEARCH_LOCATE ) {
+ retVal = ldapqry_perform_locate( qry );
+ }
+ else {
+ retVal = ldapqry_perform_search( qry );
+ }
if( retVal == LDAPRC_SUCCESS ) {
qry->server->addressCache->dataRead = TRUE;
qry->server->addressCache->accessFlag = FALSE;
/* Process callback */
if( qry->callBackEnd ) {
- qry->callBackEnd( qry );
+ qry->callBackEnd( qry, ADDRQUERY_ID(qry), ADDRQUERY_RETVAL(qry), qry->data );
}
- return qry->retVal;
+ return ADDRQUERY_RETVAL(qry);
}
/**
ldapqry_set_stop_flag( qry, FALSE );
ldapqry_touch( qry );
if( ldapqry_check_search( qry ) ) {
- if( qry->retVal == LDAPRC_SUCCESS ) {
+ if( ADDRQUERY_RETVAL(qry) == LDAPRC_SUCCESS ) {
/*
printf( "Starting LDAP search thread\n");
*/
(void *) ldapqry_search, (void *) qry );
}
}
- return qry->retVal;
-}
-
-/**
- * Join the thread associated with the query. This should probably be removed
- * to prevent joining threads.
- * \param qry Query object to process.
- */
-void ldapqry_join_threadX( LdapQuery *qry ) {
- g_return_if_fail( qry != NULL );
-
- /* Wait for thread */
- /* printf( "ldapqry_join_thread::Joining thread...\n" ); */
- pthread_join( * qry->thread, NULL );
- /* printf( "ldapqry_join_thread::Thread terminated\n" ); */
+ return ADDRQUERY_RETVAL(qry);
}
/**
qry = ( LdapQuery * ) ptr;
/*
- printf( "ldapqry_destroyer::%d::%s\n", (int) pthread_self(), qry->queryName );
+ printf( "ldapqry_destroyer::%d::%s\n", (int) pthread_self(), ADDRQUERY_NAME(qry) );
*/
/* Perform any destruction here */
g_return_if_fail( qry != NULL );
/*
- printf( "cancelling::%d::%s\n", (int) pthread_self(), qry->queryName );
+ printf( "cancelling::%d::%s\n", (int) pthread_self(), ADDRQUERY_NAME(qry) );
*/
if( ldapqry_get_busy_flag( qry ) ) {
if( qry->thread ) {
g_return_if_fail( qry != NULL );
- folder = qry->folder;
+ folder = ADDRQUERY_FOLDER(qry);
if( folder ) {
cache = qry->server->addressCache;
folder = addrcache_remove_folder_delete( cache, folder );
if( folder ) {
addritem_free_item_folder( folder );
}
- qry->folder = NULL;
+ ADDRQUERY_FOLDER(qry) = NULL;
+ }
+}
+
+/**
+ * Create a name/value pair object.
+ * \param n Name.
+ * \param v Value.
+ * \return Initialized object.
+ */
+static NameValuePair *ldapqry_create_name_value( const gchar *n, const gchar *v ) {
+ NameValuePair *nvp = g_new0( NameValuePair, 1 );
+
+ nvp->name = g_strdup( n );
+ nvp->value = g_strdup( v );
+ return nvp;
+}
+
+/**
+ * Free up name/value pair object.
+ * \param nvp Name/value object.
+ */
+void ldapqry_free_name_value( NameValuePair *nvp ) {
+ if( nvp ) {
+ g_free( nvp->name );
+ g_free( nvp->value );
+ nvp->name = nvp->value = NULL;
+ g_free( nvp );
+ }
+}
+
+/**
+ * Print name/value pair object for debug.
+ * \param nvp Name/value object.
+ * \param stream Output stream.
+ */
+void ldapqry_print_name_value( NameValuePair *nvp, FILE *stream ) {
+ if( nvp ) {
+ fprintf( stream, "n/v ::%s::%s::\n", nvp->name, nvp->value );
+ }
+}
+
+/**
+ * Free up a list name/value pair objects.
+ * \param list List of name/value objects.
+ */
+void ldapqry_free_list_name_value( GList *list ) {
+ GList *node;
+
+ node = list;
+ while( node ) {
+ NameValuePair *nvp = ( NameValuePair * ) node->data;
+ ldapqry_free_name_value( nvp );
+ node->data = NULL;
+ node = g_list_next( node );
+ }
+ g_list_free( list );
+}
+
+/**
+ * Load a list of name/value pairs from LDAP attributes.
+ * \param ld LDAP handle.
+ * \param e LDAP message.
+ * \param attr Attribute name.
+ * \param listValues List to populate.
+ * \return List of attribute name/value pairs.
+ */
+static GList *ldapqry_load_attrib_values(
+ LDAP *ld, LDAPMessage *entry, char *attr,
+ GList *listValues )
+{
+ GList *list = NULL;
+ gint i;
+ gchar **vals;
+ NameValuePair *nvp;
+
+ list = listValues;
+ if( ( vals = ldap_get_values( ld, entry, attr ) ) != NULL ) {
+ for( i = 0; vals[i] != NULL; i++ ) {
+ nvp = ldapqry_create_name_value( attr, vals[i] );
+ list = g_list_append( list, nvp );
+ }
+ }
+ ldap_value_free( vals );
+ return list;
+}
+
+/**
+ * Fetch a list of all attributes.
+ * \param ld LDAP handle.
+ * \param e LDAP message.
+ * \return List of attribute name/value pairs.
+ */
+static GList *ldapqry_fetch_attribs( LDAP *ld, LDAPMessage *e )
+{
+ char *attribute;
+ BerElement *ber;
+ GList *listValues = NULL;
+
+ /* Process all attributes */
+ for( attribute = ldap_first_attribute( ld, e, &ber ); attribute != NULL;
+ attribute = ldap_next_attribute( ld, e, ber ) ) {
+ listValues = ldapqry_load_attrib_values( ld, e, attribute, listValues );
+ ldap_memfree( attribute );
+ }
+
+ /* Free up */
+ if( ber != NULL ) {
+ ber_free( ber, 0 );
+ }
+ return listValues;
+}
+
+#define CRITERIA_SINGLE "(objectclass=*)"
+
+/**
+ * Perform the data retrieval for a specific LDAP record.
+ *
+ * \param qry Query object to process.
+ * \return Error/status code.
+ */
+static gint ldapqry_locate_retrieve( LdapQuery *qry ) {
+ LdapControl *ctl;
+ LDAP *ld;
+ LDAPMessage *result, *e;
+ gboolean entriesFound;
+ gboolean first;
+ struct timeval timeout;
+ gint rc;
+ gchar *dn;
+ GList *listValues;
+
+ /* Initialize some variables */
+ ld = qry->ldap;
+ ctl = qry->control;
+ dn = ADDRQUERY_SEARCHVALUE(qry);
+ timeout.tv_sec = ctl->timeOut;
+ timeout.tv_usec = 0L;
+ entriesFound = FALSE;
+
+ /*
+ * Execute the search - this step may take some time to complete
+ * depending on network traffic and server response time.
+ */
+ ADDRQUERY_RETVAL(qry) = LDAPRC_TIMEOUT;
+ rc = ldap_search_ext_s( ld, dn, LDAP_SCOPE_BASE, CRITERIA_SINGLE,
+ NULL, 0, NULL, NULL, &timeout, 0, &result );
+ if( rc == LDAP_TIMEOUT ) {
+ return ADDRQUERY_RETVAL(qry);
+ }
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SEARCH;
+ if( rc != LDAP_SUCCESS ) {
+ /*
+ printf( "LDAP Error: ldap_search_st: %s\n", ldap_err2string( rc ) );
+ */
+ return ADDRQUERY_RETVAL(qry);
+ }
+ ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG;
+ if( ldapqry_get_stop_flag( qry ) ) {
+ return ADDRQUERY_RETVAL(qry);
+ }
+ ldapqry_touch( qry );
+
+ /*
+ printf( "Total results are: %d\n", ldap_count_entries( ld, result ) );
+ */
+
+ /* Process results */
+ first = TRUE;
+ while( TRUE ) {
+ ldapqry_touch( qry );
+ if( qry->entriesRead >= ctl->maxEntries ) break;
+
+ /* Test for stop */
+ if( ldapqry_get_stop_flag( qry ) ) {
+ break;
+ }
+
+ /* Retrieve entry */
+ if( first ) {
+ first = FALSE;
+ e = ldap_first_entry( ld, result );
+ }
+ else {
+ e = ldap_next_entry( ld, e );
+ }
+ if( e == NULL ) break;
+
+ entriesFound = TRUE;
+
+ /* Setup a critical section here */
+ pthread_mutex_lock( qry->mutexEntry );
+
+ /* Process entry */
+ listValues = ldapqry_fetch_attribs( ld, e );
+
+ /* Process callback */
+ if( qry->callBackEntry ) {
+ qry->callBackEntry( qry, ADDRQUERY_ID(qry), listValues, qry->data );
+ }
+ ldapqry_free_list_name_value( listValues );
+ listValues = NULL;
+
+ pthread_mutex_unlock( qry->mutexEntry );
+ }
+
+ /* Free up and disconnect */
+ ldap_msgfree( result );
+
+ if( entriesFound ) {
+ ADDRQUERY_RETVAL(qry) = LDAPRC_SUCCESS;
+ }
+ else {
+ ADDRQUERY_RETVAL(qry) = LDAPRC_NOENTRIES;
+ }
+
+ return ADDRQUERY_RETVAL(qry);
+}
+
+/**
+ * Perform the search to locate a specific LDAP record identified by
+ * distinguished name (dn).
+ *
+ * \param qry Query object to process.
+ * \return Error/status code.
+ */
+gint ldapqry_perform_locate( LdapQuery *qry ) {
+ /* Connect */
+ qry->ldap = NULL;
+ ldapqry_connect( qry );
+ if( ADDRQUERY_RETVAL(qry) == LDAPRC_SUCCESS ) {
+ /* Perform search */
+ ldapqry_locate_retrieve( qry );
+ }
+ /* Disconnect */
+ ldapqry_disconnect( qry );
+ qry->ldap = NULL;
+
+ /* Process callback */
+ if( qry->callBackEnd ) {
+ qry->callBackEnd( qry, ADDRQUERY_ID(qry), ADDRQUERY_RETVAL(qry), qry->data );
+ }
+
+ return ADDRQUERY_RETVAL(qry);
+}
+
+/**
+ * Remove results (folder and data) for specified LDAP query.
+ * \param qry Query object to process.
+ */
+void ldapquery_remove_results( LdapQuery *qry ) {
+ /* Set query as aged - will be retired on a later call */
+ ldapqry_set_aged_flag( qry, TRUE );
+ if( ldapqry_get_busy_flag( qry ) ) {
+ /* Query is still busy - cancel query */
+ /* printf( "\tquery is still busy running...\n" ); */
+ ldapqry_set_stop_flag( qry, TRUE );
+ ldapqry_cancel( qry );
+ }
+ else {
+ /* Delete folder */
+ /* printf( "\tquery can be deleted!\n" ); */
+ ldapqry_delete_folder( qry );
}
}
#include <stdio.h>
#include <sys/time.h>
#include <pthread.h>
+#include <ldap.h>
+#include "addrquery.h"
#include "ldapctrl.h"
#include "ldapserver.h"
#include "addritem.h"
#include "addrcache.h"
-/*
- * Constants.
- */
-#define LDAPQUERY_NONE 0
-#define LDAPQUERY_STATIC 1
-#define LDAPQUERY_DYNAMIC 2
-
-/* Error codes */
-#define LDAPRC_SUCCESS 0
-#define LDAPRC_CONNECT -1
-#define LDAPRC_INIT -2
-#define LDAPRC_BIND -3
-#define LDAPRC_SEARCH -4
-#define LDAPRC_TIMEOUT -5
-#define LDAPRC_CRITERIA -6
-#define LDAPRC_NOENTRIES -7
-
typedef struct _LdapQuery LdapQuery;
struct _LdapQuery {
- LdapControl *control;
- gint retVal;
- gint queryType;
- gchar *queryName;
- gchar *searchValue;
- gint queryID;
- gint entriesRead;
- gint elapsedTime;
- gboolean stopFlag;
- gboolean busyFlag;
- gboolean agedFlag;
- gboolean completed;
- time_t touchTime;
- pthread_t *thread;
+ AddrQueryObject obj;
+ LdapControl *control;
+ LdapServer *server; /* Reference to (parent) LDAP server */
+ gint entriesRead;
+ gint elapsedTime;
+ gboolean stopFlag;
+ gboolean busyFlag;
+ gboolean agedFlag;
+ gboolean completed;
+ time_t startTime;
+ time_t touchTime;
+ pthread_t *thread;
pthread_mutex_t *mutexStop;
pthread_mutex_t *mutexBusy;
pthread_mutex_t *mutexEntry;
- void (*callBackStart)( void * );
- void (*callBackEntry)( void *, void * );
- void (*callBackEnd)( void * );
- ItemFolder *folder; /* Reference to folder in cache */
- LdapServer *server; /* Reference to (parent) LDAP server */
+ void (*callBackEntry)( void *, gint, void *, void * );
+ void (*callBackEnd)( void *, gint, gint, void * );
+ LDAP *ldap;
+ gpointer data;
+};
+
+typedef struct _NameValuePair NameValuePair;
+struct _NameValuePair {
+ gchar *name;
+ gchar *value;
};
/* Function prototypes */
void ldapqry_set_name ( LdapQuery* qry, const gchar *value );
void ldapqry_set_search_value ( LdapQuery *qry, const gchar *value );
void ldapqry_set_error_status ( LdapQuery* qry, const gint value );
-void ldapqry_set_query_type ( LdapQuery* qry, const gint value );
+void ldapqry_set_search_type ( LdapQuery *qry, const AddrSearchType value );
void ldapqry_set_query_id ( LdapQuery* qry, const gint value );
void ldapqry_set_entries_read ( LdapQuery* qry, const gint value );
void ldapqry_set_callback_start ( LdapQuery *qry, void *func );
gboolean ldapqry_get_busy_flag ( LdapQuery *qry );
void ldapqry_set_aged_flag ( LdapQuery *qry, const gboolean value );
gboolean ldapqry_get_aged_flag ( LdapQuery *qry );
+void ldapqry_set_data ( LdapQuery *qry, const gpointer value );
+gpointer ldapqry_get_data ( LdapQuery *qry );
gboolean ldapqry_check_search ( LdapQuery *qry );
void ldapqry_touch ( LdapQuery *qry );
gint ldapqry_search ( LdapQuery *qry );
gint ldapqry_read_data_th ( LdapQuery *qry );
-void ldapqry_join_thread ( LdapQuery *qry );
void ldapqry_cancel ( LdapQuery *qry );
void ldapqry_age ( LdapQuery *qry, gint maxAge );
void ldapqry_delete_folder ( LdapQuery *qry );
+void ldapquery_remove_results ( LdapQuery *qry );
#endif /* USE_LDAP */
node = server->listQuery;
while( node ) {
LdapQuery *qry = node->data;
- fprintf( stream, " query: %2d : %s\n", i, qry->queryName );
+ fprintf( stream, " query: %2d : %s\n", i, ADDRQUERY_NAME(qry) );
i++;
node = g_list_next( node );
}
ldapqry_initialize();
/* Perform query */
- /* printf( "ldapsvr_execute_query::reading with thread...\n" ); */
+ /* printf( "ldapsvr_execute_query::checking query...\n" ); */
if( ldapqry_check_search( qry ) ) {
+ /* printf( "ldapsvr_execute_query::reading with thread...\n" ); */
ldapqry_read_data_th( qry );
/*
if( qry->retVal == LDAPRC_SUCCESS ) {
node = server->listQuery;
while( node ) {
LdapQuery *qry = node->data;
- if( qry->queryID == queryID ) {
+ if( ADDRQUERY_ID(qry) == queryID ) {
/* Notify thread to stop */
ldapqry_set_stop_flag( qry, TRUE );
}
* \param searchTerm Search term to locate.
* \return Query object, or <i>NULL</i> if none found.
*/
-LdapQuery *ldapsvr_locate_query( LdapServer *server, const gchar *searchTerm )
+static LdapQuery *ldapsvr_locate_query(
+ const LdapServer *server, const gchar *searchTerm )
{
LdapQuery *incomplete = NULL;
GList *node;
/* Search backwards for query */
while( node ) {
LdapQuery *qry = node->data;
- if( g_strcasecmp( qry->searchValue, searchTerm ) == 0 ) {
+ if( g_strcasecmp( ADDRQUERY_SEARCHVALUE(qry), searchTerm ) == 0 ) {
if( qry->agedFlag ) continue;
if( qry->completed ) {
/* Found */
}
/**
- * Retire aged queries. Only dynamic queries are retired.
+ * Retire aged queries. Only the following queries are retired:
+ *
+ * a) Dynamic queries.
+ * b) Explicit searches that have a hidden folders.
+ * c) Locate searches that have a hidden folder.
+ *
* \param server LdapServer.
*/
void ldapsvr_retire_query( LdapServer *server ) {
GList *listQuery;
gint maxAge;
LdapControl *ctl;
+ ItemFolder *folder;
/* printf( "ldapsvr_retire_query\n" ); */
g_return_if_fail( server != NULL );
LdapQuery *qry = node->data;
node = g_list_next( node );
- if( qry->queryType == LDAPQUERY_STATIC ) continue;
+ folder = ADDRQUERY_FOLDER(qry);
+ if( folder == NULL ) continue;
+ if( ! folder->isHidden ) {
+ if( ADDRQUERY_SEARCHTYPE(qry) == ADDRSEARCH_EXPLICIT ) continue;
+ if( ADDRQUERY_SEARCHTYPE(qry) == ADDRSEARCH_LOCATE ) continue;
+ }
- /* Only dynamic queries are retired */
ldapqry_age( qry, maxAge );
if( qry->agedFlag ) {
/* Delete folder associated with query */
/*
- printf( "deleting folder... ::%s::\n", qry->queryName );
+ printf( "deleting folder... ::%s::\n", ADDRQUERY_NAME(qry) );
*/
ldapqry_delete_folder( qry );
listDelete = g_list_append( listDelete, qry );
g_list_free( listDelete );
}
+/**
+ * Return results of a previous query by executing callback for each address
+ * contained in specified folder.
+ *
+ * \param folder Address book folder to process.
+ * \param req Address query request object.
+ */
+static void ldapsvr_previous_query(
+ const ItemFolder *folder, const QueryRequest *req, AddrQueryObject *aqo )
+{
+ AddrSearchCallbackEntry *callBack;
+ GList *listEMail;
+ GList *node;
+ GList *nodeEM;
+ gpointer sender;
+
+ sender = aqo;
+ callBack = ( AddrSearchCallbackEntry * ) req->callBackEntry;
+ if( callBack ) {
+ listEMail = NULL;
+ node = folder->listPerson;
+ while( node ) {
+ AddrItemObject *aio = node->data;
+ if( aio && aio->type == ITEMTYPE_PERSON ) {
+ ItemPerson *person = node->data;
+ nodeEM = person->listEMail;
+ while( nodeEM ) {
+ ItemEMail *email = nodeEM->data;
+
+ nodeEM = g_list_next( nodeEM );
+ listEMail = g_list_append( listEMail, email );
+ }
+ }
+ node = g_list_next( node );
+ }
+ ( callBack ) ( sender, req->queryID, listEMail, NULL );
+ /* // g_list_free( listEMail ); */
+ }
+}
+
+/**
+ * Reuse search results from a previous LDAP query. If there is a query that
+ * has the same search term as specified in the query request, then the query
+ * will be reused.
+ *
+ * \param server LDAP server object.
+ * \param req Address query object.
+ * \return <i>TRUE</i> if previous query was used.
+ */
+gboolean ldapsvr_reuse_previous( const LdapServer *server, const QueryRequest *req ) {
+ LdapQuery *qry;
+ gchar *searchTerm;
+ ItemFolder *folder;
+
+ g_return_val_if_fail( server != NULL, FALSE );
+ g_return_val_if_fail( req != NULL, FALSE );
+
+ searchTerm = req->searchTerm;
+
+ /* Test whether any queries for the same term exist */
+ qry = ldapsvr_locate_query( server, searchTerm );
+ if( qry ) {
+ /* Touch query to ensure it hangs around for a bit longer */
+ ldapqry_touch( qry );
+ folder = ADDRQUERY_FOLDER(qry);
+ if( folder ) {
+ ldapsvr_previous_query( folder, req, ADDRQUERY_OBJECT(qry) );
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Construct a new LdapQuery object that will be used to perform an dynamic
+ * search request.
+ *
+ * \param server LdapServer.
+ * \param req Query request.
+ * \return LdapQuery object, or <i>NULL</i> if none created.
+ */
+LdapQuery *ldapsvr_new_dynamic_search( LdapServer *server, QueryRequest *req )
+{
+ LdapQuery *qry;
+ gchar *name;
+ gchar *searchTerm;
+
+ g_return_val_if_fail( server != NULL, NULL );
+ g_return_val_if_fail( req != NULL, NULL );
+
+ /* Retire any aged queries */
+ /* // ldapsvr_retire_query( server ); */
+
+ searchTerm = req->searchTerm;
+
+ /* Construct a query */
+ qry = ldapqry_create();
+ ldapqry_set_query_id( qry, req->queryID );
+ ldapqry_set_search_value( qry, searchTerm );
+ ldapqry_set_search_type( qry, ADDRSEARCH_DYNAMIC );
+ ldapqry_set_callback_entry( qry, req->callBackEntry );
+ ldapqry_set_callback_end( qry, req->callBackEnd );
+
+ /* Name the query */
+ name = g_strdup_printf( "Search for '%s'", searchTerm );
+ ldapqry_set_name( qry, name );
+ g_free( name );
+
+ /* Add query to request */
+ qryreq_add_query( req, ADDRQUERY_OBJECT(qry) );
+
+ /* Now start the search */
+ ldapsvr_add_query( server, qry );
+
+ return qry;
+}
+
+/**
+ * Construct a new LdapQuery object that will be used to perform an explicit
+ * search request.
+ *
+ * \param server LdapServer.
+ * \param req Query request.
+ * \param folder Folder that will be used to contain search results; may be NULL.
+ * \return LdapQuery object, or <i>NULL</i> if none created.
+ */
+LdapQuery *ldapsvr_new_explicit_search(
+ LdapServer *server, QueryRequest *req, ItemFolder *folder )
+{
+ LdapQuery *qry;
+ gchar *searchTerm;
+ gchar *name;
+
+ g_return_val_if_fail( server != NULL, NULL );
+ g_return_val_if_fail( req != NULL, NULL );
+ searchTerm = req->searchTerm;
+
+ /* Retire any aged queries */
+ /* // ldapsvr_retire_query( server ); */
+
+ /* Name the query */
+ name = g_strdup_printf( "Explicit search for '%s'", searchTerm );
+
+ /* Construct a query */
+ qry = ldapqry_create();
+ ldapqry_set_query_id( qry, req->queryID );
+ ldapqry_set_name( qry, name );
+ ldapqry_set_search_value( qry, searchTerm );
+ ldapqry_set_search_type( qry, ADDRSEARCH_EXPLICIT );
+ ldapqry_set_callback_end( qry, req->callBackEnd );
+ ldapqry_set_callback_entry( qry, req->callBackEntry );
+
+ if( folder ) {
+ /* Specify folder type and back reference */
+ ADDRQUERY_FOLDER(qry) = folder;
+ folder->folderType = ADDRFOLDER_QUERY_RESULTS;
+ folder->folderData = ( gpointer ) qry;
+ }
+
+ /* Setup server */
+ ldapsvr_add_query( server, qry );
+
+ /* Set up query request */
+ qryreq_add_query( req, ADDRQUERY_OBJECT(qry) );
+
+ g_free( name );
+
+ return qry;
+}
+
#endif /* USE_LDAP */
/*
#include "addritem.h"
#include "addrcache.h"
#include "adbookbase.h"
+#include "addrquery.h"
-#define MGU_LDAP_CONNECT -51
-#define MGU_LDAP_INIT -52
-#define MGU_LDAP_BIND -53
-#define MGU_LDAP_SEARCH -54
-#define MGU_LDAP_TIMEOUT -55
-#define MGU_LDAP_CRITERIA -56
-#define MGU_LDAP_NOENTRIES -57
+/* Error codes */
+#define LDAPRC_SUCCESS 0
+#define LDAPRC_CONNECT -1
+#define LDAPRC_INIT -2
+#define LDAPRC_BIND -3
+#define LDAPRC_SEARCH -4
+#define LDAPRC_TIMEOUT -5
+#define LDAPRC_CRITERIA -6
+#define LDAPRC_NOENTRIES -7
+#define LDAPRC_STOP_FLAG -8
typedef struct _LdapServer LdapServer;
struct _LdapServer {
void ldapsvr_cancel_all_query ( LdapServer *server );
void ldapsvr_retire_query ( LdapServer *server );
+gboolean ldapsvr_reuse_previous ( const LdapServer *server,
+ const QueryRequest *req );
+
#endif /* USE_LDAP */
#endif /* __LDAPSERVER_H__ */