view lisp/ldap.el @ 4981:4aebb0131297

Cleanups/renaming of EXTERNAL_TO_C_STRING and friends -------------------- ChangeLog entries follow: -------------------- modules/ChangeLog addition: 2010-02-05 Ben Wing <ben@xemacs.org> * postgresql/postgresql.c: * postgresql/postgresql.c (CHECK_LIVE_CONNECTION): * postgresql/postgresql.c (Fpq_connectdb): * postgresql/postgresql.c (Fpq_connect_start): * postgresql/postgresql.c (Fpq_lo_import): * postgresql/postgresql.c (Fpq_lo_export): * ldap/eldap.c (Fldap_open): * ldap/eldap.c (Fldap_search_basic): * ldap/eldap.c (Fldap_add): * ldap/eldap.c (Fldap_modify): * ldap/eldap.c (Fldap_delete): * canna/canna_api.c (Fcanna_initialize): * canna/canna_api.c (Fcanna_store_yomi): * canna/canna_api.c (Fcanna_parse): * canna/canna_api.c (Fcanna_henkan_begin): EXTERNAL_TO_C_STRING returns its argument instead of storing it in a parameter, and is renamed to EXTERNAL_TO_ITEXT. Similar things happen to related macros. See entry in src/ChangeLog. More Mule-izing of postgresql.c. Extract out common code between `pq-connectdb' and `pq-connect-start'. Fix places that signal an error string using a formatted string to instead follow the standard and have a fixed reason followed by the particular error message stored as one of the frobs. src/ChangeLog addition: 2010-02-05 Ben Wing <ben@xemacs.org> * console-msw.c (write_string_to_mswindows_debugging_output): * console-msw.c (Fmswindows_message_box): * console-x.c (x_perhaps_init_unseen_key_defaults): * console.c: * database.c (dbm_get): * database.c (dbm_put): * database.c (dbm_remove): * database.c (berkdb_get): * database.c (berkdb_put): * database.c (berkdb_remove): * database.c (Fopen_database): * device-gtk.c (gtk_init_device): * device-msw.c (msprinter_init_device_internal): * device-msw.c (msprinter_default_printer): * device-msw.c (msprinter_init_device): * device-msw.c (sync_printer_with_devmode): * device-msw.c (Fmsprinter_select_settings): * device-x.c (sanity_check_geometry_resource): * device-x.c (Dynarr_add_validified_lisp_string): * device-x.c (x_init_device): * device-x.c (Fx_put_resource): * device-x.c (Fx_valid_keysym_name_p): * device-x.c (Fx_set_font_path): * dialog-msw.c (push_lisp_string_as_unicode): * dialog-msw.c (handle_directory_dialog_box): * dialog-msw.c (handle_file_dialog_box): * dialog-x.c (dbox_descriptor_to_widget_value): * editfns.c (Fformat_time_string): * editfns.c (Fencode_time): * editfns.c (Fset_time_zone_rule): * emacs.c (make_argc_argv): * emacs.c (Fdump_emacs): * emodules.c (emodules_load): * eval.c: * eval.c (maybe_signal_error_1): * event-msw.c (Fdde_alloc_advise_item): * event-msw.c (mswindows_dde_callback): * event-msw.c (mswindows_wnd_proc): * fileio.c (report_error_with_errno): * fileio.c (Fsysnetunam): * fileio.c (Fdo_auto_save): * font-mgr.c (extract_fcapi_string): * font-mgr.c (Ffc_config_app_font_add_file): * font-mgr.c (Ffc_config_app_font_add_dir): * font-mgr.c (Ffc_config_filename): * frame-gtk.c (gtk_set_frame_text_value): * frame-gtk.c (gtk_create_widgets): * frame-msw.c (mswindows_init_frame_1): * frame-msw.c (mswindows_set_title_from_ibyte): * frame-msw.c (msprinter_init_frame_3): * frame-x.c (x_set_frame_text_value): * frame-x.c (x_set_frame_properties): * frame-x.c (start_drag_internal_1): * frame-x.c (x_cde_transfer_callback): * frame-x.c (x_create_widgets): * glyphs-eimage.c (my_jpeg_output_message): * glyphs-eimage.c (jpeg_instantiate): * glyphs-eimage.c (gif_instantiate): * glyphs-eimage.c (png_instantiate): * glyphs-eimage.c (tiff_instantiate): * glyphs-gtk.c (xbm_instantiate_1): * glyphs-gtk.c (gtk_xbm_instantiate): * glyphs-gtk.c (gtk_xpm_instantiate): * glyphs-gtk.c (gtk_xface_instantiate): * glyphs-gtk.c (cursor_font_instantiate): * glyphs-gtk.c (gtk_redisplay_widget): * glyphs-gtk.c (gtk_widget_instantiate_1): * glyphs-gtk.c (gtk_add_tab_item): * glyphs-msw.c (mswindows_xpm_instantiate): * glyphs-msw.c (bmp_instantiate): * glyphs-msw.c (mswindows_resource_instantiate): * glyphs-msw.c (xbm_instantiate_1): * glyphs-msw.c (mswindows_xbm_instantiate): * glyphs-msw.c (mswindows_xface_instantiate): * glyphs-msw.c (mswindows_redisplay_widget): * glyphs-msw.c (mswindows_widget_instantiate): * glyphs-msw.c (add_tree_item): * glyphs-msw.c (add_tab_item): * glyphs-msw.c (mswindows_combo_box_instantiate): * glyphs-msw.c (mswindows_widget_query_string_geometry): * glyphs-x.c (x_locate_pixmap_file): * glyphs-x.c (xbm_instantiate_1): * glyphs-x.c (x_xbm_instantiate): * glyphs-x.c (extract_xpm_color_names): * glyphs-x.c (x_xpm_instantiate): * glyphs-x.c (x_xface_instantiate): * glyphs-x.c (autodetect_instantiate): * glyphs-x.c (safe_XLoadFont): * glyphs-x.c (cursor_font_instantiate): * glyphs-x.c (x_redisplay_widget): * glyphs-x.c (Fchange_subwindow_property): * glyphs-x.c (x_widget_instantiate): * glyphs-x.c (x_tab_control_redisplay): * glyphs.c (pixmap_to_lisp_data): * gui-x.c (menu_separator_style_and_to_external): * gui-x.c (add_accel_and_to_external): * gui-x.c (button_item_to_widget_value): * hpplay.c (player_error_internal): * hpplay.c (play_sound_file): * hpplay.c (play_sound_data): * intl.c (Fset_current_locale): * lisp.h: * menubar-gtk.c (gtk_xemacs_set_accel_keys): * menubar-msw.c (populate_menu_add_item): * menubar-msw.c (populate_or_checksum_helper): * menubar-x.c (menu_item_descriptor_to_widget_value_1): * nt.c (init_user_info): * nt.c (get_long_basename): * nt.c (nt_get_resource): * nt.c (init_mswindows_environment): * nt.c (get_cached_volume_information): * nt.c (mswindows_readdir): * nt.c (read_unc_volume): * nt.c (mswindows_stat): * nt.c (mswindows_getdcwd): * nt.c (mswindows_executable_type): * nt.c (Fmswindows_short_file_name): * ntplay.c (nt_play_sound_file): * objects-gtk.c: * objects-gtk.c (gtk_valid_color_name_p): * objects-gtk.c (gtk_initialize_font_instance): * objects-gtk.c (gtk_font_list): * objects-msw.c (font_enum_callback_2): * objects-msw.c (parse_font_spec): * objects-x.c (x_parse_nearest_color): * objects-x.c (x_valid_color_name_p): * objects-x.c (x_initialize_font_instance): * objects-x.c (x_font_instance_truename): * objects-x.c (x_font_list): * objects-xlike-inc.c (XFUN): * objects-xlike-inc.c (xft_find_charset_font): * process-nt.c (mswindows_report_winsock_error): * process-nt.c (nt_create_process): * process-nt.c (get_internet_address): * process-nt.c (nt_open_network_stream): * process-unix.c: * process-unix.c (allocate_pty): * process-unix.c (get_internet_address): * process-unix.c (unix_canonicalize_host_name): * process-unix.c (unix_open_network_stream): * realpath.c: * select-common.h (lisp_data_to_selection_data): * select-gtk.c (symbol_to_gtk_atom): * select-gtk.c (atom_to_symbol): * select-msw.c (symbol_to_ms_cf): * select-msw.c (mswindows_register_selection_data_type): * select-x.c (symbol_to_x_atom): * select-x.c (x_atom_to_symbol): * select-x.c (hack_motif_clipboard_selection): * select-x.c (Fx_store_cutbuffer_internal): * sound.c (Fplay_sound_file): * sound.c (Fplay_sound): * sound.h (sound_perror): * sysdep.c: * sysdep.c (qxe_allocating_getcwd): * sysdep.c (qxe_execve): * sysdep.c (copy_in_passwd): * sysdep.c (qxe_getpwnam): * sysdep.c (qxe_ctime): * sysdll.c (dll_open): * sysdll.c (dll_function): * sysdll.c (dll_variable): * sysdll.c (search_linked_libs): * sysdll.c (dll_error): * sysfile.h: * sysfile.h (PATHNAME_CONVERT_OUT_TSTR): * sysfile.h (PATHNAME_CONVERT_OUT_UTF_8): * sysfile.h (PATHNAME_CONVERT_OUT): * sysfile.h (LISP_PATHNAME_CONVERT_OUT): * syswindows.h (ITEXT_TO_TSTR): * syswindows.h (LOCAL_FILE_FORMAT_TO_TSTR): * syswindows.h (TSTR_TO_LOCAL_FILE_FORMAT): * syswindows.h (LOCAL_FILE_FORMAT_TO_INTERNAL_MSWIN): * syswindows.h (LISP_LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR): * text.h: * text.h (eicpy_ext_len): * text.h (enum new_dfc_src_type): * text.h (EXTERNAL_TO_ITEXT): * text.h (GET_STRERROR): * tooltalk.c (check_status): * tooltalk.c (Fadd_tooltalk_message_arg): * tooltalk.c (Fadd_tooltalk_pattern_attribute): * tooltalk.c (Fadd_tooltalk_pattern_arg): * win32.c (tstr_to_local_file_format): * win32.c (mswindows_lisp_error_1): * win32.c (mswindows_report_process_error): * win32.c (Fmswindows_shell_execute): * win32.c (mswindows_read_link_1): Changes involving external/internal format conversion, mostly code cleanup and renaming. 1. Eliminate the previous macros like LISP_STRING_TO_EXTERNAL that stored its result in a parameter. The new version of LISP_STRING_TO_EXTERNAL returns its result through the return value, same as the previous NEW_LISP_STRING_TO_EXTERNAL. Use the new-style macros throughout the code. 2. Rename C_STRING_TO_EXTERNAL and friends to ITEXT_TO_EXTERNAL, in keeping with overall naming rationalization involving Itext and related types. Macros involved in previous two: EXTERNAL_TO_C_STRING -> EXTERNAL_TO_ITEXT EXTERNAL_TO_C_STRING_MALLOC -> EXTERNAL_TO_ITEXT_MALLOC SIZED_EXTERNAL_TO_C_STRING -> SIZED_EXTERNAL_TO_ITEXT SIZED_EXTERNAL_TO_C_STRING_MALLOC -> SIZED_EXTERNAL_TO_ITEXT_MALLOC C_STRING_TO_EXTERNAL -> ITEXT_TO_EXTERNAL C_STRING_TO_EXTERNAL_MALLOC -> ITEXT_TO_EXTERNAL_MALLOC LISP_STRING_TO_EXTERNAL LISP_STRING_TO_EXTERNAL_MALLOC LISP_STRING_TO_TSTR C_STRING_TO_TSTR -> ITEXT_TO_TSTR TSTR_TO_C_STRING -> TSTR_TO_ITEXT The following four still return their values through parameters, since they have more than one value to return: C_STRING_TO_SIZED_EXTERNAL -> ITEXT_TO_SIZED_EXTERNAL LISP_STRING_TO_SIZED_EXTERNAL C_STRING_TO_SIZED_EXTERNAL_MALLOC -> ITEXT_TO_SIZED_EXTERNAL_MALLOC LISP_STRING_TO_SIZED_EXTERNAL_MALLOC Sometimes additional casts had to be inserted, since the old macros played strange games and completely defeated the type system of the store params. 3. Rewrite many places where direct calls to TO_EXTERNAL_FORMAT occurred with calls to one of the convenience macros listed above, or to make_extstring(). 4. Eliminate SIZED_C_STRING macros (they were hardly used, anyway) and use a direct call to TO_EXTERNAL_FORMAT or TO_INTERNAL_FORMAT. 4. Use LISP_PATHNAME_CONVERT_OUT in many places instead of something like LISP_STRING_TO_EXTERNAL(..., Qfile_name). 5. Eliminate some temporary variables that are no longer necessary now that we return a value rather than storing it into a variable. 6. Some Mule-izing in database.c. 7. Error functions: -- A bit of code cleanup in maybe_signal_error_1. -- Eliminate report_file_type_error; it's just an alias for signal_error_2 with params in a different order. -- Fix some places in the hostname-handling code that directly inserted externally-retrieved error strings into the supposed ASCII "reason" param instead of doing the right thing and sticking text descriptive of what was going on in "reason" and putting the external message in a frob. 8. Use Ascbyte instead of CIbyte in process-unix.c and maybe one or two other places. 9. Some code cleanup in copy_in_passwd() in sysdep.c. 10. Fix a real bug due to accidental variable shadowing in tstr_to_local_file_format() in win32.c.
author Ben Wing <ben@xemacs.org>
date Fri, 05 Feb 2010 11:02:24 -0600 (2010-02-05)
parents e29fcfd8df5f
children f00192e1cd49 91b3aa59f49b
line wrap: on
line source
;;; ldap.el --- LDAP support for Emacs

;; Copyright (C) 1997 Free Software Foundation, Inc.

;; Author: Oscar Figueiredo <Oscar.Figueiredo@di.epfl.ch>
;; Maintainer: Oscar Figueiredo <Oscar.Figueiredo@di.epfl.ch>
;; Created: Jan 1998
;; Version: $Revision: 1.12 $
;; Keywords: help comm

;; This file is part of XEmacs

;; XEmacs is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; XEmacs is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with XEmacs; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;;; Commentary:
;;    This file provides mid-level and user-level functions to access directory
;;    servers using the LDAP protocol (RFC 1777).

;;; Installation:
;;    LDAP support must have been built into XEmacs.


;;; Code:

(globally-declare-fboundp '(ldapp ldap-open ldap-close ldap-add ldap-modify
				  ldap-delete))

(eval-when '(load)
  (if (not (fboundp 'ldap-open))
      (error "No LDAP support compiled in this XEmacs")))

(defgroup ldap nil
  "Lightweight Directory Access Protocol"
  :group 'comm)

(defcustom ldap-default-host nil
  "*Default LDAP server hostname.
A TCP port number can be appended to that name using a colon as
a separator."
  :type '(choice (string :tag "Host name")
		 (const :tag "Use library default" nil))
  :group 'ldap)

(defcustom ldap-default-port nil
  "*Default TCP port for LDAP connections.
Initialized from the LDAP library at build time. Default value is 389."
  :type '(choice (const :tag "Use library default" nil)
		 (integer :tag "Port number"))
  :group 'ldap)

(defcustom ldap-default-base nil
  "*Default base for LDAP searches.
This is a string using the syntax of RFC 1779.
For instance, \"o=ACME, c=US\" limits the search to the
Acme organization in the United States."
  :type '(choice (const :tag "Use library default" nil)
		 (string :tag "Search base"))
  :group 'ldap)


(defcustom ldap-host-parameters-alist nil
  "*Alist of host-specific options for LDAP transactions.
The format of each list element is:
\(HOST PROP1 VAL1 PROP2 VAL2 ...)
HOST is the hostname of an LDAP server (with an optional TCP port number
appended to it  using a colon as a separator).
PROPn and VALn are property/value pairs describing parameters for the server.
Valid properties include:
  `binddn' is the distinguished name of the user to bind as
    (in RFC 1779 syntax).
  `passwd' is the password to use for simple authentication.
  `auth' is the authentication method to use.
    Possible values are: `simple', `krbv41' and `krbv42'.
  `base' is the base for the search as described in RFC 1779.
  `scope' is one of the three symbols `subtree', `base' or `onelevel'.
  `deref' is one of the symbols `never', `always', `search' or `find'.
  `timelimit' is the timeout limit for the connection in seconds.
  `sizelimit' is the maximum number of matches to return."
  :type '(repeat :menu-tag "Host parameters"
		 :tag "Host parameters"
		 (list :menu-tag "Host parameters"
		       :tag "Host parameters"
		       :value nil
		       (string :tag "Host name")
		       (checklist :inline t
				  :greedy t
				  (list
				   :tag "Search Base"
				   :inline t
				   (const :tag "Search Base" base)
				   string)
				  (list
				   :tag "Binding DN"
				   :inline t
				   (const :tag "Binding DN" binddn)
				   string)
				  (list
				   :tag "Password"
				   :inline t
				   (const :tag "Password" passwd)
				   string)
				  (list
				   :tag "Authentication Method"
				   :inline t
				   (const :tag "Authentication Method" auth)
				   (choice
				    (const :menu-tag "None" :tag "None" nil)
				    (const :menu-tag "Simple" :tag "Simple" simple)
				    (const :menu-tag "Kerberos 4.1" :tag "Kerberos 4.1" krbv41)
				    (const :menu-tag "Kerberos 4.2" :tag "Kerberos 4.2" krbv42)))
				  (list
				   :tag "Search Scope"
				   :inline t
				   (const :tag "Search Scope" scope)
				   (choice
				    (const :menu-tag "Default" :tag "Default" nil)
				    (const :menu-tag "Subtree" :tag "Subtree" subtree)
				    (const :menu-tag "Base" :tag "Base" base)
				    (const :menu-tag "One Level" :tag "One Level" onelevel)))
				  (list
				   :tag "Dereferencing"
				   :inline t
				   (const :tag "Dereferencing" deref)
				   (choice
				    (const :menu-tag "Default" :tag "Default" nil)
				    (const :menu-tag "Never" :tag "Never" never)
				    (const :menu-tag "Always" :tag "Always" always)
				    (const :menu-tag "When searching" :tag "When searching" search)
				    (const :menu-tag "When locating base" :tag "When locating base" find)))
				  (list
				   :tag "Time Limit"
				   :inline t
				   (const :tag "Time Limit" timelimit)
				   (integer :tag "(in seconds)"))
				  (list
				   :tag "Size Limit"
				   :inline t
				   (const :tag "Size Limit" sizelimit)
				   (integer :tag "(number of records)")))))
:group 'ldap)

(defcustom ldap-verbose nil
  "*If non-nil, LDAP operations echo progress messages."
  :type 'boolean
  :group 'ldap)

(defcustom ldap-ignore-attribute-codings nil
  "*If non-nil, do not perform any encoding/decoding on LDAP attribute values."
  :type 'boolean
  :group 'ldap)

(defcustom ldap-default-attribute-decoder nil
  "*Decoder function to use for attributes whose syntax is unknown."
  :type 'symbol
  :group 'ldap)

(defcustom ldap-coding-system nil
  "*Coding system of LDAP string values.
LDAP v3 specifies the coding system of strings to be UTF-8.
Mule support is needed for this."
  :type 'symbol
  :group 'ldap)

(defvar ldap-attribute-syntax-encoders
  [nil					; 1  ACI Item                        N
   nil					; 2  Access Point                    Y
   nil					; 3  Attribute Type Description      Y
   nil					; 4  Audio                           N
   nil					; 5  Binary                          N
   nil					; 6  Bit String                      Y
   ldap-encode-boolean			; 7  Boolean                         Y
   nil					; 8  Certificate                     N
   nil					; 9  Certificate List                N
   nil					; 10 Certificate Pair                N
   ldap-encode-country-string		; 11 Country String                  Y
   ldap-encode-string			; 12 DN                              Y
   nil					; 13 Data Quality Syntax             Y
   nil					; 14 Delivery Method                 Y
   ldap-encode-string			; 15 Directory String                Y
   nil					; 16 DIT Content Rule Description    Y
   nil					; 17 DIT Structure Rule Description  Y
   nil					; 18 DL Submit Permission            Y
   nil					; 19 DSA Quality Syntax              Y
   nil					; 20 DSE Type                        Y
   nil					; 21 Enhanced Guide                  Y
   nil					; 22 Facsimile Telephone Number      Y
   nil					; 23 Fax                             N
   nil					; 24 Generalized Time                Y
   nil					; 25 Guide                           Y
   nil					; 26 IA5 String                      Y
   number-to-string			; 27 INTEGER                         Y
   nil					; 28 JPEG                            N
   nil					; 29 Master And Shadow Access Points Y
   nil					; 30 Matching Rule Description       Y
   nil					; 31 Matching Rule Use Description   Y
   nil					; 32 Mail Preference                 Y
   nil					; 33 MHS OR Address                  Y
   nil					; 34 Name And Optional UID           Y
   nil					; 35 Name Form Description           Y
   nil					; 36 Numeric String                  Y
   nil					; 37 Object Class Description        Y
   nil					; 38 OID                             Y
   nil					; 39 Other Mailbox                   Y
   nil					; 40 Octet String                    Y
   ldap-encode-address			; 41 Postal Address                  Y
   nil					; 42 Protocol Information            Y
   nil					; 43 Presentation Address            Y
   ldap-encode-string			; 44 Printable String                Y
   nil					; 45 Subtree Specification           Y
   nil					; 46 Supplier Information            Y
   nil					; 47 Supplier Or Consumer            Y
   nil					; 48 Supplier And Consumer           Y
   nil					; 49 Supported Algorithm             N
   nil					; 50 Telephone Number                Y
   nil					; 51 Teletex Terminal Identifier     Y
   nil					; 52 Telex Number                    Y
   nil					; 53 UTC Time                        Y
   nil					; 54 LDAP Syntax Description         Y
   nil					; 55 Modify Rights                   Y
   nil					; 56 LDAP Schema Definition          Y
   nil					; 57 LDAP Schema Description         Y
   nil					; 58 Substring Assertion             Y
   ]
  "A vector of functions used to encode LDAP attribute values.
The sequence of functions corresponds to the sequence of LDAP attribute syntax
object identifiers of the form 1.3.6.1.4.1.1466.1115.121.1.* as defined in
RFC2252 section 4.3.2")

(defvar ldap-attribute-syntax-decoders
  [nil					; 1  ACI Item                        N
   nil					; 2  Access Point                    Y
   nil					; 3  Attribute Type Description      Y
   nil					; 4  Audio                           N
   nil					; 5  Binary                          N
   nil					; 6  Bit String                      Y
   ldap-decode-boolean			; 7  Boolean                         Y
   nil					; 8  Certificate                     N
   nil					; 9  Certificate List                N
   nil					; 10 Certificate Pair                N
   ldap-decode-string			; 11 Country String                  Y
   ldap-decode-string			; 12 DN                              Y
   nil					; 13 Data Quality Syntax             Y
   nil					; 14 Delivery Method                 Y
   ldap-decode-string			; 15 Directory String                Y
   nil					; 16 DIT Content Rule Description    Y
   nil					; 17 DIT Structure Rule Description  Y
   nil					; 18 DL Submit Permission            Y
   nil					; 19 DSA Quality Syntax              Y
   nil					; 20 DSE Type                        Y
   nil					; 21 Enhanced Guide                  Y
   nil					; 22 Facsimile Telephone Number      Y
   nil					; 23 Fax                             N
   nil					; 24 Generalized Time                Y
   nil					; 25 Guide                           Y
   nil					; 26 IA5 String                      Y
   string-to-number			; 27 INTEGER                         Y
   nil					; 28 JPEG                            N
   nil					; 29 Master And Shadow Access Points Y
   nil					; 30 Matching Rule Description       Y
   nil					; 31 Matching Rule Use Description   Y
   nil					; 32 Mail Preference                 Y
   nil					; 33 MHS OR Address                  Y
   nil					; 34 Name And Optional UID           Y
   nil					; 35 Name Form Description           Y
   nil					; 36 Numeric String                  Y
   nil					; 37 Object Class Description        Y
   nil					; 38 OID                             Y
   nil					; 39 Other Mailbox                   Y
   nil					; 40 Octet String                    Y
   ldap-decode-address			; 41 Postal Address                  Y
   nil					; 42 Protocol Information            Y
   nil					; 43 Presentation Address            Y
   ldap-decode-string			; 44 Printable String                Y
   nil					; 45 Subtree Specification           Y
   nil					; 46 Supplier Information            Y
   nil					; 47 Supplier Or Consumer            Y
   nil					; 48 Supplier And Consumer           Y
   nil					; 49 Supported Algorithm             N
   nil					; 50 Telephone Number                Y
   nil					; 51 Teletex Terminal Identifier     Y
   nil					; 52 Telex Number                    Y
   nil					; 53 UTC Time                        Y
   nil					; 54 LDAP Syntax Description         Y
   nil					; 55 Modify Rights                   Y
   nil					; 56 LDAP Schema Definition          Y
   nil					; 57 LDAP Schema Description         Y
   nil					; 58 Substring Assertion             Y
   ]
  "A vector of functions used to decode LDAP attribute values.
The sequence of functions corresponds to the sequence of LDAP attribute syntax
object identifiers of the form 1.3.6.1.4.1.1466.1115.121.1.* as defined in
RFC2252 section 4.3.2")


(defvar ldap-attribute-syntaxes-alist
  '((createtimestamp . 24)
    (modifytimestamp . 24)
    (creatorsname . 12)
    (modifiersname . 12)
    (subschemasubentry . 12)
    (attributetypes . 3)
    (objectclasses . 37)
    (matchingrules . 30)
    (matchingruleuse . 31)
    (namingcontexts . 12)
    (altserver . 26)
    (supportedextension . 38)
    (supportedcontrol . 38)
    (supportedsaslmechanisms . 15)
    (supportedldapversion . 27)
    (ldapsyntaxes . 16)
    (ditstructurerules . 17)
    (nameforms . 35)
    (ditcontentrules . 16)
    (objectclass . 38)
    (aliasedobjectname . 12)
    (cn . 15)
    (sn . 15)
    (serialnumber . 44)
    (c . 15)
    (l . 15)
    (st . 15)
    (street . 15)
    (o . 15)
    (ou . 15)
    (title . 15)
    (description . 15)
    (searchguide . 25)
    (businesscategory . 15)
    (postaladdress . 41)
    (postalcode . 15)
    (postofficebox . 15)
    (physicaldeliveryofficename . 15)
    (telephonenumber . 50)
    (telexnumber . 52)
    (telexterminalidentifier . 51)
    (facsimiletelephonenumber . 22)
    (x121address . 36)
    (internationalisdnnumber . 36)
    (registeredaddress . 41)
    (destinationindicator . 44)
    (preferreddeliverymethod . 14)
    (presentationaddress . 43)
    (supportedapplicationcontext . 38)
    (member . 12)
    (owner . 12)
    (roleoccupant . 12)
    (seealso . 12)
    (userpassword . 40)
    (usercertificate . 8)
    (cacertificate . 8)
    (authorityrevocationlist . 9)
    (certificaterevocationlist . 9)
    (crosscertificatepair . 10)
    (name . 15)
    (givenname . 15)
    (initials . 15)
    (generationqualifier . 15)
    (x500uniqueidentifier . 6)
    (dnqualifier . 44)
    (enhancedsearchguide . 21)
    (protocolinformation . 42)
    (distinguishedname . 12)
    (uniquemember . 34)
    (houseidentifier . 15)
    (supportedalgorithms . 49)
    (deltarevocationlist . 9)
    (dmdname . 15))
  "A map of LDAP attribute names to their type object id minor number.
This table is built from RFC2252 Section 5 and RFC2256 Section 5")


;; Coding/decoding functions

(defun ldap-encode-boolean (bool)
  (if bool
      "TRUE"
    "FALSE"))

(defun ldap-decode-boolean (str)
  (cond
   ((string-equal str "TRUE")
    t)
   ((string-equal str "FALSE")
    nil)
   (t
    (error "Wrong LDAP boolean string: %s" str))))

(defun ldap-encode-country-string (str)
  ;; We should do something useful here...
  (if (not (= 2 (length str)))
      (error "Invalid country string: %s" str)))

(defun ldap-decode-string (str)
  (if (fboundp 'decode-coding-string)
      (decode-coding-string str ldap-coding-system)))

(defun ldap-encode-string (str)
   (if (fboundp 'encode-coding-string)
       (encode-coding-string str ldap-coding-system)))

(defun ldap-decode-address (str)
  (mapconcat 'ldap-decode-string
	     (split-string str "\\$")
	     "\n"))

(defun ldap-encode-address (str)
  (mapconcat 'ldap-encode-string
	     (split-string str "\n")
	     "$"))


;; LDAP protocol functions

(defun ldap-get-host-parameter (host parameter)
  "Get the value of PARAMETER for HOST in `ldap-host-parameters-alist'."
  (plist-get (cdr (assoc host ldap-host-parameters-alist))
	     parameter))

(defun ldap-decode-attribute (attr)
  "Decode the attribute/value pair ATTR according to LDAP rules.
The attribute name is looked up in `ldap-attribute-syntaxes-alist'
and the corresponding decoder is then retrieved from
`ldap-attribute-syntax-decoders' and applied on the value(s)."
  (let* ((name (car attr))
	 (values (cdr attr))
	 (syntax-id (cdr (assq (intern (downcase name))
			       ldap-attribute-syntaxes-alist)))
	 decoder)
    (if syntax-id
	(setq decoder (aref ldap-attribute-syntax-decoders
			    (1- syntax-id)))
      (setq decoder ldap-default-attribute-decoder))
    (if decoder
	(cons name (mapcar decoder values))
      attr)))

(defun ldap-decode-entry (entry)
  "Decode the attributes of ENTRY according to LDAP rules."
  (let (dn decoded)
    (setq dn (car entry))
    (if (stringp dn)
	(setq entry (cdr entry))
      (setq dn nil))
    (setq decoded (mapcar 'ldap-decode-attribute entry))
    (if dn
	(cons dn decoded)
      decoded)))

(defun ldap-search (arg1 &rest args)
  "Perform an LDAP search."
      (apply (if (ldapp arg1)
		 'ldap-search-basic
	       'ldap-search-entries) arg1 args))

(make-obsolete 'ldap-search
	       "Use `ldap-search-entries' instead or
`ldap-search-basic' for the low-level search API.")

(defun ldap-search-entries (filter &optional host attributes attrsonly withdn)
  "Perform an LDAP search.
FILTER is the search filter in RFC1558 syntax, i.e., something that
looks like \"(cn=John Smith)\".
HOST is the LDAP host on which to perform the search.
ATTRIBUTES is a list of attributes to retrieve; nil means retrieve all.
If ATTRSONLY is non nil, the attributes will be retrieved without
the associated values.
If WITHDN is non-nil each entry in the result will be prepennded with
its distinguished name DN.
Additional search parameters can be specified through
`ldap-host-parameters-alist' which see.
The function returns a list of matching entries.  Each entry is itself
an alist of attribute/value pairs optionally preceded by the DN of the
entry according to the value of WITHDN."
  (interactive "sFilter:")
  (or host
      (setq host ldap-default-host)
      (error "No LDAP host specified"))
  (let ((host-plist (cdr (assoc host ldap-host-parameters-alist)))
	ldap
	result)
    (if ldap-verbose
	(message "Opening LDAP connection to %s..." host))
    (setq ldap (ldap-open host host-plist))
    (if ldap-verbose
	(message "Searching with LDAP on %s..." host))
    (setq result (ldap-search ldap filter
			      (plist-get host-plist 'base)
			      (plist-get host-plist 'scope)
			      attributes attrsonly withdn
			      ldap-verbose))
    (ldap-close ldap)
    (if ldap-ignore-attribute-codings
	result
      (mapcar 'ldap-decode-entry result))))

(defun ldap-add-entries (entries &optional host binddn passwd)
  "Add entries to an LDAP directory.
ENTRIES is a list of entry specifications of
the form (DN (ATTR . VALUE) (ATTR . VALUE) ...) where
DN is the distinguished name of an entry to add, the following
are cons cells containing attribute/value string pairs.
HOST is the LDAP host, defaulting to `ldap-default-host'.
BINDDN is the DN to bind as to the server.
PASSWD is the corresponding password."
  (or host
      (setq host ldap-default-host)
      (error "No LDAP host specified"))
  (let ((host-plist (cdr (assoc host ldap-host-parameters-alist)))
	ldap
	(i 1))
    (if (or binddn passwd)
	(setq host-plist (copy-seq host-plist)))
    (if binddn
	(setq host-plist (plist-put host-plist 'binddn binddn)))
    (if passwd
	(setq host-plist (plist-put host-plist 'passwd passwd)))
    (if ldap-verbose
	(message "Opening LDAP connection to %s..." host))
    (setq ldap (ldap-open host host-plist))
    (if ldap-verbose
	(message "Adding LDAP entries..."))
    (mapc (function
           (lambda (thisentry)
             (ldap-add ldap (car thisentry) (cdr thisentry))
             (if ldap-verbose
                 (message "%d added" i))
             (setq i (1+ i))))
          entries)
    (ldap-close ldap)))


(defun ldap-modify-entries (entry-mods &optional host binddn passwd)
  "Modify entries of an LDAP directory.
ENTRY_MODS is a list of entry modifications of the form
  (DN MOD-SPEC1 MOD-SPEC2 ...) where DN is the distinguished name of
the entry to modify, the following are modification specifications.
A modification specification is itself a list of the form
\(MOD-OP ATTR VALUE1 VALUE2 ...) MOD-OP and ATTR are mandatory,
VALUEs are optional depending on MOD-OP.
MOD-OP is the type of modification, one of the symbols `add', `delete'
or `replace'. ATTR is the LDAP attribute type to modify.
HOST is the LDAP host, defaulting to `ldap-default-host'.
BINDDN is the DN to bind as to the server.
PASSWD is the corresponding password."
  (or host
      (setq host ldap-default-host)
      (error "No LDAP host specified"))
  (let ((host-plist (cdr (assoc host ldap-host-parameters-alist)))
	ldap
	(i 1))
    (if (or binddn passwd)
	(setq host-plist (copy-seq host-plist)))
    (if binddn
	(setq host-plist (plist-put host-plist 'binddn binddn)))
    (if passwd
	(setq host-plist (plist-put host-plist 'passwd passwd)))
    (if ldap-verbose
	(message "Opening LDAP connection to %s..." host))
    (setq ldap (ldap-open host host-plist))
    (if ldap-verbose
	(message "Modifying LDAP entries..."))
    (mapc (function
           (lambda (thisentry)
             (ldap-modify ldap (car thisentry) (cdr thisentry))
             (if ldap-verbose
                 (message "%d modified" i))
             (setq i (1+ i))))
          entry-mods)
    (ldap-close ldap)))


(defun ldap-delete-entries (dn &optional host binddn passwd)
  "Delete an entry from an LDAP directory.
DN is the distinguished name of an entry to delete or
a list of those.
HOST is the LDAP host, defaulting to `ldap-default-host'.
BINDDN is the DN to bind as to the server.
PASSWD is the corresponding password."
  (or host
      (setq host ldap-default-host)
      (error "No LDAP host specified"))
  (let ((host-plist (cdr (assoc host ldap-host-parameters-alist)))
	ldap)
    (if (or binddn passwd)
	(setq host-plist (copy-seq host-plist)))
    (if binddn
	(setq host-plist (plist-put host-plist 'binddn binddn)))
    (if passwd
	(setq host-plist (plist-put host-plist 'passwd passwd)))
    (if ldap-verbose
	(message "Opening LDAP connection to %s..." host))
    (setq ldap (ldap-open host host-plist))
    (if (consp dn)
	(let ((i 1))
	  (if ldap-verbose
	      (message "Deleting LDAP entries..."))
	  (mapc (function
                 (lambda (thisdn)
                   (ldap-delete ldap thisdn)
                   (if ldap-verbose
                       (message "%d deleted" i))
                   (setq i (1+ i))))
                dn))
      (if ldap-verbose
	  (message "Deleting LDAP entry..."))
      (ldap-delete ldap dn))
    (ldap-close ldap)))


(provide 'ldap)

;;; ldap.el ends here