зеркало из https://github.com/mozilla/pjs.git
Fix RFC 822 quoting for LDAP autocompleted display names (bug 89198). Fix works by creating a new "formatter" interface and implementing an addressbook-specific version of it which uses the mailnews quoting code to fix it up. Also provides infrastructure for setting the LDAP autocomplete dropdown comment field, and fixes some error-handling issues in the compose window code for setting up LDAP autocompletion. r=leif@netscape.com (backend changes), srilatha@netscape.com (compose window changes); sr=bienvenu@netscape.com
This commit is contained in:
Родитель
f1f32fab65
Коммит
8bb1453922
|
@ -346,4 +346,15 @@
|
||||||
{0x84, 0xac, 0x12, 0x48, 0x25, 0xc7, 0x78, 0xf8} \
|
{0x84, 0xac, 0x12, 0x48, 0x25, 0xc7, 0x78, 0xf8} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nsAbLDAPAutoCompFormatter
|
||||||
|
|
||||||
|
// 4e276d6d-9981-46b4-9070-92f344ac5f5a
|
||||||
|
//
|
||||||
|
#define NS_ABLDAPAUTOCOMPFORMATTER_CID \
|
||||||
|
{ 0x4e276d6d, 0x9981, 0x46b4, \
|
||||||
|
{ 0x90, 0x70, 0x92, 0xf3, 0x44, 0xac, 0x5f, 0x5a }}
|
||||||
|
|
||||||
|
#define NS_ABLDAPAUTOCOMPFORMATTER_CONTRACTID \
|
||||||
|
"@mozilla.org/ldap-autocomplete-formatter;1?type=addrbook"
|
||||||
|
|
||||||
#endif // nsAbBaseCID_h__
|
#endif // nsAbBaseCID_h__
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
|
|
||||||
/* Include all of the interfaces our factory can generate components for */
|
/* Include all of the interfaces our factory can generate components for */
|
||||||
|
|
||||||
#include "nsDirectoryDataSource.h"
|
#include "nsDirectoryDataSource.h"
|
||||||
|
@ -70,6 +69,7 @@
|
||||||
#include "nsAbLDAPDirectory.h"
|
#include "nsAbLDAPDirectory.h"
|
||||||
#include "nsAbLDAPCard.h"
|
#include "nsAbLDAPCard.h"
|
||||||
#include "nsAbLDAPDirFactory.h"
|
#include "nsAbLDAPDirFactory.h"
|
||||||
|
#include "nsAbLDAPAutoCompFormatter.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAddressBook)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAddressBook)
|
||||||
|
@ -108,6 +108,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbBooleanExpression)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbLDAPDirectory)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbLDAPDirectory)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbLDAPCard)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbLDAPCard)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbLDAPDirFactory)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbLDAPDirFactory)
|
||||||
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbLDAPAutoCompFormatter)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbDirectoryQueryProxy)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAbDirectoryQueryProxy)
|
||||||
|
@ -251,6 +252,12 @@ static nsModuleComponentInfo components[] =
|
||||||
NS_ABLDAPDIRFACTORY_CID,
|
NS_ABLDAPDIRFACTORY_CID,
|
||||||
NS_ABLDAPDIRFACTORY_CONTRACTID,
|
NS_ABLDAPDIRFACTORY_CONTRACTID,
|
||||||
nsAbLDAPDirFactoryConstructor },
|
nsAbLDAPDirFactoryConstructor },
|
||||||
|
|
||||||
|
{ "Address book LDAP autocomplete formatter",
|
||||||
|
NS_ABLDAPAUTOCOMPFORMATTER_CID,
|
||||||
|
NS_ABLDAPAUTOCOMPFORMATTER_CONTRACTID,
|
||||||
|
nsAbLDAPAutoCompFormatterConstructor },
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ "The directory query proxy interface",
|
{ "The directory query proxy interface",
|
||||||
|
|
|
@ -52,9 +52,11 @@ XPIDLSRCS = \
|
||||||
nsIAbDirectorySearch.idl \
|
nsIAbDirectorySearch.idl \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
ifdef MOZ_LDAP_XPCOM
|
ifdef MOZ_LDAP_XPCOM
|
||||||
XPIDLSRCS += nsILDAPPrefsService.idl
|
XPIDLSRCS += \
|
||||||
|
nsILDAPPrefsService.idl \
|
||||||
|
nsIAbLDAPAutoCompFormatter.idl \
|
||||||
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ XPIDLSRCS = \
|
||||||
.\nsIAbDirectorySearch.idl \
|
.\nsIAbDirectorySearch.idl \
|
||||||
!if !defined(DISABLE_LDAP)
|
!if !defined(DISABLE_LDAP)
|
||||||
.\nsILDAPPrefsService.idl \
|
.\nsILDAPPrefsService.idl \
|
||||||
|
.\nsIAbLDAPAutoCompFormatter.idl \
|
||||||
!endif
|
!endif
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 2001 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): Dan Mosedale <dmose@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nsILDAPAutoCompFormatter.idl"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for formatter LDAP messages to be used as nsAutoCompleteItems
|
||||||
|
* for use in RFC 2822 message headers.
|
||||||
|
*/
|
||||||
|
[scriptable, uuid(cde8836e-1dd1-11b2-baff-a6d918243e80)]
|
||||||
|
interface nsIAbLDAPAutoCompFormatter: nsILDAPAutoCompFormatter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All three Format attributes are templates, which work as follows:
|
||||||
|
*
|
||||||
|
* Required LDAP attributes are delimited by curly braces, and
|
||||||
|
* optional LDAP attributes are determined by brackets. Backslash
|
||||||
|
* escapes any character, including itself. Someday perhaps we'll rev
|
||||||
|
* this interface and change these to a more flexible format; perhaps
|
||||||
|
* something regexp based.
|
||||||
|
*
|
||||||
|
* If any of these are unset, components implementing this interface
|
||||||
|
* are free to choose reasonable defaults. As an example, the
|
||||||
|
*"@mozilla.org/ldap-autocomplete-formatter;1?type=addrbook"
|
||||||
|
* implementation currently happens to use the followingn defaults:
|
||||||
|
*
|
||||||
|
* nameFormat: [cn]
|
||||||
|
* addressFormat: {mail}
|
||||||
|
* commentFormat: [o]
|
||||||
|
*
|
||||||
|
* and generates autocomplete items like this:
|
||||||
|
*
|
||||||
|
* value: John Doe <john.doe@foo.org>
|
||||||
|
* comment: Foo Organization
|
||||||
|
*
|
||||||
|
* Note that nsILDAPAutoCompFormatter::getAttributes() is only
|
||||||
|
* required to be called by the nsILDAPAutoCompleteSession
|
||||||
|
* implementation when the nsILDAPAutoCompleteSession::formatter
|
||||||
|
* IDL attribute is set. So if for some reason the format
|
||||||
|
* attributes exposed through this interface get changed (eg a
|
||||||
|
* user changes their prefs), it is the changing code's
|
||||||
|
* responsibly to re-set the nsILDAPAutoCompleteSession::formatter
|
||||||
|
* IDL attribute to the same object to force a new getAttributes()
|
||||||
|
* call.
|
||||||
|
*/
|
||||||
|
|
||||||
|
attribute AString nameFormat;
|
||||||
|
attribute AString addressFormat;
|
||||||
|
attribute AString commentFormat;
|
||||||
|
};
|
|
@ -98,6 +98,7 @@ EXPORTS += nsAbLDAPDirectoryQuery.h \
|
||||||
nsAbLDAPDirectory.h \
|
nsAbLDAPDirectory.h \
|
||||||
nsAbLDAPDirFactory.h \
|
nsAbLDAPDirFactory.h \
|
||||||
nsAbLDAPCard.h \
|
nsAbLDAPCard.h \
|
||||||
|
nsAbLDAPAutoCompFormatter.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
CPPSRCS += nsAbLDAPDirectory.cpp \
|
CPPSRCS += nsAbLDAPDirectory.cpp \
|
||||||
|
@ -106,6 +107,7 @@ CPPSRCS += nsAbLDAPDirectory.cpp \
|
||||||
nsAbLDAPProperties.cpp \
|
nsAbLDAPProperties.cpp \
|
||||||
nsAbLDAPDirectoryQuery.cpp \
|
nsAbLDAPDirectoryQuery.cpp \
|
||||||
nsAbBoolExprToLDAPFilter.cpp \
|
nsAbBoolExprToLDAPFilter.cpp \
|
||||||
|
nsAbLDAPAutoCompFormatter.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ EXPORTS= \
|
||||||
nsAbLDAPDirectory.h \
|
nsAbLDAPDirectory.h \
|
||||||
nsAbLDAPDirFactory.h \
|
nsAbLDAPDirFactory.h \
|
||||||
nsAbLDAPCard.h \
|
nsAbLDAPCard.h \
|
||||||
|
nsAbLDAPAutoCompFormatter.h \
|
||||||
!endif
|
!endif
|
||||||
nsAbDirectoryRDFResource.h \
|
nsAbDirectoryRDFResource.h \
|
||||||
nsAbBooleanExpression.h \
|
nsAbBooleanExpression.h \
|
||||||
|
@ -107,6 +108,7 @@ CPP_OBJS= \
|
||||||
.\$(OBJDIR)\nsAbLDAPProperties.obj \
|
.\$(OBJDIR)\nsAbLDAPProperties.obj \
|
||||||
.\$(OBJDIR)\nsAbLDAPDirectoryQuery.obj \
|
.\$(OBJDIR)\nsAbLDAPDirectoryQuery.obj \
|
||||||
.\$(OBJDIR)\nsAbBoolExprToLDAPFilter.obj \
|
.\$(OBJDIR)\nsAbBoolExprToLDAPFilter.obj \
|
||||||
|
.\$(OBJDIR)\nsAbLDAPAutoCompFormatter.obj \
|
||||||
!endif
|
!endif
|
||||||
.\$(OBJDIR)\nsAbBooleanExpression.obj \
|
.\$(OBJDIR)\nsAbBooleanExpression.obj \
|
||||||
.\$(OBJDIR)\nsAbDirectoryRDFResource.obj \
|
.\$(OBJDIR)\nsAbDirectoryRDFResource.obj \
|
||||||
|
|
|
@ -0,0 +1,521 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 2001 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): Dan Mosedale <dmose@netscape.com> (Original Author)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Work around lack of conditional build logic in codewarrior's
|
||||||
|
// build system. The MOZ_LDAP_XPCOM preprocessor symbol is only
|
||||||
|
// defined on Mac because noone else needs this weirdness; thus
|
||||||
|
// the XP_MAC check first. This conditional encloses the entire
|
||||||
|
// file, so that in the case where the ldap option is turned off
|
||||||
|
// in the mac build, a dummy (empty) object will be generated.
|
||||||
|
//
|
||||||
|
#if !defined(XP_MAC) || defined(MOZ_LDAP_XPCOM)
|
||||||
|
|
||||||
|
#include "nsAbLDAPAutoCompFormatter.h"
|
||||||
|
#include "nsIAutoCompleteResults.h"
|
||||||
|
#include "nsIServiceManager.h"
|
||||||
|
#include "nsIMsgHeaderParser.h"
|
||||||
|
#include "nsLDAP.h"
|
||||||
|
#include "prlog.h"
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS2(nsAbLDAPAutoCompFormatter,
|
||||||
|
nsILDAPAutoCompFormatter,
|
||||||
|
nsIAbLDAPAutoCompFormatter)
|
||||||
|
|
||||||
|
nsAbLDAPAutoCompFormatter::nsAbLDAPAutoCompFormatter() :
|
||||||
|
mNameFormat(NS_LITERAL_STRING("[cn]")),
|
||||||
|
mAddressFormat(NS_LITERAL_STRING("{mail}")),
|
||||||
|
mCommentFormat(NS_LITERAL_STRING("[o]"))
|
||||||
|
{
|
||||||
|
NS_INIT_ISUPPORTS();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAbLDAPAutoCompFormatter::~nsAbLDAPAutoCompFormatter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAbLDAPAutoCompFormatter::Format(nsILDAPMessage *aMsg,
|
||||||
|
nsIAutoCompleteItem **aItem)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIMsgHeaderParser> msgHdrParser =
|
||||||
|
do_GetService("@mozilla.org/messenger/headerparser;1", &rv);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_ERROR("nsAbLDAPAutoCompFormatter::Format(): do_GetService()"
|
||||||
|
" failed trying to obtain"
|
||||||
|
" '@mozilla.org/messenger/headerparser;1'");
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the appropriate string
|
||||||
|
//
|
||||||
|
nsCAutoString name;
|
||||||
|
rv = ProcessFormat(mNameFormat, aMsg, &name, 0);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
// Something went wrong lower down the stack; a message should
|
||||||
|
// have already been logged there. Return an error, rather
|
||||||
|
// than trying to generate a bogus nsIAutoCompleteItem
|
||||||
|
//
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCAutoString address;
|
||||||
|
rv = ProcessFormat(mAddressFormat, aMsg, &address, 0);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
// Something went wrong lower down the stack; a message should have
|
||||||
|
// already been logged there. Return an error, rather than trying to
|
||||||
|
// generate a bogus nsIAutoCompleteItem.
|
||||||
|
//
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsXPIDLCString value;
|
||||||
|
/* As far as I can tell, the documentation in nsIMsgHdrParser that
|
||||||
|
* nsnull means "US-ASCII" is actually wrong, it appears to mean UTF8
|
||||||
|
*/
|
||||||
|
rv = msgHdrParser->MakeFullAddress(nsnull, name.get(), address.get(),
|
||||||
|
getter_Copies(value));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_ERROR("nsAbLDAPAutoCompFormatter::Format(): call to"
|
||||||
|
" MakeFullAddress() failed");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an nsIAutoCompleteItem to hold the returned value
|
||||||
|
//
|
||||||
|
nsCOMPtr<nsIAutoCompleteItem> item = do_CreateInstance(
|
||||||
|
NS_AUTOCOMPLETEITEM_CONTRACTID, &rv);
|
||||||
|
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_ERROR("nsAbLDAPAutoCompFormatter::Format(): couldn't"
|
||||||
|
" create " NS_AUTOCOMPLETEITEM_CONTRACTID "\n");
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is that part that actually gets autocompleted to
|
||||||
|
//
|
||||||
|
rv = item->SetValue(NS_ConvertUTF8toUCS2(value));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_ERROR("nsAbLDAPAutoCompFormatter::Format(): "
|
||||||
|
"item->SetValue failed");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the appropriate string to appear as a comment off to the side
|
||||||
|
//
|
||||||
|
nsCAutoString comment;
|
||||||
|
rv = ProcessFormat(mCommentFormat, aMsg, &comment, 0);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
// Something went wrong lower down the stack; a messagne should have
|
||||||
|
// already been logged there. Return an error rather than
|
||||||
|
// trying to generate a bogus nsIAutoCompleteItem.
|
||||||
|
//
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = item->SetComment(NS_ConvertUTF8toUCS2(comment).get());
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_ERROR("nsAbLDAPAutoCompFormatter::Format():"
|
||||||
|
" item->SetComment failed");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// all done; return the item
|
||||||
|
//
|
||||||
|
NS_IF_ADDREF(*aItem = item);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAbLDAPAutoCompFormatter::GetAttributes(PRUint32 *aCount, char ** *aAttrs)
|
||||||
|
{
|
||||||
|
if (!aCount || !aAttrs) {
|
||||||
|
return NS_ERROR_INVALID_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCStringArray mSearchAttrs;
|
||||||
|
nsresult rv = ProcessFormat(mNameFormat, 0, 0, &mSearchAttrs);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_WARNING("nsAbLDAPAutoCompFormatter::SetNameFormat(): "
|
||||||
|
"ProcessFormat() failed");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = ProcessFormat(mAddressFormat, 0, 0, &mSearchAttrs);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_WARNING("nsAbLDAPAutoCompFormatter::SetNameFormat(): "
|
||||||
|
"ProcessFormat() failed");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = ProcessFormat(mCommentFormat, 0, 0, &mSearchAttrs);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_WARNING("nsAbLDAPAutoCompFormatter::SetNameFormat(): "
|
||||||
|
"ProcessFormat() failed");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// none of the formatting templates require any LDAP attributes
|
||||||
|
//
|
||||||
|
PRUint32 count = mSearchAttrs.Count(); // size of XPCOM array we'll need
|
||||||
|
if (!count) {
|
||||||
|
NS_ERROR("nsAbLDAPAutoCompFormatter::GetAttributes(): "
|
||||||
|
"current output format (if set) requires no search "
|
||||||
|
"attributes");
|
||||||
|
return NS_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build up the raw XPCOM array to return
|
||||||
|
//
|
||||||
|
PRUint32 rawSearchAttrsSize = 0; // grown as XPCOM array is built
|
||||||
|
char **rawSearchAttrs =
|
||||||
|
NS_STATIC_CAST(char **, nsMemory::Alloc(count * sizeof(char *)));
|
||||||
|
if (!rawSearchAttrs) {
|
||||||
|
NS_ERROR("nsAbLDAPAutoCompFormatter::GetAttributes(): out of "
|
||||||
|
"memory");
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through the string array, and build up the C-array.
|
||||||
|
//
|
||||||
|
while (rawSearchAttrsSize < count) {
|
||||||
|
if (!(rawSearchAttrs[rawSearchAttrsSize] =
|
||||||
|
(mSearchAttrs.CStringAt(rawSearchAttrsSize))->ToNewCString())) {
|
||||||
|
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(rawSearchAttrsSize,
|
||||||
|
rawSearchAttrs);
|
||||||
|
NS_ERROR("nsAbLDAPAutoCompFormatter::GetAttributes(): out "
|
||||||
|
"of memory");
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
rawSearchAttrsSize++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*aCount = rawSearchAttrsSize;
|
||||||
|
*aAttrs = rawSearchAttrs;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
// parse and process a formatting attribute. If aStringArray is
|
||||||
|
// non-NULL, return a list of the attributes from mNameFormat in
|
||||||
|
// aStringArray. Otherwise, generate an autocomplete value from the
|
||||||
|
// information in aMessage and append it to aValue. Any errors
|
||||||
|
// (including failure to find a required attribute while building up aValue)
|
||||||
|
// return an NS_ERROR_* up the stack so that the caller doesn't try and
|
||||||
|
// generate an nsIAutoCompleteItem from this.
|
||||||
|
//
|
||||||
|
nsresult
|
||||||
|
nsAbLDAPAutoCompFormatter::ProcessFormat(const nsAReadableString & aFormat,
|
||||||
|
nsILDAPMessage *aMessage,
|
||||||
|
nsAWritableCString *aValue,
|
||||||
|
nsCStringArray *aAttrs)
|
||||||
|
{
|
||||||
|
nsresult rv; // temp for return values
|
||||||
|
|
||||||
|
// get some iterators to parse aFormat
|
||||||
|
//
|
||||||
|
nsReadingIterator<PRUnichar> iter, iterEnd;
|
||||||
|
aFormat.BeginReading(iter);
|
||||||
|
aFormat.EndReading(iterEnd);
|
||||||
|
|
||||||
|
// get the console service for error logging
|
||||||
|
//
|
||||||
|
nsCOMPtr<nsIConsoleService> consoleSvc =
|
||||||
|
do_GetService("@mozilla.org/consoleservice;1", &rv);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_WARNING("nsAbLDAPAutoCompFormatter::ProcessFormat(): "
|
||||||
|
"couldn't get console service");
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool attrRequired = PR_FALSE; // is this attr required or optional?
|
||||||
|
nsCAutoString attrName; // current attr to get
|
||||||
|
|
||||||
|
// parse until we hit the end of the string
|
||||||
|
//
|
||||||
|
while (iter != iterEnd) {
|
||||||
|
|
||||||
|
switch (*iter) { // process the next char
|
||||||
|
|
||||||
|
case PRUnichar('{'):
|
||||||
|
|
||||||
|
attrRequired = PR_TRUE; // this attribute is required
|
||||||
|
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
|
||||||
|
case PRUnichar('['):
|
||||||
|
|
||||||
|
rv = ParseAttrName(iter, iterEnd, attrRequired, consoleSvc,
|
||||||
|
attrName);
|
||||||
|
if ( NS_FAILED(rv) ) {
|
||||||
|
|
||||||
|
// something unrecoverable happened; stop parsing and
|
||||||
|
// propagate the error up the stack
|
||||||
|
//
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we're building an array
|
||||||
|
if ( aAttrs ) {
|
||||||
|
|
||||||
|
// and it doesn't already contain this string
|
||||||
|
if (aAttrs->IndexOfIgnoreCase(attrName) == -1) {
|
||||||
|
|
||||||
|
// add it
|
||||||
|
if (!aAttrs->AppendCString(attrName)) {
|
||||||
|
|
||||||
|
// current AppendCString always returns PR_TRUE;
|
||||||
|
// if we hit this error, something has changed in
|
||||||
|
// that code
|
||||||
|
//
|
||||||
|
NS_ERROR(
|
||||||
|
"nsAbLDAPAutoCompFormatter::ProcessFormat():"
|
||||||
|
" aAttrs->AppendCString(attrName) failed");
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// otherwise, append the first value of this attr to aValue
|
||||||
|
// XXXdmose should do better than this; bug 76595
|
||||||
|
|
||||||
|
rv = AppendFirstAttrValue(attrName, aMessage, attrRequired,
|
||||||
|
*aValue);
|
||||||
|
if ( NS_FAILED(rv) ) {
|
||||||
|
|
||||||
|
// something unrecoverable happened; stop parsing and
|
||||||
|
// propagate the error up the stack
|
||||||
|
//
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attrName.Truncate(); // clear out for next pass
|
||||||
|
attrRequired = PR_FALSE; // reset to the default for the next pass
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRUnichar('\\'):
|
||||||
|
|
||||||
|
// advance the iterator and be sure we haven't run off the end
|
||||||
|
//
|
||||||
|
++iter;
|
||||||
|
if (iter == iterEnd) {
|
||||||
|
|
||||||
|
// abort; missing escaped char
|
||||||
|
//
|
||||||
|
if (consoleSvc) {
|
||||||
|
consoleSvc->LogStringMessage(
|
||||||
|
NS_LITERAL_STRING(
|
||||||
|
"LDAP addressbook autocomplete formatter: error parsing format string: premature end of string after \\ escape").get());
|
||||||
|
|
||||||
|
NS_ERROR("LDAP addressbook autocomplete formatter: error "
|
||||||
|
"parsing format string: premature end of string "
|
||||||
|
"after \\ escape");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*FALLTHROUGH*/
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
// if we're not just building an array of attribute names, append
|
||||||
|
// this character to the item we're generating.
|
||||||
|
//
|
||||||
|
if (!aAttrs) {
|
||||||
|
|
||||||
|
// this character gets treated as a literal
|
||||||
|
//
|
||||||
|
(*aValue).Append(NS_STATIC_CAST(char, *iter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++iter; // advance the iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsAbLDAPAutoCompFormatter::ParseAttrName(
|
||||||
|
nsReadingIterator<PRUnichar> &aIter, // iterators for mOutputString
|
||||||
|
nsReadingIterator<PRUnichar> &aIterEnd,
|
||||||
|
PRBool aAttrRequired, // required? or just optional?
|
||||||
|
nsCOMPtr<nsIConsoleService> &aConsoleSvc, // no need to reacquire this
|
||||||
|
nsAWritableCString &aAttrName) // attribute token
|
||||||
|
{
|
||||||
|
// reset attrname, and move past the opening brace
|
||||||
|
//
|
||||||
|
++aIter;
|
||||||
|
|
||||||
|
// get the rest of the attribute name
|
||||||
|
//
|
||||||
|
do {
|
||||||
|
|
||||||
|
// be sure we haven't run off the end
|
||||||
|
//
|
||||||
|
if (aIter == aIterEnd) {
|
||||||
|
|
||||||
|
// abort; missing closing delimiter
|
||||||
|
//
|
||||||
|
if (aConsoleSvc) {
|
||||||
|
aConsoleSvc->LogStringMessage(
|
||||||
|
NS_LITERAL_STRING(
|
||||||
|
"LDAP address book autocomplete formatter: error parsing format string: missing } or ]").get());
|
||||||
|
|
||||||
|
NS_ERROR("LDAP address book autocomplete formatter: error "
|
||||||
|
"parsing format string: missing } or ]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_ERROR_ILLEGAL_VALUE;
|
||||||
|
|
||||||
|
} else if ( (aAttrRequired && *aIter == PRUnichar('}')) ||
|
||||||
|
(!aAttrRequired && *aIter == PRUnichar(']')) ) {
|
||||||
|
|
||||||
|
// done with this attribute
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// this must be part of the attribute name
|
||||||
|
//
|
||||||
|
aAttrName.Append(NS_STATIC_CAST(char,*aIter));
|
||||||
|
}
|
||||||
|
|
||||||
|
++aIter;
|
||||||
|
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsAbLDAPAutoCompFormatter::AppendFirstAttrValue(
|
||||||
|
nsAReadableCString &aAttrName, // attr to get
|
||||||
|
nsILDAPMessage *aMessage, // msg to get values from
|
||||||
|
PRBool aAttrRequired, // is this a required value?
|
||||||
|
nsAWritableCString &aValue)
|
||||||
|
{
|
||||||
|
// get the attribute values for the field which will be used
|
||||||
|
// to fill in nsIAutoCompleteItem::value
|
||||||
|
//
|
||||||
|
PRUint32 numVals;
|
||||||
|
PRUnichar **values;
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
rv = aMessage->GetValues(PromiseFlatCString(aAttrName).get(), &numVals,
|
||||||
|
&values);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
|
||||||
|
switch (rv) {
|
||||||
|
case NS_ERROR_LDAP_DECODING_ERROR:
|
||||||
|
// this may not be an error, per se; it could just be that the
|
||||||
|
// requested attribute does not exist in this particular message,
|
||||||
|
// either because we didn't request it with the search operation,
|
||||||
|
// or because it doesn't exist on the server.
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NS_ERROR_OUT_OF_MEMORY:
|
||||||
|
case NS_ERROR_UNEXPECTED:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NS_ERROR("nsLDAPAutoCompleteSession::OnLDAPSearchEntry(): "
|
||||||
|
"unexpected return code from aMessage->getValues()");
|
||||||
|
rv = NS_ERROR_UNEXPECTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this was a required attribute, don't append anything to aValue
|
||||||
|
// and return the error code
|
||||||
|
//
|
||||||
|
if (aAttrRequired) {
|
||||||
|
return rv;
|
||||||
|
} else {
|
||||||
|
// otherwise forget about this attribute, but return NS_OK, which
|
||||||
|
// will cause our caller to continue processing nameFormat in
|
||||||
|
// order to generate an nsIAutoCompleteItem.
|
||||||
|
//
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// append the value to our string; then free the array of results
|
||||||
|
//
|
||||||
|
aValue.Append(NS_ConvertUCS2toUTF8(values[0]));
|
||||||
|
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(numVals, values);
|
||||||
|
|
||||||
|
// if this attribute wasn't required, we fall through to here, and return
|
||||||
|
// ok
|
||||||
|
//
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// attribute AString nameFormat;
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAbLDAPAutoCompFormatter::GetNameFormat(nsAWritableString & aNameFormat)
|
||||||
|
{
|
||||||
|
aNameFormat = mNameFormat;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAbLDAPAutoCompFormatter::SetNameFormat(const nsAReadableString & aNameFormat)
|
||||||
|
{
|
||||||
|
mNameFormat = aNameFormat;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// attribute AString addressFormat;
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAbLDAPAutoCompFormatter::GetAddressFormat(nsAWritableString & aAddressFormat)
|
||||||
|
{
|
||||||
|
aAddressFormat = mAddressFormat;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAbLDAPAutoCompFormatter::SetAddressFormat(const nsAReadableString &
|
||||||
|
aAddressFormat)
|
||||||
|
{
|
||||||
|
mAddressFormat = aAddressFormat;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// attribute AString commentFormat;
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAbLDAPAutoCompFormatter::GetCommentFormat(nsAWritableString & aCommentFormat)
|
||||||
|
{
|
||||||
|
aCommentFormat = mCommentFormat;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsAbLDAPAutoCompFormatter::SetCommentFormat(const nsAReadableString &
|
||||||
|
aCommentFormat)
|
||||||
|
{
|
||||||
|
mCommentFormat = aCommentFormat;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,64 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 2001 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): Dan Mosedale <dmose@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsIAbLDAPAutoCompFormatter.h"
|
||||||
|
#include "nsIConsoleService.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsVoidArray.h"
|
||||||
|
|
||||||
|
class nsAbLDAPAutoCompFormatter : public nsIAbLDAPAutoCompFormatter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSILDAPAUTOCOMPFORMATTER
|
||||||
|
NS_DECL_NSIABLDAPAUTOCOMPFORMATTER
|
||||||
|
|
||||||
|
nsAbLDAPAutoCompFormatter();
|
||||||
|
virtual ~nsAbLDAPAutoCompFormatter();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nsString mNameFormat; // how to format these pieces
|
||||||
|
nsString mAddressFormat;
|
||||||
|
nsString mCommentFormat;
|
||||||
|
|
||||||
|
// parse and process format
|
||||||
|
nsresult ProcessFormat(const nsAReadableString & aFormat,
|
||||||
|
nsILDAPMessage *aMessage,
|
||||||
|
nsAWritableCString *aValue,
|
||||||
|
nsCStringArray *aAttrs);
|
||||||
|
|
||||||
|
// process a single attribute while parsing format
|
||||||
|
nsresult ParseAttrName(nsReadingIterator<PRUnichar> & aIter,
|
||||||
|
nsReadingIterator<PRUnichar> & aIterEnd,
|
||||||
|
PRBool aAttrRequired,
|
||||||
|
nsCOMPtr<nsIConsoleService> & aConsoleSvc,
|
||||||
|
nsAWritableCString & aAttrName);
|
||||||
|
|
||||||
|
// append the first value associated with aAttrName in aMessage to aValue
|
||||||
|
nsresult AppendFirstAttrValue(nsAReadableCString &aAttrName,
|
||||||
|
nsILDAPMessage *aMessage,
|
||||||
|
PRBool aAttrRequired,
|
||||||
|
nsAWritableCString &aValue);
|
||||||
|
};
|
||||||
|
|
|
@ -519,7 +519,13 @@ var messageComposeOfflineObserver = {
|
||||||
else
|
else
|
||||||
isOffline = false;
|
isOffline = false;
|
||||||
MessageComposeOfflineStateChanged(isOffline);
|
MessageComposeOfflineStateChanged(isOffline);
|
||||||
setupLdapAutocompleteSession();
|
|
||||||
|
try {
|
||||||
|
setupLdapAutocompleteSession();
|
||||||
|
} catch (ex) {
|
||||||
|
// catch the exception and ignore it, so that if LDAP setup
|
||||||
|
// fails, the entire compose window stuff doesn't get aborted
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,7 +566,12 @@ function MessageComposeOfflineStateChanged(goingOffline)
|
||||||
|
|
||||||
var directoryServerObserver = {
|
var directoryServerObserver = {
|
||||||
Observe: function(subject, topic, value) {
|
Observe: function(subject, topic, value) {
|
||||||
setupLdapAutocompleteSession();
|
try {
|
||||||
|
setupLdapAutocompleteSession();
|
||||||
|
} catch (ex) {
|
||||||
|
// catch the exception and ignore it, so that if LDAP setup
|
||||||
|
// fails, the entire compose window doesn't get horked
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,31 +616,33 @@ function RemoveDirectorySettingsObserver(prefstring)
|
||||||
|
|
||||||
function setupLdapAutocompleteSession()
|
function setupLdapAutocompleteSession()
|
||||||
{
|
{
|
||||||
gSetupLdapAutocomplete = true;
|
|
||||||
var autocompleteLdap = false;
|
var autocompleteLdap = false;
|
||||||
var autocompleteDirectory = null;
|
var autocompleteDirectory = null;
|
||||||
var prevAutocompleteDirectory = currentAutocompleteDirectory;
|
var prevAutocompleteDirectory = currentAutocompleteDirectory;
|
||||||
|
|
||||||
try {
|
autocompleteLdap = prefs.GetBoolPref("ldap_2.autoComplete.useDirectory");
|
||||||
autocompleteLdap = prefs.GetBoolPref(
|
if (autocompleteLdap)
|
||||||
"ldap_2.autoComplete.useDirectory");
|
autocompleteDirectory = prefs.CopyCharPref(
|
||||||
if (autocompleteLdap)
|
"ldap_2.autoComplete.directoryServer");
|
||||||
autocompleteDirectory = prefs.CopyCharPref(
|
|
||||||
"ldap_2.autoComplete.directoryServer");
|
|
||||||
} catch(ex) {
|
|
||||||
dump("ERROR: " + ex + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(gCurrentIdentity.overrideGlobalPref) {
|
if(gCurrentIdentity.overrideGlobalPref) {
|
||||||
autocompleteDirectory = gCurrentIdentity.directoryServer;
|
autocompleteDirectory = gCurrentIdentity.directoryServer;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
if (!gLDAPSession)
|
// use a temporary to do the setup so that we don't overwrite the
|
||||||
gLDAPSession = Components.classes["@mozilla.org/autocompleteSession;1?type=ldap"].createInstance()
|
// global, then have some problem and throw an exception, and leave the
|
||||||
.QueryInterface(Components.interfaces.nsILDAPAutoCompleteSession);
|
// global with a partially setup session. we'll assign the temp
|
||||||
} catch (ex) {
|
// into the global after we're done setting up the session
|
||||||
dump ("ERROR:" + ex + "\n");
|
//
|
||||||
|
var LDAPSession;
|
||||||
|
if (gLDAPSession) {
|
||||||
|
LDAPSession = gLDAPSession;
|
||||||
|
} else {
|
||||||
|
LDAPSession = Components.classes[
|
||||||
|
"@mozilla.org/autocompleteSession;1?type=ldap"].createInstance()
|
||||||
|
.QueryInterface(Components.interfaces.nsILDAPAutoCompleteSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autocompleteDirectory && !isOffline) {
|
if (autocompleteDirectory && !isOffline) {
|
||||||
// Add observer on the directory server we are autocompleting against
|
// Add observer on the directory server we are autocompleting against
|
||||||
// only if current server is different from previous.
|
// only if current server is different from previous.
|
||||||
|
@ -643,13 +656,10 @@ function setupLdapAutocompleteSession()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
AddDirectorySettingsObserver();
|
AddDirectorySettingsObserver();
|
||||||
if (gLDAPSession) {
|
|
||||||
if (!sessionAdded) {
|
// fill in the session params if there is a session
|
||||||
// add session for all the recipients
|
//
|
||||||
for (var i=1; i <= MAX_RECIPIENTS; i++)
|
if (LDAPSession) {
|
||||||
document.getElementById("msgRecipient#" + i).addSession(gLDAPSession);
|
|
||||||
sessionAdded = true;
|
|
||||||
}
|
|
||||||
var serverURL = Components.classes[
|
var serverURL = Components.classes[
|
||||||
"@mozilla.org/network/ldap-url;1"].
|
"@mozilla.org/network/ldap-url;1"].
|
||||||
createInstance().QueryInterface(
|
createInstance().QueryInterface(
|
||||||
|
@ -661,22 +671,69 @@ function setupLdapAutocompleteSession()
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
dump("ERROR: " + ex + "\n");
|
dump("ERROR: " + ex + "\n");
|
||||||
}
|
}
|
||||||
gLDAPSession.serverURL = serverURL;
|
LDAPSession.serverURL = serverURL;
|
||||||
|
|
||||||
// don't search on strings shorter than this
|
// don't search on strings shorter than this
|
||||||
//
|
//
|
||||||
try {
|
try {
|
||||||
gLDAPSession.minStringLength = prefs.GetIntPref(
|
LDAPSession.minStringLength = prefs.GetIntPref(
|
||||||
autocompleteDirectory + ".autoComplete.minStringLength");
|
autocompleteDirectory + ".autoComplete.minStringLength");
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
// if this pref isn't there, no big deal. just let
|
// if this pref isn't there, no big deal. just let
|
||||||
// nsLDAPAutoCompleteSession use its default.
|
// nsLDAPAutoCompleteSession use its default.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we don't try/catch here, because if this fails, we're outta luck
|
||||||
|
//
|
||||||
|
var ldapFormatter = Components.classes[
|
||||||
|
"@mozilla.org/ldap-autocomplete-formatter;1?type=addrbook"]
|
||||||
|
.createInstance().QueryInterface(
|
||||||
|
Components.interfaces.nsIAbLDAPAutoCompFormatter);
|
||||||
|
|
||||||
|
// override autocomplete name format?
|
||||||
|
//
|
||||||
|
try {
|
||||||
|
ldapFormatter.nameFormat =
|
||||||
|
prefs.CopyUnicharPref(autocompleteDirectory +
|
||||||
|
".autoComplete.nameFormat");
|
||||||
|
} catch (ex) {
|
||||||
|
// if this pref isn't there, no big deal. just let
|
||||||
|
// nsAbLDAPAutoCompFormatter use its default.
|
||||||
|
}
|
||||||
|
|
||||||
|
// override autocomplete mail address format?
|
||||||
|
//
|
||||||
|
try {
|
||||||
|
ldapFormatter.addressFormat =
|
||||||
|
prefs.CopyUnicharPref(autocompleteDirectory +
|
||||||
|
".autoComplete.addressFormat");
|
||||||
|
} catch (ex) {
|
||||||
|
// if this pref isn't there, no big deal. just let
|
||||||
|
// nsAbLDAPAutoCompFormatter use its default.
|
||||||
|
}
|
||||||
|
|
||||||
|
// override autocomplete entry comment format?
|
||||||
|
//
|
||||||
|
try {
|
||||||
|
ldapFormatter.commentFormat =
|
||||||
|
prefs.CopyUnicharPref(autocompleteDirectory +
|
||||||
|
".autoComplete.commentFormat");
|
||||||
|
} catch (ex) {
|
||||||
|
// if this pref isn't there, no big deal. just let
|
||||||
|
// nsAbLDAPAutoCompFormatter use its default.
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the session's formatter, which also happens to
|
||||||
|
// force a call to the formatter's getAttributes() method
|
||||||
|
// -- which is why this needs to happen after we've set the
|
||||||
|
// various formats
|
||||||
|
//
|
||||||
|
LDAPSession.formatter = ldapFormatter;
|
||||||
|
|
||||||
// override autocomplete entry formatting?
|
// override autocomplete entry formatting?
|
||||||
//
|
//
|
||||||
try {
|
try {
|
||||||
gLDAPSession.outputFormat =
|
LDAPSession.outputFormat =
|
||||||
prefs.CopyUnicharPref(autocompleteDirectory +
|
prefs.CopyUnicharPref(autocompleteDirectory +
|
||||||
".autoComplete.outputFormat");
|
".autoComplete.outputFormat");
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
|
@ -687,26 +744,35 @@ function setupLdapAutocompleteSession()
|
||||||
// override default search filter template?
|
// override default search filter template?
|
||||||
//
|
//
|
||||||
try {
|
try {
|
||||||
gLDAPSession.filterTemplate = prefs.CopyUnicharPref(
|
LDAPSession.filterTemplate = prefs.CopyUnicharPref(
|
||||||
autocompleteDirectory + ".autoComplete.filterTemplate");
|
autocompleteDirectory + ".autoComplete.filterTemplate");
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
// if this pref isn't there, no big deal. just let
|
// if this pref isn't there, no big deal. just let
|
||||||
// nsLDAPAutoCompleteSession use its default
|
// nsLDAPAutoCompleteSession use its default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// override default maxHits (currently 100)
|
// override default maxHits (currently 100)
|
||||||
//
|
//
|
||||||
try {
|
try {
|
||||||
// XXXdmose should really use .autocomplete.maxHits,
|
// XXXdmose should really use .autocomplete.maxHits,
|
||||||
// but there's no UI for that yet
|
// but there's no UI for that yet
|
||||||
//
|
//
|
||||||
gLDAPSession.maxHits =
|
LDAPSession.maxHits =
|
||||||
prefs.GetIntPref(autocompleteDirectory + ".maxHits");
|
prefs.GetIntPref(autocompleteDirectory + ".maxHits");
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
// if this pref isn't there, or is out of range, no big deal.
|
// if this pref isn't there, or is out of range, no big deal.
|
||||||
// just let nsLDAPAutoCompleteSession use its default.
|
// just let nsLDAPAutoCompleteSession use its default.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sessionAdded) {
|
||||||
|
// if we make it here, we know that session initialization has
|
||||||
|
// succeeded; add the session for all recipients, and
|
||||||
|
// remember that we've done so
|
||||||
|
for (var i=1; i <= MAX_RECIPIENTS; i++)
|
||||||
|
document.getElementById("msgRecipient#" + i).
|
||||||
|
addSession(LDAPSession);
|
||||||
|
sessionAdded = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (currentAutocompleteDirectory) {
|
if (currentAutocompleteDirectory) {
|
||||||
|
@ -717,10 +783,14 @@ function setupLdapAutocompleteSession()
|
||||||
}
|
}
|
||||||
if (gLDAPSession && sessionAdded) {
|
if (gLDAPSession && sessionAdded) {
|
||||||
for (var i=1; i <= MAX_RECIPIENTS; i++)
|
for (var i=1; i <= MAX_RECIPIENTS; i++)
|
||||||
document.getElementById("msgRecipient#" + i).removeSession(gLDAPSession);
|
document.getElementById("msgRecipient#" + i).
|
||||||
|
removeSession(gLDAPSession);
|
||||||
sessionAdded = false;
|
sessionAdded = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gLDAPSession = LDAPSession;
|
||||||
|
gSetupLdapAutocomplete = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DoCommandClose()
|
function DoCommandClose()
|
||||||
|
@ -1983,8 +2053,14 @@ function LoadIdentity(startup)
|
||||||
}
|
}
|
||||||
|
|
||||||
AddDirectoryServerObserver(false);
|
AddDirectoryServerObserver(false);
|
||||||
if (!startup)
|
if (!startup) {
|
||||||
setupLdapAutocompleteSession();
|
try {
|
||||||
|
setupLdapAutocompleteSession();
|
||||||
|
} catch (ex) {
|
||||||
|
// catch the exception and ignore it, so that if LDAP setup
|
||||||
|
// fails, the entire compose window doesn't end up horked
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2003,8 +2079,14 @@ function setupAutocomplete()
|
||||||
gAutocompleteSession = 1;
|
gAutocompleteSession = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!gSetupLdapAutocomplete)
|
if (!gSetupLdapAutocomplete) {
|
||||||
setupLdapAutocompleteSession();
|
try {
|
||||||
|
setupLdapAutocompleteSession();
|
||||||
|
} catch (ex) {
|
||||||
|
// catch the exception and ignore it, so that if LDAP setup
|
||||||
|
// fails, the entire compose window doesn't end up horked
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function subjectKeyPress(event)
|
function subjectKeyPress(event)
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
nsIAutoCompleteSession.idl
|
|
||||||
nsILDAPAutoCompleteSession.idl
|
|
|
@ -37,7 +37,10 @@ XPIDLSRCS = \
|
||||||
|
|
||||||
ifdef MOZ_LDAP_XPCOM
|
ifdef MOZ_LDAP_XPCOM
|
||||||
REQUIRES += mozldap necko
|
REQUIRES += mozldap necko
|
||||||
XPIDLSRCS += nsILDAPAutoCompleteSession.idl
|
XPIDLSRCS += \
|
||||||
|
nsILDAPAutoCompleteSession.idl \
|
||||||
|
nsILDAPAutoCompFormatter.idl \
|
||||||
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
|
@ -32,6 +32,7 @@ XPIDLSRCS=\
|
||||||
.\nsIAutoCompleteResults.idl \
|
.\nsIAutoCompleteResults.idl \
|
||||||
.\nsIAutoCompleteSession.idl \
|
.\nsIAutoCompleteSession.idl \
|
||||||
!if !defined(DISABLE_LDAP)
|
!if !defined(DISABLE_LDAP)
|
||||||
|
.\nsILDAPAutoCompFormatter.idl \
|
||||||
.\nsILDAPAutoCompleteSession.idl \
|
.\nsILDAPAutoCompleteSession.idl \
|
||||||
!endif
|
!endif
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is mozilla.org code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape
|
||||||
|
* Communications Corporation. Portions created by Netscape are
|
||||||
|
* Copyright (C) 2001 Netscape Communications Corporation. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): Dan Mosedale <dmose@netscape.com> (Original Author)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nsISupports.idl"
|
||||||
|
#include "nsILDAPMessage.idl"
|
||||||
|
|
||||||
|
interface nsIAutoCompleteItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface to allow different users of nsILDAPAutoCompleteSession to
|
||||||
|
* format each nsILDAPMessage into an nsIAutoCompleteItem as it sees fit.
|
||||||
|
*/
|
||||||
|
[scriptable, uuid(cbec617c-22d2-4286-8308-0ef8bf57c0ce)]
|
||||||
|
interface nsILDAPAutoCompFormatter : nsISupports {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an nsIAutoCompleteItem generated from the data in
|
||||||
|
* the given nsILDAPMessage.
|
||||||
|
*
|
||||||
|
* @param aMessage message to be formatted
|
||||||
|
* @return resulting nsIAutoCompleteItem
|
||||||
|
*/
|
||||||
|
nsIAutoCompleteItem format(in nsILDAPMessage aMessage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of all the LDAP attributes that should be requested
|
||||||
|
* from the LDAP server when a lookup is done. This avoids
|
||||||
|
* wasting server time, bandwidth, and client time processing
|
||||||
|
* unused attributes.
|
||||||
|
*
|
||||||
|
* Note that this is only required to be called by the
|
||||||
|
* nsILDAPAutoCompleteSession implementation when the
|
||||||
|
* nsILDAPAutoCompleteSession::formatter IDL attribute is set. .
|
||||||
|
* So if for some reason, the LDAP attributes to be returned by
|
||||||
|
* searches has to change (eg because the user changed a
|
||||||
|
* preference), the nsILDAPAutoCompleteSession::formatter IDL
|
||||||
|
* attribute should be re-set to the same object to force a new
|
||||||
|
* getAttributes() call.
|
||||||
|
*
|
||||||
|
* @param aCount number of attributes in the array
|
||||||
|
* @param aAttrs list of LDAP attributes to request
|
||||||
|
*/
|
||||||
|
void getAttributes(out unsigned long aCount,
|
||||||
|
[retval, array, size_is(aCount)] out string aAttrs);
|
||||||
|
};
|
|
@ -23,7 +23,10 @@
|
||||||
|
|
||||||
#include "nsIAutoCompleteSession.idl"
|
#include "nsIAutoCompleteSession.idl"
|
||||||
|
|
||||||
interface nsILDAPURL; // forward decl
|
// forward decls
|
||||||
|
//
|
||||||
|
interface nsILDAPURL;
|
||||||
|
interface nsILDAPAutoCompFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends nsIAutoCompleteSession to have various LDAP-specific parameters.
|
* Extends nsIAutoCompleteSession to have various LDAP-specific parameters.
|
||||||
|
@ -50,32 +53,6 @@ interface nsILDAPAutoCompleteSession : nsIAutoCompleteSession {
|
||||||
*/
|
*/
|
||||||
attribute wstring filterTemplate;
|
attribute wstring filterTemplate;
|
||||||
|
|
||||||
/**
|
|
||||||
* A template string for formatting the autocompletion results.
|
|
||||||
*
|
|
||||||
* Required attributes are delimited by curly braces, and optional
|
|
||||||
* attributes are determined by brackets. Backslash escapes any
|
|
||||||
* character, including itself.
|
|
||||||
*
|
|
||||||
* If outputFormat is not set, or is set to the empty string,
|
|
||||||
* the component implementing this interface should set the outputFormat
|
|
||||||
* to a reasonable default.
|
|
||||||
*
|
|
||||||
* As an example, the "@mozilla.org/autocompleteSession;1?type=ldap"
|
|
||||||
* implementation currently happens to use a default of "[cn] <{mail}>",
|
|
||||||
* without the quotes. This will generate autocomplete items of the
|
|
||||||
* form "John Doe <john.doe@foo.com>", or, if the cn is not found,
|
|
||||||
* " <john.doe@foo.com>". This latter form is suboptimal, in that
|
|
||||||
* the space and angle brackets are a bit ugly, but should work as an
|
|
||||||
* email address. See bug 81961.
|
|
||||||
*
|
|
||||||
* @exception NS_ERROR_NULL_POINTER getter: NULL pointer passed in
|
|
||||||
* @exception NS_ERROR_OUT_OF_MEMORY getter/setter: allocation error
|
|
||||||
* @exception NS_ERROR_ILLEGAL_VALUE setter: invalid template specified
|
|
||||||
* @exception NS_ERROR_UNEXPECTED setter: probably a bug
|
|
||||||
*/
|
|
||||||
attribute wstring outputFormat;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* At most this many nsIAutoCompleteItems will be returned. This
|
* At most this many nsIAutoCompleteItems will be returned. This
|
||||||
* is useful for keeping bandwidth usage over slow-speed
|
* is useful for keeping bandwidth usage over slow-speed
|
||||||
|
@ -112,4 +89,10 @@ interface nsILDAPAutoCompleteSession : nsIAutoCompleteSession {
|
||||||
* @exception NS_ERROR_NULL_POINTER NULL pointer passed to getter
|
* @exception NS_ERROR_NULL_POINTER NULL pointer passed to getter
|
||||||
*/
|
*/
|
||||||
attribute nsILDAPURL serverURL;
|
attribute nsILDAPURL serverURL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback used to format an individual LDAP message into an
|
||||||
|
* nsIAutoCompleteItem.
|
||||||
|
*/
|
||||||
|
attribute nsILDAPAutoCompFormatter formatter;
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,19 +117,8 @@ nsLDAPAutoCompleteSession::OnStartLookup(const PRUnichar *searchString,
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if mOutputFormat is unset, set it to our default, using the
|
NS_ASSERTION(mFormatter, "nsLDAPAutoCompleteSession::OnStartLookup(): "
|
||||||
// XPCOM setter so that the internal array will be built up
|
"formatter attribute has not been set");
|
||||||
//
|
|
||||||
if (mOutputFormat.IsEmpty()) {
|
|
||||||
rv = SetOutputFormat(NS_LITERAL_STRING("[cn] <{mail}>").get());
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
// if we got here, we've either hit a bug or run out of memory
|
|
||||||
// in either case, we're screwed. In a debug build, something
|
|
||||||
// will have already been logged. Time to bail out.
|
|
||||||
FinishAutoCompleteLookup(nsIAutoCompleteStatus::failed);
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// see if this is a narrow search that we could potentially do locally
|
// see if this is a narrow search that we could potentially do locally
|
||||||
//
|
//
|
||||||
|
@ -461,8 +450,6 @@ nsLDAPAutoCompleteSession::OnLDAPBind(nsILDAPMessage *aMessage)
|
||||||
nsresult
|
nsresult
|
||||||
nsLDAPAutoCompleteSession::OnLDAPSearchEntry(nsILDAPMessage *aMessage)
|
nsLDAPAutoCompleteSession::OnLDAPSearchEntry(nsILDAPMessage *aMessage)
|
||||||
{
|
{
|
||||||
nsresult rv; // temporary for return vals
|
|
||||||
|
|
||||||
PR_LOG(sLDAPAutoCompleteLogModule, PR_LOG_DEBUG,
|
PR_LOG(sLDAPAutoCompleteLogModule, PR_LOG_DEBUG,
|
||||||
("nsLDAPAutoCompleteSession::OnLDAPSearchEntry entered\n"));
|
("nsLDAPAutoCompleteSession::OnLDAPSearchEntry entered\n"));
|
||||||
|
|
||||||
|
@ -473,43 +460,22 @@ nsLDAPAutoCompleteSession::OnLDAPSearchEntry(nsILDAPMessage *aMessage)
|
||||||
"nsLDAPAutoCompleteSession::OnLDAPSearchEntry(): "
|
"nsLDAPAutoCompleteSession::OnLDAPSearchEntry(): "
|
||||||
"mResultsArrayItems is uninitialized");
|
"mResultsArrayItems is uninitialized");
|
||||||
|
|
||||||
nsAutoString value;
|
// Errors in this method return an error (which ultimately gets
|
||||||
rv = ProcessOutputFormat(mOutputFormat, aMessage, &value, 0);
|
// ignored, since this is being called through an async proxy).
|
||||||
if (NS_FAILED(rv)) {
|
// But the important thing is that we're bailing out here rather
|
||||||
// Something went wrong lower down the stack; a message should have
|
// than trying to generate a bogus nsIAutoCompleteItem. Also note
|
||||||
// already been logged there. Return an error (which ultimately gets
|
// that FinishAutoCompleteLookup is _NOT_ being called here, because
|
||||||
// ignored, since this is being called through an async proxy). But
|
// this error may just have to do with this particular item.
|
||||||
// the important thing is that we're bailing out here rather than
|
|
||||||
// trying to generate a bogus nsIAutoCompleteItem
|
|
||||||
//
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create an nsIAutoCompleteItem to hold the returned value
|
// generate an autocomplete item from this message by calling the
|
||||||
|
// formatter
|
||||||
//
|
//
|
||||||
nsCOMPtr<nsIAutoCompleteItem> item = do_CreateInstance(
|
nsCOMPtr<nsIAutoCompleteItem> item;
|
||||||
NS_AUTOCOMPLETEITEM_CONTRACTID, &rv);
|
nsresult rv = mFormatter->Format(aMessage, getter_AddRefs(item));
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
NS_ERROR("nsLDAPAutoCompleteSession::OnLDAPSearchEntry couldn't"
|
PR_LOG(sLDAPAutoCompleteLogModule, PR_LOG_DEBUG,
|
||||||
" create " NS_AUTOCOMPLETEITEM_CONTRACTID "\n");
|
("nsLDAPAutoCompleteSession::OnLDAPSearchEntry(): "
|
||||||
|
"mFormatter->Format() failed"));
|
||||||
// don't call FinishAutoCompleteLookup(), as this could conceivably
|
|
||||||
// be an anomaly, and perhaps the next message will be ok. if this
|
|
||||||
// really was a problem, this search should eventually get
|
|
||||||
// reaped by a timeout (once that code gets implemented).
|
|
||||||
//
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// just use the first value for the email attribute; subsequent values
|
|
||||||
// are ignored. XXXdmose should do better than this; bug 76595.
|
|
||||||
//
|
|
||||||
rv = item->SetValue(value);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
NS_ERROR("nsLDAPAutoCompleteSession::OnLDAPSearchEntry(): "
|
|
||||||
"item->SetValue failed");
|
|
||||||
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,267 +493,6 @@ nsLDAPAutoCompleteSession::OnLDAPSearchEntry(nsILDAPMessage *aMessage)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse and process the outputFormat attribute. If aStringArray is
|
|
||||||
// non-NULL, return a list of the attributes from mOutputFormat in
|
|
||||||
// aStringArray. Otherwise, generate an autocomplete value from the
|
|
||||||
// information in aMessage and append it to aValue. Any errors
|
|
||||||
// (including failure to find a required attribute while building up aValue)
|
|
||||||
// return an NS_ERROR_* up the stack so that the caller doesn't try and
|
|
||||||
// generate an nsIAutoCompleteItem from this.
|
|
||||||
//
|
|
||||||
nsresult
|
|
||||||
nsLDAPAutoCompleteSession::ProcessOutputFormat(
|
|
||||||
nsAReadableString &aOutputFormat, nsILDAPMessage *aMessage,
|
|
||||||
nsAWritableString *aValue, nsCStringArray *aAttrs)
|
|
||||||
{
|
|
||||||
nsresult rv; // temp for return values
|
|
||||||
|
|
||||||
// get some iterators to parse aOutputFormat
|
|
||||||
//
|
|
||||||
nsReadingIterator<PRUnichar> iter, iterEnd;
|
|
||||||
aOutputFormat.BeginReading(iter);
|
|
||||||
aOutputFormat.EndReading(iterEnd);
|
|
||||||
|
|
||||||
// get the console service for error logging
|
|
||||||
//
|
|
||||||
nsCOMPtr<nsIConsoleService> consoleSvc =
|
|
||||||
do_GetService("@mozilla.org/consoleservice;1", &rv);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
NS_WARNING("nsLDAPAutoCompleteSession::ProcessOutputFormat(): "
|
|
||||||
"couldn't get console service");
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool attrRequired = PR_FALSE; // is this attr required or optional?
|
|
||||||
nsCAutoString attrName; // current attr to get
|
|
||||||
|
|
||||||
// parse until we hit the end of the string
|
|
||||||
//
|
|
||||||
while (iter != iterEnd) {
|
|
||||||
|
|
||||||
switch (*iter) { // process the next char
|
|
||||||
|
|
||||||
case PRUnichar('{'):
|
|
||||||
|
|
||||||
attrRequired = PR_TRUE; // this attribute is required
|
|
||||||
|
|
||||||
/*FALLTHROUGH*/
|
|
||||||
|
|
||||||
case PRUnichar('['):
|
|
||||||
|
|
||||||
rv = ParseAttrName(iter, iterEnd, attrRequired, consoleSvc,
|
|
||||||
attrName);
|
|
||||||
if ( NS_FAILED(rv) ) {
|
|
||||||
|
|
||||||
// something unrecoverable happened; stop parsing and
|
|
||||||
// propagate the error up the stack
|
|
||||||
//
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we're building an array
|
|
||||||
if ( aAttrs ) {
|
|
||||||
|
|
||||||
// and it doesn't already contain this string
|
|
||||||
if (aAttrs->IndexOfIgnoreCase(attrName) == -1) {
|
|
||||||
|
|
||||||
// add it
|
|
||||||
if (!aAttrs->AppendCString(attrName)) {
|
|
||||||
|
|
||||||
// current AppendCString always returns PR_TRUE;
|
|
||||||
// if we hit this error, something has changed in
|
|
||||||
// that code
|
|
||||||
//
|
|
||||||
NS_ERROR(
|
|
||||||
"nsLDAPAutoCompleteSession::ProcessOutputFormat():"
|
|
||||||
" aAttrs->AppendCString(attrName) failed");
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// otherwise, append the first value of this attr to aValue
|
|
||||||
|
|
||||||
rv = AppendFirstAttrValue(attrName, aMessage, attrRequired,
|
|
||||||
*aValue);
|
|
||||||
if ( NS_FAILED(rv) ) {
|
|
||||||
|
|
||||||
// something unrecoverable happened; stop parsing and
|
|
||||||
// propagate the error up the stack
|
|
||||||
//
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
attrName.Truncate(); // clear out for next pass
|
|
||||||
attrRequired = PR_FALSE; // reset to the default for the next pass
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PRUnichar('\\'):
|
|
||||||
|
|
||||||
// advance the iterator and be sure we haven't run off the end
|
|
||||||
//
|
|
||||||
++iter;
|
|
||||||
if (iter == iterEnd) {
|
|
||||||
|
|
||||||
// abort; missing escaped char
|
|
||||||
//
|
|
||||||
if (consoleSvc) {
|
|
||||||
consoleSvc->LogStringMessage(
|
|
||||||
NS_LITERAL_STRING(
|
|
||||||
"LDAP autocomplete session: error parsing outputFormat: premature end of string after \\ escape").get());
|
|
||||||
|
|
||||||
NS_ERROR("LDAP autocomplete session: error parsing "
|
|
||||||
"outputFormat: premature end of string after \\ "
|
|
||||||
"escape");
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*FALLTHROUGH*/
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
// if we're not just building an array of attribute names, append
|
|
||||||
// this character to the item we're generating.
|
|
||||||
//
|
|
||||||
if (!aAttrs) {
|
|
||||||
|
|
||||||
// this character gets treated as a literal
|
|
||||||
//
|
|
||||||
(*aValue).Append(*iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++iter; // advance the iterator
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsLDAPAutoCompleteSession::ParseAttrName(
|
|
||||||
nsReadingIterator<PRUnichar> &aIter, // iterators for mOutputString
|
|
||||||
nsReadingIterator<PRUnichar> &aIterEnd,
|
|
||||||
PRBool aAttrRequired, // required? or just optional?
|
|
||||||
nsCOMPtr<nsIConsoleService> &aConsoleSvc, // no need to reacquire this
|
|
||||||
nsAWritableCString &aAttrName) // attribute token
|
|
||||||
{
|
|
||||||
// reset attrname, and move past the opening brace
|
|
||||||
//
|
|
||||||
++aIter;
|
|
||||||
|
|
||||||
// get the rest of the attribute name
|
|
||||||
//
|
|
||||||
do {
|
|
||||||
|
|
||||||
// be sure we haven't run off the end
|
|
||||||
//
|
|
||||||
if (aIter == aIterEnd) {
|
|
||||||
|
|
||||||
// abort; missing closing delimiter
|
|
||||||
//
|
|
||||||
if (aConsoleSvc) {
|
|
||||||
aConsoleSvc->LogStringMessage(
|
|
||||||
NS_LITERAL_STRING(
|
|
||||||
"LDAP autocomplete session: error parsing outputFormat: missing } or ]").get());
|
|
||||||
|
|
||||||
NS_ERROR("LDAP autocomplete session: error parsing "
|
|
||||||
"outputFormat: missing } or ]");
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_ERROR_ILLEGAL_VALUE;
|
|
||||||
|
|
||||||
} else if ( (aAttrRequired && *aIter == PRUnichar('}')) ||
|
|
||||||
(!aAttrRequired && *aIter == PRUnichar(']')) ) {
|
|
||||||
|
|
||||||
// done with this attribute
|
|
||||||
//
|
|
||||||
break;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// this must be part of the attribute name
|
|
||||||
//
|
|
||||||
aAttrName.Append(char(*aIter));
|
|
||||||
}
|
|
||||||
|
|
||||||
++aIter;
|
|
||||||
|
|
||||||
} while (1);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsLDAPAutoCompleteSession::AppendFirstAttrValue(
|
|
||||||
nsAReadableCString &aAttrName, // attr to get
|
|
||||||
nsILDAPMessage *aMessage, // msg to get values from
|
|
||||||
PRBool aAttrRequired, // is this a required value?
|
|
||||||
nsAWritableString &aValue)
|
|
||||||
{
|
|
||||||
// get the attribute values for the field which will be used
|
|
||||||
// to fill in nsIAutoCompleteItem::value
|
|
||||||
//
|
|
||||||
PRUint32 numVals;
|
|
||||||
PRUnichar **values;
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
rv = aMessage->GetValues(PromiseFlatCString(aAttrName).get(), &numVals,
|
|
||||||
&values);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
|
|
||||||
switch (rv) {
|
|
||||||
case NS_ERROR_LDAP_DECODING_ERROR:
|
|
||||||
// this may not be an error, per se; it could just be that the
|
|
||||||
// requested attribute does not exist in this particular message,
|
|
||||||
// either because we didn't request it with the search operation,
|
|
||||||
// or because it doesn't exist on the server.
|
|
||||||
//
|
|
||||||
PR_LOG(sLDAPAutoCompleteLogModule, PR_LOG_WARNING,
|
|
||||||
("nsLDAPAutoCompleteSession::OnLDAPSearchEntry(): "
|
|
||||||
"couldn't decode '%s' attribute",
|
|
||||||
PromiseFlatCString(aAttrName).get()));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NS_ERROR_OUT_OF_MEMORY:
|
|
||||||
case NS_ERROR_UNEXPECTED:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
NS_ERROR("nsLDAPAutoCompleteSession::OnLDAPSearchEntry(): "
|
|
||||||
"unexpected return code from aMessage->getValues()");
|
|
||||||
rv = NS_ERROR_UNEXPECTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this was a required attribute, don't append anything to aValue
|
|
||||||
// and return the error code
|
|
||||||
//
|
|
||||||
if (aAttrRequired) {
|
|
||||||
return rv;
|
|
||||||
} else {
|
|
||||||
// otherwise forget about this attribute, but return NS_OK, which
|
|
||||||
// will cause our caller to continue processing outputFormat in
|
|
||||||
// order to generate an nsIAutoCompleteItem.
|
|
||||||
//
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// append the value to our string; then free the array of results
|
|
||||||
//
|
|
||||||
aValue.Append(values[0]);
|
|
||||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(numVals, values);
|
|
||||||
|
|
||||||
// if this attribute wasn't required, we fall through to here, and return
|
|
||||||
// ok
|
|
||||||
//
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsLDAPAutoCompleteSession::OnLDAPSearchResult(nsILDAPMessage *aMessage)
|
nsLDAPAutoCompleteSession::OnLDAPSearchResult(nsILDAPMessage *aMessage)
|
||||||
{
|
{
|
||||||
|
@ -1315,74 +1020,6 @@ nsLDAPAutoCompleteSession::SetFilterTemplate(const PRUnichar * aFilterTemplate)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// attribute wstring outputFormat;
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsLDAPAutoCompleteSession::GetOutputFormat(PRUnichar * *aOutputFormat)
|
|
||||||
{
|
|
||||||
if (!aOutputFormat) {
|
|
||||||
return NS_ERROR_NULL_POINTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aOutputFormat = mOutputFormat.ToNewUnicode();
|
|
||||||
if (!*aOutputFormat) {
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsLDAPAutoCompleteSession::SetOutputFormat(const PRUnichar * aOutputFormat)
|
|
||||||
{
|
|
||||||
// set up an array of search attributes to be used in any calls to
|
|
||||||
// nsLDAPOperation::SearchExt(). This also allows any errors in
|
|
||||||
// aOutputFormat to be caught sooner, rather than later.
|
|
||||||
//
|
|
||||||
nsCStringArray searchAttrs;
|
|
||||||
nsresult rv = ProcessOutputFormat(nsDependentString(aOutputFormat), 0, 0,
|
|
||||||
&searchAttrs);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
NS_WARNING("nsLDAPAutoCompleteSession::SetOutputFormat(): "
|
|
||||||
"ProcessOutputFormat() failed");
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// build up the raw XPCOM array that we'll be passing to
|
|
||||||
// SearchExt()
|
|
||||||
//
|
|
||||||
PRUint32 count = searchAttrs.Count(); // size of XPCOM array we'll need
|
|
||||||
PRUint32 rawSearchAttrsSize = 0; // grown as XPCOM array is built
|
|
||||||
char **rawSearchAttrs =
|
|
||||||
NS_STATIC_CAST(char **, nsMemory::Alloc(count * sizeof(char *)));
|
|
||||||
if (!rawSearchAttrs) {
|
|
||||||
NS_ERROR("nsLDAPAutoCompleteSession::SetOutputFormat: out of memory");
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through the string array, and build up the C-array.
|
|
||||||
//
|
|
||||||
while (rawSearchAttrsSize < count) {
|
|
||||||
if (!(rawSearchAttrs[rawSearchAttrsSize] =
|
|
||||||
(searchAttrs.CStringAt(rawSearchAttrsSize))->ToNewCString())) {
|
|
||||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(rawSearchAttrsSize,
|
|
||||||
rawSearchAttrs);
|
|
||||||
NS_ERROR("nsLDAPAutoCompleteSession::SetOutputFormat: out of "
|
|
||||||
"memory");
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
rawSearchAttrsSize++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ok, we've succeed in building up the new array. deallocate the
|
|
||||||
// old array as necessary, then assign in the new member vars.
|
|
||||||
//
|
|
||||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mSearchAttrsSize, mSearchAttrs);
|
|
||||||
|
|
||||||
mSearchAttrsSize = rawSearchAttrsSize;
|
|
||||||
mSearchAttrs = rawSearchAttrs;
|
|
||||||
mOutputFormat = aOutputFormat;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// attribute long maxHits;
|
// attribute long maxHits;
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -1414,8 +1051,7 @@ nsLDAPAutoCompleteSession::GetServerURL(nsILDAPURL * *aServerURL)
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
*aServerURL = mServerURL;
|
NS_IF_ADDREF(*aServerURL = mServerURL);
|
||||||
NS_IF_ADDREF(*aServerURL);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -1511,6 +1147,41 @@ nsLDAPAutoCompleteSession::IsMessageCurrent(nsILDAPMessage *aMessage,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// attribute nsILDAPAutoCompFormatter formatter
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsLDAPAutoCompleteSession::GetFormatter(nsILDAPAutoCompFormatter* *aFormatter)
|
||||||
|
{
|
||||||
|
if (! aFormatter ) {
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IF_ADDREF(*aFormatter = mFormatter);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsLDAPAutoCompleteSession::SetFormatter(nsILDAPAutoCompFormatter* aFormatter)
|
||||||
|
{
|
||||||
|
if (! aFormatter ) {
|
||||||
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(mState == UNBOUND || mState == BOUND,
|
||||||
|
"nsLDAPAutoCompleteSession::SetFormatter was called when "
|
||||||
|
"mState was set to something other than BOUND or UNBOUND");
|
||||||
|
|
||||||
|
mFormatter = aFormatter;
|
||||||
|
|
||||||
|
// get and cache the attributes that will be used to do lookups
|
||||||
|
//
|
||||||
|
nsresult rv = mFormatter->GetAttributes(&mSearchAttrsSize, &mSearchAttrs);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_ERROR("nsLDAPAutoCompleteSession::SetFormatter(): "
|
||||||
|
" mFormatter->GetAttributes failed");
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "nsILDAPConnection.h"
|
#include "nsILDAPConnection.h"
|
||||||
#include "nsILDAPMessageListener.h"
|
#include "nsILDAPMessageListener.h"
|
||||||
#include "nsILDAPAutoCompleteSession.h"
|
#include "nsILDAPAutoCompleteSession.h"
|
||||||
|
#include "nsILDAPAutoCompFormatter.h"
|
||||||
#include "nsILDAPURL.h"
|
#include "nsILDAPURL.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsISupportsArray.h"
|
#include "nsISupportsArray.h"
|
||||||
|
@ -60,13 +61,16 @@ class nsLDAPAutoCompleteSession : public nsILDAPMessageListener,
|
||||||
nsCOMPtr<nsISupportsArray> mResultsArray; // cached, to avoid re-gets
|
nsCOMPtr<nsISupportsArray> mResultsArray; // cached, to avoid re-gets
|
||||||
nsString mSearchString; // autocomplete this string
|
nsString mSearchString; // autocomplete this string
|
||||||
nsString mFilterTemplate; // search filter template
|
nsString mFilterTemplate; // search filter template
|
||||||
nsString mOutputFormat; // how to format output
|
|
||||||
nsCOMPtr<nsILDAPURL> mServerURL; // URL for the directory to search
|
nsCOMPtr<nsILDAPURL> mServerURL; // URL for the directory to search
|
||||||
PRInt32 mMaxHits; // return at most this many entries
|
PRInt32 mMaxHits; // return at most this many entries
|
||||||
PRUint32 mMinStringLength; // strings < this size are ignored
|
PRUint32 mMinStringLength; // strings < this size are ignored
|
||||||
char **mSearchAttrs; // outputFormat search attrs for SearchExt call
|
char **mSearchAttrs; // outputFormat search attrs for SearchExt call
|
||||||
PRUint32 mSearchAttrsSize; // size of above array
|
PRUint32 mSearchAttrsSize; // size of above array
|
||||||
|
|
||||||
|
// used to format the ldap message into an nsIAutoCompleteItem
|
||||||
|
//
|
||||||
|
nsCOMPtr<nsILDAPAutoCompFormatter> mFormatter;
|
||||||
|
|
||||||
// stopgap until nsLDAPService works
|
// stopgap until nsLDAPService works
|
||||||
nsresult InitConnection();
|
nsresult InitConnection();
|
||||||
|
|
||||||
|
@ -76,25 +80,6 @@ class nsLDAPAutoCompleteSession : public nsILDAPMessageListener,
|
||||||
// add to the results set
|
// add to the results set
|
||||||
nsresult OnLDAPSearchEntry(nsILDAPMessage *aMessage);
|
nsresult OnLDAPSearchEntry(nsILDAPMessage *aMessage);
|
||||||
|
|
||||||
// parse and process outputFormat
|
|
||||||
nsresult ProcessOutputFormat(nsAReadableString & aOutputFormat,
|
|
||||||
nsILDAPMessage *aMessage,
|
|
||||||
nsAWritableString *aValue,
|
|
||||||
nsCStringArray *aAttrs);
|
|
||||||
|
|
||||||
// process a single attribute while parsing outputFormat
|
|
||||||
nsresult ParseAttrName(nsReadingIterator<PRUnichar> & aIter,
|
|
||||||
nsReadingIterator<PRUnichar> & aIterEnd,
|
|
||||||
PRBool aAttrRequired,
|
|
||||||
nsCOMPtr<nsIConsoleService> & aConsoleSvc,
|
|
||||||
nsAWritableCString & aAttrName);
|
|
||||||
|
|
||||||
// append the first value associated with aAttrName in aMessage to aValue
|
|
||||||
nsresult AppendFirstAttrValue(nsAReadableCString &aAttrName,
|
|
||||||
nsILDAPMessage *aMessage,
|
|
||||||
PRBool aAttrRequired,
|
|
||||||
nsAWritableString &aValue);
|
|
||||||
|
|
||||||
// all done; call OnAutoComplete
|
// all done; call OnAutoComplete
|
||||||
nsresult OnLDAPSearchResult(nsILDAPMessage *aMessage);
|
nsresult OnLDAPSearchResult(nsILDAPMessage *aMessage);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче