From e41d94885aeee12b9d00ad52611517901ff3d2c3 Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Thu, 7 Feb 2013 17:18:09 +0000 Subject: [PATCH] make evolution-3.6 work with address book Change-Id: I04d2a4d7d1520567dd0eb929ffb5d9fa53d35dd4 --- connectivity/source/drivers/evoab2/EApi.cxx | 109 ++--- connectivity/source/drivers/evoab2/EApi.h | 25 ++ .../source/drivers/evoab2/NDatabaseMetaData.cxx | 136 +++++-- connectivity/source/drivers/evoab2/NResultSet.cxx | 441 ++++++++++++++------- connectivity/source/drivers/evoab2/NResultSet.hxx | 24 +- .../source/core/api/SingleSelectQueryComposer.cxx | 12 + 6 files changed, 510 insertions(+), 237 deletions(-) diff --git a/connectivity/source/drivers/evoab2/EApi.cxx b/connectivity/source/drivers/evoab2/EApi.cxx index 84701e1..608b1f9 100644 --- a/connectivity/source/drivers/evoab2/EApi.cxx +++ b/connectivity/source/drivers/evoab2/EApi.cxx @@ -22,6 +22,7 @@ #define DECLARE_FN_POINTERS 1 #include "EApi.h" static const char *eBookLibNames[] = { + "libebook-1.2.so.14", // bumped again (evolution-3.6) "libebook-1.2.so.13", // bumped again (evolution-3.4) "libebook-1.2.so.12", // bumped again "libebook-1.2.so.10", // bumped again @@ -34,25 +35,23 @@ static const char *eBookLibNames[] = { typedef void (*SymbolFunc) (void); #define SYM_MAP(a) { #a, (SymbolFunc *)&a } - static struct { +struct ApiMap +{ const char *sym_name; SymbolFunc *ref_value; - } aApiMap[] = { +}; + +static ApiMap aCommonApiMap[] = +{ + SYM_MAP( eds_check_version ), SYM_MAP( e_contact_field_name ), SYM_MAP( e_contact_get ), SYM_MAP( e_contact_get_type ), SYM_MAP( e_contact_field_id ), - SYM_MAP( e_source_peek_name ), - SYM_MAP( e_source_get_property ), - SYM_MAP( e_source_list_peek_groups ), - SYM_MAP( e_source_group_peek_sources ), SYM_MAP( e_book_new ), SYM_MAP( e_book_open ), - SYM_MAP( e_book_get_uri ), SYM_MAP( e_book_get_source ), - SYM_MAP( e_book_get_addressbooks ), SYM_MAP( e_book_get_contacts ), - SYM_MAP( e_book_authenticate_user ), SYM_MAP( e_book_query_field_test ), SYM_MAP( e_book_query_and ), SYM_MAP( e_book_query_or ), @@ -61,26 +60,55 @@ typedef void (*SymbolFunc) (void); SYM_MAP( e_book_query_unref ), SYM_MAP( e_book_query_from_string ), SYM_MAP( e_book_query_to_string ), - SYM_MAP( e_book_query_field_exists ), - SYM_MAP( e_source_group_peek_base_uri) - }; + SYM_MAP( e_book_query_field_exists ) +}; + +//< 3-6 api +static ApiMap aOldApiMap[] = +{ + SYM_MAP( e_book_get_addressbooks ), + SYM_MAP( e_book_get_uri ), + SYM_MAP( e_book_authenticate_user ), + SYM_MAP( e_source_group_peek_base_uri), + SYM_MAP( e_source_peek_name ), + SYM_MAP( e_source_get_property ), + SYM_MAP( e_source_list_peek_groups ), + SYM_MAP( e_source_group_peek_sources ) +}; + +//>= 3-6 api +static ApiMap aNewApiMap[] = +{ + SYM_MAP( e_source_registry_list_sources ), + SYM_MAP( e_source_registry_new_sync ), + SYM_MAP( e_source_has_extension ), + SYM_MAP( e_source_get_extension ), + SYM_MAP( e_source_backend_get_backend_name ), + SYM_MAP( e_source_get_display_name ), + SYM_MAP( e_source_get_uid ), + SYM_MAP( e_source_registry_ref_source), + SYM_MAP( e_book_client_new ), + SYM_MAP( e_client_open_sync ), + SYM_MAP( e_client_get_source ), + SYM_MAP( e_book_client_get_contacts_sync ), + SYM_MAP( e_client_util_free_object_slist ) +}; #undef SYM_MAP static bool -tryLink( oslModule &aModule, const char *pName ) +tryLink( oslModule &aModule, const char *pName, ApiMap *pMap, guint nEntries ) { - for( guint i = 0; i < G_N_ELEMENTS( aApiMap ); i++ ) + for (guint i = 0; i < nEntries; ++i) { - SymbolFunc aMethod; - aMethod = (SymbolFunc) osl_getFunctionSymbol - ( aModule, rtl::OUString::createFromAscii ( aApiMap[ i ].sym_name ).pData ); - if( !aMethod ) - { - fprintf( stderr, "Warning: missing symbol '%s' in '%s'", - aApiMap[ i ].sym_name, pName ); - return false; - } - * aApiMap[ i ].ref_value = aMethod; + SymbolFunc aMethod = (SymbolFunc)osl_getFunctionSymbol + (aModule, OUString::createFromAscii ( pMap[ i ].sym_name ).pData); + if( !aMethod ) + { + fprintf( stderr, "Warning: missing symbol '%s' in '%s'\n", + pMap[ i ].sym_name, pName ); + return false; + } + *pMap[ i ].ref_value = aMethod; } return true; } @@ -96,8 +124,18 @@ bool EApiInit() SAL_LOADMODULE_DEFAULT ); if( aModule) { - if ( tryLink( aModule, eBookLibNames[ j ] ) ) - return true; + if (tryLink( aModule, eBookLibNames[ j ], aCommonApiMap, G_N_ELEMENTS(aCommonApiMap))) + { + if (eds_check_version(3, 6, 0) == NULL) + { + if (tryLink( aModule, eBookLibNames[ j ], aNewApiMap, G_N_ELEMENTS(aNewApiMap))) + return true; + } + else if (tryLink( aModule, eBookLibNames[ j ], aOldApiMap, G_N_ELEMENTS(aOldApiMap))) + { + return true; + } + } osl_unloadModule( aModule ); } } @@ -105,23 +143,4 @@ bool EApiInit() return false; } -#if 0 -// hjs: SOLARDEF does no longer exist please lookup the required -// defines in a regular compile line -/* - * Test code - enable & - * - * Compile with ( after source LinuxIntelEnv.Set.sh ) - gcc $SOLARDEF -I $SOLARVER/$UPD/$INPATH/inc \ - -I. `pkg-config --cflags --libs gobject-2.0` \ - -L $SOLARVER/$UPD/$INPATH/lib -luno_sal -lstdc++ EApi.cxx - */ - -int main( int argc, char **argv) -{ - return EApiInit(); -} - -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/evoab2/EApi.h b/connectivity/source/drivers/evoab2/EApi.h index bf3a901..8d188a9 100644 --- a/connectivity/source/drivers/evoab2/EApi.h +++ b/connectivity/source/drivers/evoab2/EApi.h @@ -130,6 +130,31 @@ typedef struct { char *code; char *country; } EContactAddress; + +#define E_SOURCE_EXTENSION_ADDRESS_BOOK "Address Book" +typedef void ESourceRegistry; +typedef void GCancellable; +typedef void ESourceBackend; +typedef void EClient; +typedef EClient EBookClient; +EAPI_EXTERN ESourceRegistry* (*e_source_registry_new_sync) (GCancellable *cancellable, GError **error); +EAPI_EXTERN GList* (*e_source_registry_list_sources) (ESourceRegistry *registry, const gchar *extension_name); +EAPI_EXTERN gboolean (*e_source_has_extension) (ESource *source, const gchar *extension_name); +EAPI_EXTERN gpointer (*e_source_get_extension) (ESource *source, const gchar *extension_name); +EAPI_EXTERN const gchar* (*e_source_backend_get_backend_name) (ESourceBackend *extension); +EAPI_EXTERN const gchar* (*e_source_get_display_name) (ESource *source); +EAPI_EXTERN const gchar* (*eds_check_version) (guint required_major, guint required_minor, guint required_micro); +EAPI_EXTERN const gchar* (*e_source_get_uid) (ESource *source); +EAPI_EXTERN ESource* (*e_source_registry_ref_source) (ESourceRegistry *registry, const gchar *uid); +EAPI_EXTERN EBookClient* (*e_book_client_new) (ESource *source, GError **error); +EAPI_EXTERN gboolean (*e_client_open_sync) (EClient *client, gboolean only_if_exists, GCancellable *cancellable, GError **error); +EAPI_EXTERN ESource* (*e_client_get_source) (EClient *client); +EAPI_EXTERN gboolean (*e_book_client_get_contacts_sync) (EBookClient *client, const gchar *sexp, GSList **contacts, GCancellable *cancellable, GError **error); +EAPI_EXTERN void (*e_client_util_free_object_slist) (GSList *objects); + +ESourceRegistry *get_e_source_registry(); +bool isSourceBackend(ESource *pSource, const char *backendname); + G_END_DECLS #endif diff --git a/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx b/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx index d0198e5..a83de24 100644 --- a/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx +++ b/connectivity/source/drivers/evoab2/NDatabaseMetaData.cxx @@ -1074,7 +1074,25 @@ Reference< XResultSet > SAL_CALL OEvoabDatabaseMetaData::getColumns( pResultSet->setRows( getColumnRows( columnNamePattern ) ); return xResultSet; } + +ESourceRegistry *get_e_source_registry() +{ + static ESourceRegistry *theInstance; + if (!theInstance) + theInstance = e_source_registry_new_sync(NULL, NULL); + return theInstance; +} + // ------------------------------------------------------------------------- +bool isSourceBackend(ESource *pSource, const char *backendname) +{ + if (!pSource || !e_source_has_extension (pSource, E_SOURCE_EXTENSION_ADDRESS_BOOK)) + return false; + + gpointer extension = e_source_get_extension (pSource, E_SOURCE_EXTENSION_ADDRESS_BOOK); + return extension && g_strcmp0 (e_source_backend_get_backend_name (extension), backendname) == 0; +} + Reference< XResultSet > SAL_CALL OEvoabDatabaseMetaData::getTables( const Any& /*catalog*/, const ::rtl::OUString& /*schemaPattern*/, const ::rtl::OUString& /*tableNamePattern*/, const Sequence< ::rtl::OUString >& types ) throw(SQLException, RuntimeException) @@ -1111,50 +1129,96 @@ Reference< XResultSet > SAL_CALL OEvoabDatabaseMetaData::getTables( ODatabaseMetaDataResultSet::ORows aRows; - ESourceList *pSourceList; - if( !e_book_get_addressbooks (&pSourceList, NULL) ) - pSourceList = NULL; - - GSList *g; - for( g = e_source_list_peek_groups( pSourceList ); g; g = g->next) + if (eds_check_version(3, 6, 0) == NULL) { - GSList *s; - const char *p = e_source_group_peek_base_uri(E_SOURCE_GROUP(g->data)); - - switch (m_pConnection->getSDBCAddressType()) { - case SDBCAddress::EVO_GWISE: - if ( !strncmp( "groupwise://", p, 11 )) - break; - else - continue; - case SDBCAddress::EVO_LOCAL: - if ( !strncmp( "file://", p, 6 ) || - !strncmp( "local://", p, 6 ) ) - break; - else - continue; - case SDBCAddress::EVO_LDAP: - if ( !strncmp( "ldap://", p, 6 )) - break; - else - continue; - case SDBCAddress::Unknown: - break; - } - for (s = e_source_group_peek_sources (E_SOURCE_GROUP (g->data)); s; s = s->next) - { - ESource *pSource = E_SOURCE (s->data); + GList *pSources = e_source_registry_list_sources(get_e_source_registry(), E_SOURCE_EXTENSION_ADDRESS_BOOK); - rtl::OUString aName = rtl::OStringToOUString( e_source_peek_name( pSource ), - RTL_TEXTENCODING_UTF8 ); + for (GList* liter = pSources; liter; liter = liter->next) + { + ESource *pSource = E_SOURCE (liter->data); + bool can = false; + switch (m_pConnection->getSDBCAddressType()) + { + case SDBCAddress::EVO_GWISE: + can = isSourceBackend( pSource, "groupwise"); // not supported in evo/eds 3.6.x+, somehow + break; + case SDBCAddress::EVO_LOCAL: + can = isSourceBackend( pSource, "local"); + break; + case SDBCAddress::EVO_LDAP: + can = isSourceBackend( pSource, "ldap"); + break; + case SDBCAddress::Unknown: + can = true; + break; + } + if (!can) + continue; ODatabaseMetaDataResultSet::ORow aRow(3); aRow.reserve(6); - aRow.push_back(new ORowSetValueDecorator(aName)); + OUString aHumanName = OStringToOUString( e_source_get_display_name( pSource ), + RTL_TEXTENCODING_UTF8 ); + aRow.push_back(new ORowSetValueDecorator(aHumanName)); //tablename aRow.push_back(new ORowSetValueDecorator(aTable)); - aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); + OUString aUID = OStringToOUString( e_source_get_uid( pSource ), + RTL_TEXTENCODING_UTF8 ); + aRow.push_back(new ORowSetValueDecorator(aUID)); //comment + //I'd prefer to swap the comment and the human name and + //just use e_source_registry_ref_source(get_e_source_registry(), aUID); + //in open book rather than search for the name again aRows.push_back(aRow); } + + g_list_free_full (pSources, g_object_unref); + } + else + { + ESourceList *pSourceList; + if( !e_book_get_addressbooks (&pSourceList, NULL) ) + pSourceList = NULL; + + GSList *g; + for( g = e_source_list_peek_groups( pSourceList ); g; g = g->next) + { + GSList *s; + const char *p = e_source_group_peek_base_uri(E_SOURCE_GROUP(g->data)); + + switch (m_pConnection->getSDBCAddressType()) { + case SDBCAddress::EVO_GWISE: + if ( !strncmp( "groupwise://", p, 11 )) + break; + else + continue; + case SDBCAddress::EVO_LOCAL: + if ( !strncmp( "file://", p, 6 ) || + !strncmp( "local://", p, 6 ) ) + break; + else + continue; + case SDBCAddress::EVO_LDAP: + if ( !strncmp( "ldap://", p, 6 )) + break; + else + continue; + case SDBCAddress::Unknown: + break; + } + for (s = e_source_group_peek_sources (E_SOURCE_GROUP (g->data)); s; s = s->next) + { + ESource *pSource = E_SOURCE (s->data); + + rtl::OUString aName = rtl::OStringToOUString( e_source_peek_name( pSource ), + RTL_TEXTENCODING_UTF8 ); + + ODatabaseMetaDataResultSet::ORow aRow(3); + aRow.reserve(6); + aRow.push_back(new ORowSetValueDecorator(aName)); + aRow.push_back(new ORowSetValueDecorator(aTable)); + aRow.push_back(ODatabaseMetaDataResultSet::getEmptyValue()); + aRows.push_back(aRow); + } + } } pResult->setRows(aRows); diff --git a/connectivity/source/drivers/evoab2/NResultSet.cxx b/connectivity/source/drivers/evoab2/NResultSet.cxx index b5f4640..26690b1 100644 --- a/connectivity/source/drivers/evoab2/NResultSet.cxx +++ b/connectivity/source/drivers/evoab2/NResultSet.cxx @@ -87,109 +87,17 @@ sal_Bool SAL_CALL OEvoabResultSet::supportsService( const ::rtl::OUString& _rSer return pSupported != pEnd; } -// ------------------------------------------------------------------------- -OEvoabResultSet::OEvoabResultSet( OCommonStatement* pStmt, OEvoabConnection *pConnection ) - :OResultSet_BASE(m_aMutex) - ,::comphelper::OPropertyContainer( OResultSet_BASE::rBHelper ) - ,m_pStatement(pStmt) - ,m_pConnection(pConnection) - ,m_xMetaData(NULL) - ,m_bWasNull(sal_True) - ,m_nFetchSize(0) - ,m_nResultSetType(ResultSetType::SCROLL_INSENSITIVE) - ,m_nFetchDirection(FetchDirection::FORWARD) - ,m_nResultSetConcurrency(ResultSetConcurrency::READ_ONLY) - ,m_pContacts(NULL) - ,m_nIndex(-1) - ,m_nLength(0) -{ - #define REGISTER_PROP( id, member ) \ - registerProperty( \ - OMetaConnection::getPropMap().getNameByIndex( id ), \ - id, \ - PropertyAttribute::READONLY, \ - &member, \ - ::getCppuType( &member ) \ - ); - - REGISTER_PROP( PROPERTY_ID_FETCHSIZE, m_nFetchSize ); - REGISTER_PROP( PROPERTY_ID_RESULTSETTYPE, m_nResultSetType ); - REGISTER_PROP( PROPERTY_ID_FETCHDIRECTION, m_nFetchDirection ); - REGISTER_PROP( PROPERTY_ID_RESULTSETCONCURRENCY, m_nResultSetConcurrency ); -} - -// ------------------------------------------------------------------------- -OEvoabResultSet::~OEvoabResultSet() -{ -} - -// ------------------------------------------------------------------------- - -static ESource * -findSource( const char *name ) +struct ComparisonData { - ESourceList *pSourceList = NULL; + const SortDescriptor& rSortOrder; + IntlWrapper aIntlWrapper; - g_return_val_if_fail (name != NULL, NULL); - - if (!e_book_get_addressbooks (&pSourceList, NULL)) - pSourceList = NULL; - - for ( GSList *g = e_source_list_peek_groups (pSourceList); g; g = g->next) + ComparisonData( const SortDescriptor& _rSortOrder, const Reference< XComponentContext >& _rxContext ) + :rSortOrder( _rSortOrder ) + ,aIntlWrapper( _rxContext, SvtSysLocale().GetLanguageTag() ) { - for (GSList *s = e_source_group_peek_sources (E_SOURCE_GROUP (g->data)); s; s = s->next) - { - ESource *pSource = E_SOURCE (s->data); - if (!strcmp (e_source_peek_name (pSource), name)) - return pSource; - } } - return NULL; -} - -static EBook * -openBook( const char *abname ) -{ - ESource *pSource = findSource (abname); - EBook *pBook = NULL; - if (pSource) - pBook = e_book_new (pSource, NULL); - - if (pBook && !e_book_open (pBook, TRUE, NULL)) - { - g_object_unref (G_OBJECT (pBook)); - pBook = NULL; - } - - return pBook; -} - -static bool isLDAP( EBook *pBook ) -{ - return pBook && !strncmp( "ldap://", e_book_get_uri( pBook ), 6 ); -} - -static bool isLocal( EBook *pBook ) -{ - return pBook && ( !strncmp( "file://", e_book_get_uri( pBook ), 6 ) || - !strncmp( "local:", e_book_get_uri( pBook ), 6 ) ); -} - -static bool isAuthRequired( EBook *pBook ) -{ - return e_source_get_property( e_book_get_source( pBook ), - "auth" ) != NULL; -} - -static rtl::OString getUserName( EBook *pBook ) -{ - rtl::OString aName; - if( isLDAP( pBook ) ) - aName = e_source_get_property( e_book_get_source( pBook ), "binddn" ); - else - aName = e_source_get_property( e_book_get_source( pBook ), "user" ); - return aName; -} +}; static ::rtl::OUString valueToOUString( GValue& _rValue ) @@ -209,29 +117,6 @@ valueToBool( GValue& _rValue ) return bResult; } -static bool -executeQuery (EBook* pBook, EBookQuery* pQuery, GList **ppList, - rtl::OString &rPassword, GError **pError) -{ - ESource *pSource = e_book_get_source( pBook ); - bool bSuccess = false; - bool bAuthSuccess = true; - - *ppList = NULL; - - if( isAuthRequired( pBook ) ) - { - rtl::OString aUser( getUserName( pBook ) ); - const char *pAuth = e_source_get_property( pSource, "auth" ); - bAuthSuccess = e_book_authenticate_user( pBook, aUser.getStr(), rPassword.getStr(), pAuth, pError ); - } - - if (bAuthSuccess) - bSuccess = e_book_get_contacts( pBook, pQuery, ppList, pError ); - - return bSuccess; -} - static int whichAddress(int value) { @@ -368,6 +253,7 @@ handleSplitAddress( EContact *pContact,GValue *pStackValue, int value ) return false; } + static bool getValue( EContact* pContact, sal_Int32 nColumnNum, GType nType, GValue* pStackValue, bool& _out_rWasNull ) { @@ -420,21 +306,6 @@ getValue( EContact* pContact, sal_Int32 nColumnNum, GType nType, GValue* pStackV return true; } -namespace -{ - struct ComparisonData - { - const SortDescriptor& rSortOrder; - IntlWrapper aIntlWrapper; - - ComparisonData( const SortDescriptor& _rSortOrder, const Reference< XComponentContext >& _rxContext ) - :rSortOrder( _rSortOrder ) - ,aIntlWrapper( _rxContext, SvtSysLocale().GetLanguageTag() ) - { - } - }; -} - extern "C" int CompareContacts( gconstpointer _lhs, gconstpointer _rhs, gpointer _userData ) { @@ -493,13 +364,278 @@ int CompareContacts( gconstpointer _lhs, gconstpointer _rhs, gpointer _userData return 0; } -static GList* -sortContacts( GList* _pContactList, const ComparisonData& _rCompData ) +OString OEvoabVersionHelper::getUserName( EBook *pBook ) { - OSL_ENSURE( !_rCompData.rSortOrder.empty(), "sortContacts: no need to call this without any sort order!" ); - ENSURE_OR_THROW( _rCompData.aIntlWrapper.getCaseCollator(), "no collator for comparing strings" ); + OString aName; + if( isLDAP( pBook ) ) + aName = e_source_get_property( e_book_get_source( pBook ), "binddn" ); + else + aName = e_source_get_property( e_book_get_source( pBook ), "user" ); + return aName; +} + +class OEvoabVersion36Helper : public OEvoabVersionHelper +{ +private: + GSList *m_pContacts; +public: + OEvoabVersion36Helper() + : m_pContacts(NULL) + { + } + + ~OEvoabVersion36Helper() + { + freeContacts(); + } + + virtual EBook* openBook(const char *abname) + { + //It would be better if here we had id to begin with, see + //NDatabaseMetaData.cxx + const char *id = NULL; + GList *pSources = e_source_registry_list_sources(get_e_source_registry(), E_SOURCE_EXTENSION_ADDRESS_BOOK); + for (GList* liter = pSources; liter; liter = liter->next) + { + ESource *pSource = E_SOURCE (liter->data); - return g_list_sort_with_data( _pContactList, &CompareContacts, const_cast< gpointer >( static_cast< gconstpointer >( &_rCompData ) ) ); + if (strcmp(abname, e_source_get_display_name( pSource )) == 0) + { + id = e_source_get_uid( pSource ); + break; + } + } + g_list_free_full (pSources, g_object_unref); + if (!id) + return NULL; + + ESource *pSource = e_source_registry_ref_source(get_e_source_registry(), id); + EBookClient *pBook = pSource ? e_book_client_new (pSource, NULL) : NULL; + if (pBook && !e_client_open_sync (pBook, TRUE, NULL, NULL)) + { + g_object_unref (G_OBJECT (pBook)); + pBook = NULL; + } + if (pSource) + g_object_unref (pSource); + return pBook; + } + + bool isBookBackend( EBookClient *pBook, const char *backendname) + { + if (!pBook) + return false; + ESource *pSource = e_client_get_source ((EClient *) pBook); + return isSourceBackend(pSource, backendname); + } + + virtual bool isLDAP( EBook *pBook ) + { + return isBookBackend(pBook, "ldap"); + } + + virtual bool isLocal( EBook *pBook ) + { + return isBookBackend(pBook, "local"); + } + + virtual void freeContacts() + { + e_client_util_free_object_slist(m_pContacts); + m_pContacts = NULL; + } + + virtual bool executeQuery (EBook* pBook, EBookQuery* pQuery, OString &/*rPassword*/) + { + freeContacts(); + char *sexp = e_book_query_to_string( pQuery ); + bool bSuccess = e_book_client_get_contacts_sync( pBook, sexp, &m_pContacts, NULL, NULL ); + g_free (sexp); + return bSuccess; + } + + virtual EContact *getContact(sal_Int32 nIndex) + { + gpointer pData = g_slist_nth_data (m_pContacts, nIndex); + return pData ? E_CONTACT (pData) : NULL; + } + + virtual sal_Int32 getNumContacts() + { + return g_slist_length( m_pContacts ); + } + + virtual bool hasContacts() + { + return m_pContacts != NULL; + } + + virtual void sortContacts( const ComparisonData& _rCompData ) + { + OSL_ENSURE( !_rCompData.rSortOrder.empty(), "sortContacts: no need to call this without any sort order!" ); + ENSURE_OR_THROW( _rCompData.aIntlWrapper.getCaseCollator(), "no collator for comparing strings" ); + + m_pContacts = g_slist_sort_with_data( m_pContacts, &CompareContacts, + const_cast< gpointer >( static_cast< gconstpointer >( &_rCompData ) ) ); + } +}; + +class OEvoabVersion35Helper : public OEvoabVersionHelper +{ +private: + GList *m_pContacts; + + ESource * findSource( const char *id ) + { + ESourceList *pSourceList = NULL; + + g_return_val_if_fail (id != NULL, NULL); + + if (!e_book_get_addressbooks (&pSourceList, NULL)) + pSourceList = NULL; + + for ( GSList *g = e_source_list_peek_groups (pSourceList); g; g = g->next) + { + for (GSList *s = e_source_group_peek_sources (E_SOURCE_GROUP (g->data)); s; s = s->next) + { + ESource *pSource = E_SOURCE (s->data); + if (!strcmp (e_source_peek_name (pSource), id)) + return pSource; + } + } + return NULL; + } + + bool isAuthRequired( EBook *pBook ) + { + return e_source_get_property( e_book_get_source( pBook ), + "auth" ) != NULL; + } + +public: + OEvoabVersion35Helper() + : m_pContacts(NULL) + { + } + + ~OEvoabVersion35Helper() + { + freeContacts(); + } + + virtual EBook* openBook(const char *abname) + { + ESource *pSource = findSource (abname); + EBook *pBook = pSource ? e_book_new (pSource, NULL) : NULL; + if (pBook && !e_book_open (pBook, TRUE, NULL)) + { + g_object_unref (G_OBJECT (pBook)); + pBook = NULL; + } + return pBook; + } + + virtual bool isLDAP( EBook *pBook ) + { + return pBook && !strncmp( "ldap://", e_book_get_uri( pBook ), 6 ); + } + + virtual bool isLocal( EBook *pBook ) + { + return pBook && ( !strncmp( "file://", e_book_get_uri( pBook ), 6 ) || + !strncmp( "local:", e_book_get_uri( pBook ), 6 ) ); + } + + virtual void freeContacts() + { + g_list_free(m_pContacts); + m_pContacts = NULL; + } + + virtual bool executeQuery (EBook* pBook, EBookQuery* pQuery, OString &rPassword) + { + freeContacts(); + + ESource *pSource = e_book_get_source( pBook ); + bool bSuccess = false; + bool bAuthSuccess = true; + + if( isAuthRequired( pBook ) ) + { + rtl::OString aUser( getUserName( pBook ) ); + const char *pAuth = e_source_get_property( pSource, "auth" ); + bAuthSuccess = e_book_authenticate_user( pBook, aUser.getStr(), rPassword.getStr(), pAuth, NULL ); + } + + if (bAuthSuccess) + bSuccess = e_book_get_contacts( pBook, pQuery, &m_pContacts, NULL ); + + return bSuccess; + } + + virtual EContact *getContact(sal_Int32 nIndex) + { + gpointer pData = g_list_nth_data (m_pContacts, nIndex); + return pData ? E_CONTACT (pData) : NULL; + } + + virtual sal_Int32 getNumContacts() + { + return g_list_length( m_pContacts ); + } + + virtual bool hasContacts() + { + return m_pContacts != NULL; + } + + virtual void sortContacts( const ComparisonData& _rCompData ) + { + OSL_ENSURE( !_rCompData.rSortOrder.empty(), "sortContacts: no need to call this without any sort order!" ); + ENSURE_OR_THROW( _rCompData.aIntlWrapper.getCaseCollator(), "no collator for comparing strings" ); + + m_pContacts = g_list_sort_with_data( m_pContacts, &CompareContacts, + const_cast< gpointer >( static_cast< gconstpointer >( &_rCompData ) ) ); + } +}; + +OEvoabResultSet::OEvoabResultSet( OCommonStatement* pStmt, OEvoabConnection *pConnection ) + :OResultSet_BASE(m_aMutex) + ,::comphelper::OPropertyContainer( OResultSet_BASE::rBHelper ) + ,m_pStatement(pStmt) + ,m_pConnection(pConnection) + ,m_xMetaData(NULL) + ,m_bWasNull(sal_True) + ,m_nFetchSize(0) + ,m_nResultSetType(ResultSetType::SCROLL_INSENSITIVE) + ,m_nFetchDirection(FetchDirection::FORWARD) + ,m_nResultSetConcurrency(ResultSetConcurrency::READ_ONLY) + ,m_nIndex(-1) + ,m_nLength(0) +{ + if (eds_check_version(3, 6, 0) == NULL) + m_pVersionHelper = new OEvoabVersion36Helper; + else + m_pVersionHelper = new OEvoabVersion35Helper; + + #define REGISTER_PROP( id, member ) \ + registerProperty( \ + OMetaConnection::getPropMap().getNameByIndex( id ), \ + id, \ + PropertyAttribute::READONLY, \ + &member, \ + ::getCppuType( &member ) \ + ); + + REGISTER_PROP( PROPERTY_ID_FETCHSIZE, m_nFetchSize ); + REGISTER_PROP( PROPERTY_ID_RESULTSETTYPE, m_nResultSetType ); + REGISTER_PROP( PROPERTY_ID_FETCHDIRECTION, m_nFetchDirection ); + REGISTER_PROP( PROPERTY_ID_RESULTSETCONCURRENCY, m_nResultSetConcurrency ); +} + +// ------------------------------------------------------------------------- +OEvoabResultSet::~OEvoabResultSet() +{ } // ------------------------------------------------------------------------- @@ -507,17 +643,16 @@ void OEvoabResultSet::construct( const QueryData& _rData ) { ENSURE_OR_THROW( _rData.getQuery(), "internal error: no EBookQuery" ); - EBook *pBook = openBook(::rtl::OUStringToOString(_rData.sTable, RTL_TEXTENCODING_UTF8).getStr()); + EBook *pBook = m_pVersionHelper->openBook(OUStringToOString(_rData.sTable, RTL_TEXTENCODING_UTF8).getStr()); if ( !pBook ) m_pConnection->throwGenericSQLException( STR_CANNOT_OPEN_BOOK, *this ); - g_list_free(m_pContacts); - m_pContacts = NULL; + m_pVersionHelper->freeContacts(); bool bExecuteQuery = true; switch ( _rData.eFilterType ) { case eFilterNone: - if ( !isLocal( pBook ) ) + if ( !m_pVersionHelper->isLocal( pBook ) ) { SQLError aErrorFactory( m_pConnection->getDriver().getMSFactory() ); SQLException aAsException = aErrorFactory.getSQLException( ErrorCondition::DATA_CANNOT_SELECT_UNFILTERED, *this ); @@ -541,16 +676,16 @@ void OEvoabResultSet::construct( const QueryData& _rData ) if ( bExecuteQuery ) { rtl::OString aPassword = m_pConnection->getPassword(); - executeQuery( pBook, _rData.getQuery(), &m_pContacts, aPassword, NULL ); + m_pVersionHelper->executeQuery(pBook, _rData.getQuery(), aPassword); m_pConnection->setPassword( aPassword ); - if ( m_pContacts && !_rData.aSortOrder.empty() ) + if ( m_pVersionHelper->hasContacts() && !_rData.aSortOrder.empty() ) { ComparisonData aCompData( _rData.aSortOrder, comphelper::getComponentContext(getConnection()->getDriver().getMSFactory()) ); - m_pContacts = sortContacts( m_pContacts, aCompData ); + m_pVersionHelper->sortContacts( aCompData ); } } - m_nLength = g_list_length( m_pContacts ); + m_nLength = m_pVersionHelper->getNumContacts(); OSL_TRACE( "Query return %d records", m_nLength ); m_nIndex = -1; @@ -567,10 +702,10 @@ void OEvoabResultSet::disposing(void) ::comphelper::OPropertyContainer::disposing(); ::osl::MutexGuard aGuard(m_aMutex); - g_list_free(m_pContacts); - m_pContacts = NULL; + delete m_pVersionHelper; + m_pVersionHelper = NULL; m_pStatement = NULL; -m_xMetaData.clear(); + m_xMetaData.clear(); } // ------------------------------------------------------------------------- Any SAL_CALL OEvoabResultSet::queryInterface( const Type & rType ) throw(RuntimeException) diff --git a/connectivity/source/drivers/evoab2/NResultSet.hxx b/connectivity/source/drivers/evoab2/NResultSet.hxx index fd049fd..c3d7ab4 100644 --- a/connectivity/source/drivers/evoab2/NResultSet.hxx +++ b/connectivity/source/drivers/evoab2/NResultSet.hxx @@ -45,6 +45,24 @@ namespace connectivity { namespace evoab { + class ComparisonData; + + class OEvoabVersionHelper + { + public: + virtual EBook* openBook(const char *abname) = 0; + virtual bool executeQuery (EBook* pBook, EBookQuery* pQuery, OString &rPassword) = 0; + virtual void freeContacts() = 0; + virtual bool isLDAP( EBook *pBook ) = 0; + virtual bool isLocal( EBook *pBook ) = 0; + virtual EContact *getContact(sal_Int32 nIndex) = 0; + virtual sal_Int32 getNumContacts() = 0; + virtual bool hasContacts() = 0; + virtual void sortContacts( const ComparisonData& _rCompData ) = 0; + OString getUserName( EBook *pBook ); + virtual ~OEvoabVersionHelper() {} + }; + typedef ::cppu::WeakComponentImplHelper8 < ::com::sun::star::sdbc::XResultSet , ::com::sun::star::sdbc::XRow , ::com::sun::star::sdbc::XResultSetMetaDataSupplier @@ -61,6 +79,8 @@ namespace connectivity ,public ::comphelper::OPropertyContainer ,public ::comphelper::OPropertyArrayUsageHelper { + private: + OEvoabVersionHelper *m_pVersionHelper; protected: @@ -79,13 +99,11 @@ namespace connectivity // // Data & iteration - GList *m_pContacts; sal_Int32 m_nIndex; sal_Int32 m_nLength; EContact *getCur() { - gpointer pData = g_list_nth_data (m_pContacts, m_nIndex); - return pData ? E_CONTACT (pData) : NULL; + return m_pVersionHelper->getContact(m_nIndex); } // OPropertyArrayUsageHelper diff --git a/dbaccess/source/core/api/SingleSelectQueryComposer.cxx b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx index 837836d..ad68908 100644 --- a/dbaccess/source/core/api/SingleSelectQueryComposer.cxx +++ b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx @@ -955,6 +955,18 @@ Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns( ) thr } while ( false ); + bool bMissingSomeColumnLabels = !aNames.empty() && aNames.size() != aSelectColumns->get().size(); + SAL_WARN_IF(bMissingSomeColumnLabels, "dbaccess", "We have column labels for *some* columns but not all"); + //^^this happens in the evolution address book where we have real column names of e.g. + //first_name, second_name and city. On parsing via + //OSQLParseTreeIterator::appendColumns it creates some labels using those real names + //but the evo address book gives them proper labels of First Name, Second Name and City + //the munge means that here we have e.g. just "City" as a label because it matches + // + //This is all a horrible mess + if (bMissingSomeColumnLabels) + aNames.clear(); + if ( aNames.empty() ) m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex ); else -- 1.8.1