Index: directory/xpcom/base/public/nsILDAPConnection.idl =================================================================== RCS file: /mozilla/mozilla/directory/xpcom/base/public/nsILDAPConnection.idl,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/directory/xpcom/base/public/nsILDAPConnection.idl 22 Oct 2003 02:37:04 -0000 1.1.1.1 +++ miss/build/mozilla/directory/xpcom/base/public/nsILDAPConnection.idl 22 Oct 2003 09:45:04 -0000 1.2 @@ -69,7 +69,7 @@ * @exception NS_ERROR_FAILURE * @exception NS_ERROR_UNEXPECTED internal error */ - void init(in string aHost, in short aPort, in boolean aSSL, + void init(in string aHost, in long aPort, in boolean aSSL, in wstring aBindName, in nsILDAPMessageListener aMessageListener); Index: directory/xpcom/base/src/nsLDAPConnection.cpp =================================================================== RCS file: /mozilla/mozilla/directory/xpcom/base/src/nsLDAPConnection.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/directory/xpcom/base/src/nsLDAPConnection.cpp 22 Oct 2003 02:37:04 -0000 1.1.1.1 +++ miss/build/mozilla/directory/xpcom/base/src/nsLDAPConnection.cpp 22 Oct 2003 09:45:04 -0000 1.2 @@ -48,7 +48,6 @@ #include "nsIConsoleService.h" #include "nsIDNSService.h" #include "nsIRequestObserver.h" -#include "nsIProxyObjectManager.h" #include "netCore.h" const char kConsoleServiceContractId[] = "@mozilla.org/consoleservice;1"; @@ -169,11 +168,10 @@ NS_IMETHODIMP -nsLDAPConnection::Init(const char *aHost, PRInt16 aPort, PRBool aSSL, +nsLDAPConnection::Init(const char *aHost, PRInt32 aPort, PRBool aSSL, const PRUnichar *aBindName, nsILDAPMessageListener *aMessageListener) { - nsCOMPtr selfProxy; nsresult rv; if ( !aHost || !aMessageListener) { @@ -222,22 +220,6 @@ return NS_ERROR_FAILURE; } - // Get a proxy object so the callback happens on the current thread. - // This is now a Synchronous proxy, due to the fact that the DNS - // service hands out data which it later deallocates, and the async - // proxy makes this unreliable. See bug 102227 for more details. - // - rv = NS_GetProxyForObject(NS_CURRENT_EVENTQ, - NS_GET_IID(nsIDNSListener), - NS_STATIC_CAST(nsIDNSListener*, this), - PROXY_SYNC | PROXY_ALWAYS, - getter_AddRefs(selfProxy)); - - if (NS_FAILED(rv)) { - NS_ERROR("nsLDAPConnection::Init(): couldn't " - "create proxy to this object for callback"); - return NS_ERROR_FAILURE; - } // Do the pre-resolve of the hostname, using the DNS service. This // will also initialize the LDAP connection properly, once we have @@ -256,7 +238,8 @@ return NS_ERROR_FAILURE; } rv = pDNSService->Lookup(aHost, - selfProxy, + //selfProxy, + this, // SDBC change nsnull, getter_AddRefs(mDNSRequest)); Index: directory/xpcom/base/src/nsLDAPConnection.h =================================================================== RCS file: /mozilla/mozilla/directory/xpcom/base/src/nsLDAPConnection.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/directory/xpcom/base/src/nsLDAPConnection.h 22 Oct 2003 02:37:04 -0000 1.1.1.1 +++ miss/build/mozilla/directory/xpcom/base/src/nsLDAPConnection.h 22 Oct 2003 09:45:04 -0000 1.2 @@ -119,7 +119,7 @@ nsSupportsHashtable *mPendingOperations; // keep these around for callbacks nsLDAPConnectionLoop *mRunnable; // nsIRunnable object - PRInt16 mPort; // The LDAP port we're binding to + PRInt32 mPort; // The LDAP port we're binding to PRBool mSSL; // the options nsCString mResolvedIP; // Preresolved list of host IPs Index: mailnews/addrbook/Makefile.in =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/Makefile.in,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/Makefile.in 22 Oct 2003 02:43:08 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/Makefile.in 9 Dec 2003 03:27:41 -0000 1.2 @@ -31,7 +31,7 @@ EXTRA_COMPONENTS += src/nsLDAPPrefsService.js endif -DIRS = public src build +DIRS = public src build include $(topsrcdir)/config/rules.mk Index: mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.cpp =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.cpp 22 Oct 2003 02:43:10 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.cpp 22 Oct 2003 09:45:04 -0000 1.2 @@ -39,6 +39,7 @@ #include "nsAbBoolExprToLDAPFilter.h" #include "nsAbLDAPProperties.h" #include "nsXPIDLString.h" +#include "nsAbUtils.h" const int nsAbBoolExprToLDAPFilter::TRANSLATE_CARD_PROPERTY = 1 << 0 ; const int nsAbBoolExprToLDAPFilter::ALLOW_NON_CONVERTABLE_CARD_PROPERTY = 1 << 1 ; @@ -80,6 +81,35 @@ if (count == 0) return NS_OK; + /* + * 3rd party query integration with Mozilla is achieved + * by calling nsAbLDAPDirectoryQuery::DoQuery(). Thus + * we can arrive here with a query asking for all the + * ldap attributes using the card:nsIAbCard interface. + * + * So we need to check that we are not creating a condition + * filter against this otherwise we can end an + * invalid filter equal to "(|)". + */ + + if (count == 1 ) + { + nsCOMPtr item; + rv = childExpressions->GetElementAt (0, getter_AddRefs (item)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr childCondition(do_QueryInterface(item, &rv)); + if (NS_SUCCEEDED(rv)) + { + nsXPIDLCString name; + rv = childCondition->GetName (getter_Copies (name)); + NS_ENSURE_SUCCESS(rv, rv); + + if(name.Equals("card:nsIAbCard")) + return NS_OK; + } + } + filter += NS_LITERAL_CSTRING("("); switch (operation) { @@ -157,13 +187,16 @@ rv = condition->GetName (getter_Copies (name)); NS_ENSURE_SUCCESS(rv, rv); - const char* ldapProperty = name.get (); + CharPtrArrayGuard attrs; if (flags & TRANSLATE_CARD_PROPERTY) { - const MozillaLdapPropertyRelation* p = - MozillaLdapPropertyRelator::findLdapPropertyFromMozilla (name.get ()); - if (p) - ldapProperty = p->ldapProperty; + if(const MozillaLdapPropertyRelation* property = + MozillaLdapPropertyRelator::findLdapPropertyFromMozilla (name.get ())) + { + // allow even single ldap attribute mapppings to go through this to simplify the filter creation later. + rv = MozillaLdapPropertyRelator::getAllLDAPAttrsFromMozilla (property->ldapProperty, attrs.GetSizeAddr(), attrs.GetArrayAddr() ); + NS_ENSURE_SUCCESS(rv, rv); + } else if (!(flags & ALLOW_NON_CONVERTABLE_CARD_PROPERTY)) return NS_OK; } @@ -173,6 +206,37 @@ NS_ENSURE_SUCCESS(rv, rv); NS_ConvertUCS2toUTF8 vUTF8 (value); + // check if using multiple ldap attributes + if(attrs.GetSize() == 1 ) + GenerateSingleFilter(conditionType,filter,vUTF8,attrs.GetArray()[0]); + else + { + // add the opening brace if using multiple ldap attributes + switch (conditionType) + { + // 'NOT' conditionals use the 'AND' operator + case nsIAbBooleanConditionTypes::DoesNotExist: + case nsIAbBooleanConditionTypes::DoesNotContain: + case nsIAbBooleanConditionTypes::IsNot: + filter += NS_LITERAL_CSTRING("(&"); + break; + default: + filter += NS_LITERAL_CSTRING("(|"); + break; + } + GenerateMultipleFilter(conditionType,filter,vUTF8,&attrs); + // add the closing brace if using multiple ldap attributes + filter += NS_LITERAL_CSTRING(")"); + } + + return rv; +} +void nsAbBoolExprToLDAPFilter:: GenerateSingleFilter( + nsAbBooleanConditionType conditionType, + nsCString& filter, + NS_ConvertUCS2toUTF8 &vUTF8, + const char *ldapProperty) +{ switch (conditionType) { case nsIAbBooleanConditionTypes::DoesNotExist: @@ -253,7 +317,47 @@ default: break; } - - return rv; } +void nsAbBoolExprToLDAPFilter:: GenerateMultipleFilter( + nsAbBooleanConditionType conditionType, + nsCString& filter, + NS_ConvertUCS2toUTF8 &vUTF8, + CharPtrArrayGuard *pAttrs) +{ + PRUint16 i = 0; + PRUint16 inner = 0; + /* + * This function is based on the fact that we are trying to generate support + * for multiple occurring ldap attributes. Consider the following query: + * (PagerNumber,=,123456) where PagerNumber = pager|pagerphone translates to: + * (|(&(pager=*)(pager=123456))(&(!(pager=*))(pagerphone=123456))) + * This can be shortened to: + * (|(pager=123456)(&(!(pager=*))(pagerphone=123456))) + * + * i.e. use the first occurring attribute if it exists otherwise if first + * does not exist use the second etc. The assumption is that the first + * always takes precedence. + * This translates to: + * GenerateSingleFilter(Is); + * GenerateSingleFilter(DoesNotExists); + * GenerateSingleFilter(Is); + */ + + for (i = 0; i < pAttrs->GetSize(); i++) + { + if(i == 0) + GenerateSingleFilter(conditionType,filter,vUTF8,pAttrs->GetArray()[i]); + else + { + filter += NS_LITERAL_CSTRING("(&"); + nsAbBooleanConditionType doesNotExistsType = nsIAbBooleanConditionTypes::DoesNotExist; + for(inner = 0; inner < i; ++inner) + { + GenerateSingleFilter(doesNotExistsType,filter,vUTF8,pAttrs->GetArray()[inner]); + } + GenerateSingleFilter(conditionType,filter,vUTF8,pAttrs->GetArray()[i]); + filter += NS_LITERAL_CSTRING(")"); + } + } +} Index: mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.h =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.h 22 Oct 2003 02:43:10 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbBoolExprToLDAPFilter.h 22 Oct 2003 09:45:04 -0000 1.2 @@ -42,6 +42,7 @@ #include "nsIAbBooleanExpression.h" #include "nsCOMPtr.h" #include "nsString.h" +#include "nsAbUtils.h" class nsAbBoolExprToLDAPFilter { @@ -67,6 +68,16 @@ nsIAbBooleanConditionString* condition, nsCString& filter, int flags); + static void GenerateMultipleFilter( + nsAbBooleanConditionType conditionType, + nsCString& filter, + NS_ConvertUCS2toUTF8 &vUTF8, + CharPtrArrayGuard *pAttrs); + static void GenerateSingleFilter( + nsAbBooleanConditionType conditionType, + nsCString& filter, + NS_ConvertUCS2toUTF8 &vUTF8, + const char *ldapProperty); }; #endif Index: mailnews/addrbook/src/nsAbLDAPDirectory.cpp =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbLDAPDirectory.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -w -b -i -r1.1.1.1 -r1.3 --- miss/build/mozilla/mailnews/addrbook/src/nsAbLDAPDirectory.cpp 22 Oct 2003 02:43:10 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbLDAPDirectory.cpp 8 Jan 2004 04:26:20 -0000 1.3 @@ -112,15 +112,82 @@ // use mURINoQuery to get a prefName nsCAutoString prefName; - prefName = nsDependentCString(mURINoQuery.get() + kLDAPDirectoryRootLen) + NS_LITERAL_CSTRING(".uri"); + prefName = nsDependentCString(mURINoQuery.get() + kLDAPDirectoryRootLen) ; // turn moz-abldapdirectory://ldap_2.servers.nscpphonebook into -> "ldap_2.servers.nscpphonebook.uri" nsXPIDLCString URI; - rv = prefs->CopyCharPref(prefName.get(), getter_Copies(URI)); + nsCAutoString uriPrefName; + uriPrefName = prefName + NS_LITERAL_CSTRING(".uri"); + rv = prefs->CopyCharPref(uriPrefName.get(), getter_Copies(URI)); + if (NS_FAILED(rv)) + { + /* + * A recent change in Mozilla now means that the LDAP Address Book + * RDF Resource URI is based on the unique preference name value i.e. + * [moz-abldapdirectory://prefName] + * Prior to this valid change it was based on the actual uri i.e. + * [moz-abldapdirectory://host:port/basedn] + * Basing the resource on the prefName allows these attributes to + * change. + * + * But the uri value was also the means by which third-party + * products could integrate with Mozilla's LDAP Address Books without + * necessarily having an entry in the preferences file or more importantly + * needing to be able to change the preferences entries. Thus to set the + * URI Spec now, it is only necessary to read the uri pref entry, while in the case + * where it is not a preference, we need to replace the "moz-abldapdirectory". + */ + nsCAutoString tempLDAPURL(mURINoQuery); + tempLDAPURL.ReplaceSubstring("moz-abldapdirectory:", "ldap:"); + rv = mURL->SetSpec(tempLDAPURL); NS_ENSURE_SUCCESS(rv,rv); + nsCAutoString aHost; + mURL->GetHost(aHost); + aHost.ReplaceChar('.','_'); + prefName = nsDependentCString("ldap_2.servers.") + aHost; + PRBool useSSL=0; + rv = prefs->GetBoolPref( + PromiseFlatCString(prefName + + NS_LITERAL_CSTRING(".UseSSL")).get(), + &useSSL + ); + + // If use SSL,ldap url will look like this ldaps://host:port/..... + if (!NS_FAILED(rv) && useSSL) + { + tempLDAPURL.ReplaceSubstring("ldap:", "ldaps:"); + rv = mURL->SetSpec(tempLDAPURL); + } + //NS_FAILED(rv) means ldap_2.servers.nscpphonebook.UseSSL not exist + rv = 0; + + } + else + { rv = mURL->SetSpec(URI); + } NS_ENSURE_SUCCESS(rv, rv); + + // get the login information, if there is any + // + rv = prefs->GetCharPref( + PromiseFlatCString(prefName + + NS_LITERAL_CSTRING(".auth.dn")).get(), + getter_Copies(mLogin)); + if (NS_FAILED(rv)) { + mLogin.Truncate(); // zero out mLogin + } + + // get the password information, if there is any + // + rv = prefs->GetCharPref( + PromiseFlatCString(prefName + + NS_LITERAL_CSTRING(".auth.pwd")).get(), + getter_Copies(mPassword)); + if (NS_FAILED(rv)) { + mPassword.Truncate(); // zero out mLogin + } mConnection = do_CreateInstance(NS_LDAPCONNECTION_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); Index: mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -w -b -i -r1.1.1.1 -r1.3 --- miss/build/mozilla/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp 22 Oct 2003 02:43:10 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.cpp 8 Jan 2004 04:26:20 -0000 1.3 @@ -68,7 +68,7 @@ PRInt32 resultLimit = -1, PRInt32 timeOut = 0); virtual ~nsAbQueryLDAPMessageListener (); - + void SetPassword(const nsAString& aPassword){m_sPassword = aPassword;}; protected: nsresult OnLDAPMessageBind (nsILDAPMessage *aMessage); nsresult OnLDAPMessageSearchEntry (nsILDAPMessage *aMessage, @@ -99,6 +99,8 @@ PRBool mInitialized; PRBool mCanceled; + nsAutoString m_sPassword; + nsCOMPtr mSearchOperation; PRLock* mLock; @@ -253,6 +255,7 @@ do_CreateInstance(NS_LDAPOPERATION_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); +#if 0 nsCOMPtr proxyListener; rv = NS_GetProxyForObject(NS_UI_THREAD_EVENTQ, NS_GET_IID(nsILDAPMessageListener), @@ -261,10 +264,14 @@ getter_AddRefs(proxyListener)); rv = ldapOperation->Init(mConnection, proxyListener); +#endif +#if 1 + rv = ldapOperation->Init(mConnection, this); +#endif NS_ENSURE_SUCCESS(rv, rv); // Bind - rv = ldapOperation->SimpleBind(nsnull); + rv = ldapOperation->SimpleBind(m_sPassword.get()); NS_ENSURE_SUCCESS(rv, rv); return rv; @@ -280,6 +287,7 @@ mSearchOperation = do_CreateInstance(NS_LDAPOPERATION_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); +#if 0 nsCOMPtr proxyMgr = do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); @@ -290,6 +298,10 @@ NS_ENSURE_SUCCESS(rv, rv); rv = mSearchOperation->Init (mConnection, proxyListener); +#endif +#if 1 + rv = mSearchOperation->Init (mConnection, this); +#endif NS_ENSURE_SUCCESS(rv, rv); nsXPIDLCString dn; @@ -519,6 +531,23 @@ rv = nsAbBoolExprToLDAPFilter::Convert (expression, filter); NS_ENSURE_SUCCESS(rv, rv); + /* + * Mozilla itself cannot arrive here with a blank filter + * as the nsAbLDAPDirectory::StartSearch() disallows it. + * But 3rd party LDAP query integration with Mozilla begins + * in this method. + * + * Default the filter string if blank, otherwise it gets + * set to (objectclass=*) which returns everything. Set + * the default to (objectclass=inetorgperson) as this + * is the most appropriate default objectclass which is + * central to the makeup of the mozilla ldap address book + * entries. + */ + if(filter.IsEmpty()) + { + filter += NS_LITERAL_CSTRING("(objectclass=inetorgperson)"); + } // Set up the search ldap url nsCOMPtr directoryUrl; @@ -592,6 +621,11 @@ timeOut); if (_messageListener == NULL) return NS_ERROR_OUT_OF_MEMORY; + + nsAutoString wPassword; + wPassword.AssignWithConversion(mPassword.get()); + _messageListener->SetPassword(wPassword); + messageListener = _messageListener; nsVoidKey key (NS_REINTERPRET_CAST(void *,contextID)); @@ -604,9 +638,12 @@ *_retval = contextID; + nsAutoString wLogin; + wLogin.AssignWithConversion(mLogin.get()); + // Now lets initialize the LDAP connection properly. We'll kick // off the bind operation in the callback function, |OnLDAPInit()|. - rv = ldapConnection->Init(host.get(), port, options, nsnull, + rv = ldapConnection->Init(host.get(), port, options, wLogin.get(), messageListener); NS_ENSURE_SUCCESS(rv, rv); Index: mailnews/addrbook/src/nsAbLDAPDirectoryQuery.h =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.h 22 Oct 2003 02:43:10 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbLDAPDirectoryQuery.h 8 Jan 2004 04:26:20 -0000 1.2 @@ -72,6 +72,8 @@ friend class nsAbQueryLDAPMessageListener; nsresult RemoveListener (PRInt32 contextID); nsresult Initiate (); + nsXPIDLCString mLogin; // authenticate to the LDAP server as... + nsXPIDLCString mPassword; // password to the LDAP server as... private: nsCString mLdapUrl; Index: mailnews/addrbook/src/nsAbLDAPProperties.cpp =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbLDAPProperties.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsAbLDAPProperties.cpp 22 Oct 2003 02:43:10 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbLDAPProperties.cpp 22 Oct 2003 09:45:04 -0000 1.2 @@ -39,6 +39,7 @@ #include "nsAbLDAPProperties.h" #include "nsAbUtils.h" +#include "nsCRT.h" #include "nsCOMPtr.h" #include "nsString.h" @@ -59,6 +60,21 @@ If there are multiple entries for a mozilla property the first takes precedence. + But where we need to do a query against + a multiple occurring ldap attribute we + need to OR all the possible ldap entries e.g. + + (CellularNumber=123456) translates to + (|(mobile=123456)(&(!(mobile=*))(cellphone=123456))(&(!(mobile=*))(!(cellphone=*))(carphone=123456))) + + i.e. use the first occurring attribute otherwise if + first does not exist use the second etc. + + [Multiple occurring ldap attributes do not + include aliases. We have also ignored the case + for including 'displayname' as the first occurring + attribute 'cn' is a required attribute.] + This ensures that 1) Generality is maintained when mapping from @@ -101,55 +117,32 @@ {MozillaProperty_String, "FaxNumber", "fax"}, // organizationalPerson {MozillaProperty_String, "FaxNumber", "facsimiletelephonenumber"}, - // inetOrgPerson - {MozillaProperty_String, "PagerNumber", "pager"}, - // ? - {MozillaProperty_String, "PagerNumber", "pagerphone"}, - // inetOrgPerson - {MozillaProperty_String, "CellularNumber", "mobile"}, - // ? - {MozillaProperty_String, "CellularNumber", "cellphone"}, - // ? - {MozillaProperty_String, "CellularNumber", "carphone"}, + // inetOrgPerson ? + {MozillaProperty_String, "PagerNumber", "pager,pagerphone"}, + // inetOrgPerson ? ? + {MozillaProperty_String, "CellularNumber", "mobile,cellphone,carphone"}, // No Home* properties defined yet - // organizationalPerson - {MozillaProperty_String, "WorkAddress", "postofficebox"}, - // ? - {MozillaProperty_String, "WorkAddress", "streetaddress"}, + // organizationalPerson ? + {MozillaProperty_String, "WorkAddress", "postofficebox,streetaddress"}, // ? {MozillaProperty_String, "WorkCity", "l"}, // ? {MozillaProperty_String, "WorkCity", "locality"}, - // ? - {MozillaProperty_String, "WorkState", "st"}, - // ? - {MozillaProperty_String, "WorkState", "region"}, - // organizationalPerson - {MozillaProperty_String, "WorkZipCode", "postalcode"}, - // ? - {MozillaProperty_String, "WorkZipCode", "zip"}, + // ? ? + {MozillaProperty_String, "WorkState", "st,region"}, + // organizationalPerson ? + {MozillaProperty_String, "WorkZipCode", "postalcode,zip"}, // ? {MozillaProperty_String, "WorkCountry", "countryname"}, // organizationalPerson {MozillaProperty_String, "JobTitle", "title"}, - // ? - {MozillaProperty_String, "Department", "ou"}, - // ? - {MozillaProperty_String, "Department", "orgunit"}, - // ? - {MozillaProperty_String, "Department", "department"}, - // ? - {MozillaProperty_String, "Department", "departmentnumber"}, - // inetOrgPerson - {MozillaProperty_String, "Company", "o"}, - // ? - {MozillaProperty_String, "Company", "company"}, - // ? - {MozillaProperty_String, "WorkCountry", "countryname"}, - + // ? ? ? ? + {MozillaProperty_String, "Department", "ou,orgunit,department,departmentnumber"}, + // inetOrgPerson ? + {MozillaProperty_String, "Company", "o,company"}, // ? {MozillaProperty_String, "WebPage1", "workurl"}, // ? @@ -167,10 +160,8 @@ // ? {MozillaProperty_String, "Custom4", "custom4"}, - // ? - {MozillaProperty_String, "Notes", "notes"}, - // person - {MozillaProperty_String, "Notes", "description"}, + // ? person + {MozillaProperty_String, "Notes", "notes,description"}, // mozilla specfic {MozillaProperty_Int, "PreferMailFormat", "xmozillausehtmlmail"}, @@ -208,10 +199,22 @@ if (IsInitialized) { return ; } for (int i = tableSize - 1 ; i >= 0 ; -- i) { - nsCStringKey keyMozilla (table [i].mozillaProperty, -1, nsCStringKey::NEVER_OWN); - nsCStringKey keyLdap (table [i].ldapProperty, -1, nsCStringKey::NEVER_OWN); + char *attrToken = nsnull; + char *LDAPProperty = nsCRT::strdup(table[i].ldapProperty); + char *tmpLDAPProperty; + + attrToken = nsCRT::strtok(LDAPProperty, ",", &tmpLDAPProperty); + while (attrToken != nsnull) + { + while ( ' ' == *attrToken) + attrToken++; + nsCStringKey keyLdap (attrToken, -1, nsCStringKey::NEVER_OWN); mLdapToMozilla.Put(&keyLdap, NS_REINTERPRET_CAST(void *, NS_CONST_CAST(MozillaLdapPropertyRelation*, &table[i]))) ; + attrToken = nsCRT::strtok(tmpLDAPProperty, ",", &tmpLDAPProperty); + } + + nsCStringKey keyMozilla (table [i].mozillaProperty, -1, nsCStringKey::NEVER_OWN); mMozillaToLdap.Put(&keyMozilla, NS_REINTERPRET_CAST(void *, NS_CONST_CAST(MozillaLdapPropertyRelation*, &table[i]))) ; } IsInitialized = PR_TRUE; @@ -233,10 +236,13 @@ const MozillaLdapPropertyRelation* MozillaLdapPropertyRelator::findMozillaPropertyFromLdap (const char* ldapProperty) { Initialize(); + char *attrToken; + char *tmpLDAPProperty; + attrToken = nsCRT::strtok(NS_CONST_CAST(char *,ldapProperty), ",", &tmpLDAPProperty); // ensure that we always do a case insensitive comparison // against the incoming ldap attributes. - nsCAutoString lowercasedProp (ldapProperty) ; - ToLowerCase(nsDependentCString(ldapProperty),lowercasedProp); + nsCAutoString lowercasedProp (attrToken) ; + ToLowerCase(nsDependentCString(attrToken),lowercasedProp); nsCStringKey key (lowercasedProp) ; return NS_REINTERPRET_CAST(const MozillaLdapPropertyRelation *, mLdapToMozilla.Get(&key)) ; @@ -286,5 +292,66 @@ } } + return rv; +} + +// Parse the input string which may contain a single ldap attribute or multiple attributes in the form +// "string" or "string1,string2,string3" respectively and assign to the array. +nsresult MozillaLdapPropertyRelator::getAllLDAPAttrsFromMozilla (const char* aLDAPProperty, PRUint32 *aAttrCount, char * **aAttributes) +{ + NS_ENSURE_ARG_POINTER(aAttrCount); + NS_ENSURE_ARG_POINTER(aAttributes); + + nsresult rv = NS_OK; + + *aAttributes = 0; + // we must have at least one attribute + *aAttrCount = 1; + + // if no multiple ldap attributes then allocate our single entry and exit + if (!strchr(aLDAPProperty,',')) + { + if (!(*aAttributes = NS_STATIC_CAST(char **, nsMemory::Alloc(sizeof(char *))))) + return NS_ERROR_OUT_OF_MEMORY; + if (!((*aAttributes)[0] = nsCRT::strdup(aLDAPProperty))) + return NS_ERROR_OUT_OF_MEMORY; + + return rv; + } + + char *attrToken = nsnull; + char *LDAPProperty = nsnull; + char *tmpLDAPProperty; + + if((LDAPProperty = nsCRT::strdup(aLDAPProperty)) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + // set our tokenizer to the start + attrToken = nsCRT::strtok(LDAPProperty, ",", &tmpLDAPProperty); + + // Count up the attribute names + while ((attrToken = nsCRT::strtok(tmpLDAPProperty, ",", &tmpLDAPProperty)) != nsnull) + *aAttrCount += 1; + + nsCRT::free (LDAPProperty); + if(!(*aAttributes = NS_STATIC_CAST(char **, nsMemory::Alloc(*aAttrCount * sizeof(char *))))) + return NS_ERROR_OUT_OF_MEMORY; + + if((LDAPProperty = nsCRT::strdup(aLDAPProperty)) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + PRInt32 j = 0; + attrToken = nsCRT::strtok(LDAPProperty, ",", &tmpLDAPProperty); + while (nsnull != attrToken) { + if(((*aAttributes)[j++] = nsCRT::strdup(attrToken)) == nsnull) + { + nsCRT::free(LDAPProperty); + return NS_ERROR_OUT_OF_MEMORY; + } + + attrToken = nsCRT::strtok(tmpLDAPProperty, ",", &tmpLDAPProperty); + } + + nsCRT::free(LDAPProperty); return rv; } Index: mailnews/addrbook/src/nsAbLDAPProperties.h =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbLDAPProperties.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsAbLDAPProperties.h 22 Oct 2003 02:43:10 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbLDAPProperties.h 22 Oct 2003 09:45:04 -0000 1.2 @@ -85,6 +85,7 @@ static nsresult createCardPropertyFromLDAPMessage (nsILDAPMessage* message, nsIAbCard* card, PRBool* hasSetCardProperty); + static nsresult getAllLDAPAttrsFromMozilla (const char* aLDAPProperty, PRUint32 *aAttrCount, char * **aAttributes); }; #endif Index: mailnews/addrbook/src/nsAbOutlookCard.cpp =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbOutlookCard.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsAbOutlookCard.cpp 22 Oct 2003 02:43:10 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbOutlookCard.cpp 9 Dec 2003 03:26:47 -0000 1.2 @@ -97,6 +97,8 @@ { index_DisplayName = 0, index_EmailAddress, + index_SecondEmailAddress, + //index_ScreenName, index_FirstName, index_LastName, index_NickName, @@ -124,32 +126,35 @@ static const ULONG OutlookCardMAPIProps [] = { - PR_DISPLAY_NAME_W, - PR_EMAIL_ADDRESS_W, - PR_GIVEN_NAME_W, - PR_SURNAME_W, - PR_NICKNAME_W, - PR_BUSINESS_TELEPHONE_NUMBER_W, - PR_HOME_TELEPHONE_NUMBER_W, - PR_BUSINESS_FAX_NUMBER_W, - PR_PAGER_TELEPHONE_NUMBER_W, - PR_MOBILE_TELEPHONE_NUMBER_W, - PR_HOME_ADDRESS_CITY_W, - PR_HOME_ADDRESS_STATE_OR_PROVINCE_W, - PR_HOME_ADDRESS_POSTAL_CODE_W, - PR_HOME_ADDRESS_COUNTRY_W, - PR_BUSINESS_ADDRESS_CITY_W, - PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE_W, - PR_BUSINESS_ADDRESS_POSTAL_CODE_W, - PR_BUSINESS_ADDRESS_COUNTRY_W, - PR_TITLE_W, - PR_DEPARTMENT_NAME_W, - PR_COMPANY_NAME_W, - PR_BUSINESS_HOME_PAGE_W, - PR_PERSONAL_HOME_PAGE_W, - PR_COMMENT_W + PR_DISPLAY_NAME_A,//0x8035001E,//PR_DISPLAY_NAME_A, + PR_EMAIL_ADDRESS_A,//0x8034001E,//PR_EMAIL_ADDRESS_A, + PR_SECOND_EMAIL_ADDRESS_A,//Second Email Address + //PR_SCREEN_NAME_A,//AimScreenName + PR_GIVEN_NAME_A, + PR_SURNAME_A, + PR_NICKNAME_A, + PR_BUSINESS_TELEPHONE_NUMBER_A, + PR_HOME_TELEPHONE_NUMBER_A, + PR_BUSINESS_FAX_NUMBER_A, + PR_PAGER_TELEPHONE_NUMBER_A, + PR_MOBILE_TELEPHONE_NUMBER_A, + PR_HOME_ADDRESS_CITY_A, + PR_HOME_ADDRESS_STATE_OR_PROVINCE_A, + PR_HOME_ADDRESS_POSTAL_CODE_A, + PR_HOME_ADDRESS_COUNTRY_A, + PR_BUSINESS_ADDRESS_CITY_A, + PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE_A, + PR_BUSINESS_ADDRESS_POSTAL_CODE_A, + PR_BUSINESS_ADDRESS_COUNTRY_A, + PR_TITLE_A, + PR_DEPARTMENT_NAME_A, + PR_COMPANY_NAME_A, + PR_BUSINESS_HOME_PAGE_A, + PR_PERSONAL_HOME_PAGE_A, + PR_COMMENT_A } ; + nsresult nsAbOutlookCard::Init(const char *aUri) { nsresult retCode = nsRDFResource::Init(aUri) ; @@ -176,6 +181,8 @@ SetDisplayName(unichars [index_DisplayName]->get()) ; SetNickName(unichars [index_NickName]->get()) ; SetPrimaryEmail(unichars [index_EmailAddress]->get()) ; + SetSecondEmail(unichars [index_SecondEmailAddress]->get()) ; + //SetAimScreenName(unichars [index_ScreenName]->get()) ; SetWorkPhone(unichars [index_WorkPhoneNumber]->get()) ; SetHomePhone(unichars [index_HomePhoneNumber]->get()) ; SetFaxNumber(unichars [index_WorkFaxNumber]->get()) ; @@ -210,12 +217,12 @@ nsAutoString unichar ; nsAutoString unicharBis ; - if (mapiAddBook->GetPropertyUString(*mMapiData, PR_HOME_ADDRESS_STREET_W, unichar)) { + if (mapiAddBook->GetPropertyUString(*mMapiData, PR_HOME_ADDRESS_STREET_A, unichar)) { splitString(unichar, unicharBis) ; SetHomeAddress(unichar.get()) ; SetHomeAddress2(unicharBis.get()) ; } - if (mapiAddBook->GetPropertyUString(*mMapiData, PR_BUSINESS_ADDRESS_STREET_W, unichar)) { + if (mapiAddBook->GetPropertyUString(*mMapiData, PR_BUSINESS_ADDRESS_STREET_A, unichar)) { splitString(unichar, unicharBis) ; SetWorkAddress(unichar.get()) ; SetWorkAddress2(unicharBis.get()) ; @@ -297,6 +304,8 @@ SetDisplayName(properties [index_DisplayName]) ; GetNickName(getter_Copies(properties [index_NickName])) ; GetPrimaryEmail(getter_Copies(properties [index_EmailAddress])) ; + GetSecondEmail(getter_Copies(properties [index_SecondEmailAddress])) ; + //GetAimScreenName(getter_Copies(properties [index_ScreenName])) ; GetWorkPhone(getter_Copies(properties [index_WorkPhoneNumber])) ; GetHomePhone(getter_Copies(properties [index_HomePhoneNumber])) ; GetFaxNumber(getter_Copies(properties [index_WorkFaxNumber])) ; @@ -316,11 +325,20 @@ GetWebPage1(getter_Copies(properties [index_WorkWebPage])) ; GetWebPage2(getter_Copies(properties [index_HomeWebPage])) ; GetNotes(getter_Copies(properties [index_Comments])) ; - if (!mapiAddBook->SetPropertiesUString(*mMapiData, OutlookCardMAPIProps, - index_LastProp, properties)) { - PRINTF(("Cannot set general properties.\n")) ; + + int i=0; + for (i=0;iSetPropertyUString(*mMapiData, + OutlookCardMAPIProps[i], + properties[i])) + { + PRINTF(("Cannot set properties:%d.\n",OutlookCardMAPIProps[i])) ; } + } + delete [] properties ; + nsXPIDLString unichar ; nsXPIDLString unichar2 ; WORD year = 0 ; Index: mailnews/addrbook/src/nsAbOutlookDirFactory.cpp =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbOutlookDirFactory.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsAbOutlookDirFactory.cpp 22 Oct 2003 02:43:10 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbOutlookDirFactory.cpp 9 Dec 2003 03:26:47 -0000 1.2 @@ -125,8 +125,8 @@ nsCAutoString uri ; nsCOMPtr resource ; - for (ULONG i = 0 ; i < folders.mNbEntries ; ++ i) { - folders.mEntries [i].ToString(entryId) ; + for (ULONG i = 0 ; i < folders.GetSize() ; ++ i) { + folders[i].ToString(entryId) ; buildAbWinUri(kOutlookDirectoryScheme, abType, uri) ; uri.Append(entryId) ; Index: mailnews/addrbook/src/nsAbOutlookDirectory.cpp =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbOutlookDirectory.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -w -b -i -r1.1.1.1 -r1.3 --- miss/build/mozilla/mailnews/addrbook/src/nsAbOutlookDirectory.cpp 22 Oct 2003 02:43:11 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbOutlookDirectory.cpp 9 Dec 2003 03:26:47 -0000 1.3 @@ -125,7 +125,7 @@ PRINTF(("Cannot get type.\n")) ; return NS_ERROR_FAILURE ; } - if (!mapiAddBook->GetPropertyUString(*mMapiData, PR_DISPLAY_NAME_W, unichars)) { + if (!mapiAddBook->GetPropertyUString(*mMapiData, PR_DISPLAY_NAME_A, unichars)) { PRINTF(("Cannot get name.\n")) ; return NS_ERROR_FAILURE ; } @@ -161,45 +161,85 @@ return retCode ; } +nsresult nsAbOutlookDirectory::BuildCardFromURI(const nsCString& uriName,nsIAbCard **aNewCard, + PRBool aSearchForOld, PRBool& aIsNewCard) +{ + nsresult retCode = NS_OK ; + if (aSearchForOld) { + nsCStringKey key(uriName) ; + nsCOMPtr existingCard = mCardList.Get(&key) ; + + if (existingCard) { + nsCOMPtr card(do_QueryInterface(existingCard, &retCode)) ; + + NS_ENSURE_SUCCESS(retCode, retCode) ; + NS_IF_ADDREF(*aNewCard = card) ; + aIsNewCard = PR_FALSE ; + return retCode ; + } + } + aIsNewCard = PR_TRUE ; + nsCOMPtr resource ; + + nsCOMPtr childCard = do_CreateInstance(NS_ABOUTLOOKCARD_CONTRACTID, &retCode); + NS_ENSURE_SUCCESS(retCode, retCode) ; + resource = do_QueryInterface(childCard, &retCode) ; + NS_ENSURE_SUCCESS(retCode, retCode) ; + retCode = resource->Init(uriName.get()) ; + NS_ENSURE_SUCCESS(retCode, retCode) ; + NS_IF_ADDREF(*aNewCard = childCard); + return retCode ; +} + NS_IMETHODIMP nsAbOutlookDirectory::GetChildCards(nsIEnumerator **aCards) { if (!aCards) { return NS_ERROR_NULL_POINTER ; } *aCards = nsnull ; nsCOMPtr cardList ; + nsCStringArray uriList ; + nsAbWinHelperGuard mapiAddBook (mAbWinType) ; nsresult retCode ; - mCardList.Reset() ; if (mIsQueryURI) { retCode = StartSearch() ; - NS_NewISupportsArray(getter_AddRefs(cardList)) ; } else { - retCode = GetChildCards(getter_AddRefs(cardList), nsnull) ; + retCode = GetChildCards(uriList, nsnull) ; } + NS_NewISupportsArray(getter_AddRefs(cardList)) ; if (NS_SUCCEEDED(retCode)) { // Fill the results array and update the card list // Also update the address list and notify any changes. PRUint32 nbCards = 0 ; - nsCOMPtr element ; + nsCAutoString uriName; + nsCOMPtr childCard; + PRBool searchForOldCards = (mCardList.Count() != 0) ; + + nbCards = uriList.Count(); + NS_NewISupportsArray(getter_AddRefs(m_AddressList)); - cardList->Enumerate(aCards) ; - cardList->Count(&nbCards) ; for (PRUint32 i = 0 ; i < nbCards ; ++ i) { - cardList->GetElementAt(i, getter_AddRefs(element)) ; - nsVoidKey newKey (NS_STATIC_CAST(void *, element)) ; - nsCOMPtr oldElement = mCardList.Get(&newKey) ; + PRBool isNewCard = PR_FALSE ; + + uriList.CStringAt(i,uriName); + retCode = BuildCardFromURI(uriName,getter_AddRefs(childCard), searchForOldCards, isNewCard); + NS_ENSURE_SUCCESS(retCode, retCode) ; + cardList->AppendElement(childCard); - if (!oldElement) { + if (isNewCard) { // We are dealing with a new element (probably directly // added from Outlook), we may need to sync m_AddressList - mCardList.Put(&newKey, element) ; - nsCOMPtr card (do_QueryInterface(element, &retCode)) ; + nsCStringKey newKey(uriName) ; + + mCardList.Put(&newKey, childCard) ; + nsCOMPtr card (do_QueryInterface(childCard, &retCode)) ; NS_ENSURE_SUCCESS(retCode, retCode) ; PRBool isMailList = PR_FALSE ; retCode = card->GetIsMailList(&isMailList) ; NS_ENSURE_SUCCESS(retCode, retCode) ; + if (isMailList) { // We can have mailing lists only in folder, // we must add the directory to m_AddressList @@ -222,18 +262,33 @@ NotifyItemAddition(card) ; } } - else { - NS_ASSERTION(oldElement == element, "Different card stored") ; } } + return cardList->Enumerate(aCards) ; } + +static nsresult ExtractUriFromCard(nsIAbCard *aCard, nsCString& aUri) { + nsresult retCode = NS_OK ; + nsCOMPtr resource (do_QueryInterface(aCard, &retCode)) ; + + // Receiving a non-RDF card is accepted + if (NS_FAILED(retCode)) { return NS_OK ; } + nsXPIDLCString uri ; + + retCode = resource->GetValue(getter_Copies(uri)) ; + NS_ENSURE_SUCCESS(retCode, retCode) ; + aUri = uri.get() ; return retCode ; } NS_IMETHODIMP nsAbOutlookDirectory::HasCard(nsIAbCard *aCard, PRBool *aHasCard) { if (!aCard || !aHasCard) { return NS_ERROR_NULL_POINTER ; } - nsVoidKey key (NS_STATIC_CAST(void *, aCard)) ; + *aHasCard = PR_FALSE ; + nsCString uri ; + + ExtractUriFromCard(aCard, uri) ; + nsCStringKey key(uri) ; *aHasCard = mCardList.Exists(&key) ; return NS_OK ; @@ -315,7 +370,10 @@ PRINTF(("Cannot delete card %s.\n", entryString.get())) ; } else { - nsVoidKey key (NS_STATIC_CAST(void *, element)) ; + nsCString uri ; + + ExtractUriFromCard(card, uri) ; + nsCStringKey key(uri) ; mCardList.Remove(&key) ; if (m_IsMailList) { m_AddressList->RemoveElement(element) ; } @@ -378,7 +436,10 @@ } retCode = CreateCard(aData, addedCard) ; NS_ENSURE_SUCCESS(retCode, retCode) ; - nsVoidKey newKey (NS_STATIC_CAST(void *, *addedCard)) ; + nsCString uri ; + + ExtractUriFromCard(*addedCard, uri) ; + nsCStringKey newKey(uri) ; mCardList.Put(&newKey, *addedCard) ; if (m_IsMailList) { m_AddressList->AppendElement(*addedCard) ; } @@ -449,7 +510,7 @@ if (!mapiAddBook->IsOK()) { return NS_ERROR_FAILURE ; } retCode = GetDirName(getter_Copies(name)) ; NS_ENSURE_SUCCESS(retCode, retCode) ; - if (!mapiAddBook->SetPropertyUString(*mMapiData, PR_DISPLAY_NAME_W, name.get())) { + if (!mapiAddBook->SetPropertyUString(*mMapiData, PR_DISPLAY_NAME_A, name.get())) { return NS_ERROR_FAILURE ; } retCode = CommitAddressList() ; @@ -510,6 +571,8 @@ {"DisplayName", PR_DISPLAY_NAME_A}, {"NickName", PR_NICKNAME_A}, {"PrimaryEmail", PR_EMAIL_ADDRESS_A}, + //{"_AimScreenName",PR_SCREEN_NAME_A}, + {"SecondEmail",PR_SECOND_EMAIL_ADDRESS_A}, {"WorkPhone", PR_BUSINESS_TELEPHONE_NUMBER_A}, {"HomePhone", PR_HOME_TELEPHONE_NUMBER_A}, {"FaxNumber", PR_BUSINESS_FAX_NUMBER_A}, @@ -950,6 +1013,7 @@ delete threadArgs ; return NS_ERROR_OUT_OF_MEMORY ; } + nsIntegerKey newKey(*aReturnValue) ; mQueryThreads.Put(&newKey, newThread) ; @@ -1018,7 +1082,10 @@ nsresult nsAbOutlookDirectory::OnSearchFoundCard(nsIAbCard *aCard) { - nsVoidKey newKey (NS_STATIC_CAST(void *, aCard)) ; + nsCString uri ; + + ExtractUriFromCard(aCard, uri) ; + nsCStringKey newKey(uri) ; nsresult retCode = NS_OK ; mCardList.Put(&newKey, aCard) ; @@ -1042,14 +1109,14 @@ retCode = BuildRestriction(aArguments, arguments) ; NS_ENSURE_SUCCESS(retCode, retCode) ; nsCOMPtr resultsArray ; + nsCStringArray uriArray ; PRUint32 nbResults = 0 ; - retCode = GetChildCards(getter_AddRefs(resultsArray), + retCode = GetChildCards(uriArray, arguments.rt == RES_COMMENT ? nsnull : &arguments) ; DestroyRestriction(arguments) ; NS_ENSURE_SUCCESS(retCode, retCode) ; - retCode = resultsArray->Count(&nbResults) ; - NS_ENSURE_SUCCESS(retCode, retCode) ; + nbResults = uriArray.Count() ; nsCOMPtr result ; nsAbDirectoryQueryResult *newResult = nsnull ; @@ -1057,15 +1124,18 @@ nbResults = NS_STATIC_CAST(PRUint32, aResultLimit) ; } PRUint32 i = 0 ; - nsCOMPtr element ; nsCOMPtr propertyValues ; + nsCAutoString uriName; + nsCOMPtr card; + for (i = 0 ; i < nbResults ; ++ i) { - retCode = resultsArray->GetElementAt(i, getter_AddRefs(element)) ; - NS_ENSURE_SUCCESS(retCode, retCode) ; - nsCOMPtr card (do_QueryInterface(element, &retCode)) ; + PRBool isNewCard = PR_FALSE ; + uriArray.CStringAt(i,uriName); + retCode = BuildCardFromURI(uriName,getter_AddRefs(card), PR_FALSE, isNewCard); NS_ENSURE_SUCCESS(retCode, retCode) ; + FillPropertyValues(card, aArguments, getter_AddRefs(propertyValues)) ; newResult = new nsAbDirectoryQueryResult(0, aArguments, nsIAbDirectoryQueryResult::queryResultMatch, @@ -1090,6 +1160,38 @@ if (!aCards) { return NS_ERROR_NULL_POINTER ; } *aCards = nsnull ; nsresult retCode = NS_OK ; + + nsCOMPtr cards; + retCode = NS_NewISupportsArray(getter_AddRefs(cards)); + NS_ENSURE_SUCCESS(retCode, retCode) ; + + nsCStringArray uriList; + retCode = GetChildCards(uriList,aRestriction); + NS_ENSURE_SUCCESS(retCode, retCode) ; + + nsCAutoString uriName; + nsCOMPtr childCard; + PRUint32 nbURIs = 0 ; + nbURIs = uriList.Count(); + PRUint32 i = 0 ; + + for (i = 0 ; i < nbURIs ; ++ i) { + PRBool isNewCard = PR_FALSE ; + + uriList.CStringAt(i,uriName); + retCode = BuildCardFromURI(uriName,getter_AddRefs(childCard), PR_TRUE, isNewCard); + NS_ENSURE_SUCCESS(retCode, retCode) ; + cards->AppendElement(childCard); + } + + NS_IF_ADDREF(*aCards = cards); + return retCode ; +} + +nsresult nsAbOutlookDirectory::GetChildCards(nsCStringArray& aURI, + void *aRestriction) +{ + nsresult retCode = NS_OK ; nsCOMPtr cards ; nsAbWinHelperGuard mapiAddBook (mAbWinType) ; nsMapiEntryArray cardEntries ; @@ -1104,18 +1206,14 @@ } nsCAutoString entryId ; nsCAutoString uriName ; - nsCOMPtr resource ; + aURI.Clear(); - for (ULONG card = 0 ; card < cardEntries.mNbEntries ; ++ card) { - cardEntries.mEntries [card].ToString(entryId) ; + for (ULONG card = 0 ; card < cardEntries.GetSize() ; ++ card) { + cardEntries [card].ToString(entryId) ; buildAbWinUri(kOutlookCardScheme, mAbWinType, uriName) ; uriName.Append(entryId) ; - retCode = gRDFService->GetResource(uriName.get(), getter_AddRefs(resource)) ; - NS_ENSURE_SUCCESS(retCode, retCode) ; - cards->AppendElement(resource) ; + aURI.AppendCString(uriName); } - *aCards = cards ; - NS_ADDREF(*aCards) ; return retCode ; } @@ -1139,8 +1237,8 @@ nsCAutoString uriName ; nsCOMPtr resource ; - for (ULONG node = 0 ; node < nodeEntries.mNbEntries ; ++ node) { - nodeEntries.mEntries [node].ToString(entryId) ; + for (ULONG node = 0 ; node < nodeEntries.GetSize() ; ++ node) { + nodeEntries [node].ToString(entryId) ; buildAbWinUri(kOutlookDirectoryScheme, mAbWinType, uriName) ; uriName.Append(entryId) ; retCode = gRDFService->GetResource(uriName.get(), getter_AddRefs(resource)) ; @@ -1261,7 +1359,7 @@ // In the case of a mailing list, we cannot directly create a new card, // we have to create a temporary one in a real folder (to be able to use // templates) and then copy it to the mailing list. - if (m_IsMailList) { + if (m_IsMailList && mAbWinType == nsAbWinType_OutlookExp) { nsMapiEntry parentEntry ; nsMapiEntry temporaryEntry ; @@ -1291,10 +1389,11 @@ uri.Append(entryString) ; nsCOMPtr resource ; - retCode = gRDFService->GetResource(uri.get(), getter_AddRefs(resource)) ; + nsCOMPtr newCard = do_CreateInstance(NS_ABOUTLOOKCARD_CONTRACTID, &retCode); NS_ENSURE_SUCCESS(retCode, retCode) ; - nsCOMPtr newCard(do_QueryInterface(resource, &retCode)) ; - + resource = do_QueryInterface(newCard, &retCode) ; + NS_ENSURE_SUCCESS(retCode, retCode) ; + retCode = resource->Init(uri.get()) ; NS_ENSURE_SUCCESS(retCode, retCode) ; if (!didCopy) { retCode = newCard->Copy(aData) ; Index: mailnews/addrbook/src/nsAbOutlookDirectory.h =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbOutlookDirectory.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsAbOutlookDirectory.h 22 Oct 2003 02:43:11 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbOutlookDirectory.h 22 Oct 2003 09:45:04 -0000 1.2 @@ -46,6 +46,7 @@ #include "nsHashtable.h" #include "nsISupportsArray.h" +#include "nsVoidArray.h" struct nsMapiEntry ; @@ -91,6 +92,8 @@ protected: // Retrieve hierarchy as cards, with an optional restriction nsresult GetChildCards(nsISupportsArray **aCards, void *aRestriction) ; + // Retrieve hierarchy as URIs, with an optional restriction + nsresult GetChildCards(nsCStringArray& aURI, void *aRestriction) ; // Retrieve hierarchy as directories nsresult GetChildNodes(nsISupportsArray **aNodes) ; // Create a new card @@ -102,6 +105,9 @@ nsresult CommitAddressList(void) ; // Read MAPI repository nsresult UpdateAddressList(void) ; + // Search for an existing card or build a new one + nsresult BuildCardFromURI(const nsCString& uriName,nsIAbCard **aNewCard, + PRBool aSearchForOld, PRBool& aIsNewCard) ; nsMapiEntry *mMapiData ; // Container for the query threads Index: mailnews/addrbook/src/nsAbWinHelper.cpp =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbWinHelper.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -w -b -i -r1.1.1.1 -r1.3 --- miss/build/mozilla/mailnews/addrbook/src/nsAbWinHelper.cpp 22 Oct 2003 02:43:11 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbWinHelper.cpp 9 Dec 2003 03:26:47 -0000 1.3 @@ -41,6 +41,9 @@ #define USES_IID_IABContainer #define USES_IID_IMAPITable #define USES_IID_IDistList +#define USES_IID_IMsgStore +#define USES_IID_IMessage +#define USES_IID_IMAPIFolder #include "nsAbWinHelper.h" #include "nsAbUtils.h" @@ -59,19 +62,6 @@ #define PRINTF(args) PR_LOG(gAbWinHelperLog, PR_LOG_DEBUG, args) -// Small utility to ensure release of all MAPI interfaces -template struct nsMapiInterfaceWrapper -{ - tInterface mInterface ; - - nsMapiInterfaceWrapper(void) : mInterface(NULL) {} - ~nsMapiInterfaceWrapper(void) { - if (mInterface != NULL) { mInterface->Release() ; } - } - operator LPUNKNOWN *(void) { return NS_REINTERPRET_CAST(LPUNKNOWN *, &mInterface) ; } - tInterface operator -> (void) const { return mInterface ; } - operator tInterface *(void) { return &mInterface ; } -} ; static void assignEntryID(LPENTRYID& aTarget, LPENTRYID aSource, ULONG aByteCount) { @@ -249,24 +239,28 @@ MOZ_DECL_CTOR_COUNTER(nsMapiEntryArray) nsMapiEntryArray::nsMapiEntryArray(void) -: mEntries(NULL), mNbEntries(0) { MOZ_COUNT_CTOR(nsMapiEntryArray) ; } nsMapiEntryArray::~nsMapiEntryArray(void) { - if (mEntries) { delete [] mEntries ; } + CleanUp(); MOZ_COUNT_DTOR(nsMapiEntryArray) ; } - +void nsMapiEntryArray::AddItem(nsMapiEntry * aEntries) +{ + m_array.AppendElement(aEntries); +} void nsMapiEntryArray::CleanUp(void) { - if (mEntries != NULL) { - delete [] mEntries ; - mEntries = NULL ; - mNbEntries = 0 ; + nsMapiEntry *pEntries; + for (int i = 0; i < m_array.Count(); i++) + { + pEntries = (nsMapiEntry *)m_array.ElementAt( i); + delete pEntries; } + m_array.Clear(); } MOZ_DECL_CTOR_COUNTER(nsAbWinHelper) @@ -280,100 +274,55 @@ // same protection (MAPI is supposed to be thread-safe). PRLock *nsAbWinHelper::mMutex = PR_NewLock() ; +int nsAbWinHelper::m_clients = 0; + +PRUnichar * nsAbWinHelper::m_pUniBuff = NULL; +int nsAbWinHelper::m_uniBuffLen = 0; +char * nsAbWinHelper::m_pCStrBuff = NULL; +int nsAbWinHelper::m_cstrBuffLen = 0; + nsAbWinHelper::nsAbWinHelper(void) -: mAddressBook(NULL), mLastError(S_OK) +:mLastError(S_OK) { MOZ_COUNT_CTOR(nsAbWinHelper) ; + m_clients++; } nsAbWinHelper::~nsAbWinHelper(void) { MOZ_COUNT_DTOR(nsAbWinHelper) ; -} - -BOOL nsAbWinHelper::GetFolders(nsMapiEntryArray& aFolders) + m_clients--; + if (!m_clients) { - aFolders.CleanUp() ; - nsMapiInterfaceWrapper rootFolder ; - nsMapiInterfaceWrapper folders ; - ULONG objType = 0 ; - ULONG rowCount = 0 ; - SRestriction restriction ; - SPropTagArray folderColumns ; - - mLastError = mAddressBook->OpenEntry(0, NULL, NULL, 0, &objType, - rootFolder) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot open root %08x.\n", mLastError)) ; - return FALSE ; + delete [] m_pUniBuff; + m_pUniBuff = NULL; + m_uniBuffLen = 0; + delete [] m_pCStrBuff; + m_pCStrBuff = NULL; + m_cstrBuffLen = 0; } - mLastError = rootFolder->GetHierarchyTable(0, folders) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot get hierarchy %08x.\n", mLastError)) ; - return FALSE ; - } - // We only take into account modifiable containers, - // otherwise, we end up with all the directory services... - restriction.rt = RES_BITMASK ; - restriction.res.resBitMask.ulPropTag = PR_CONTAINER_FLAGS ; - restriction.res.resBitMask.relBMR = BMR_NEZ ; - restriction.res.resBitMask.ulMask = AB_MODIFIABLE ; - mLastError = folders->Restrict(&restriction, 0) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot restrict table %08x.\n", mLastError)) ; - } - folderColumns.cValues = 1 ; - folderColumns.aulPropTag [0] = PR_ENTRYID ; - mLastError = folders->SetColumns(&folderColumns, 0) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot set columns %08x.\n", mLastError)) ; - return FALSE ; } - mLastError = folders->GetRowCount(0, &rowCount) ; - if (HR_SUCCEEDED(mLastError)) { - aFolders.mEntries = new nsMapiEntry [rowCount] ; - aFolders.mNbEntries = 0 ; - do { - LPSRowSet rowSet = NULL ; - rowCount = 0 ; - mLastError = folders->QueryRows(1, 0, &rowSet) ; - if (HR_SUCCEEDED(mLastError)) { - rowCount = rowSet->cRows ; - if (rowCount > 0) { - nsMapiEntry& current = aFolders.mEntries [aFolders.mNbEntries ++] ; - SPropValue& currentValue = rowSet->aRow->lpProps [0] ; - - current.Assign(currentValue.Value.bin.cb, - NS_REINTERPRET_CAST(LPENTRYID, currentValue.Value.bin.lpb)) ; - } - MyFreeProws(rowSet) ; - } - else { - PRINTF(("Cannot query rows %08x.\n", mLastError)) ; - } - } while (rowCount > 0) ; - } - return HR_SUCCEEDED(mLastError) ; -} BOOL nsAbWinHelper::GetCards(const nsMapiEntry& aParent, LPSRestriction aRestriction, nsMapiEntryArray& aCards) { aCards.CleanUp() ; - return GetContents(aParent, aRestriction, &aCards.mEntries, aCards.mNbEntries, 0) ; + return GetContents(aParent, aRestriction, &aCards, 0) ; } BOOL nsAbWinHelper::GetNodes(const nsMapiEntry& aParent, nsMapiEntryArray& aNodes) { aNodes.CleanUp() ; - return GetContents(aParent, NULL, &aNodes.mEntries, aNodes.mNbEntries, MAPI_DISTLIST) ; + return GetContents(aParent, NULL, &aNodes, MAPI_DISTLIST) ; } BOOL nsAbWinHelper::GetCardsCount(const nsMapiEntry& aParent, ULONG& aNbCards) { - aNbCards = 0 ; - return GetContents(aParent, NULL, NULL, aNbCards, 0) ; + nsMapiEntryArray aCards; + BOOL ret=GetContents(aParent, NULL, &aCards, 0) ; + aNbCards=aCards.GetSize(); + return ret; } BOOL nsAbWinHelper::GetPropertyString(const nsMapiEntry& aObject, @@ -390,7 +339,7 @@ aName = values->Value.lpszA ; } else if (PROP_TYPE(values->ulPropTag) == PT_UNICODE) { - aName.AssignWithConversion(values->Value.lpszW) ; + UnicodeToCStr(values->Value.lpszW,aName) ; } } FreeBuffer(values) ; @@ -410,7 +359,7 @@ aName = values->Value.lpszW ; } else if (PROP_TYPE(values->ulPropTag) == PT_STRING8) { - aName.AssignWithConversion(values->Value.lpszA) ; + CStrToUnicode(values->Value.lpszA,aName) ; } } FreeBuffer(values) ; @@ -431,16 +380,24 @@ ULONG i = 0 ; for (i = 0 ; i < valueCount ; ++ i) { - if (values [i].ulPropTag == aPropertyTags [i]) { + + if (PROP_TYPE( values [i].ulPropTag) != PT_ERROR && values [i].Value.l != MAPI_E_NOT_FOUND) + { if (PROP_TYPE(values [i].ulPropTag) == PT_STRING8) { nsAutoString temp ; - temp.AssignWithConversion (values [i].Value.lpszA) ; + CStrToUnicode(values [i].Value.lpszA,temp) ; aNames.AppendString(temp) ; } else if (PROP_TYPE(values [i].ulPropTag) == PT_UNICODE) { aNames.AppendString(nsAutoString (values [i].Value.lpszW)) ; } + else if (aPropertyTags [i] == PR_EMAIL_ADDRESS_A) { + nsAutoString temp ; + + CStrToUnicode (values [i].Value.lpszA,temp) ; + aNames.AppendString(temp) ; + } else { aNames.AppendString(nsAutoString((const PRUnichar *) "")) ; } @@ -466,7 +423,6 @@ if (!GetMAPIProperties(aObject, &aPropertyTag, 1, values, valueCount)) { return FALSE ; } if (valueCount == 1 && values != NULL && PROP_TYPE(values->ulPropTag) == PT_SYSTIME) { SYSTEMTIME readableTime ; - if (FileTimeToSystemTime(&values->Value.ft, &readableTime)) { aYear = readableTime.wYear ; aMonth = readableTime.wMonth ; @@ -518,7 +474,7 @@ nsMapiInterfaceWrapper subObject ; ULONG objType = 0 ; - mLastError = mAddressBook->OpenEntry(aContainer.mByteCount, aContainer.mEntryId, + mLastError = OpenEntry(aContainer.mByteCount, aContainer.mEntryId, &IID_IMAPIContainer, 0, &objType, container) ; if (HR_FAILED(mLastError)) { @@ -537,7 +493,7 @@ SBinary entry ; SBinaryArray entryArray ; - mLastError = mAddressBook->OpenEntry(aContainer.mByteCount, aContainer.mEntryId, + mLastError = OpenEntry(aContainer.mByteCount, aContainer.mEntryId, &IID_IABContainer, MAPI_MODIFY, &objType, container) ; if (HR_FAILED(mLastError)) { @@ -567,14 +523,15 @@ value.Value.lpszW = NS_CONST_CAST(WORD *, aValue) ; } else if (PROP_TYPE(aPropertyTag) == PT_STRING8) { - alternativeValue.AssignWithConversion(aValue) ; + UnicodeToCStr(aValue,alternativeValue) ; value.Value.lpszA = NS_CONST_CAST(char *, alternativeValue.get()) ; } else { PRINTF(("Property %08x is not a string.\n", aPropertyTag)) ; return TRUE ; } - return SetMAPIProperties(aObject, 1, &value) ; + LPSPropValue values=&value; + return SetMAPIProperties(aObject, 1, values) ; } BOOL nsAbWinHelper::SetPropertiesUString(const nsMapiEntry& aObject, const ULONG *aPropertiesTag, @@ -592,7 +549,7 @@ values [currentValue ++].Value.lpszW = NS_CONST_CAST(WORD *, aValues [i].get()) ; } else if (PROP_TYPE(aPropertiesTag [i]) == PT_STRING8) { - alternativeValue.AssignWithConversion(aValues [i].get()) ; + UnicodeToCStr(aValues [i].get(),alternativeValue) ; values [currentValue ++].Value.lpszA = nsCRT::strdup(alternativeValue.get()) ; } } @@ -624,7 +581,8 @@ readableTime.wSecond = 0 ; readableTime.wMilliseconds = 0 ; if (SystemTimeToFileTime(&readableTime, &value.Value.ft)) { - return SetMAPIProperties(aObject, 1, &value) ; + LPSPropValue values=&value; + return SetMAPIProperties(aObject, 1, values) ; } return TRUE ; } @@ -636,7 +594,7 @@ nsMapiInterfaceWrapper container ; ULONG objType = 0 ; - mLastError = mAddressBook->OpenEntry(aParent.mByteCount, aParent.mEntryId, + mLastError = OpenEntry(aParent.mByteCount, aParent.mEntryId, &IID_IABContainer, MAPI_MODIFY, &objType, container) ; if (HR_FAILED(mLastError)) { @@ -699,7 +657,7 @@ nsMapiInterfaceWrapper container ; ULONG objType = 0 ; - mLastError = mAddressBook->OpenEntry(aParent.mByteCount, aParent.mEntryId, + mLastError = OpenEntry(aParent.mByteCount, aParent.mEntryId, &IID_IABContainer, MAPI_MODIFY, &objType, container) ; if (HR_FAILED(mLastError)) { @@ -764,7 +722,7 @@ nsMapiInterfaceWrapper container ; ULONG objType = 0 ; - mLastError = mAddressBook->OpenEntry(aContainer.mByteCount, aContainer.mEntryId, + mLastError = OpenEntry(aContainer.mByteCount, aContainer.mEntryId, &IID_IABContainer, MAPI_MODIFY, &objType, container) ; if (HR_FAILED(mLastError)) { @@ -801,194 +759,77 @@ return TRUE ; } -BOOL nsAbWinHelper::GetDefaultContainer(nsMapiEntry& aContainer) -{ - LPENTRYID entryId = NULL ; - ULONG byteCount = 0 ; - mLastError = mAddressBook->GetPAB(&byteCount, &entryId) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot get PAB %08x.\n", mLastError)) ; - return FALSE ; - } - aContainer.Assign(byteCount, entryId) ; - FreeBuffer(entryId) ; - return TRUE ; -} -enum -{ - ContentsColumnEntryId = 0, - ContentsColumnObjectType, - ContentsColumnsSize -} ; -static const SizedSPropTagArray(ContentsColumnsSize, ContentsColumns) = -{ - ContentsColumnsSize, - { - PR_ENTRYID, - PR_OBJECT_TYPE - } -} ; - -BOOL nsAbWinHelper::GetContents(const nsMapiEntry& aParent, LPSRestriction aRestriction, - nsMapiEntry **aList, ULONG& aNbElements, ULONG aMapiType) +void nsAbWinHelper::MyFreeProws(LPSRowSet aRowset) { - if (aList != NULL) { *aList = NULL ; } - aNbElements = 0 ; - nsMapiInterfaceWrapper parent ; - nsMapiInterfaceWrapper contents ; - ULONG objType = 0 ; - ULONG rowCount = 0 ; + if (aRowset == NULL) { return ; } + ULONG i = 0 ; - mLastError = mAddressBook->OpenEntry(aParent.mByteCount, aParent.mEntryId, - &IID_IMAPIContainer, 0, &objType, - parent) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot open parent %08x.\n", mLastError)) ; - return FALSE ; - } - // Here, flags for WAB and MAPI could be different, so this works - // only as long as we don't want to use any flag in GetContentsTable - mLastError = parent->GetContentsTable(0, contents) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot get contents %08x.\n", mLastError)) ; - return FALSE ; - } - if (aRestriction != NULL) { - mLastError = contents->Restrict(aRestriction, 0) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot set restriction %08x.\n", mLastError)) ; - return FALSE ; - } - } - mLastError = contents->SetColumns((LPSPropTagArray) &ContentsColumns, 0) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot set columns %08x.\n", mLastError)) ; - return FALSE ; - } - mLastError = contents->GetRowCount(0, &rowCount) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot get result count %08x.\n", mLastError)) ; - return FALSE ; + for (i = 0 ; i < aRowset->cRows ; ++ i) { + FreeBuffer(aRowset->aRow [i].lpProps) ; } - if (aList != NULL) { *aList = new nsMapiEntry [rowCount] ; } - aNbElements = 0 ; - do { - LPSRowSet rowSet = NULL ; - - rowCount = 0 ; - mLastError = contents->QueryRows(1, 0, &rowSet) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot query rows %08x.\n", mLastError)) ; - return FALSE ; + FreeBuffer(aRowset) ; } - rowCount = rowSet->cRows ; - if (rowCount > 0 && - (aMapiType == 0 || - rowSet->aRow->lpProps[ContentsColumnObjectType].Value.ul == aMapiType)) { - if (aList != NULL) { - nsMapiEntry& current = (*aList) [aNbElements] ; - SPropValue& currentValue = rowSet->aRow->lpProps[ContentsColumnEntryId] ; - - current.Assign(currentValue.Value.bin.cb, - NS_REINTERPRET_CAST(LPENTRYID, currentValue.Value.bin.lpb)) ; +void nsAbWinHelper::CStrToUnicode( const char *pStr, nsString& result) +{ + result.Truncate( 0); + int wLen = MultiByteToWideChar( CP_ACP, 0, pStr, -1, m_pUniBuff, 0); + if (wLen >= m_uniBuffLen) + { + delete [] m_pUniBuff; + m_pUniBuff = new PRUnichar[wLen + 64]; + m_uniBuffLen = wLen + 64; } - ++ aNbElements ; + if (wLen) + { + MultiByteToWideChar( CP_ACP, 0, pStr, -1, m_pUniBuff, m_uniBuffLen); + result = m_pUniBuff; } - MyFreeProws(rowSet) ; - } while (rowCount > 0) ; - return TRUE ; } - -BOOL nsAbWinHelper::GetMAPIProperties(const nsMapiEntry& aObject, const ULONG *aPropertyTags, - ULONG aNbProperties, LPSPropValue& aValue, - ULONG& aValueCount) +void nsAbWinHelper::UnicodeToCStr( const PRUnichar *pUStr,nsCString& result) { - nsMapiInterfaceWrapper object ; - ULONG objType = 0 ; - LPSPropTagArray properties = NULL ; - ULONG i = 0 ; - - mLastError = mAddressBook->OpenEntry(aObject.mByteCount, aObject.mEntryId, - &IID_IMAPIProp, 0, &objType, - object) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot open entry %08x.\n", mLastError)) ; - return FALSE ; + result.Truncate( 0); + int cLen = WideCharToMultiByte( CP_ACP, 0, pUStr, -1, m_pCStrBuff, 0,NULL,NULL); + if (cLen >= m_cstrBuffLen) { + if (m_pCStrBuff) + delete [] m_pCStrBuff; + m_pCStrBuff = new char[cLen + 64]; + m_cstrBuffLen = cLen + 64; } - AllocateBuffer(CbNewSPropTagArray(aNbProperties), - NS_REINTERPRET_CAST(void **, &properties)) ; - properties->cValues = aNbProperties ; - for (i = 0 ; i < aNbProperties ; ++ i) { - properties->aulPropTag [i] = aPropertyTags [i] ; + if (cLen) { + WideCharToMultiByte( CP_ACP, 0, pUStr, -1, m_pCStrBuff, m_cstrBuffLen,NULL,NULL); + result = m_pCStrBuff; } - mLastError = object->GetProps(properties, 0, &aValueCount, &aValue) ; - FreeBuffer(properties) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot get props %08x.\n", mLastError)) ; - } - return HR_SUCCEEDED(mLastError) ; } -BOOL nsAbWinHelper::SetMAPIProperties(const nsMapiEntry& aObject, ULONG aNbProperties, - const LPSPropValue& aValues) -{ - nsMapiInterfaceWrapper object ; - ULONG objType = 0 ; - LPSPropProblemArray problems = NULL ; +static nsAbWinHelper *getOutlookAddressBook(void) { + static nsMapiAddressBook *addressBook = NULL ; - mLastError = mAddressBook->OpenEntry(aObject.mByteCount, aObject.mEntryId, - &IID_IMAPIProp, MAPI_MODIFY, &objType, - object) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot open entry %08x.\n", mLastError)) ; - return FALSE ; - } - mLastError = object->SetProps(aNbProperties, aValues, &problems) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot update the object %08x.\n", mLastError)) ; - return FALSE ; - } - if (problems != NULL) { - for (ULONG i = 0 ; i < problems->cProblem ; ++ i) { - PRINTF(("Problem %d: index %d code %08x.\n", i, - problems->aProblem [i].ulIndex, - problems->aProblem [i].scode)) ; - } - } - mLastError = object->SaveChanges(0) ; - if (HR_FAILED(mLastError)) { - PRINTF(("Cannot commit changes %08x.\n", mLastError)) ; - } - return HR_SUCCEEDED(mLastError) ; + if (addressBook == NULL) { addressBook = new nsMapiAddressBook ; } + return addressBook ; } -void nsAbWinHelper::MyFreeProws(LPSRowSet aRowset) -{ - if (aRowset == NULL) { return ; } - ULONG i = 0 ; +static nsAbWinHelper *getOutlookExpAddressBook(void) { + static nsWabAddressBook *addressBook = NULL ; - for (i = 0 ; i < aRowset->cRows ; ++ i) { - FreeBuffer(aRowset->aRow [i].lpProps) ; - } - FreeBuffer(aRowset) ; + if (addressBook == NULL) { addressBook = new nsWabAddressBook ; } + return addressBook ; } nsAbWinHelperGuard::nsAbWinHelperGuard(PRUint32 aType) : mHelper(NULL) { switch(aType) { - case nsAbWinType_Outlook: mHelper = new nsMapiAddressBook ; break ; - case nsAbWinType_OutlookExp: mHelper = new nsWabAddressBook ; break ; + case nsAbWinType_Outlook: mHelper = getOutlookAddressBook() ; break ; + case nsAbWinType_OutlookExp: mHelper = getOutlookExpAddressBook() ; break ; default: break ; } } nsAbWinHelperGuard::~nsAbWinHelperGuard(void) { - delete mHelper ; } const char *kOutlookDirectoryScheme = "moz-aboutlookdirectory://" ; Index: mailnews/addrbook/src/nsAbWinHelper.h =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsAbWinHelper.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsAbWinHelper.h 22 Oct 2003 02:43:11 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsAbWinHelper.h 9 Dec 2003 03:26:47 -0000 1.2 @@ -45,6 +45,24 @@ #include "nsVoidArray.h" #include "nsXPIDLString.h" +#define PR_SECOND_EMAIL_ADDRESS_A 0x8033001E +#define PR_SCREEN_NAME_A 0x805B001E + + +// Small utility to ensure release of all MAPI interfaces +template struct nsMapiInterfaceWrapper +{ + tInterface mInterface ; + + nsMapiInterfaceWrapper(void) : mInterface(NULL) {} + ~nsMapiInterfaceWrapper(void) { + if (mInterface ) { mInterface->Release() ; } + } + operator LPUNKNOWN *(void) { return NS_REINTERPRET_CAST(LPUNKNOWN *, &mInterface) ; } + tInterface operator -> (void) const { return mInterface ; } + operator tInterface *(void) { return &mInterface ; } +} ; + struct nsMapiEntry { ULONG mByteCount ; @@ -62,14 +80,28 @@ struct nsMapiEntryArray { - nsMapiEntry *mEntries ; - ULONG mNbEntries ; nsMapiEntryArray(void) ; ~nsMapiEntryArray(void) ; - const nsMapiEntry& operator [] (int aIndex) const { return mEntries [aIndex] ; } + void AddItem(nsMapiEntry * aEntries); + void AddItem( ULONG mByteCount , LPENTRYID mEntryId ) + { + nsMapiEntry * aEntries=new nsMapiEntry(); + aEntries->Assign(mByteCount,mEntryId); + AddItem(aEntries); + } + + ULONG GetSize( void) { return( m_array.Count());} + nsMapiEntry& operator [] (int aIndex) { return *(nsMapiEntry*)m_array.ElementAt(aIndex); } + nsMapiEntry* ElementAt(int aIndex) { return (nsMapiEntry*)m_array.ElementAt(aIndex); } void CleanUp(void) ; + void Remove(nsMapiEntry * aEntries){ m_array.RemoveElement(aEntries); } + void Remove(int index){ m_array.RemoveElementAt(index); } + ULONG IndexOf(nsMapiEntry * aEntries){return m_array.IndexOf(aEntries);}; +private: + nsVoidArray m_array; + } ; class nsAbWinHelper @@ -79,7 +111,7 @@ virtual ~nsAbWinHelper(void) ; // Get the top address books - BOOL GetFolders(nsMapiEntryArray& aFolders) ; + virtual BOOL GetFolders(nsMapiEntryArray& aFolders) =0; // Get a list of entries for cards/mailing lists in a folder/mailing list BOOL GetCards(const nsMapiEntry& aParent, LPSRestriction aRestriction, nsMapiEntryArray& aCards) ; @@ -97,18 +129,14 @@ BOOL GetPropertiesUString(const nsMapiEntry& aObject, const ULONG *aPropertiesTag, ULONG aNbProperties, nsStringArray& aValues) ; // Get the value of a MAPI property of type SYSTIME - BOOL GetPropertyDate(const nsMapiEntry& aObject, ULONG aPropertyTag, + virtual BOOL GetPropertyDate(const nsMapiEntry& aObject, ULONG aPropertyTag, WORD& aYear, WORD& aMonth, WORD& aDay) ; - // Get the value of a MAPI property of type LONG - BOOL GetPropertyLong(const nsMapiEntry& aObject, ULONG aPropertyTag, ULONG& aValue) ; // Get the value of a MAPI property of type BIN BOOL GetPropertyBin(const nsMapiEntry& aObject, ULONG aPropertyTag, nsMapiEntry& aValue) ; // Tests if a container contains an entry BOOL TestOpenEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aEntry) ; - // Delete an entry in the address book - BOOL DeleteEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aEntry) ; // Set the value of a MAPI property of type string in unicode - BOOL SetPropertyUString (const nsMapiEntry& aObject, ULONG aPropertyTag, + virtual BOOL SetPropertyUString (const nsMapiEntry& aObject, ULONG aPropertyTag, const PRUnichar *aValue) ; // Same as previous, but with a bunch of properties in one call BOOL SetPropertiesUString(const nsMapiEntry& aObject, const ULONG *aPropertiesTag, @@ -117,32 +145,44 @@ BOOL SetPropertyDate(const nsMapiEntry& aObject, ULONG aPropertyTag, WORD aYear, WORD aMonth, WORD aDay) ; // Create entry in the address book - BOOL CreateEntry(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry) ; + virtual BOOL CreateEntry(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry) ; + // Delete an entry in the address book + virtual BOOL DeleteEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aEntry) ; // Create a distribution list in the address book - BOOL CreateDistList(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry) ; + virtual BOOL CreateDistList(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry) ; // Copy an existing entry in the address book - BOOL CopyEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aSource, nsMapiEntry& aTarget) ; + virtual BOOL CopyEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aSource, nsMapiEntry& aTarget) ; // Get a default address book container - BOOL GetDefaultContainer(nsMapiEntry& aContainer) ; + virtual BOOL GetDefaultContainer(nsMapiEntry& aContainer) =0; // Is the helper correctly initialised? - BOOL IsOK(void) const { return mAddressBook != NULL ; } + virtual BOOL IsOK(void) =0;/*const { return mAddressBook != NULL ; }*/ + + // Get the value of a MAPI property of type LONG + virtual BOOL GetPropertyLong(const nsMapiEntry& aObject, ULONG aPropertyTag, ULONG& aValue) ; protected: HRESULT mLastError ; - LPADRBOOK mAddressBook ; static ULONG mEntryCounter ; static PRLock *mMutex ; + virtual HRESULT OpenEntry(ULONG cbEntryID, + LPENTRYID lpEntryID, + LPCIID lpInterface, + ULONG ulFlags, + ULONG FAR * lpulObjType, + LPUNKNOWN FAR * lppUnk + ) = 0; + // Retrieve the contents of a container, with an optional restriction - BOOL GetContents(const nsMapiEntry& aParent, LPSRestriction aRestriction, - nsMapiEntry **aList, ULONG &aNbElements, ULONG aMapiType) ; + virtual BOOL GetContents(const nsMapiEntry& aParent, LPSRestriction aRestriction, + nsMapiEntryArray *aList, ULONG aMapiType) =0; // Retrieve the values of a set of properties on a MAPI object - BOOL GetMAPIProperties(const nsMapiEntry& aObject, const ULONG *aPropertyTags, + virtual BOOL GetMAPIProperties(const nsMapiEntry& aObject, const ULONG *aPropertyTags, ULONG aNbProperties, - LPSPropValue& aValues, ULONG& aValueCount) ; + LPSPropValue& aValues, ULONG& aValueCount) =0; // Set the values of a set of properties on a MAPI object - BOOL SetMAPIProperties(const nsMapiEntry& aObject, ULONG aNbProperties, - const LPSPropValue& aValues) ; + virtual BOOL SetMAPIProperties(const nsMapiEntry& aObject, ULONG aNbProperties, + LPSPropValue& aValues) =0; // Clean-up a rowset returned by QueryRows void MyFreeProws(LPSRowSet aSet) ; // Allocation of a buffer for transmission to interfaces @@ -150,7 +190,16 @@ // Destruction of a buffer provided by the interfaces virtual void FreeBuffer(LPVOID aBuffer) = 0 ; + static void CStrToUnicode( const char *pStr, nsString& result); + static void UnicodeToCStr( const PRUnichar *pStr, nsCString& result); + private: + static int m_clients; + static PRUnichar * m_pUniBuff; + static int m_uniBuffLen; + static char * m_pCStrBuff; + static int m_cstrBuffLen; + } ; enum nsAbWinType @@ -168,6 +217,7 @@ nsAbWinHelper *operator ->(void) { return mHelper ; } + static void FreeWinAbLibrarys(); private: nsAbWinHelper *mHelper ; } ; Index: mailnews/addrbook/src/nsMapiAddressBook.cpp =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsMapiAddressBook.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsMapiAddressBook.cpp 22 Oct 2003 02:43:11 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsMapiAddressBook.cpp 9 Dec 2003 03:26:47 -0000 1.2 @@ -41,6 +41,22 @@ #include "prlog.h" +static char * stristr(const char *big, const char *little) +{ + PRUint32 len; + + if (!big || !little || !*big || !*little) + return 0; + len = strlen(little); + + for( ; *big; big++ ) + if(!_strnicmp (big, little, 1) && ! _strnicmp (big, little, len) ) + return (char *)big; + + return (char *)0; + +} + #ifdef PR_LOGGING static PRLogModuleInfo* gMapiAddressBookLog = PR_NewLogModule("nsMapiAddressBookLog"); @@ -48,6 +64,60 @@ #define PRINTF(args) PR_LOG(gMapiAddressBookLog, PR_LOG_DEBUG, args) +#define OUTLOOK_EMAIL_DIAPLAY_MAPI_ID 0x00008005 //use to get and set display +#define OUTLOOK_EMAIL1_MAPI_ID 0x00008084 //use to get and set primary email address +#define OUTLOOK_EMAIL2_MAPI_ID 0x00008094 //use to get and set second email address +#define OUTLOOK_EMAIL_SCREEN_NAME 0x8061001E //use to get and set screen name +#define OUTLOOK_EMAIL_ORGID 0x00008085 //use to get orginal entryid to add to distlist +#define OUTLOOK_EMAIL_LIST1 0x00008054 //use to get distlist table +#define OUTLOOK_EMAIL_LIST2 0x00008055 //use to set distlist table + +static const TagMap TagMaps[]={ + {PR_DISPLAY_NAME_A, OUTLOOK_EMAIL_DIAPLAY_MAPI_ID, PT_STRING8}, + {PR_EMAIL_ADDRESS_A, OUTLOOK_EMAIL1_MAPI_ID, PT_STRING8}, + {PR_SECOND_EMAIL_ADDRESS_A, OUTLOOK_EMAIL2_MAPI_ID, PT_STRING8}, + {PR_SCREEN_NAME_A, OUTLOOK_EMAIL_SCREEN_NAME, PT_STRING8}}; + +enum { + ieidPR_ENTRYID = 0, + ieidPR_OBJECT_TYPE, + ieidPR_DISPLAY_NAME, + ieidPR_MESSAGE_CLASS, + ieidPR_STORE_ENTRYID, + ieidPR_MESSAGE_RECIPIENTS, + ieidMax +}; + +static const SizedSPropTagArray(ieidMax, ptaEid)= +{ + ieidMax, + { + PR_ENTRYID, + PR_OBJECT_TYPE, + PR_DISPLAY_NAME, + PR_MESSAGE_CLASS, + PR_STORE_ENTRYID, + PR_MESSAGE_RECIPIENTS + } +}; + +enum +{ + ContentsColumnEntryId = 0, + ContentsColumnObjectType, + ContentsColumnMessageClass, + ContentsColumnsSize +} ; + +static const SizedSPropTagArray(ContentsColumnsSize, ContentsColumns) = +{ + ContentsColumnsSize, + { + PR_ENTRYID, + PR_OBJECT_TYPE, + PR_MESSAGE_CLASS + } +} ; HMODULE nsMapiAddressBook::mLibrary = NULL ; PRInt32 nsMapiAddressBook::mLibUsage = 0 ; @@ -60,7 +130,6 @@ BOOL nsMapiAddressBook::mInitialized = FALSE ; BOOL nsMapiAddressBook::mLogonDone = FALSE ; LPMAPISESSION nsMapiAddressBook::mRootSession = NULL ; -LPADRBOOK nsMapiAddressBook::mRootBook = NULL ; BOOL nsMapiAddressBook::LoadMapiLibrary(void) { @@ -106,22 +175,19 @@ MAPI_NEW_SESSION, &mRootSession) ; if (HR_FAILED(retCode)) { - PRINTF(("Cannot logon to MAPI %08x.\n", retCode)) ; return FALSE ; + PRINTF(("Cannot logon to MAPI %08x.\n", retCode)) ; + return FALSE ; } mLogonDone = TRUE ; - retCode = mRootSession->OpenAddressBook(0, NULL, 0, &mRootBook) ; - if (HR_FAILED(retCode)) { - PRINTF(("Cannot open MAPI address book %08x.\n", retCode)) ; - } + return HR_SUCCEEDED(retCode) ; } void nsMapiAddressBook::FreeMapiLibrary(void) { if (mLibrary) { - if (-- mLibUsage == 0) { + if (--mLibUsage < 0) { { - if (mRootBook) { mRootBook->Release() ; } if (mRootSession) { if (mLogonDone) { mRootSession->Logoff(NULL, 0, 0) ; @@ -135,6 +201,7 @@ } } FreeLibrary(mLibrary) ; + mRootSession = NULL; mLibrary = NULL ; } } @@ -146,7 +213,6 @@ : nsAbWinHelper() { BOOL result = Initialize() ; - NS_ASSERTION(result == TRUE, "Couldn't initialize Mapi Helper") ; MOZ_COUNT_CTOR(nsMapiAddressBook) ; } @@ -154,35 +220,1691 @@ nsMapiAddressBook::~nsMapiAddressBook(void) { nsAutoLock guard(mMutex) ; - + CleanUpMDB(); FreeMapiLibrary() ; MOZ_COUNT_DTOR(nsMapiAddressBook) ; } -BOOL nsMapiAddressBook::Initialize(void) +LPSPropValue nsMapiAddressBook::GetMapiProperty( LPMAPIPROP pProp, ULONG tag) { - if (mAddressBook) { return TRUE ; } - nsAutoLock guard(mMutex) ; + if (!pProp) + return( NULL); - if (!LoadMapiLibrary()) { - PRINTF(("Cannot load library.\n")) ; + int sz = CbNewSPropTagArray( 1); + SPropTagArray *pTag = (SPropTagArray *) new char[sz]; + pTag->cValues = 1; + pTag->aulPropTag[0] = tag; + LPSPropValue lpProp = NULL; + ULONG cValues = 0; + HRESULT hr = pProp->GetProps( pTag, 0, &cValues, &lpProp); + delete pTag; + if (HR_FAILED( hr) || (cValues != 1)) { + if (lpProp) + mMAPIFreeBuffer( lpProp); + return( NULL); + } + else { + if (PROP_TYPE( lpProp->ulPropTag) == PT_ERROR) { + if (lpProp->Value.l == MAPI_E_NOT_FOUND) { + mMAPIFreeBuffer( lpProp); + lpProp = NULL; + } + } + } + + return( lpProp); +} +BOOL nsMapiAddressBook::GetEntryIdFromProp( LPSPropValue pVal, ULONG& cbEntryId, LPENTRYID& lpEntryId, BOOL delVal) +{ + if (!pVal) + return( FALSE); + + BOOL bResult = TRUE; + switch (PROP_TYPE(pVal->ulPropTag)) + { + case PT_BINARY: + cbEntryId = pVal->Value.bin.cb; + mMAPIAllocateBuffer( cbEntryId, (LPVOID *) &lpEntryId); + memcpy( lpEntryId, pVal->Value.bin.lpb, cbEntryId); + break; + + default: + PRINTF(( "EntryId not in BINARY prop value\n")); + bResult = FALSE; + break; + } + + if (pVal && delVal) + mMAPIFreeBuffer( pVal); + + return( bResult); +} + +BOOL nsMapiAddressBook::HandleContentsItem(ULONG oType, ULONG cb, LPENTRYID pEntry,nsMapiEntryArray& aFolders) +{ + LPMDB lpMsgStore; + ULONG objType=0; + HRESULT hr; + + if (oType == MAPI_MESSAGE) + return FALSE; + if (oType == MAPI_STORE) + { + hr=mRootSession->OpenEntry( + cb, + pEntry, + &IID_IMsgStore, + 0, + &objType, + (IUnknown**)&lpMsgStore); + if (FAILED(hr)) return FALSE ; + //Add MDB to a list to make it can be released when class destroyed. + //We must leave it openned or else we can't open address store in it. + AddToMDBArray(lpMsgStore); + + LPSPropValue pVal; + pVal=GetMapiProperty(lpMsgStore,PR_IPM_SUBTREE_ENTRYID); + + + if (pVal) { + ULONG cbEntry; + LPENTRYID pEntry; + nsMapiInterfaceWrapper lpSubTree; + + if (GetEntryIdFromProp( pVal, cbEntry, pEntry)) { + // Open up the folder! + BOOL bResult = TRUE; + bResult = lpMsgStore->OpenEntry( + cbEntry, + pEntry, + NULL, + 0, + &objType, + lpSubTree); + mMAPIFreeBuffer( pEntry); + if (!bResult && *(LPMAPICONTAINER*)&lpSubTree) { + // Iterate the subtree with the results going into the folder list + bResult = IterateHierarchy(*(LPMAPICONTAINER*)&lpSubTree,aFolders); + } + else { + PRINTF(( "GetStoreFolders: Error opening sub tree.\n")); + } + } + else { + PRINTF(( "GetStoreFolders: Error getting entryID from sub tree property val.\n")); } - mAddressBook = mRootBook ; + } + else { + PRINTF(( "GetStoreFolders: Error getting sub tree property.\n")); + } + } + else + { + PRINTF(("Type:%d\n",oType)); + } + return TRUE ; } -void nsMapiAddressBook::AllocateBuffer(ULONG aByteCount, LPVOID *aBuffer) +BOOL nsMapiAddressBook::IterateHierarchy(LPMAPICONTAINER pFolder,nsMapiEntryArray& aFolders, ULONG flags) { - mMAPIAllocateBuffer(aByteCount, aBuffer) ; + // flags can be CONVENIENT_DEPTH or 0 + // CONVENIENT_DEPTH will return all depths I believe instead + // of just children + HRESULT hr; + nsMapiInterfaceWrapper lpTable; + hr = pFolder->GetHierarchyTable( CONVENIENT_DEPTH , lpTable); + if (HR_FAILED(hr)) { + PRINTF(( "IterateHierarchy: GetContentsTable failed: 0x%lx, %d\n", (long)hr, (int)hr)); + return( FALSE); } -void nsMapiAddressBook::FreeBuffer(LPVOID aBuffer) + ULONG rowCount; + hr = lpTable->GetRowCount( 0, &rowCount); + if (!rowCount) { + return( TRUE); + } + + hr = lpTable->SetColumns( (LPSPropTagArray)&ptaEid, 0); + if (HR_FAILED(hr)) { + PRINTF(( "IterateHierarchy: SetColumns failed: 0x%lx, %d\n", (long)hr, (int)hr)); + return( FALSE); + } + + hr = lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL); + if (HR_FAILED(hr)) { + PRINTF(( "IterateHierarchy: SeekRow failed: 0x%lx, %d\n", (long)hr, (int)hr)); + return( FALSE); + } + + int cNumRows = 0; + LPSRowSet lpRow; + BOOL keepGoing = TRUE; + BOOL bResult = TRUE; + do { + + lpRow = NULL; + hr = lpTable->QueryRows( 1, 0, &lpRow); + + if (HR_FAILED(hr)) { - mMAPIFreeBuffer(aBuffer) ; + PRINTF(( "QueryRows failed: 0x%lx, %d\n", (long)hr, (int)hr)); + bResult = FALSE; + break; + } + + if (lpRow){ + cNumRows = lpRow->cRows; + + if (cNumRows) { + LPENTRYID lpEntry = (LPENTRYID) lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb; + ULONG cb = lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb; + ULONG oType = lpRow->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.ul; + + keepGoing = HandleHierarchyItem( oType, cb, lpEntry,aFolders); + + } + MyFreeProws(lpRow); + } + + } while ( SUCCEEDED(hr) && cNumRows && lpRow && keepGoing); + + + if (bResult && !keepGoing) + bResult = FALSE; + + return( bResult); +} +BOOL nsMapiAddressBook::HandleHierarchyItem( ULONG oType, ULONG cb, LPENTRYID pEntry,nsMapiEntryArray& aFolders) +{ + ULONG objType=0; + if (oType == MAPI_FOLDER) + { + nsMapiInterfaceWrapper pFolder ; + if (!mRootSession->OpenEntry( + cb, + pEntry, + 0, + NULL, + &objType, + pFolder)) + { + LPSPropValue pVal; + + + pVal = GetMapiProperty(*(LPMAPICONTAINER*)&pFolder, PR_CONTAINER_CLASS); + if (pVal) + { + if (strcmp("IPF.Contact",pVal->Value.lpszA) == 0) + { + SPropValue *currentValue=GetMapiProperty( *(LPMAPICONTAINER*)&pFolder, PR_ENTRYID); + + aFolders.AddItem(currentValue->Value.bin.cb, + NS_REINTERPRET_CAST(LPENTRYID, currentValue->Value.bin.lpb)) ; + + } + } + } + } + else + { + PRINTF(( "GetStoreFolders - HandleHierarchyItem: Unhandled ObjectType: %ld\n", oType)); + } + + return( TRUE); +} + + +BOOL nsMapiAddressBook::GetFolders(nsMapiEntryArray& aFolders) +{ + aFolders.CleanUp() ; + nsMapiInterfaceWrapper rootFolder ; + nsMapiInterfaceWrapper folders ; + ULONG objType = 0 ; + ULONG rowCount = 0 ; + + nsMapiInterfaceWrapper lpTable; + + mLastError = mRootSession->GetMsgStoresTable( 0, lpTable); + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open MAPI MsgStores %08x.\n", mLastError)); + return mLastError; + } + + mLastError = lpTable->GetRowCount( 0, &rowCount); + + mLastError = lpTable->SetColumns( (LPSPropTagArray)&ptaEid, 0); + if (FAILED(mLastError)) + return( mLastError); + mLastError = lpTable->SeekRow( BOOKMARK_BEGINNING, 0, NULL); + if (FAILED(mLastError)) + return mLastError; + + int cNumRows = 0; + LPSRowSet lpRow; + BOOL keepGoing = TRUE; + BOOL bResult = TRUE; + do { + + lpRow = NULL; + mLastError = lpTable->QueryRows( 1, 0, &lpRow); + + if (HR_FAILED(mLastError)){ + bResult = FALSE; + break; + } + + if (lpRow){ + cNumRows = lpRow->cRows; + + if (cNumRows) { + LPENTRYID lpEID = (LPENTRYID) lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb; + ULONG cbEID = lpRow->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb; + ULONG oType = lpRow->aRow[0].lpProps[ieidPR_OBJECT_TYPE].Value.ul; + + + keepGoing = HandleContentsItem( oType, cbEID, lpEID,aFolders); + } + MyFreeProws( lpRow); + } + + } while ( SUCCEEDED(mLastError) && cNumRows && lpRow && keepGoing); + + + return HR_SUCCEEDED(mLastError) ; +} +BOOL nsMapiAddressBook::CorrectRestriction(const LPMAPIPROP aMapiProp,ULONG aRestrictionNum, LPSRestriction aRestriction) +{ + ULONG conditionType = 0 ; + ULONG ulResIndex; + if (!aRestriction) + return FALSE; + for (ulResIndex=0;ulResIndex < aRestrictionNum;ulResIndex++) + { + conditionType = aRestriction[ulResIndex].rt; + switch (conditionType) + { + case RES_EXIST : + aRestriction[ulResIndex].res.resExist.ulPropTag = + GetRealMapiPropertyTag(aMapiProp,aRestriction[ulResIndex].res.resExist.ulPropTag); + break ; + case RES_BITMASK : + aRestriction[ulResIndex].res.resBitMask.ulPropTag = + GetRealMapiPropertyTag(aMapiProp,aRestriction[ulResIndex].res.resBitMask.ulPropTag); + break ; + case RES_CONTENT : + aRestriction[ulResIndex].res.resContent.ulPropTag = + GetRealMapiPropertyTag(aMapiProp,aRestriction[ulResIndex].res.resContent.ulPropTag); + aRestriction[ulResIndex].res.resContent.lpProp->ulPropTag = + GetRealMapiPropertyTag(aMapiProp,aRestriction[ulResIndex].res.resContent.lpProp->ulPropTag); + break ; + case RES_PROPERTY : + aRestriction[ulResIndex].res.resProperty.ulPropTag = + GetRealMapiPropertyTag(aMapiProp,aRestriction[ulResIndex].res.resProperty.ulPropTag); + aRestriction[ulResIndex].res.resProperty.lpProp->ulPropTag = + GetRealMapiPropertyTag(aMapiProp,aRestriction[ulResIndex].res.resProperty.lpProp->ulPropTag); + break ; + case RES_SIZE : + aRestriction[ulResIndex].res.resSize.ulPropTag = + GetRealMapiPropertyTag(aMapiProp,aRestriction[ulResIndex].res.resSize.ulPropTag); + break ; + case RES_COMPAREPROPS : + aRestriction[ulResIndex].res.resCompareProps.ulPropTag1 = + GetRealMapiPropertyTag(aMapiProp,aRestriction[ulResIndex].res.resCompareProps.ulPropTag1); + aRestriction[ulResIndex].res.resCompareProps.ulPropTag2 = + GetRealMapiPropertyTag(aMapiProp,aRestriction[ulResIndex].res.resCompareProps.ulPropTag2); + break ; + case RES_NOT : + CorrectRestriction(aMapiProp,1,aRestriction[ulResIndex].res.resNot.lpRes); + break; + case RES_AND : + CorrectRestriction(aMapiProp, + aRestriction[ulResIndex].res.resAnd.cRes, + aRestriction[ulResIndex].res.resAnd.lpRes); + break; + case RES_OR : + CorrectRestriction(aMapiProp, + aRestriction[ulResIndex].res.resOr.cRes, + aRestriction[ulResIndex].res.resOr.lpRes); + break; + + case RES_COMMENT : + CorrectRestriction(aMapiProp,1,aRestriction[ulResIndex].res.resComment.lpRes); + aRestriction[ulResIndex].res.resComment.lpProp->ulPropTag = + GetRealMapiPropertyTag(aMapiProp,aRestriction[ulResIndex].res.resComment.lpProp->ulPropTag); + break; + case RES_SUBRESTRICTION : + CorrectRestriction(aMapiProp,1,aRestriction[ulResIndex].res.resSub.lpRes); + break; + default: + return FALSE; + } + } + return TRUE; +} +BOOL nsMapiAddressBook::Filter( LPSRestriction aRestriction,nsMapiEntryArray * aList) +{ + if (!aRestriction) + return FALSE; + + ULONG conditionType = 0 ; + + nsMapiEntryArray listOut; + ULONG listindex=0; + + nsMapiEntryArray listDel; + ULONG delindex=0; + + ULONG listsize; + ULONG resCount = 0; + ULONG resIndex = 0; + + listsize = aList->GetSize(); + conditionType = aRestriction->rt; + switch (conditionType) + { + case RES_EXIST : + case RES_BITMASK : + case RES_CONTENT : + case RES_PROPERTY : + case RES_SIZE : + case RES_COMPAREPROPS : + case RES_COMMENT : + case RES_SUBRESTRICTION : + { + while(listindex < aList->GetSize()) + { + if (!FilterOnOneRow(aList->ElementAt(listindex),aRestriction)) + aList->Remove(listindex); + else + listindex++; + } + } + break; + case RES_NOT : + aRestriction->res.resNot.ulReserved = 1; + case RES_AND : + case RES_OR : + { + if (conditionType == RES_OR) + { + for(listindex=0;listindexGetSize();listindex++) + { + listDel.AddItem(aList->ElementAt(listindex)); + } + } + + resCount = aRestriction->res.resAnd.cRes; + //notice that SAndRestriction ,SNotRestriction ,SOrRestriction + //use the same struct + for (resIndex = 0;resIndex < resCount;resIndex++) + { + //can't call listOut.CleanUp() here + //because it will destroy all Element too + while(listOut.GetSize()) + { + listOut.Remove(0); + } + + for(listindex=0;listindexGetSize();listindex++) + { + listOut.AddItem(aList->ElementAt(listindex)); + } + + Filter(&aRestriction->res.resAnd.lpRes[resIndex],&listOut); + if (conditionType == RES_NOT) + { + for(listindex=0;listindexRemove(listOut.ElementAt(listindex)); + } + } + else if (conditionType == RES_AND ) + { + for(listindex=0;listindexIndexOf(listOut.ElementAt(listindex))) + { + aList->Remove(listOut.ElementAt(listindex)); + } + } + } + else if (conditionType == RES_OR ) + { + for(listindex=0;listindexRemove(listDel.ElementAt(listindex)); + } + } + } + + } + while(listDel.GetSize()) + { + listDel.Remove(0); + } + while(listOut.GetSize()) + { + listOut.Remove(0); + } + + + return TRUE; +} + +BOOL nsMapiAddressBook::FilterOnOneRow(nsMapiEntry *aEntry,LPSRestriction aRestriction) +{ + LPMAPIPROP object ; + ULONG objType = 0 ; + LPSPropValue realValue = NULL ; + LPSPropValue resValue = NULL ; + ULONG valueCount = 0 ; + + mLastError = OpenEntry(aEntry->mByteCount, aEntry->mEntryId, + &IID_IMAPIProp, 0, &objType, + (IUnknown **)&object) ; + + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open entry %08x.\n", mLastError)) ; + return FALSE ; + } + + ULONG conditionType = 0 ; + conditionType = aRestriction->rt; + + switch (conditionType) + { + case RES_EXIST : + if (!GetMAPIProperties(*aEntry,&aRestriction->res.resExist.ulPropTag,1,realValue,valueCount)) + return FALSE; + resValue = NULL; + break ; + case RES_CONTENT : + if (!GetMAPIProperties(*aEntry,&aRestriction->res.resContent.ulPropTag,1,realValue,valueCount)) + return FALSE; + resValue = aRestriction->res.resContent.lpProp; + break ; + case RES_PROPERTY : + if (!GetMAPIProperties(*aEntry,&aRestriction->res.resProperty.ulPropTag,1,realValue,valueCount)) + return FALSE; + resValue = aRestriction->res.resProperty.lpProp; + break ; + case RES_BITMASK : + return FALSE; //not support + break ; + case RES_SIZE : + return FALSE;//not been used now + break ; + case RES_COMPAREPROPS : + return FALSE;//not been used now + break ; + case RES_NOT : + return FALSE;//not need care here + break; + case RES_AND : + return FALSE;//not need care here + break; + case RES_OR : + return FALSE;//not need care here + break; + case RES_COMMENT : + return TRUE;//comment + break; + case RES_SUBRESTRICTION : + return FALSE;//not been used now + break ; +} + return AtomyFilter(aRestriction,realValue,resValue); + +} + +BOOL nsMapiAddressBook::AtomyFilter(LPSRestriction aRestriction,LPSPropValue aRealValue,LPSPropValue aFilterValue) +{ + ULONG conditionType = 0 ; + conditionType = aRestriction->rt; + + BOOL bTagEq=(aRealValue && + PROP_TYPE( aRealValue->ulPropTag ) != PT_ERROR) && + aFilterValue; + // PROP_TYPE( aRealValue->ulPropTag ) == PROP_TYPE( aFilterValue->ulPropTag )); + switch (conditionType) + { + case RES_EXIST : + return (aRealValue && PROP_TYPE( aRealValue->ulPropTag ) != PT_ERROR) ; + break ; + case RES_CONTENT : + if (bTagEq) + { + switch(aRestriction->res.resContent.ulFuzzyLevel) + { + case FL_FULLSTRING : + return !stricmp(aRealValue->Value.lpszA,aFilterValue->Value.lpszA); + break; + case FL_PREFIX : + return stristr(aRealValue->Value.lpszA,aFilterValue->Value.lpszA) == aRealValue->Value.lpszA; + break; + case FL_SUBSTRING : + default: + return stristr(aRealValue->Value.lpszA,aFilterValue->Value.lpszA) != NULL; + break; + } + } + return FALSE; + break ; + case RES_PROPERTY : + if (bTagEq) + { + switch(aRestriction->res.resProperty.relop) + { + case RELOP_GE : + return stricmp(aRealValue->Value.lpszA,aFilterValue->Value.lpszA) >= 0; + break; + case RELOP_GT : + return stricmp(aRealValue->Value.lpszA,aFilterValue->Value.lpszA) > 0; + break; + case RELOP_LE : + return stricmp(aRealValue->Value.lpszA,aFilterValue->Value.lpszA) <= 0; + break; + case RELOP_LT : + return stricmp(aRealValue->Value.lpszA,aFilterValue->Value.lpszA) < 0; + break; + case RELOP_EQ : + return stricmp(aRealValue->Value.lpszA,aFilterValue->Value.lpszA) == 0; + break; + case RELOP_NE : + return stricmp(aRealValue->Value.lpszA,aFilterValue->Value.lpszA) != 0; + break; + case RELOP_RE : + default: + return stristr(aRealValue->Value.lpszA,aFilterValue->Value.lpszA) != NULL; + break; + + } + } + return FALSE; + break ; + case RES_BITMASK : + return FALSE; //not support + break ; + case RES_SIZE : + return FALSE;//not been used now + break ; + case RES_COMPAREPROPS : + return FALSE;//not been used now + break ; + case RES_NOT : + return FALSE;//not need care here + break; + case RES_AND : + return FALSE;//not need care here + break; + case RES_OR : + return FALSE;//not need care here + break; + case RES_COMMENT : + return TRUE;//comment + break; + case RES_SUBRESTRICTION : + return FALSE;//not been used now + break ; + } + return TRUE; +} + +BOOL nsMapiAddressBook::GetContents(const nsMapiEntry& aParent, LPSRestriction aRestriction, + nsMapiEntryArray *aList, ULONG aMapiType) +{ + if (aList) + aList->CleanUp(); + + nsMapiInterfaceWrapper parent ; + nsMapiInterfaceWrapper contents ; + ULONG objType = 0 ; + ULONG rowCount = 0 ; + + + nsMapiInterfaceWrapper pFolder; + nsCString cs; + aParent.ToString(cs); + + mLastError = OpenEntry(aParent.mByteCount, aParent.mEntryId, + 0, 0, &objType, pFolder); + if (HR_FAILED(mLastError)) + { + PRINTF(("Cannot open folder %08x.\n", mLastError)) ; + return FALSE; + } + + + LPSPropValue msgClass=GetMapiProperty(*(LPMAPIPROP*)&pFolder,PR_MESSAGE_CLASS); + if (msgClass && strcmp("IPM.DistList",msgClass->Value.lpszA) == 0) + { + HRESULT hr; + LPSPropValue aValue = NULL ; + ULONG aValueCount = 0 ; + + LPSPropTagArray properties = NULL ; + mMAPIAllocateBuffer(CbNewSPropTagArray(1), + (void **)&properties); + properties->cValues = 1; + properties->aulPropTag [0] = GetEmailPropertyTag(*(LPMAPIPROP*)&pFolder,OUTLOOK_EMAIL_LIST1); + hr = pFolder->GetProps(properties, 0, &aValueCount, &aValue) ; + + SBinaryArray *sa=&aValue->Value.MVbin; + + LPENTRYID lpEID; + ULONG cbEID; + + ULONG idx; + nsMapiEntry testEntry; + nsCString sClass; + for (idx=0;sa->lpbin && idxcValues ;idx++) + { + lpEID= (LPENTRYID) sa->lpbin[idx].lpb; + cbEID = sa->lpbin[idx].cb; + testEntry.Assign(sa->lpbin[idx].cb,NS_REINTERPRET_CAST(LPENTRYID,sa->lpbin[idx].lpb)); + + if (GetPropertyString(testEntry,PR_MESSAGE_CLASS,sClass)) //Error get property + { + aList->AddItem(cbEID,lpEID); + } + } + Filter(aRestriction,aList); + } + else + { + if (aRestriction && !CorrectRestriction(*(LPMAPICONTAINER*)&pFolder,1,aRestriction)) + return FALSE; + mLastError = OpenEntry(aParent.mByteCount, aParent.mEntryId, + &IID_IMAPIContainer, 0, &objType, + parent) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open parent %08x.\n", mLastError)) ; + return FALSE ; + } + + mLastError = parent->GetContentsTable(0, contents) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot get contents %08x.\n", mLastError)) ; + return FALSE; + } + if (aRestriction) { + mLastError = contents->Restrict(aRestriction, TBL_BATCH) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set restriction %08x.\n", mLastError)) ; + return FALSE ; + } + } + mLastError = contents->SetColumns((LPSPropTagArray)&ContentsColumns, 0); + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set columns %08x.\n", mLastError)) ; + return FALSE ; + } + mLastError = contents->GetRowCount(0, &rowCount) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot get result count %08x.\n", mLastError)) ; + return FALSE ; + } + do { + LPSRowSet rowSet = NULL ; + + rowCount = 0 ; + mLastError = contents->QueryRows(1, 0, &rowSet) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot query rows %08x.\n", mLastError)) ; + return FALSE ; + } + rowCount = rowSet->cRows ; + if (rowCount > 0 && aList) + { + if (aMapiType == 0 || rowSet->aRow->lpProps[ContentsColumnObjectType].Value.ul == aMapiType) + { + SPropValue& currentValue = rowSet->aRow->lpProps[ContentsColumnEntryId] ; + aList->AddItem(currentValue.Value.bin.cb, + NS_REINTERPRET_CAST(LPENTRYID, currentValue.Value.bin.lpb)) ; + } + else if (aMapiType == MAPI_DISTLIST) + { + if (strcmp("IPM.DistList",rowSet->aRow->lpProps[ContentsColumnMessageClass].Value.lpszA)==0) + { + SPropValue& currentValue = rowSet->aRow->lpProps[ContentsColumnEntryId] ; + aList->AddItem(currentValue.Value.bin.cb, + NS_REINTERPRET_CAST(LPENTRYID, currentValue.Value.bin.lpb)) ; + + } } + } + MyFreeProws(rowSet) ; + } while (rowCount > 0) ; + } + return TRUE ; +} +BOOL nsMapiAddressBook::GetMAPIProperties(const nsMapiEntry& aObject, const ULONG *aPropertyTags, + ULONG aNbProperties, LPSPropValue& aValue, + ULONG& aValueCount) +{ + nsMapiInterfaceWrapper object ; + ULONG objType = 0 ; + LPSPropTagArray properties = NULL ; + ULONG i = 0 ; + + mLastError = OpenEntry(aObject.mByteCount, aObject.mEntryId, + &IID_IMAPIProp, 0, &objType, + object) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open entry %08x.\n", mLastError)) ; + return FALSE ; + } + AllocateBuffer(CbNewSPropTagArray(aNbProperties), + NS_REINTERPRET_CAST(void **, &properties)); + properties->cValues = aNbProperties ; + for (i = 0 ; i < aNbProperties ; ++ i) + { + properties->aulPropTag [i] = GetRealMapiPropertyTag(*(LPMAPIPROP*)&object,aPropertyTags [i],TRUE); + } + mLastError = object->GetProps(properties, 0 , &aValueCount, &aValue) ; + FreeBuffer(properties) ; + + if (HR_FAILED(mLastError)) { + PRINTF(("Error get props %08x.\n", mLastError)) ; + } + return HR_SUCCEEDED(mLastError); +} + +BOOL nsMapiAddressBook::SetMAPIProperties(const nsMapiEntry& aObject, ULONG aNbProperties, + LPSPropValue& aValues) +{ + nsMapiInterfaceWrapper object; + ULONG objType = 0 ; + LPSPropProblemArray problems = NULL ; + ULONG i = 0 ; + + LPMDB lpMsgStore=GetMsgStore(aObject); + + if (!lpMsgStore) + { + return FALSE; + } + mLastError = lpMsgStore->OpenEntry(aObject.mByteCount, aObject.mEntryId, + &IID_IMessage, MAPI_MODIFY , &objType, + object) ; + lpMsgStore->Release(); + + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open entry %08x.\n", mLastError)) ; + return FALSE ; + } + for (i = 0 ; i < aNbProperties ; ++ i) + { + aValues[i].ulPropTag = GetRealMapiPropertyTag(*(LPMESSAGE*)&object,aValues[i].ulPropTag,TRUE); + } + mLastError = object->SetProps(aNbProperties, aValues, &problems) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot update the object %08x.\n", mLastError)) ; + return FALSE ; + } + if (problems) { + for (ULONG i = 0 ; i < problems->cProblem ; ++ i) { + PRINTF(("Problem %d: index %d code %08x.\n", i, + problems->aProblem [i].ulIndex, + problems->aProblem [i].scode)) ; + } + } + mLastError = object->SaveChanges(0) ; + if (MAPI_E_OBJECT_CHANGED == mLastError) + { + mLastError = object->SaveChanges(FORCE_SAVE ) ; + } + return HR_SUCCEEDED(mLastError) ; +} + +BOOL nsMapiAddressBook::GetDefaultContainer(nsMapiEntry& aContainer) +{ + return FALSE ; +} + +BOOL nsMapiAddressBook::IsOK(void) +{ + return mRootSession && mLibUsage; +} + +BOOL nsMapiAddressBook::Initialize(void) +{ + + nsAutoLock guard(mMutex) ; + + if (!LoadMapiLibrary()) { + PRINTF(("Cannot load library.\n")) ; + return FALSE ; + } + return TRUE; +} + +void nsMapiAddressBook::AllocateBuffer(ULONG aByteCount, LPVOID *aBuffer) +{ + mMAPIAllocateBuffer(aByteCount, aBuffer) ; +} + +void nsMapiAddressBook::FreeBuffer(LPVOID aBuffer) +{ + mMAPIFreeBuffer(aBuffer) ; +} + +ULONG nsMapiAddressBook::GetEmailPropertyTag(LPMAPIPROP lpProp, LONG nameID) +{ + static GUID emailGUID = + { + 0x00062004, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 + }; + + + MAPINAMEID mapiNameID; + mapiNameID.lpguid = &emailGUID; + mapiNameID.ulKind = MNID_ID; + mapiNameID.Kind.lID = nameID; + + LPMAPINAMEID lpMapiNames = &mapiNameID; + LPSPropTagArray lpMailTagArray = NULL; + + HRESULT result = lpProp->GetIDsFromNames(1L, &lpMapiNames, 0, &lpMailTagArray); + if (result == S_OK) + { + ULONG lTag = lpMailTagArray->aulPropTag[0]; + mMAPIFreeBuffer(lpMailTagArray); + return lTag; + } + return 0L; +} +ULONG nsMapiAddressBook::GetRealMapiPropertyTag(LPMAPIPROP lpProp, LONG aPropertyTag,BOOL aTest) +{ + LPSPropValue addr; + ULONG upRealTag=aPropertyTag; + ULONG lSize=sizeof(TagMaps) / sizeof(TagMap); + + for(int i=0; iValue.lpszA)) + { + if (kPriEmailColumn) + upRealTag = kPriEmailColumn | TagMaps[i].TypeMask; + } + else + { + FreeBuffer(msgClass); + upRealTag = aPropertyTag; + } + } + else //PR_DISPLAY_NAME_A == aPropertyTag + { + addr=GetMapiProperty(lpProp,aPropertyTag); + if (!addr || PROP_TYPE( addr->ulPropTag) == PT_ERROR || + addr->Value.l == MAPI_E_NOT_FOUND) + { + if (kPriEmailColumn) + upRealTag = kPriEmailColumn | TagMaps[i].TypeMask; + } + } + } + else //aTest + { + if (kPriEmailColumn) + upRealTag = kPriEmailColumn | TagMaps[i].TypeMask; + } + + break; //we find it,exit + } + } + + return upRealTag; +} + +BOOL nsMapiAddressBook::GetPropertyLong(const nsMapiEntry& aObject, + ULONG aPropertyTag, + ULONG& aValue) +{ + aValue = 0 ; + LPSPropValue values = NULL ; + ULONG valueCount = 0 ; + + if (PR_OBJECT_TYPE == aPropertyTag) + { + nsMapiInterfaceWrapper pFolder ; + ULONG objType=0; + mLastError = OpenEntry(aObject.mByteCount,aObject.mEntryId, + NULL,0,&objType, pFolder); + if (HR_FAILED(mLastError)) + { + PRINTF(("Cannot open folder %08x.\n", mLastError)) ; + return FALSE; + } + LPSPropValue msgClass=GetMapiProperty(*(LPMAPIFOLDER*)&pFolder,PR_MESSAGE_CLASS); + if (msgClass && strcmp("IPM.DistList",msgClass->Value.lpszA) == 0) + { + FreeBuffer(msgClass); + aValue = MAPI_DISTLIST; + return TRUE; + } + } + + if (!GetMAPIProperties(aObject, &aPropertyTag, 1, values, valueCount)) + return FALSE ; + + if (valueCount == 1 && values && PROP_TYPE(values->ulPropTag) == PT_LONG) { + aValue = values->Value.ul ; + } + FreeBuffer(values) ; + return TRUE ; +} + +BOOL nsMapiAddressBook::GetPropertyDate(const nsMapiEntry& aObject, ULONG aPropertyTag, + WORD& aYear, WORD& aMonth, WORD& aDay) +{ + aYear = 0; + aMonth = 0; + aDay = 0; + LPSPropValue values = NULL ; + ULONG valueCount = 0 ; + + if (!GetMAPIProperties(aObject, &aPropertyTag, 1, values, valueCount)) + return FALSE ; + + if (valueCount == 1 && values && PROP_TYPE(values->ulPropTag) == PT_SYSTIME) { + SYSTEMTIME readableTime ; + FILETIME localTime ; + FileTimeToLocalFileTime(&values->Value.ft,&localTime); + if (FileTimeToSystemTime(&localTime, &readableTime)) { + aYear = readableTime.wYear ; + aMonth = readableTime.wMonth ; + aDay = readableTime.wDay ; + } + } + FreeBuffer(values) ; + return TRUE ; +} + +HRESULT nsMapiAddressBook::OpenEntry(ULONG cbEntryID, + LPENTRYID lpEntryID, + LPCIID lpInterface, + ULONG ulFlags, + ULONG FAR * lpulObjType, + LPUNKNOWN FAR * lppUnk + ) +{ + + int err; + HRESULT rv; + __try + { + rv=mRootSession->OpenEntry(cbEntryID, + lpEntryID, + lpInterface, + ulFlags , + lpulObjType, + lppUnk + ); + }__except(err) + { + return (-1); + } + + if (HR_FAILED(rv) && !m_MDBArray.Count()) + { + //There are no openned Message store,so we have to open them all + nsMapiEntryArray aFolders; + if (GetFolders(aFolders)) + { + __try + { + rv=mRootSession->OpenEntry(cbEntryID, + lpEntryID, + lpInterface, + ulFlags , + lpulObjType, + lppUnk + ); + }__except(err) + { + return (-1); + } + } + } + return rv; + +} + +BOOL nsMapiAddressBook::AddEntryToList(const nsMapiEntry& aDistlist, const nsMapiEntry& aNewEntry) +{ + nsMapiInterfaceWrapper container ; + ULONG objType = 0 ; + + nsMapiEntry parentEntry; + if (!GetEntryParent(aDistlist,parentEntry)) + return FALSE; + + LPMDB lpMsgStore=GetMsgStore(parentEntry); + + if (!lpMsgStore) + return FALSE; + mLastError = lpMsgStore->OpenEntry(aDistlist.mByteCount, aDistlist.mEntryId, + &IID_IMAPIProp, MAPI_MODIFY, &objType, + container) ; + lpMsgStore->Release(); + + if (HR_FAILED(mLastError)) + return FALSE ; + + + /* + When add mail address to distlist,Mapi need update 2 tag. + */ + //update OUTLOOK_EMAIL_LIST1 + ULONG listTag=GetEmailPropertyTag(*(LPMAPIPROP*)&container,OUTLOOK_EMAIL_LIST1) | PT_MV_BINARY; + SBinaryArray oldChilds; + LPSBinary bins=NULL; + SBinaryArray newChilds; + LPSPropValue oldChildValue = NULL ; + ULONG valueCount = 0 ; + + if (!GetMAPIProperties(aDistlist, &listTag, 1, oldChildValue, valueCount)) + { + PRINTF(("Cannot get old childs %08x.\n", mLastError)) ; + return FALSE; + } + + if (! (oldChildValue->Value.l == MAPI_E_NOT_FOUND)) + { + oldChilds = oldChildValue->Value.MVbin; + newChilds.cValues=oldChilds.cValues + 1; + mMAPIAllocateBuffer(sizeof(SBinary) * newChilds.cValues,(void**)& bins); + newChilds.lpbin = bins; + for (ULONG i=0;iSetProps(1, &childs, &problems) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set childs %08x.\n", mLastError)) ; + return FALSE ; + } + + //update OUTLOOK_EMAIL_LIST2 + listTag = GetEmailPropertyTag(*(LPMAPIPROP*)&container,OUTLOOK_EMAIL_LIST2) | PT_MV_BINARY; + if (!GetMAPIProperties(aDistlist, &listTag, 1, oldChildValue, valueCount)) + { + PRINTF(("Cannot get old childs %08x.\n", mLastError)) ; + return FALSE; + } + + if (! (oldChildValue->Value.l == MAPI_E_NOT_FOUND)) + { + oldChilds = oldChildValue->Value.MVbin; + newChilds.cValues=oldChilds.cValues + 1; + mMAPIAllocateBuffer(sizeof(SBinary) * newChilds.cValues,(void**)& bins); + newChilds.lpbin = bins; + for (ULONG i=0;iSetProps(1, &childs, &problems) ; + if (HR_FAILED(mLastError)) + { + PRINTF(("Cannot set childs %08x.\n", mLastError)) ; + return FALSE ; + } + + mMAPIFreeBuffer(bins); + + mLastError = container->SaveChanges(KEEP_OPEN_READONLY) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot commit new entry %08x.\n", mLastError)) ; + return FALSE ; + } + + return TRUE ; +} +BOOL nsMapiAddressBook::DeleteEntryFromList(const nsMapiEntry& aDistlist, const nsMapiEntry& aNewEntry) +{ + nsMapiInterfaceWrapper container ; + ULONG objType = 0 ; + + nsMapiEntry parentEntry; + if (!GetEntryParent(aDistlist,parentEntry)) + return FALSE; + + LPMDB lpMsgStore=GetMsgStore(parentEntry); + if (!lpMsgStore) + return FALSE; + + mLastError = lpMsgStore->OpenEntry(aDistlist.mByteCount, aDistlist.mEntryId, + &IID_IMAPIProp, MAPI_MODIFY, &objType, + container) ; + lpMsgStore->Release(); + + if (HR_FAILED(mLastError)) + return FALSE ; + /* + When delete mail address from distlist,Mapi need update 2 tag. + */ + //update OUTLOOK_EMAIL_LIST1 + ULONG listTag=GetEmailPropertyTag(*(LPMAPIPROP*)&container,OUTLOOK_EMAIL_LIST1) | PT_MV_BINARY; + + SBinaryArray oldChilds; + LPSBinary bins=NULL; + SBinaryArray newChilds; + LPSPropValue oldChildValue = NULL ; + ULONG valueCount = 0 ; + + newChilds.lpbin=NULL; + + ULONG lDeleteEntry=0; + ULONG newIndex=0; + ULONG oldIndex=0; + if (!GetMAPIProperties(aDistlist, &listTag, 1, oldChildValue, valueCount)) + { + PRINTF(("Cannot get old childs %08x.\n", mLastError)) ; + return FALSE; + } + + if (! (oldChildValue->Value.l == MAPI_E_NOT_FOUND)) + { + oldChilds = oldChildValue->Value.MVbin; + newChilds.cValues=oldChilds.cValues - 1; + mMAPIAllocateBuffer(sizeof(SBinary) * newChilds.cValues,(void**)& bins); + newChilds.lpbin = bins; + for (oldIndex=0;oldIndexab), + oldChilds.lpbin[oldIndex].cb-4)) + { + lDeleteEntry=oldIndex; + } + else + { + newChilds.lpbin[newIndex].lpb = oldChilds.lpbin[oldIndex].lpb; + newChilds.lpbin[newIndex].cb = oldChilds.lpbin[oldIndex].cb; + newIndex++; + } + } + } + else + return FALSE; + + + SPropValue childs; + LPSPropProblemArray problems = NULL ; + + if (newChilds.cValues == 0) + { + SPropTagArray delTags; + delTags.cValues = 1; + delTags.aulPropTag[0] = listTag; + + mLastError = container->DeleteProps(&delTags, &problems) ; + } + else + { + childs.ulPropTag = listTag; + childs.Value.MVbin = newChilds; + mLastError = container->SetProps(1, &childs, &problems) ; + } + + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set childs %08x.\n", mLastError)) ; + return FALSE ; + } + + //update OUTLOOK_EMAIL_LIST2 + listTag = GetEmailPropertyTag(*(LPMAPIPROP*)&container,OUTLOOK_EMAIL_LIST2) | PT_MV_BINARY; + if (!GetMAPIProperties(aDistlist, &listTag, 1, oldChildValue, valueCount)) + { + PRINTF(("Cannot get old childs %08x.\n", mLastError)) ; + return FALSE; + } + + newIndex=0; + if (! (oldChildValue->Value.l == MAPI_E_NOT_FOUND)) + { + oldChilds = oldChildValue->Value.MVbin; + newChilds.cValues=oldChilds.cValues - 1; + mMAPIAllocateBuffer(sizeof(SBinary) * newChilds.cValues,(void**)& bins); + newChilds.lpbin = bins; + for (oldIndex=0;oldIndexDeleteProps(&delTags, &problems) ; + } + else + { + childs.ulPropTag = listTag; + childs.Value.MVbin = newChilds; + mLastError = container->SetProps(1, &childs, &problems) ; + } + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set childs %08x.\n", mLastError)) ; + return FALSE ; + } + + mMAPIFreeBuffer(bins); + + mLastError = container->SaveChanges(KEEP_OPEN_READONLY) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot commit new entry %08x.\n", mLastError)) ; + return FALSE ; + } + + return TRUE ; +} + +BOOL nsMapiAddressBook::GetEntryParent(const nsMapiEntry& aParent, nsMapiEntry& aParentEntry) +{ + nsMapiInterfaceWrapper object ; + ULONG objType = 0 ; + mLastError = OpenEntry(aParent.mByteCount, aParent.mEntryId, + &IID_IMAPIProp, 0, &objType, + (IUnknown **)&object) ; + + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open entry %08x.\n", mLastError)) ; + return FALSE ; + } + SPropValue *parentID=GetMapiProperty(*(LPMAPIPROP*)&object, PR_PARENT_ENTRYID); + + if (parentID->Value.l == MAPI_E_NOT_FOUND) + return FALSE; + aParentEntry.Assign(parentID->Value.bin.cb, NS_REINTERPRET_CAST(LPENTRYID, parentID->Value.bin.lpb)); + return TRUE; +} +BOOL nsMapiAddressBook::CreateEntryInList(const nsMapiEntry& aDistlist, nsMapiEntry& aNewEntry) +{ + nsMapiInterfaceWrapper container ; + ULONG objType = 0 ; + + nsMapiEntry parentEntry; + if (!GetEntryParent(aDistlist,parentEntry)) + { + return FALSE; + } + nsMapiInterfaceWrapper newEntry ; + if (!CreateEntry(parentEntry,aNewEntry)) //Create a entry in parent folder + return FALSE; + + return AddEntryToList(aDistlist,aNewEntry); +} + +BOOL nsMapiAddressBook::CreateEntry(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry) +{ + nsMapiInterfaceWrapper container ; + ULONG objType = 0 ; + + nsMapiInterfaceWrapper object; + mLastError = OpenEntry(aParent.mByteCount, aParent.mEntryId, + &IID_IMAPIProp, 0, &objType, + object) ; + + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open entry %08x.\n", mLastError)) ; + return NULL ; + } + LPSPropValue msgClass=GetMapiProperty(*(LPMAPIPROP*)&object,PR_MESSAGE_CLASS); + + if (msgClass && strcmp("IPM.DistList",msgClass->Value.lpszA) == 0) + return CreateEntryInList(aParent,aNewEntry); //Create entry in DistList + + LPMDB lpMsgStore=GetMsgStore(aParent); + + if (!lpMsgStore) + return FALSE; + + mLastError = lpMsgStore->OpenEntry(aParent.mByteCount, aParent.mEntryId, + &IID_IMAPIFolder, MAPI_MODIFY, &objType, + container) ; + lpMsgStore->Release(); + + if (HR_FAILED(mLastError)) + return FALSE; + + nsMapiInterfaceWrapper newEntry ; + + mLastError = container->CreateMessage(&IID_IMessage, + 0, + newEntry) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot create new entry %08x.\n", mLastError)) ; + return FALSE ; + } + SPropValue messageclass ; + LPSPropProblemArray problems = NULL ; + nsCString tempName ; + + messageclass.ulPropTag = PR_MESSAGE_CLASS_A ; + tempName.Assign("IPM.Contact") ; + messageclass.Value.lpszA = NS_CONST_CAST(char *, tempName.get()) ; + mLastError = newEntry->SetProps(1, &messageclass, &problems) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set temporary name %08x.\n", mLastError)) ; + return FALSE ; + } + mLastError = newEntry->SaveChanges(KEEP_OPEN_READONLY) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot commit new entry %08x.\n", mLastError)) ; + return FALSE ; + } + + SPropTagArray property ; + LPSPropValue value = NULL ; + ULONG valueCount = 0 ; + + property.cValues = 1 ; + property.aulPropTag [0] = PR_ENTRYID ; + mLastError = newEntry->GetProps(&property, 0, &valueCount, &value) ; + if (HR_FAILED(mLastError) || valueCount != 1) { + PRINTF(("Cannot get entry id %08x.\n", mLastError)) ; + return FALSE ; + } + aNewEntry.Assign(value->Value.bin.cb, NS_REINTERPRET_CAST(LPENTRYID, value->Value.bin.lpb)) ; + FreeBuffer(value) ; + return TRUE ; +} + +BOOL nsMapiAddressBook::CreateDistList(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry) +{ + nsMapiInterfaceWrapper container ; + ULONG objType = 0 ; + + LPMDB lpMsgStore=GetMsgStore(aParent); + if (!lpMsgStore) + return FALSE; + mLastError = lpMsgStore->OpenEntry(aParent.mByteCount, aParent.mEntryId, + &IID_IMAPIFolder, MAPI_MODIFY, &objType, + container) ; + lpMsgStore->Release(); + + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open container %08x.\n", mLastError)) ; + return FALSE ; + } + + nsMapiInterfaceWrapper newEntry ; + mLastError = container->CreateMessage(&IID_IMAPIProp, + 0, + newEntry) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot create new entry %08x.\n", mLastError)) ; + return FALSE ; + } + SPropValue messageclass ; + LPSPropProblemArray problems = NULL ; + nsCString tempName ; + + messageclass.ulPropTag = PR_MESSAGE_CLASS_A ; + tempName.Assign("IPM.DistList") ; + messageclass.Value.lpszA = NS_CONST_CAST(char *, tempName.get()) ; + mLastError = newEntry->SetProps(1, &messageclass, &problems) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set PR_MESSAGE_CLASS_A %08x.\n", mLastError)) ; + return FALSE ; + } + mLastError = newEntry->SaveChanges(KEEP_OPEN_READONLY) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot commit new entry %08x.\n", mLastError)) ; + return FALSE ; + } + + ULONG valueCount = 0 ; + SPropTagArray property ; + LPSPropValue value = NULL ; + + property.cValues = 1 ; + property.aulPropTag [0] = PR_ENTRYID ; + mLastError = newEntry->GetProps(&property, 0, &valueCount, &value) ; + if (HR_FAILED(mLastError) || valueCount != 1) { + PRINTF(("Cannot get entry id %08x.\n", mLastError)) ; + return FALSE ; + } + aNewEntry.Assign(value->Value.bin.cb, NS_REINTERPRET_CAST(LPENTRYID, value->Value.bin.lpb)) ; + + FreeBuffer(value) ; + return TRUE ; +} + + +BOOL nsMapiAddressBook::CopyEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aSource, + nsMapiEntry& aTarget) +{ + nsMapiInterfaceWrapper container ; + nsMapiInterfaceWrapper targetFolder ; + ULONG objType = 0 ; + nsMapiInterfaceWrapper object; + mLastError = OpenEntry(aContainer.mByteCount, aContainer.mEntryId, + &IID_IMAPIProp, 0, &objType, + object) ; + + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open entry %08x.\n", mLastError)) ; + return FALSE ; + } + LPSPropValue msgClass=GetMapiProperty(*(LPMAPIPROP*)&object,PR_MESSAGE_CLASS); + + if (msgClass && strcmp("IPM.DistList",msgClass->Value.lpszA) == 0) + { + //Add Entry To DistList + if (!AddEntryToList(aContainer,aSource)) + return FALSE; + aTarget.Assign(aSource.mByteCount,aSource.mEntryId); + return TRUE; + } + + SBinary entry ; + SBinaryArray entryArray ; + + entry.cb = aSource.mByteCount ; + entry.lpb = NS_REINTERPRET_CAST(LPBYTE, aSource.mEntryId) ; + entryArray.cValues = 1 ; + entryArray.lpbin = &entry ; + + mLastError = OpenEntry(aContainer.mByteCount, aContainer.mEntryId, + &IID_IMAPIFolder, MAPI_MODIFY, &objType, + container) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open container %08x.\n", mLastError)) ; + return FALSE ; + } + + mLastError = OpenEntry(aTarget.mByteCount, aTarget.mEntryId, + &IID_IMAPIFolder, MAPI_MODIFY, &objType, + targetFolder) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open Target folder %08x.\n", mLastError)) ; + return FALSE ; + } + + nsMapiInterfaceWrapper newEntry ; + + mLastError = container->CopyMessages(&entryArray, + &IID_IMessage, + (void*)&targetFolder, + 0, + NULL, + NULL) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot create new entry %08x.\n", mLastError)) ; + return FALSE ; + } + return TRUE ; +} + +BOOL nsMapiAddressBook::DeleteEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aEntry) +{ + nsMapiInterfaceWrapper container ; + ULONG objType = 0 ; + SBinary entry ; + SBinaryArray entryArray ; + + + nsMapiInterfaceWrapper object; + mLastError = OpenEntry(aContainer.mByteCount, aContainer.mEntryId, + &IID_IMAPIProp, 0, &objType, + object) ; + + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open entry %08x.\n", mLastError)) ; + return FALSE ; + } + LPSPropValue msgClass=GetMapiProperty(*(LPMAPIPROP*)&object,PR_MESSAGE_CLASS); + + if (msgClass && strcmp("IPM.DistList",msgClass->Value.lpszA) == 0) + return DeleteEntryFromList(aContainer,aEntry); //Delete Entry from DistList + + LPMDB lpMsgStore=GetMsgStore(aContainer); + if (!lpMsgStore) + return FALSE; + + mLastError = lpMsgStore->OpenEntry(aContainer.mByteCount, aContainer.mEntryId, + &IID_IMAPIFolder, MAPI_MODIFY, &objType, + container) ; + lpMsgStore->Release(); + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open container %08x.\n", mLastError)) ; + return FALSE ; + } + entry.cb = aEntry.mByteCount ; + entry.lpb = NS_REINTERPRET_CAST(LPBYTE, aEntry.mEntryId) ; + entryArray.cValues = 1 ; + entryArray.lpbin = &entry ; + mLastError = container->DeleteMessages(&entryArray, 0,0,0) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot delete entry %08x.\n", mLastError)) ; + return FALSE ; + } + return TRUE ; +} + +//Use to open message store in write mode +LPMDB nsMapiAddressBook::GetMsgStore(const nsMapiEntry& aEntry) +{ + nsMapiInterfaceWrapper object; + ULONG objType=0; + + mLastError = OpenEntry(aEntry.mByteCount, aEntry.mEntryId, + &IID_IMAPIProp, MAPI_BEST_ACCESS , &objType, + object) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open entry %08x.\n", mLastError)) ; + return NULL ; + } + SPropValue *svMsgSore=GetMapiProperty( *(LPMAPIPROP*)&object, PR_STORE_ENTRYID);; + + LPMDB lpMsgStore=NULL; + mLastError=mRootSession->OpenMsgStore(0, + svMsgSore->Value.bin.cb, + (ENTRYID*)svMsgSore->Value.bin.lpb, + &IID_IMsgStore, + MDB_NO_MAIL | MDB_WRITE , + &lpMsgStore); + + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open MsgStore %08x.\n", mLastError)) ; + return NULL ; + } + + return lpMsgStore; +} Index: mailnews/addrbook/src/nsMapiAddressBook.h =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsMapiAddressBook.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsMapiAddressBook.h 22 Oct 2003 02:43:11 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsMapiAddressBook.h 9 Dec 2003 03:26:47 -0000 1.2 @@ -40,12 +40,42 @@ #include "nsAbWinHelper.h" +struct TagMap +{ + ULONG AddressTag; + ULONG NameID; + ULONG TypeMask; +}; class nsMapiAddressBook : public nsAbWinHelper { public : nsMapiAddressBook(void) ; virtual ~nsMapiAddressBook(void) ; + // Get the top address books + virtual BOOL GetFolders(nsMapiEntryArray& aFolders); + + // Get a default address book container + virtual BOOL GetDefaultContainer(nsMapiEntry& aContainer); + // Is the helper correctly initialised? + virtual BOOL IsOK(void); + virtual BOOL GetPropertyLong(const nsMapiEntry& aObject, + ULONG aPropertyTag, + ULONG& aValue); + // Get the value of a MAPI property of type SYSTIME + virtual BOOL GetPropertyDate(const nsMapiEntry& aObject, ULONG aPropertyTag, + WORD& aYear, WORD& aMonth, WORD& aDay); + // Create entry in the address book + virtual BOOL CreateEntry(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry) ; + // Delete an entry in the address book + virtual BOOL DeleteEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aEntry) ; + // Create a distribution list in the address book + virtual BOOL CreateDistList(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry) ; + // Copy an existing entry in the address book + virtual BOOL CopyEntry(const nsMapiEntry& aContainer, const nsMapiEntry& aSource, nsMapiEntry& aTarget) ; + + static void FreeMapiLibrary(void) ; + protected : // Class members to handle the library/entry points static HMODULE mLibrary ; @@ -67,19 +97,77 @@ static BOOL mInitialized ; static BOOL mLogonDone ; static LPMAPISESSION mRootSession ; - static LPADRBOOK mRootBook ; + // Load the MAPI environment BOOL Initialize(void) ; + + virtual HRESULT OpenEntry(ULONG cbEntryID, + LPENTRYID lpEntryID, + LPCIID lpInterface, + ULONG ulFlags, + ULONG FAR * lpulObjType, + LPUNKNOWN FAR * lppUnk + ); + + + // Retrieve the contents of a container, with an optional restriction + virtual BOOL GetContents(const nsMapiEntry& aParent, LPSRestriction aRestriction, + nsMapiEntryArray *aList, ULONG aMapiType) ; + // Retrieve the values of a set of properties on a MAPI object + virtual BOOL GetMAPIProperties(const nsMapiEntry& aObject, const ULONG *aPropertyTags, + ULONG aNbProperties, + LPSPropValue& aValues, ULONG& aValueCount) ; + // Set the values of a set of properties on a MAPI object + virtual BOOL SetMAPIProperties(const nsMapiEntry& aObject, ULONG aNbProperties, + LPSPropValue& aValues); + + // Allocation of a buffer for transmission to interfaces virtual void AllocateBuffer(ULONG aByteCount, LPVOID *aBuffer) ; // Destruction of a buffer provided by the interfaces virtual void FreeBuffer(LPVOID aBuffer) ; // Library management static BOOL LoadMapiLibrary(void) ; - static void FreeMapiLibrary(void) ; + + BOOL HandleContentsItem(ULONG oType, ULONG cb, LPENTRYID pEntry,nsMapiEntryArray& aFolders); + LPSPropValue GetMapiProperty( LPMAPIPROP pProp, ULONG tag); + BOOL GetEntryIdFromProp( LPSPropValue pVal, ULONG& cbEntryId, LPENTRYID& lpEntryId, BOOL delVal=FALSE); + BOOL HandleHierarchyItem( ULONG oType, ULONG cb, LPENTRYID pEntry,nsMapiEntryArray& aFolders); + BOOL IterateHierarchy(IMAPIContainer * pFolder, nsMapiEntryArray& aFolders,ULONG flags=0); + ULONG GetEmailPropertyTag(LPMAPIPROP lpProp, LONG nameID); + ULONG GetRealMapiPropertyTag(LPMAPIPROP lpProp, LONG aPropertyTag,BOOL aTest=FALSE); + LPMDB GetMsgStore(const nsMapiEntry& aEntry); + BOOL CreateEntryInList(const nsMapiEntry& aParent, nsMapiEntry& aNewEntry); + BOOL AddEntryToList(const nsMapiEntry& aParent,const nsMapiEntry& aNewEntry); + BOOL DeleteEntryFromList(const nsMapiEntry& aDistlist, const nsMapiEntry& aNewEntry); + BOOL GetEntryParent(const nsMapiEntry& aParent, nsMapiEntry& aParentEntry); + BOOL CorrectRestriction(const LPMAPIPROP aMapiProp,ULONG aRestrictionNum, LPSRestriction aRestriction); + + //filter + BOOL Filter( LPSRestriction aRestriction,nsMapiEntryArray * aList); + BOOL FilterOnOneRow(nsMapiEntry *aEntry,LPSRestriction aRestriction); + BOOL AtomyFilter(LPSRestriction aRestriction,LPSPropValue aRealValue,LPSPropValue aFilterValue); + + void AddToMDBArray(LPMDB aMDB) + { + m_MDBArray.AppendElement(aMDB); + } + void CleanUpMDB() + { + LPMDB mdb; + for (int i = 0; i < m_MDBArray.Count(); i++) + { + mdb = (LPMDB)m_MDBArray.ElementAt(i); + mdb->Release(); + } + m_MDBArray.Clear(); + } private : + //use to keep all openned MsgStore,if we not open a message store,we can't open any thing on it + //so we have to kill message stores openned + nsVoidArray m_MDBArray; } ; #endif // nsMapiAddressBook_h___ Index: mailnews/addrbook/src/nsWabAddressBook.cpp =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsWabAddressBook.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsWabAddressBook.cpp 22 Oct 2003 02:43:11 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsWabAddressBook.cpp 9 Dec 2003 03:26:47 -0000 1.2 @@ -47,6 +47,22 @@ #define PRINTF(args) PR_LOG(gWabAddressBookLog, PR_LOG_DEBUG, args) +enum +{ + ContentsColumnEntryId = 0, + ContentsColumnObjectType, + ContentsColumnsSize +} ; + +static const SizedSPropTagArray(ContentsColumnsSize, ContentsColumns) = +{ + ContentsColumnsSize, + { + PR_ENTRYID, + PR_OBJECT_TYPE + } +} ; + HMODULE nsWabAddressBook::mLibrary = NULL ; PRInt32 nsWabAddressBook::mLibUsage = 0 ; LPWABOPEN nsWabAddressBook::mWABOpen = NULL ; @@ -95,7 +111,7 @@ MOZ_DECL_CTOR_COUNTER(nsWabAddressBook) nsWabAddressBook::nsWabAddressBook(void) -: nsAbWinHelper() +: nsAbWinHelper(),mAddressBook(NULL) { BOOL result = Initialize() ; @@ -110,9 +126,254 @@ MOZ_COUNT_DTOR(nsWabAddressBook) ; } +BOOL nsWabAddressBook::GetFolders(nsMapiEntryArray& aFolders) +{ + aFolders.CleanUp() ; + nsMapiInterfaceWrapper rootFolder ; + nsMapiInterfaceWrapper folders ; + ULONG objType = 0 ; + ULONG rowCount = 0 ; + SRestriction restriction ; + SPropTagArray folderColumns ; + + mLastError = OpenEntry(0, NULL, NULL, 0, &objType, + rootFolder); + if (HR_FAILED(mLastError)){ + PRINTF(("Cannot open root %08x.\n", mLastError)); + return FALSE; + } + mLastError = rootFolder->GetHierarchyTable(0, folders); + if (HR_FAILED(mLastError)){ + PRINTF(("Cannot get hierarchy %08x.\n", mLastError)); + return FALSE; + } + // We only take into account modifiable containers, + // otherwise, we end up with all the directory services... + restriction.rt = RES_BITMASK ; + restriction.res.resBitMask.ulPropTag = PR_CONTAINER_FLAGS ; + restriction.res.resBitMask.relBMR = BMR_NEZ ; + restriction.res.resBitMask.ulMask = AB_MODIFIABLE ; + mLastError = folders->Restrict(&restriction, 0) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot restrict table %08x.\n", mLastError)) ; + } + folderColumns.cValues = 1 ; + folderColumns.aulPropTag [0] = PR_ENTRYID ; + mLastError = folders->SetColumns(&folderColumns, 0) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set columns %08x.\n", mLastError)) ; + return FALSE ; + } + mLastError = folders->GetRowCount(0, &rowCount) ; + if (HR_SUCCEEDED(mLastError)) { + do { + LPSRowSet rowSet = NULL ; + + rowCount = 0 ; + mLastError = folders->QueryRows(1, 0, &rowSet) ; + if (HR_SUCCEEDED(mLastError)) { + rowCount = rowSet->cRows ; + if (rowCount > 0) { + SPropValue& currentValue = rowSet->aRow->lpProps [0] ; + + aFolders.AddItem(currentValue.Value.bin.cb, + NS_REINTERPRET_CAST(LPENTRYID, currentValue.Value.bin.lpb)) ; + } + MyFreeProws(rowSet) ; + } + else { + PRINTF(("Cannot query rows %08x.\n", mLastError)) ; + } + } while (rowCount > 0) ; + } + return HR_SUCCEEDED(mLastError) ; +} +BOOL nsWabAddressBook::GetContents(const nsMapiEntry& aParent, LPSRestriction aRestriction, + nsMapiEntryArray *aList, ULONG aMapiType) +{ + if (aList) { aList->CleanUp(); } + nsMapiInterfaceWrapper parent ; + nsMapiInterfaceWrapper contents ; + ULONG objType = 0 ; + ULONG rowCount = 0 ; + + mLastError = OpenEntry(aParent.mByteCount, aParent.mEntryId, + &IID_IMAPIContainer, 0, &objType, + parent) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open parent %08x.\n", mLastError)) ; + return FALSE ; + } + // Here, flags for WAB and MAPI could be different, so this works + // only as long as we don't want to use any flag in GetContentsTable + mLastError = parent->GetContentsTable(0, contents) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot get contents %08x.\n", mLastError)) ; + return FALSE ; + } + if (aRestriction) { + mLastError = contents->Restrict(aRestriction, 0) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set restriction %08x.\n", mLastError)) ; + return FALSE ; + } + } + int entryId = ContentsColumnEntryId ; + int objectType = ContentsColumnObjectType ; + + if (aRestriction) + { + LPSPropTagArray allColumns = NULL ; + + mLastError = contents->QueryColumns(TBL_ALL_COLUMNS, &allColumns) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot query columns %08x.\n", mLastError)) ; + return FALSE ; + } + + for (unsigned int j = 0 ; j < allColumns->cValues ; ++ j) { + if (allColumns->aulPropTag [j] == PR_ENTRYID) { + entryId = j ; + } + else if (allColumns->aulPropTag [j] == PR_OBJECT_TYPE) { + objectType = j ; + } + } + mLastError = contents->SetColumns(allColumns, 0) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set columns %08x.\n", mLastError)) ; + return FALSE ; + } + FreeBuffer(allColumns) ; + } + else + { + + mLastError = contents->SetColumns((LPSPropTagArray) &ContentsColumns, 0) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot set columns %08x.\n", mLastError)) ; + return FALSE ; + } + } + + mLastError = contents->GetRowCount(0, &rowCount) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot get result count %08x.\n", mLastError)) ; + return FALSE ; + } + do { + LPSRowSet rowSet = NULL ; + + rowCount = 0 ; + mLastError = contents->QueryRows(1, 0, &rowSet) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot query rows %08x.\n", mLastError)) ; + return FALSE ; + } + rowCount = rowSet->cRows ; + if (rowCount > 0 && + (aMapiType == 0 || + rowSet->aRow->lpProps[objectType].Value.ul == aMapiType)) { + if (aList) { + SPropValue& currentValue = rowSet->aRow->lpProps[entryId] ; + + aList->AddItem(currentValue.Value.bin.cb, + NS_REINTERPRET_CAST(LPENTRYID, currentValue.Value.bin.lpb)) ; + + } + } + MyFreeProws(rowSet) ; + } while (rowCount > 0) ; + return TRUE ; +} + +BOOL nsWabAddressBook::GetMAPIProperties(const nsMapiEntry& aObject, const ULONG *aPropertyTags, + ULONG aNbProperties, LPSPropValue& aValue, + ULONG& aValueCount) +{ + nsMapiInterfaceWrapper object ; + IMsgStore * mdb=NULL; + ULONG objType = 0 ; + LPSPropTagArray properties = NULL ; + ULONG i = 0 ; + + mLastError = OpenEntry(aObject.mByteCount, aObject.mEntryId, + &IID_IMAPIProp, 0, &objType, + object) ; + + if (HR_FAILED(mLastError)){ + PRINTF(("Cannot open entry %08x.\n", mLastError)); + return FALSE; + } + AllocateBuffer(CbNewSPropTagArray(aNbProperties), + NS_REINTERPRET_CAST(void **, &properties)); + properties->cValues = aNbProperties; + for (i = 0 ; i < aNbProperties ; ++ i) { + properties->aulPropTag [i] = aPropertyTags [i]; + } + mLastError = object->GetProps(properties, 0, &aValueCount, &aValue); + FreeBuffer(properties); + if (HR_FAILED(mLastError)){ + PRINTF(("Cannot get props %08x.\n", mLastError)); + } + return HR_SUCCEEDED(mLastError) ; +} + +BOOL nsWabAddressBook::SetMAPIProperties(const nsMapiEntry& aObject, ULONG aNbProperties, + LPSPropValue& aValues) +{ + nsMapiInterfaceWrapper object ; + ULONG objType = 0 ; + LPSPropProblemArray problems = NULL ; + + mLastError = OpenEntry(aObject.mByteCount, aObject.mEntryId, + &IID_IMAPIProp, MAPI_MODIFY, &objType, + object) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot open entry %08x.\n", mLastError)) ; + return FALSE ; + } + mLastError = object->SetProps(aNbProperties, aValues, &problems) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot update the object %08x.\n", mLastError)) ; + return FALSE ; + } + if (problems) { + for (ULONG i = 0 ; i < problems->cProblem ; ++ i) { + PRINTF(("Problem %d: index %d code %08x.\n", i, + problems->aProblem [i].ulIndex, + problems->aProblem [i].scode)); + } + } + mLastError = object->SaveChanges(0) ; + if (HR_FAILED(mLastError)) { + PRINTF(("Cannot commit changes %08x.\n", mLastError)) ; + } + return HR_SUCCEEDED(mLastError) ; +} + +BOOL nsWabAddressBook::GetDefaultContainer(nsMapiEntry& aContainer) +{ + LPENTRYID entryId = NULL; + ULONG byteCount = 0; + + mLastError = mAddressBook->GetPAB(&byteCount, &entryId); + if (HR_FAILED(mLastError)){ + PRINTF(("Cannot get PAB %08x.\n", mLastError)); + return FALSE; + } + aContainer.Assign(byteCount, entryId); + FreeBuffer(entryId) ; + return TRUE ; +} + +BOOL nsWabAddressBook::IsOK(void) +{ + return mAddressBook != NULL ; +} + BOOL nsWabAddressBook::Initialize(void) { - if (mAddressBook) { return TRUE ; } nsAutoLock guard(mMutex) ; if (!LoadWabLibrary()) { Index: mailnews/addrbook/src/nsWabAddressBook.h =================================================================== RCS file: /mozilla/mozilla/mailnews/addrbook/src/nsWabAddressBook.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/mailnews/addrbook/src/nsWabAddressBook.h 22 Oct 2003 02:43:11 -0000 1.1.1.1 +++ miss/build/mozilla/mailnews/addrbook/src/nsWabAddressBook.h 9 Dec 2003 03:26:47 -0000 1.2 @@ -47,6 +47,15 @@ nsWabAddressBook(void) ; virtual ~nsWabAddressBook(void) ; + // Get the top address books + virtual BOOL GetFolders(nsMapiEntryArray& aFolders); + + // Get a default address book container + virtual BOOL GetDefaultContainer(nsMapiEntry& aContainer); + // Is the helper correctly initialised? + virtual BOOL IsOK(void); + static void FreeWabLibrary(void) ; + protected : // Session and address book that will be shared by all instances // (see nsMapiAddressBook.h for details) @@ -57,15 +66,46 @@ static HMODULE mLibrary ; static LPWABOPEN mWABOpen ; + LPADRBOOK mAddressBook ; + // Load the WAB environment BOOL Initialize(void) ; + + virtual HRESULT OpenEntry(ULONG cbEntryID, + LPENTRYID lpEntryID, + LPCIID lpInterface, + ULONG ulFlags, + ULONG FAR * lpulObjType, + LPUNKNOWN FAR * lppUnk + ) + { + return mAddressBook->OpenEntry(cbEntryID, + lpEntryID, + lpInterface, + ulFlags, + lpulObjType, + lppUnk + ); + } + + + // Retrieve the contents of a container, with an optional restriction + virtual BOOL GetContents(const nsMapiEntry& aParent, LPSRestriction aRestriction, + nsMapiEntryArray *aList, ULONG aMapiType) ; + // Retrieve the values of a set of properties on a MAPI object + virtual BOOL GetMAPIProperties(const nsMapiEntry& aObject, const ULONG *aPropertyTags, + ULONG aNbProperties, + LPSPropValue& aValues, ULONG& aValueCount) ; + // Set the values of a set of properties on a MAPI object + virtual BOOL SetMAPIProperties(const nsMapiEntry& aObject, ULONG aNbProperties, + LPSPropValue& aValues) ; + // Allocation of a buffer for transmission to interfaces virtual void AllocateBuffer(ULONG aByteCount, LPVOID *aBuffer) ; // Destruction of a buffer provided by the interfaces virtual void FreeBuffer(LPVOID aBuffer) ; // Manage the library static BOOL LoadWabLibrary(void) ; - static void FreeWabLibrary(void) ; private : } ; Index: profile/src/nsProfile.cpp =================================================================== RCS file: /mozilla/mozilla/profile/src/nsProfile.cpp,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -w -b -i -r1.1.1.1 -r1.2 --- miss/build/mozilla/profile/src/nsProfile.cpp 22 Oct 2003 02:40:14 -0000 1.1.1.1 +++ miss/build/mozilla/profile/src/nsProfile.cpp 22 Oct 2003 09:45:04 -0000 1.2 @@ -555,6 +555,7 @@ rv = curProfileDir->Exists(&exists); if (NS_FAILED(rv) || !exists) profileURLStr = PROFILE_MANAGER_URL; +#if 0 if (exists) { // If the profile is locked, we need the UI @@ -564,6 +565,7 @@ if (NS_FAILED(rv)) profileURLStr = PROFILE_MANAGER_URL; } +#endif } else profileURLStr = PROFILE_SELECTION_URL; @@ -1200,6 +1202,7 @@ else isSwitch = PR_FALSE; +#if 0 nsProfileLock localLock; nsCOMPtr localProfileDir(do_QueryInterface(profileDir, &rv)); if (NS_FAILED(rv)) return rv; @@ -1209,6 +1212,7 @@ NS_ERROR("Could not get profile directory lock."); return rv; } +#endif nsCOMPtr observerService = do_GetService("@mozilla.org/observer-service;1", &rv); @@ -1244,7 +1248,9 @@ gProfileDataAccess->SetCurrentProfile(aCurrentProfile); gProfileDataAccess->mProfileDataChanged = PR_TRUE; gProfileDataAccess->UpdateRegistry(nsnull); +#if 0 mCurrentProfileLock = localLock; +#endif if (NS_FAILED(rv)) return rv; mCurrentProfileAvailable = PR_TRUE; @@ -1331,7 +1337,9 @@ UpdateCurrentProfileModTime(PR_TRUE); mCurrentProfileAvailable = PR_FALSE; mCurrentProfileName.Truncate(0); +#if 0 mCurrentProfileLock.Unlock(); +#endif return NS_OK; } --- miss/build/mozilla/.mozconfig Tue Jul 22 21:52:27 2003 +++ misc/build/mozilla/.mozconfig Mon Jul 28 15:07:20 2003 @@ -0,0 +1,8 @@ +ac_add_options --disable-tests +ac_add_options --disable-xprint +ac_add_options --without-system-zlib +ac_add_options --enable-ldap +ac_add_options --disable-debug +ac_add_options --enable-optimize +ac_add_options --enable-crypto +ac_add_options --enable-strip --- misc/build/mozilla/client.mk Fri Aug 1 10:14:27 2003 +++ misc/build/mozilla/client.mk Fri Aug 1 10:11:31 2003 @@ -386,9 +386,9 @@ fi ifdef _IS_FIRST_CHECKOUT -all:: checkout build +all:: build else -all:: checkout alldep +all:: alldep endif # Windows equivalents