aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2015-03-09 18:13:13 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2015-03-10 14:35:22 +0100
commit25400cb17e2e531266e0e1c7149800c3fa0609dd (patch)
tree23d813c1daa7c004e0456c8e132dac03dbf007c5
parentLink to version 1.0 (diff)
downloadlualdap-25400cb17e2e531266e0e1c7149800c3fa0609dd.tar.xz
lualdap-25400cb17e2e531266e0e1c7149800c3fa0609dd.zip
Modernize project1.2.0
-rw-r--r--.gitignore1
-rwxr-xr-xCVSROOT/checkoutlist13
-rwxr-xr-xCVSROOT/commitinfo24
-rwxr-xr-xCVSROOT/config37
-rwxr-xr-xCVSROOT/cvswrappers19
-rwxr-xr-xCVSROOT/loginfo31
-rwxr-xr-xCVSROOT/modules26
-rwxr-xr-xCVSROOT/notify17
-rwxr-xr-xCVSROOT/rcsinfo13
-rwxr-xr-xCVSROOT/taginfo40
-rwxr-xr-xCVSROOT/verifymsg29
-rw-r--r--Makefile21
-rw-r--r--README.md278
-rw-r--r--lualdap.c1056
-rwxr-xr-xlualdap/Makefile28
-rwxr-xr-xlualdap/Makefile.win22
-rwxr-xr-xlualdap/README28
-rwxr-xr-xlualdap/config26
-rwxr-xr-xlualdap/config.win30
-rwxr-xr-xlualdap/doc/us/index.html140
-rwxr-xr-xlualdap/doc/us/license.html122
-rwxr-xr-xlualdap/doc/us/lualdap.pngbin7868 -> 0 bytes
-rwxr-xr-xlualdap/doc/us/manual.html352
-rwxr-xr-xlualdap/src/lualdap.c1000
-rwxr-xr-xlualdap/src/lualdap.def6
-rwxr-xr-xlualdap/src/open2winldap.h47
-rwxr-xr-xlualdap/vc6/lualdap.def5
-rwxr-xr-xlualdap/vc6/lualdap.dsw78
-rwxr-xr-xlualdap/vc6/lualdap.rc109
-rwxr-xr-xlualdap/vc6/lualdap_dll.dsp127
-rwxr-xr-xlualdap/vc6/resource.h15
-rw-r--r--[-rwxr-xr-x]unit-tests.lua (renamed from lualdap/tests/test.lua)13
32 files changed, 1361 insertions, 2392 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..81270f7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+lualdap.so
diff --git a/CVSROOT/checkoutlist b/CVSROOT/checkoutlist
deleted file mode 100755
index 2921bff..0000000
--- a/CVSROOT/checkoutlist
+++ /dev/null
@@ -1,13 +0,0 @@
-# The "checkoutlist" file is used to support additional version controlled
-# administrative files in $CVSROOT/CVSROOT, such as template files.
-#
-# The first entry on a line is a filename which will be checked out from
-# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
-# The remainder of the line is an error message to use if the file cannot
-# be checked out.
-#
-# File format:
-#
-# [<whitespace>]<filename>[<whitespace><error message>]<end-of-line>
-#
-# comment lines begin with '#'
diff --git a/CVSROOT/commitinfo b/CVSROOT/commitinfo
deleted file mode 100755
index d4ade55..0000000
--- a/CVSROOT/commitinfo
+++ /dev/null
@@ -1,24 +0,0 @@
-# The "commitinfo" file is used to control pre-commit checks.
-# The filter on the right is invoked with the repository and a list
-# of files to check. A non-zero exit of the filter program will
-# cause the commit to be aborted.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being committed to, relative
-# to the $CVSROOT. For the first match that is found, then the remainder
-# of the line is the name of the filter to run.
-#
-# Format strings present in the filter will be replaced as follows:
-# %p = path relative to repository
-# %r = repository (path portion of $CVSROOT)
-# %{s} = file name, file name, ...
-#
-# If no format strings are present in the filter string, a default of
-# " %r %s" will be appended to the filter string, but this usage is
-# deprecated.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/CVSROOT/config b/CVSROOT/config
deleted file mode 100755
index 6accc36..0000000
--- a/CVSROOT/config
+++ /dev/null
@@ -1,37 +0,0 @@
-# Set this to "no" if pserver shouldn't check system users/passwords
-#SystemAuth=no
-
-# Put CVS lock files in this directory rather than directly in the repository.
-#LockDir=/var/lock/cvs
-
-# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top
-# level of the new working directory when using the `cvs checkout'
-# command.
-#TopLevelAdmin=no
-
-# Set `LogHistory' to `all' or `TOEFWUPCGMAR' to log all transactions to the
-# history file, or a subset as needed (ie `TMAR' logs all write operations)
-#LogHistory=TOEFWUPCGMAR
-
-# Set `RereadLogAfterVerify' to `always' (the default) to allow the verifymsg
-# script to change the log message. Set it to `stat' to force CVS to verify
-# that the file has changed before reading it (this can take up to an extra
-# second per directory being committed, so it is not recommended for large
-# repositories. Set it to `never' (the previous CVS behavior) to prevent
-# verifymsg scripts from changing the log message.
-#RereadLogAfterVerify=always
-
-# Set `UserAdminOptions' to the list of `cvs admin' commands (options)
-# that users not in the `cvsadmin' group are allowed to run. This
-# defaults to `k', or only allowing the changing of the default
-# keyword expansion mode for files for users not in the `cvsadmin' group.
-# This value is ignored if the `cvsadmin' group does not exist.
-#
-# The following string would enable all `cvs admin' commands for all
-# users:
-#UserAdminOptions=aAbceIklLmnNostuU
-
-# Set `UseNewInfoFmtStrings' to `no' if you must support a legacy system by
-# enabling the deprecated old style info file command line format strings.
-# Be warned that these strings could be disabled in any new version of CVS.
-UseNewInfoFmtStrings=yes
diff --git a/CVSROOT/cvswrappers b/CVSROOT/cvswrappers
deleted file mode 100755
index e989b75..0000000
--- a/CVSROOT/cvswrappers
+++ /dev/null
@@ -1,19 +0,0 @@
-# This file affects handling of files based on their names.
-#
-# The -m option specifies whether CVS attempts to merge files.
-#
-# The -k option specifies keyword expansion (e.g. -kb for binary).
-#
-# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
-#
-# wildcard [option value][option value]...
-#
-# where option is one of
-# -f from cvs filter value: path to filter
-# -t to cvs filter value: path to filter
-# -m update methodology value: MERGE or COPY
-# -k expansion mode value: b, o, kkv, &c
-#
-# and value is a single-quote delimited value.
-# For example:
-#*.gif -k 'b'
diff --git a/CVSROOT/loginfo b/CVSROOT/loginfo
deleted file mode 100755
index 4dd6562..0000000
--- a/CVSROOT/loginfo
+++ /dev/null
@@ -1,31 +0,0 @@
-# The "loginfo" file controls where "cvs commit" log information
-# is sent. The first entry on a line is a regular expression which must match
-# the directory that the change is being made to, relative to the
-# $CVSROOT. If a match is found, then the remainder of the line is a filter
-# program that should expect log information on its standard input.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name ALL appears as a regular expression it is always used
-# in addition to the first matching regex or DEFAULT.
-#
-# If any format strings are present in the filter, they will be replaced as follows:
-# %p = path relative to repository
-# %r = repository (path portion of $CVSROOT)
-# %{sVv} = attribute list = file name, old version number (pre-checkin),
-# new version number (post-checkin). When either old or new revision is
-# unknown, doesn't exist, or isn't applicable, the string "NONE" will be
-# placed on the command line instead.
-#
-# Note that %{sVv} is a list operator and not all elements are necessary. Thus %{sv} is
-# a legal format string, but will only be replaced with file name and new revision.
-# it also generates multiple arguments for each file being operated upon. i.e. if two
-# files, file1 & file2, are being commited from 1.1 to version 1.1.2.1 and from 1.1.2.2
-# to 1.1.2.3, respectively, %{sVv} will generate the following six arguments in this
-# order: file1, 1.1, 1.1.2.1, file2, 1.1.2.2, 1.1.2.3.
-#
-# For example:
-#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
-# or
-#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog
diff --git a/CVSROOT/modules b/CVSROOT/modules
deleted file mode 100755
index cb9e9ef..0000000
--- a/CVSROOT/modules
+++ /dev/null
@@ -1,26 +0,0 @@
-# Three different line formats are valid:
-# key -a aliases...
-# key [options] directory
-# key [options] directory files...
-#
-# Where "options" are composed of:
-# -i prog Run "prog" on "cvs commit" from top-level of module.
-# -o prog Run "prog" on "cvs checkout" of module.
-# -e prog Run "prog" on "cvs export" of module.
-# -t prog Run "prog" on "cvs rtag" of module.
-# -u prog Run "prog" on "cvs update" of module.
-# -d dir Place module in directory "dir" instead of module name.
-# -l Top-level directory only -- do not recurse.
-#
-# NOTE: If you change any of the "Run" options above, you'll have to
-# release and re-checkout any working directories of these modules.
-#
-# And "directory" is a path to a directory relative to $CVSROOT.
-#
-# The "-a" option specifies an alias. An alias is interpreted as if
-# everything on the right of the "-a" had been typed on the command line.
-#
-# You can encode a module within a module by using the special '&'
-# character to interpose another module into the current module. This
-# can be useful for creating a module that consists of many directories
-# spread out over the entire source repository.
diff --git a/CVSROOT/notify b/CVSROOT/notify
deleted file mode 100755
index 196c3ea..0000000
--- a/CVSROOT/notify
+++ /dev/null
@@ -1,17 +0,0 @@
-# The "notify" file controls where notifications from watches set by
-# "cvs watch add" or "cvs edit" are sent. The first entry on a line is
-# a regular expression which is tested against the directory that the
-# change is being made to, relative to the $CVSROOT. If it matches,
-# then the remainder of the line is a filter program that should contain
-# one occurrence of %s for the user to notify, and information on its
-# standard input.
-#
-# "ALL" or "DEFAULT" can be used in place of the regular expression.
-#
-# format strings are replaceed as follows:
-# %p = path relative to repository
-# %r = repository (path portion of $CVSROOT)
-# %s = user to notify
-#
-# For example:
-#ALL (echo Committed to %r/%p; cat) |mail %s -s "CVS notification"
diff --git a/CVSROOT/rcsinfo b/CVSROOT/rcsinfo
deleted file mode 100755
index 49e59f4..0000000
--- a/CVSROOT/rcsinfo
+++ /dev/null
@@ -1,13 +0,0 @@
-# The "rcsinfo" file is used to control templates with which the editor
-# is invoked on commit and import.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being made to, relative to the
-# $CVSROOT. For the first match that is found, then the remainder of the
-# line is the name of the file that contains the template.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/CVSROOT/taginfo b/CVSROOT/taginfo
deleted file mode 100755
index 025657c..0000000
--- a/CVSROOT/taginfo
+++ /dev/null
@@ -1,40 +0,0 @@
-# The "taginfo" file is used to control pre-tag checks.
-# The filter on the right is invoked with the following arguments if no format strings are present:
-#
-# $1 -- tagname
-# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
-# $3 -- tagtype "?" on delete, "T" for branch, "N" for static
-# $4 -- repository
-# $5-> file revision [file revision ...]
-#
-# If any format strings are present in the filter, they will be replaced as follows:
-# %b = branch mode = "?" (delete ops - unknown) | "T" (branch) | "N" (not branch)
-# %o = operation = "add" | "mov" | "del"
-# %p = path relative to repository
-# %r = repository (path portion of $CVSROOT)
-# %t = tagname
-# %{sVv} = attribute list = file name, old version tag will be deleted from,
-# new version tag will be added to (or deleted from, but this feature is
-# deprecated. When either old or new revision is unknown, doesn't exist,
-# or isn't applicable, the string "NONE" will be placed on the command
-# line.
-#
-# Note that %{sVv} is a list operator and not all elements are necessary. Thus %{sV} is
-# a legal format string, but will only be replaced with file name and old revision.
-# it also generates multiple arguments for each file being operated upon. i.e. if two
-# files, file1 & file2, are having a tag moved from version 1.1 to versoin 1.1.2.9, %{sVv}
-# will generate the following six arguments in this order: file1, 1.1, 1.1.2.9, file2, 1.1,
-# 1.1.2.9.
-#
-# A non-zero exit of the filter program will cause the tag to be aborted.
-#
-# The first entry on a line is a regular expression which is tested
-# against the directory that the change is being committed to, relative
-# to the $CVSROOT. For the first match that is found, then the remainder
-# of the line is the name of the filter to run.
-#
-# If the repository name does not match any of the regular expressions in this
-# file, the "DEFAULT" line is used, if it is specified.
-#
-# If the name "ALL" appears as a regular expression it is always used
-# in addition to the first matching regex or "DEFAULT".
diff --git a/CVSROOT/verifymsg b/CVSROOT/verifymsg
deleted file mode 100755
index 165d1cd..0000000
--- a/CVSROOT/verifymsg
+++ /dev/null
@@ -1,29 +0,0 @@
-# The "verifymsg" file is used to allow verification of logging
-# information. It works best when a template (as specified in the
-# rcsinfo file) is provided for the logging procedure. Given a
-# template with locations for, a bug-id number, a list of people who
-# reviewed the code before it can be checked in, and an external
-# process to catalog the differences that were code reviewed, the
-# following test can be applied to the code:
-#
-# Making sure that the entered bug-id number is correct.
-# Validating that the code that was reviewed is indeed the code being
-# checked in (using the bug-id number or a seperate review
-# number to identify this particular code set.).
-#
-# If any of the above test failed, then the commit would be aborted.
-#
-# Format strings present in the filter will be replaced as follows:
-# %p = path relative to repository
-# %r = repository (path portion of $CVSROOT)
-# %l = name of log file to be verified.
-#
-# If no format strings are present in the filter, a default " %l" will
-# be appended to the filter, but this usage is deprecated.
-#
-# Actions such as mailing a copy of the report to each reviewer are
-# better handled by an entry in the loginfo file.
-#
-# One thing that should be noted is the the ALL keyword is not
-# supported. There can be only one entry that matches a given
-# repository.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3ff7bc1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+CFLAGS += $(shell pkg-config --cflags lua)
+LDLIBS += $(shell pkg-config --libs lua) -lldap
+
+LUA_MODULES := $(shell pkg-config --variable=INSTALL_CMOD lua)
+
+all: lualdap.so
+
+lualdap.so: lualdap.c
+ $(CC) -fPIC -shared $(CFLAGS) -o $@ $^ $(LDLIBS)
+
+install: lualdap.so
+ mkdir -p "$(DESTDIR)$(LUA_MODULES)"
+ cp lualdap.so "$(DESTDIR)$(LUA_MODULES)"
+
+uninstall:
+ rm -f "$(DESTDIR)$(LUA_MODULES)/lualdap.so"
+
+clean:
+ rm -f lualdap.so
+
+.PHONY: uninstall clean all
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9c2841f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,278 @@
+# LuaLDAP - A Lua interface to an LDAP library
+
+## Overview
+
+LuaLDAP is a simple interface from Lua to OpenLDAP. It enables a Lua program to:
+
+ * Connect to an LDAP server;
+ * Execute any operation (search, add, compare, delete, modify and rename);
+ * Retrieve entries and references of the search result.
+
+LuaLDAP is free software and uses the same license as Lua 5.1.
+
+### Contributing
+
+Please send any patches or requests to <Jason@zx2c4.com>.
+
+### Credits
+
+LuaLDAP was originally designed by Roberto Ierusalimschy, Andre Carregal and Tomas Guisasola as part of the Kepler Project. It was implemented by Tomas Guisasola and Leonardo Godinho with contributions by Mark Edgar. LuaLDAP development was sponsored by Fabrica Digital and FINEP.
+
+It was abandoned in 2007, and revived in 2015 by Jason Donenfeld.
+
+## Manual
+
+### Introduction
+
+LuaLDAP defines one single global variable: a table called `lualdap`. This
+table holds the functions used to create an LDAP connection object.
+
+A connection object offers methods to perform any operation on the
+directory such as comparing values, adding new entries, modifying
+attributes on existing entries, removing entries, and the most common of
+all: searching. Entries are represented as Lua tables; attributes are its
+fields. The attribute values can be strings or tables of strings (used to
+represent multiple values).
+
+### Representing attributes
+
+Many LDAP operations manage sets of attributes and values. LuaLDAP
+provides a uniform way of representing them by using Lua tables. The table
+attributes can be Lua string, a binary string (a string of bits), or table
+of n values indexed from 1 to n. Some operations have different approaches
+that will be explained as necessary.
+
+Here is a simple example:
+
+ entry = {
+ an_attribute = "a value",
+ other_attribute = {
+ "first value of other attribute",
+ "another value of other attribute",
+ },
+ }
+
+Attribute names cannot contain the '\0' character.
+
+### Distinguished names
+
+The distinguished name (DN) is the term used to identify an entry on the
+directory information tree. It is formed by the relative distinguished
+name (RDN) of the entry and the distinguished name of its parent. LuaLDAP
+will always use a string to represent the DN of any entry.
+
+### Initialization functions
+
+LuaLDAP provides a single way to connect to an LDAP server:
+
+#### `lualdap.open_simple (connection_info_table)`
+
+Initializes a session with an LDAP server, and binds to it. The `connection_info_table`
+contains the following entries:
+
+##### uri
+
+An ldap:// or ldaps:// or similar URI for the requested server.
+
+##### who
+
+The DN of the user logging in.
+
+##### password
+
+A password to use in SASL.
+
+##### starttls
+
+A boolean of whether or not STARTTLS is to be used.
+
+##### certfile
+
+A path to a client certificate.
+
+##### keyfile
+
+A path to a client certificate key.
+
+##### cacertfile
+
+A path to a CA certificate chain.
+
+##### cacertdir
+
+A path to a CA certificate directory.
+
+### Connection objects
+
+A connection object offers methods which implement LDAP operations. Almost
+all of them need a distinguished name to identify the entry on which the
+operation will be executed.
+
+These methods execute asynchronous operations and return a function that
+should be called to obtain the results. The called functions will return
+true indicating the success of the operation. The only exception is the
+compare function which can return either true or false (as the result of
+the comparison) on a successful operation.
+
+There are two types of errors: API errors, such as wrong parameters,
+absent connection etc.; and LDAP errors, such as malformed DN, unknown
+attribute etc. API errors will raise a Lua error, while LDAP errors will
+be reported by the function/method returning nil plus the error message
+provided by the OpenLDAP client.
+
+A connection object can be created by calling the Initialization function.
+
+### Methods
+
+#### `conn:add (distinguished_name, table_of_attributes)`
+
+Adds a new entry to the directory with the given attributes and values.
+
+#### `conn:close()`
+
+Closes the connection conn.
+
+#### `conn:compare (distinguished_name, attribute, value)`
+
+Compares a value to an entry.
+
+#### `conn:delete (distinguished_name)`
+
+Deletes an entry from the directory.
+
+#### `conn:modify (distinguished_name, table_of_operations*)`
+
+Changes the values of attributes in the given entry. The tables of
+operations are tables of attributes with the value on index 1
+indicating the operation to be performed. The valid operations
+are:
+
+ * '+' to add the values to the attributes
+ * '-' to delete the values of the attributes
+ * '=' to replace the values of the attributes
+
+Any number of tables of operations will be used in a single LDAP
+modify operation.
+
+#### `conn:rename (distinguished_name, new_relative_dn, new_parent)`
+
+Changes an entry name (i.e. change its distinguished name).
+
+#### `conn:search (table_of_search_parameters)`
+
+Performs a search operation on the directory.
+The search method will return a search iterator which is a
+function that requires no arguments. The search iterator is used
+to get the search result and will return a string representing the
+distinguished name and a table of attributes as returned by the
+search request.
+
+The parameters are described below:
+
+##### attrs
+
+a string or a list of attribute names to be retrieved
+(default is to retrieve all attributes).
+
+##### attrsonly
+
+a Boolean value that must be either false (default)
+if both attribute names and values are to be
+retrieved, or true if only names are wanted.
+
+##### base
+
+The distinguished name of the entry at which to start
+the search.
+
+##### filter
+
+A string representing the search filter as described
+in The String Representation of LDAP Search Filters
+(RFC 2254).
+
+##### scope
+
+A string indicating the scope of the search. The
+valid strings are: "base", "onelevel" and "subtree".
+The empty string ("") and nil will be treated as the
+default scope.
+
+##### sizelimit
+
+The maximum number of entries to return (default is
+no limit).
+
+##### timeout
+
+The timeout in seconds (default is no timeout). The
+precision is microseconds.
+
+
+### Example
+
+Here is a some sample code that demonstrate the basic use of the library:
+
+ require "lualdap"
+
+ ld = assert (lualdap.open_simple { uri = "ldap://ldap.server",
+ who = "mydn=manoeljoaquim,ou=people,dc=ldap,dc=world",
+ password = "mysecurepassword" })
+
+ for dn, attribs in ld:search { base = "ou=people,dc=ldap,dc=world" } do
+ io.write (string.format ("\t[%s]\n", dn))
+ for name, values in pairs (attribs) do
+ io.write ("["..name.."] : ")
+ if type (values) == "string" then
+ io.write (values)
+ elseif type (values) == "table" then
+ local n = table.getn(values)
+ for i = 1, (n-1) do
+ io.write (values[i]..",")
+ end
+ io.write (values[n])
+ end
+ io.write ("\n")
+ end
+ end
+
+ ld:add ("mydn=newuser,ou=people,dc=ldap,dc=world", {
+ objectClass = { "", "", },
+ mydn = "newuser",
+ abc = "qwerty",
+ tel = { "123456758", "98765432", },
+ givenName = "New User",
+ })()
+
+ ld:modify {"mydn=newuser,ou=people,dc=ldp,dc=world",
+ { '=', givenName = "New", cn = "New", sn = "User", },
+ { '+', o = { "University", "College", },
+ mail = "newuser@university.edu", },
+ { '-', abc = true, tel = "123456758", },
+ { '+', tel = "13579113", },
+ }()
+
+ ld:delete ("mydn=newuser,ou=people,dc=ldp,dc=world")()
+
+## License
+
+ Copyright (c) 2003-2007 The Kepler Project.
+ Copyright (c) 2015 Jason A. Donenfeld <Jason@zx2c4.com>.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
diff --git a/lualdap.c b/lualdap.c
new file mode 100644
index 0000000..a3f42a9
--- /dev/null
+++ b/lualdap.c
@@ -0,0 +1,1056 @@
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <ldap.h>
+#include <lua.h>
+#include <lauxlib.h>
+
+#define LUALDAP_PREFIX "LuaLDAP: "
+#define LUALDAP_TABLENAME "lualdap"
+#define LUALDAP_CONNECTION_METATABLE "LuaLDAP connection"
+#define LUALDAP_SEARCH_METATABLE "LuaLDAP search"
+
+#define LUALDAP_MOD_ADD (LDAP_MOD_ADD | LDAP_MOD_BVALUES)
+#define LUALDAP_MOD_DEL (LDAP_MOD_DELETE | LDAP_MOD_BVALUES)
+#define LUALDAP_MOD_REP (LDAP_MOD_REPLACE | LDAP_MOD_BVALUES)
+#define LUALDAP_NO_OP 0
+
+/* Maximum number of attributes manipulated in an operation */
+#ifndef LUALDAP_MAX_ATTRS
+#define LUALDAP_MAX_ATTRS 100
+#endif
+
+/* Size of buffer of NULL-terminated arrays of pointers to struct values */
+#ifndef LUALDAP_ARRAY_VALUES_SIZE
+#define LUALDAP_ARRAY_VALUES_SIZE (2 * LUALDAP_MAX_ATTRS)
+#endif
+
+/* Maximum number of values structures */
+#ifndef LUALDAP_MAX_VALUES
+#define LUALDAP_MAX_VALUES (LUALDAP_ARRAY_VALUES_SIZE / 2)
+#endif
+
+
+typedef struct {
+ LDAP *ld; /* LDAP connection */
+} conn_data;
+
+
+/* LDAP search context information */
+typedef struct {
+ int conn; /* conn_data reference */
+ int msgid;
+} search_data;
+
+
+/* LDAP attribute modification structure */
+typedef struct {
+ LDAPMod * attrs[LUALDAP_MAX_ATTRS + 1];
+ LDAPMod mods[LUALDAP_MAX_ATTRS];
+ int ai;
+ BerValue * values[LUALDAP_ARRAY_VALUES_SIZE];
+ int vi;
+ BerValue bvals[LUALDAP_MAX_VALUES];
+ int bi;
+} attrs_data;
+
+
+int luaopen_lualdap(lua_State *L);
+
+
+/*
+** Typical error situation.
+*/
+static int faildirect(lua_State *L, const char *errmsg)
+{
+ lua_pushnil(L);
+ lua_pushstring(L, errmsg);
+ return 2;
+}
+
+
+/*
+** Get a connection object from the first stack position.
+*/
+static conn_data *getconnection(lua_State *L)
+{
+ conn_data *conn = (conn_data *)luaL_checkudata(L, 1, LUALDAP_CONNECTION_METATABLE);
+ luaL_argcheck(L, conn != NULL, 1, LUALDAP_PREFIX "LDAP connection expected");
+ luaL_argcheck(L, conn->ld, 1, LUALDAP_PREFIX "LDAP connection is closed");
+ return conn;
+}
+
+
+/*
+** Get a search object from the first upvalue position.
+*/
+static search_data *getsearch(lua_State *L)
+{
+ /* don't need to check upvalue's integrity */
+ search_data *search = (search_data *)lua_touserdata(L, lua_upvalueindex(1));
+ luaL_argcheck (L, search->conn != LUA_NOREF, 1, LUALDAP_PREFIX "LDAP search is closed");
+ return search;
+}
+
+
+/*
+** Set metatable of userdata on top of the stack.
+*/
+static void lualdap_setmeta(lua_State *L, const char *name)
+{
+ luaL_getmetatable(L, name);
+ lua_setmetatable(L, -2);
+}
+
+
+/*
+** Error on option.
+*/
+static int option_error(lua_State *L, const char *name, const char *type)
+{
+ return luaL_error(L, LUALDAP_PREFIX "invalid value on option `%s': %s expected, got %s", name, type, lua_typename(L, lua_type(L, -1)));
+}
+
+
+/*
+** Get the field called name of the table at position 2.
+*/
+static void strgettable(lua_State *L, const char *name)
+{
+ lua_pushstring(L, name);
+ lua_gettable(L, 2);
+}
+
+
+/*
+** Get the field named name as a string.
+** The table MUST be at position 2.
+*/
+static const char *strtabparam(lua_State *L, const char *name, char *def)
+{
+ strgettable(L, name);
+ if (lua_isnil(L, -1))
+ return def;
+ else if (lua_isstring(L, -1))
+ return lua_tostring(L, -1);
+ else {
+ option_error(L, name, "string");
+ return NULL;
+ }
+}
+
+
+/*
+** Get the field named name as an integer.
+** The table MUST be at position 2.
+*/
+static long longtabparam(lua_State *L, const char *name, int def)
+{
+ strgettable(L, name);
+ if (lua_isnil(L, -1))
+ return def;
+ else if (lua_isnumber(L, -1))
+ return (long)lua_tonumber(L, -1);
+ else
+ return option_error(L, name, "number");
+}
+
+
+/*
+** Get the field named name as a double.
+** The table MUST be at position 2.
+*/
+static double numbertabparam(lua_State *L, const char *name, double def)
+{
+ strgettable(L, name);
+ if (lua_isnil(L, -1))
+ return def;
+ else if (lua_isnumber(L, -1))
+ return lua_tonumber(L, -1);
+ else
+ return option_error(L, name, "number");
+}
+
+
+/*
+** Get the field named name as a boolean.
+** The table MUST be at position 2.
+*/
+static int booltabparam(lua_State *L, const char *name, int def)
+{
+ strgettable(L, name);
+ if (lua_isnil(L, -1))
+ return def;
+ else if (lua_isboolean(L, -1))
+ return lua_toboolean(L, -1);
+ else
+ return option_error(L, name, "boolean");
+}
+
+
+/*
+** Error on attribute's value.
+*/
+static void value_error(lua_State *L, const char *name)
+{
+ luaL_error(L, LUALDAP_PREFIX "invalid value of attribute `%s' (%s)",
+ name, lua_typename(L, lua_type(L, -1)));
+}
+
+
+/*
+** Initialize attributes structure.
+*/
+static void A_init(attrs_data *attrs)
+{
+ attrs->ai = 0;
+ attrs->attrs[0] = NULL;
+ attrs->vi = 0;
+ attrs->values[0] = NULL;
+ attrs->bi = 0;
+}
+
+
+/*
+** Store the string on top of the stack on the attributes structure.
+** Increment the bvals counter.
+*/
+static BerValue *A_setbval(lua_State *L, attrs_data *a, const char *n)
+{
+ BerValue *ret = &(a->bvals[a->bi]);
+ if (a->bi >= LUALDAP_MAX_VALUES) {
+ luaL_error(L, LUALDAP_PREFIX "too many values");
+ return NULL;
+ } else if (!lua_isstring(L, -1)) {
+ value_error(L, n);
+ return NULL;
+ }
+ a->bvals[a->bi].bv_len = lua_strlen(L, -1);
+ a->bvals[a->bi].bv_val = (char *)lua_tostring(L, -1);
+ a->bi++;
+ return ret;
+}
+
+
+/*
+** Store a pointer to the value on top of the stack on the attributes structure.
+*/
+static BerValue **A_setval(lua_State *L, attrs_data *a, const char *n)
+{
+ BerValue **ret = &(a->values[a->vi]);
+ if (a->vi >= LUALDAP_ARRAY_VALUES_SIZE) {
+ luaL_error(L, LUALDAP_PREFIX "too many values");
+ return NULL;
+ }
+ a->values[a->vi] = A_setbval(L, a, n);
+ a->vi++;
+ return ret;
+}
+
+
+/*
+** Store a NULL pointer on the attributes structure.
+*/
+static BerValue **A_nullval(lua_State *L, attrs_data *a)
+{
+ BerValue **ret = &(a->values[a->vi]);
+ if (a->vi >= LUALDAP_ARRAY_VALUES_SIZE) {
+ luaL_error(L, LUALDAP_PREFIX "too many values");
+ return NULL;
+ }
+ a->values[a->vi] = NULL;
+ a->vi++;
+ return ret;
+}
+
+
+/*
+** Store the value of an attribute.
+** Valid values are:
+** true => no values;
+** string => one value; or
+** table of strings => many values.
+*/
+static BerValue **A_tab2val(lua_State *L, attrs_data *a, const char *name)
+{
+ int tab = lua_gettop(L);
+ BerValue **ret = &(a->values[a->vi]);
+ if (lua_isboolean(L, tab) && (lua_toboolean(L, tab) == 1)) /* true */
+ return NULL;
+ else if (lua_isstring(L, tab)) /* string */
+ A_setval(L, a, name);
+ else if (lua_istable(L, tab)) { /* list of strings */
+ int i;
+ int n = luaL_getn(L, tab);
+
+ for (i = 1; i <= n; i++) {
+ lua_rawgeti(L, tab, i); /* push table element */
+ A_setval(L, a, name);
+ }
+ lua_pop(L, n);
+ } else {
+ value_error(L, name);
+ return NULL;
+ }
+ A_nullval(L, a);
+ return ret;
+}
+
+
+/*
+** Set a modification value (which MUST be on top of the stack).
+*/
+static void A_setmod(lua_State *L, attrs_data *a, int op, const char *name)
+{
+ if (a->ai >= LUALDAP_MAX_ATTRS) {
+ luaL_error(L, LUALDAP_PREFIX "too many attributes");
+ return;
+ }
+ a->mods[a->ai].mod_op = op;
+ a->mods[a->ai].mod_type = (char *)name;
+ a->mods[a->ai].mod_bvalues = A_tab2val(L, a, name);
+ a->attrs[a->ai] = &a->mods[a->ai];
+ a->ai++;
+}
+
+
+/*
+** Convert a Lua table into an array of modifications.
+** An array of modifications is a NULL-terminated array of LDAPMod's.
+*/
+static void A_tab2mod(lua_State *L, attrs_data *a, int tab, int op)
+{
+ lua_pushnil(L); /* first key for lua_next */
+ while (lua_next(L, tab) != 0) {
+ /* attribute must be a string and not a number */
+ if ((!lua_isnumber(L, -2)) && (lua_isstring(L, -2)))
+ A_setmod(L, a, op, lua_tostring(L, -2));
+ /* pop value and leave last key on the stack as next key for lua_next */
+ lua_pop(L, 1);
+ }
+}
+
+
+/*
+** Terminate the array of attributes.
+*/
+static void A_lastattr(lua_State *L, attrs_data *a)
+{
+ if (a->ai >= LUALDAP_MAX_ATTRS) {
+ luaL_error(L, LUALDAP_PREFIX "too many attributes");
+ return;
+ }
+ a->attrs[a->ai] = NULL;
+ a->ai++;
+}
+
+
+/*
+** Copy a string or a table of strings from Lua to a NULL-terminated array
+** of C-strings.
+*/
+static int table2strarray(lua_State *L, int tab, char *array[], int limit)
+{
+ if (lua_isstring(L, tab)) {
+ if (limit < 2)
+ return luaL_error(L, LUALDAP_PREFIX "too many arguments");
+ array[0] = (char *)lua_tostring(L, tab);
+ array[1] = NULL;
+ } else if (lua_istable(L, tab)) {
+ int i;
+ int n = luaL_getn(L, tab);
+
+ if (limit < (n+1))
+ return luaL_error(L, LUALDAP_PREFIX "too many arguments");
+ for (i = 0; i < n; i++) {
+ lua_rawgeti(L, tab, i+1); /* push table element */
+ if (lua_isstring(L, -1))
+ array[i] = (char *)lua_tostring(L, -1);
+ else {
+ return luaL_error(L, LUALDAP_PREFIX "invalid value #%d", i+1);
+ }
+ }
+ array[n] = NULL;
+ } else
+ return luaL_error(L, LUALDAP_PREFIX "bad argument #%d (table or string expected, got %s)", tab, lua_typename(L, lua_type(L, tab)));
+ return 0;
+}
+
+
+/*
+** Get the result message of an operation.
+** #1 upvalue == connection
+** #2 upvalue == msgid
+** #3 upvalue == result code of the message (ADD, DEL etc.) to be received.
+*/
+static int result_message(lua_State *L)
+{
+ struct timeval *timeout = NULL; /* ??? function parameter ??? */
+ LDAPMessage *res;
+ int rc;
+ conn_data *conn = (conn_data *)lua_touserdata(L, lua_upvalueindex(1));
+ int msgid = (int)lua_tonumber(L, lua_upvalueindex(2));
+ luaL_argcheck(L, conn->ld, 1, LUALDAP_PREFIX "LDAP connection is closed");
+ rc = ldap_result(conn->ld, msgid, LDAP_MSG_ONE, timeout, &res);
+ if (rc == 0)
+ return faildirect(L, LUALDAP_PREFIX "result timeout expired");
+ else if (rc < 0) {
+ ldap_msgfree(res);
+ return faildirect(L, LUALDAP_PREFIX "result error");
+ } else {
+ int err, ret = 1;
+ char *mdn, *msg;
+
+ rc = ldap_parse_result(conn->ld, res, &err, &mdn, &msg, NULL, NULL, 1);
+ if (rc != LDAP_SUCCESS)
+ return faildirect(L, ldap_err2string(rc));
+ switch (err) {
+ case LDAP_SUCCESS:
+ case LDAP_COMPARE_TRUE:
+ lua_pushboolean(L, 1);
+ break;
+ case LDAP_COMPARE_FALSE:
+ lua_pushboolean(L, 0);
+ break;
+ default:
+ lua_pushnil(L);
+ lua_pushliteral(L, LUALDAP_PREFIX);
+ lua_pushstring(L, msg);
+ lua_pushliteral(L, " ");
+ lua_pushstring(L, ldap_err2string(err));
+ lua_concat(L, 4);
+ ret = 2;
+ }
+ ldap_memfree(mdn);
+ ldap_memfree(msg);
+ return ret;
+ }
+}
+
+
+/*
+** Push a function to process the LDAP result.
+*/
+static int create_future(lua_State *L, int rc, int conn, int msgid, int code)
+{
+ if (rc != LDAP_SUCCESS)
+ return faildirect(L, ldap_err2string(rc));
+ lua_pushvalue(L, conn); /* push connection as #1 upvalue */
+ lua_pushnumber(L, msgid); /* push msgid as #2 upvalue */
+ lua_pushnumber(L, code); /* push code as #3 upvalue */
+ lua_pushcclosure(L, result_message, 3);
+ return 1;
+}
+
+
+/*
+** Unbind from the directory.
+** @param #1 LDAP connection.
+** @return 1 in case of success; nothing when already closed.
+*/
+static int lualdap_close(lua_State *L)
+{
+ conn_data *conn = (conn_data *)luaL_checkudata(L, 1, LUALDAP_CONNECTION_METATABLE);
+ luaL_argcheck(L, conn != NULL, 1, LUALDAP_PREFIX "LDAP connection expected");
+ if (conn->ld == NULL) /* already closed */
+ return 0;
+ ldap_unbind_ext(conn->ld, NULL, NULL);
+ conn->ld = NULL;
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+
+/*
+** Add a new entry to the directory.
+** @param #1 LDAP connection.
+** @param #2 String with new entry's DN.
+** @param #3 Table with new entry's attributes and values.
+** @return Function to process the LDAP result.
+*/
+static int lualdap_add(lua_State *L)
+{
+ conn_data *conn = getconnection(L);
+ const char *dn = luaL_checkstring(L, 2);
+ attrs_data attrs;
+ int rc, msgid;
+ A_init(&attrs);
+ if (lua_istable(L, 3))
+ A_tab2mod(L, &attrs, 3, LUALDAP_MOD_ADD);
+ A_lastattr(L, &attrs);
+ rc = ldap_add_ext(conn->ld, dn, attrs.attrs, NULL, NULL, &msgid);
+ return create_future(L, rc, 1, msgid, LDAP_RES_ADD);
+}
+
+
+/*
+** Compare a value against an entry.
+** @param #1 LDAP connection.
+** @param #2 String with entry's DN.
+** @param #3 String with attribute's name.
+** @param #4 String with attribute's value.
+** @return Function to process the LDAP result.
+*/
+static int lualdap_compare(lua_State *L)
+{
+ conn_data *conn = getconnection(L);
+ const char *dn = luaL_checkstring(L, 2);
+ const char *attr = luaL_checkstring(L, 3);
+ BerValue bvalue;
+ int rc, msgid;
+ bvalue.bv_val = (char *)luaL_checkstring(L, 4);
+ bvalue.bv_len = lua_strlen(L, 4);
+ rc = ldap_compare_ext(conn->ld, dn, attr, &bvalue, NULL, NULL, &msgid);
+ return create_future(L, rc, 1, msgid, LDAP_RES_COMPARE);
+}
+
+
+/*
+** Delete an entry.
+** @param #1 LDAP connection.
+** @param #2 String with entry's DN.
+** @return Boolean.
+*/
+static int lualdap_delete(lua_State *L)
+{
+ conn_data *conn = getconnection(L);
+ const char *dn = luaL_checkstring(L, 2);
+ int rc, msgid;
+ rc = ldap_delete_ext(conn->ld, dn, NULL, NULL, &msgid);
+ return create_future(L, rc, 1, msgid, LDAP_RES_DELETE);
+}
+
+
+/*
+** Convert a string into an internal LDAP_MOD operation code.
+*/
+static int op2code(const char *s)
+{
+ if (!s)
+ return LUALDAP_NO_OP;
+ switch (*s) {
+ case '+':
+ return LUALDAP_MOD_ADD;
+ case '-':
+ return LUALDAP_MOD_DEL;
+ case '=':
+ return LUALDAP_MOD_REP;
+ default:
+ return LUALDAP_NO_OP;
+ }
+}
+
+
+/*
+** Modify an entry.
+** @param #1 LDAP connection.
+** @param #2 String with entry's DN.
+** @param #3, #4... Tables with modifications to apply.
+** @return True on success or nil, error message otherwise.
+*/
+static int lualdap_modify(lua_State *L)
+{
+ conn_data *conn = getconnection(L);
+ const char *dn = luaL_checkstring(L, 2);
+ attrs_data attrs;
+ int rc, msgid;
+ int param = 3;
+ A_init(&attrs);
+ while (lua_istable(L, param)) {
+ int op;
+ /* get operation ('+','-','=' operations allowed) */
+ lua_rawgeti(L, param, 1);
+ op = op2code(lua_tostring(L, -1));
+ if (op == LUALDAP_NO_OP)
+ return luaL_error(L, LUALDAP_PREFIX "forgotten operation on argument #%d", param);
+ /* get array of attributes and values */
+ A_tab2mod(L, &attrs, param, op);
+ param++;
+ }
+ A_lastattr(L, &attrs);
+ rc = ldap_modify_ext(conn->ld, dn, attrs.attrs, NULL, NULL, &msgid);
+ return create_future(L, rc, 1, msgid, LDAP_RES_MODIFY);
+}
+
+
+/*
+** Change the distinguished name of an entry.
+*/
+static int lualdap_rename(lua_State *L)
+{
+ conn_data *conn = getconnection(L);
+ const char *dn = luaL_checkstring(L, 2);
+ const char *rdn = luaL_checkstring(L, 3);
+ const char *par = luaL_optlstring(L, 4, NULL, NULL);
+ const int del = luaL_optnumber(L, 5, 0);
+ int msgid;
+ int rc = ldap_rename(conn->ld, dn, rdn, par, del, NULL, NULL, &msgid);
+ return create_future(L, rc, 1, msgid, LDAP_RES_MODDN);
+}
+
+
+/*
+** Push an attribute value (or a table of values) on top of the stack.
+** @param L lua_State.
+** @param ld LDAP Connection.
+** @param entry Current entry.
+** @param attr Name of entry's attribute to get values from.
+** @return 1 in case of success.
+*/
+static int push_values(lua_State *L, LDAP *ld, LDAPMessage *entry, char *attr)
+{
+ int i, n;
+ BerValue **vals = ldap_get_values_len(ld, entry, attr);
+ n = ldap_count_values_len(vals);
+ if (n == 0) /* no values */
+ lua_pushboolean(L, 1);
+ else if (n == 1) /* just one value */
+ lua_pushlstring(L, vals[0]->bv_val, vals[0]->bv_len);
+ else { /* Multiple values */
+ lua_newtable(L);
+ for (i = 0; i < n; i++) {
+ lua_pushlstring(L, vals[i]->bv_val, vals[i]->bv_len);
+ lua_rawseti(L, -2, i+1);
+ }
+ }
+ ldap_value_free_len(vals);
+ return 1;
+}
+
+
+/*
+** Store entry's attributes and values at the given table.
+** @param entry Current entry.
+** @param tab Absolute stack index of the table.
+*/
+static void set_attribs(lua_State *L, LDAP *ld, LDAPMessage *entry, int tab)
+{
+ char *attr;
+ BerElement *ber = NULL;
+ for (attr = ldap_first_attribute(ld, entry, &ber);
+ attr != NULL;
+ attr = ldap_next_attribute(ld, entry, ber)) {
+ lua_pushstring(L, attr);
+ push_values(L, ld, entry, attr);
+ lua_rawset(L, tab); /* tab[attr] = vals */
+ ldap_memfree(attr);
+ }
+ ber_free(ber, 0); /* don't need to test if (ber == NULL) */
+}
+
+
+/*
+** Get the distinguished name of the given entry and pushes it on the stack.
+*/
+static void push_dn(lua_State *L, LDAP *ld, LDAPMessage *entry)
+{
+ char *dn = ldap_get_dn(ld, entry);
+ lua_pushstring(L, dn);
+ ldap_memfree(dn);
+}
+
+
+/*
+** Release connection reference.
+*/
+static void search_close(lua_State *L, search_data *search)
+{
+ luaL_unref(L, LUA_REGISTRYINDEX, search->conn);
+ search->conn = LUA_NOREF;
+}
+
+
+/*
+** Retrieve next message...
+** @return #1 entry's distinguished name.
+** @return #2 table with entry's attributes and values.
+*/
+static int next_message(lua_State *L)
+{
+ search_data *search = getsearch(L);
+ conn_data *conn;
+ struct timeval *timeout = NULL; /* ??? function parameter ??? */
+ LDAPMessage *res;
+ int rc;
+ int ret;
+ lua_rawgeti(L, LUA_REGISTRYINDEX, search->conn);
+ conn = (conn_data *)lua_touserdata(L, -1); /* get connection */
+ rc = ldap_result(conn->ld, search->msgid, LDAP_MSG_ONE, timeout, &res);
+ if (rc == 0)
+ return faildirect(L, LUALDAP_PREFIX "result timeout expired");
+ else if (rc == -1)
+ return faildirect(L, LUALDAP_PREFIX "result error");
+ else if (rc == LDAP_RES_SEARCH_RESULT) { /* last message => nil */
+ /* close search object to avoid reuse */
+ search_close(L, search);
+ ret = 0;
+ } else {
+ LDAPMessage *msg = ldap_first_message(conn->ld, res);
+ switch (ldap_msgtype(msg)) {
+ case LDAP_RES_SEARCH_ENTRY: {
+ LDAPMessage *entry = ldap_first_entry(conn->ld, msg);
+ push_dn(L, conn->ld, entry);
+ lua_newtable(L);
+ set_attribs(L, conn->ld, entry, lua_gettop(L));
+ ret = 2; /* two return values */
+ break;
+ }
+ case LDAP_RES_SEARCH_REFERENCE: {
+ LDAPMessage *ref = ldap_first_reference(conn->ld, msg);
+ push_dn(L, conn->ld, ref); /* is this supposed to work? */
+ lua_pushnil(L);
+ ret = 2; /* two return values */
+ break;
+ }
+ case LDAP_RES_SEARCH_RESULT:
+ /* close search object to avoid reuse */
+ search_close(L, search);
+ ret = 0;
+ break;
+ default:
+ ldap_msgfree(res);
+ return luaL_error(L, LUALDAP_PREFIX "error on search result chain");
+ }
+ }
+ ldap_msgfree(res);
+ return ret;
+}
+
+
+/*
+** Convert a string to one of the possible scopes of the search.
+*/
+static int string2scope(lua_State *L, const char *s)
+{
+ if ((s == NULL) || (*s == '\0'))
+ return LDAP_SCOPE_DEFAULT;
+ switch (*s) {
+ case 'b':
+ return LDAP_SCOPE_BASE;
+ case 'o':
+ return LDAP_SCOPE_ONELEVEL;
+ case 's':
+ return LDAP_SCOPE_SUBTREE;
+ default:
+ return luaL_error(L, LUALDAP_PREFIX "invalid search scope `%s'", s);
+ }
+}
+
+
+/*
+** Close the search object.
+*/
+static int lualdap_search_close(lua_State *L)
+{
+ search_data *search = (search_data *)luaL_checkudata(L, 1, LUALDAP_SEARCH_METATABLE);
+ luaL_argcheck (L, search != NULL, 1, LUALDAP_PREFIX "LDAP search expected");
+ if (search->conn == LUA_NOREF)
+ return 0;
+ search_close(L, search);
+ lua_pushnumber(L, 1);
+ return 1;
+}
+
+
+/*
+** Create a search object and leaves it on top of the stack.
+*/
+static void create_search(lua_State *L, int conn_index, int msgid)
+{
+ search_data *search = (search_data *)lua_newuserdata(L, sizeof(search_data));
+ lualdap_setmeta(L, LUALDAP_SEARCH_METATABLE);
+ search->conn = LUA_NOREF;
+ search->msgid = msgid;
+ lua_pushvalue(L, conn_index);
+ search->conn = luaL_ref(L, LUA_REGISTRYINDEX);
+}
+
+
+/*
+** Fill in the attrs array, according to the attrs parameter.
+*/
+static int get_attrs_param(lua_State *L, char *attrs[])
+{
+ lua_pushstring(L, "attrs");
+ lua_gettable(L, 2);
+ if (lua_isstring(L, -1)) {
+ attrs[0] = (char *)lua_tostring(L, -1);
+ attrs[1] = NULL;
+ } else if (!lua_istable(L, -1))
+ attrs[0] = NULL;
+ else if (table2strarray(L, lua_gettop(L), attrs, LUALDAP_MAX_ATTRS))
+ return 0;
+ return 1;
+}
+
+
+/*
+** Fill in the struct timeval, according to the timeout parameter.
+*/
+static struct timeval *get_timeout_param(lua_State *L, struct timeval *st)
+{
+ double t = numbertabparam(L, "timeout", 0);
+ st->tv_sec = (long)t;
+ st->tv_usec = (long)(1000000 * (t - st->tv_sec));
+ if (st->tv_sec == 0 && st->tv_usec == 0)
+ return NULL;
+ else
+ return st;
+}
+
+
+/*
+** Perform a search operation.
+** @return #1 Function to iterate over the result entries.
+** @return #2 nil.
+** @return #3 nil as first entry.
+** The search result is defined as an upvalue of the iterator.
+*/
+static int lualdap_search(lua_State *L)
+{
+ conn_data *conn = getconnection(L);
+ const char *base;
+ const char *filter;
+ char *attrs[LUALDAP_MAX_ATTRS];
+ int scope, attrsonly, msgid, rc, sizelimit;
+ struct timeval st, *timeout;
+ if (!lua_istable(L, 2))
+ return luaL_error(L, LUALDAP_PREFIX "no search specification");
+ if (!get_attrs_param(L, attrs))
+ return 2;
+ /* get other parameters */
+ attrsonly = booltabparam(L, "attrsonly", 0);
+ base = strtabparam(L, "base", NULL);
+ filter = strtabparam(L, "filter", NULL);
+ scope = string2scope(L, strtabparam(L, "scope", NULL));
+ sizelimit = longtabparam(L, "sizelimit", LDAP_NO_LIMIT);
+ timeout = get_timeout_param(L, &st);
+ rc = ldap_search_ext(conn->ld, base, scope, filter, attrs, attrsonly,
+ NULL, NULL, timeout, sizelimit, &msgid);
+ if (rc != LDAP_SUCCESS)
+ return luaL_error(L, LUALDAP_PREFIX "%s", ldap_err2string(rc));
+
+ create_search(L, 1, msgid);
+ lua_pushcclosure(L, next_message, 1);
+ return 1;
+}
+
+
+/*
+** Return the name of the object's metatable.
+** This function is used by `tostring'.
+*/
+static int lualdap_conn_tostring(lua_State *L)
+{
+ char buff[100];
+ conn_data *conn = (conn_data *)lua_touserdata(L, 1);
+ if (conn->ld == NULL)
+ strcpy(buff, "closed");
+ else
+ sprintf(buff, "%p", conn);
+ lua_pushfstring(L, "%s (%s)", LUALDAP_CONNECTION_METATABLE, buff);
+ return 1;
+}
+
+
+/*
+** Return the name of the object's metatable.
+** This function is used by `tostring'.
+*/
+static int lualdap_search_tostring(lua_State *L)
+{
+ char buff[100];
+ search_data *search = (search_data *)lua_touserdata(L, 1);
+ luaL_argcheck (L, search->conn != LUA_NOREF, 1, LUALDAP_PREFIX "LDAP search is closed");
+ if (search->conn == LUA_NOREF)
+ strcpy(buff, "closed");
+ else
+ snprintf(buff, 100, "%p", search);
+ lua_pushfstring(L, "%s (%s)", LUALDAP_SEARCH_METATABLE, buff);
+ return 1;
+}
+
+
+/*
+** Create a metatable.
+*/
+static int lualdap_createmeta(lua_State *L)
+{
+ const luaL_reg methods[] = {
+ {"close", lualdap_close},
+ {"add", lualdap_add},
+ {"compare", lualdap_compare},
+ {"delete", lualdap_delete},
+ {"modify", lualdap_modify},
+ {"rename", lualdap_rename},
+ {"search", lualdap_search},
+ {NULL, NULL}
+ };
+
+ if (!luaL_newmetatable(L, LUALDAP_CONNECTION_METATABLE))
+ return 0;
+
+ /* define methods */
+ luaL_register(L, NULL, methods);
+
+ /* define metamethods */
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, lualdap_close);
+ lua_settable(L, -3);
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, -2);
+ lua_settable(L, -3);
+
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, lualdap_conn_tostring);
+ lua_settable(L, -3);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushliteral(L, LUALDAP_PREFIX "you're not allowed to get this metatable");
+ lua_settable(L, -3);
+
+ if (!luaL_newmetatable(L, LUALDAP_SEARCH_METATABLE))
+ return 0;
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, lualdap_search_close);
+ lua_settable(L, -3);
+
+ lua_pushliteral(L, "__tostring");
+ lua_pushcclosure(L, lualdap_search_tostring, 1);
+ lua_settable(L, -3);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushliteral(L, LUALDAP_PREFIX "you're not allowed to get this metatable");
+ lua_settable(L, -3);
+
+ return 0;
+}
+
+
+/*
+** Open and initialize a connection to a server.
+** @param #1 table of connection options { uri, who, password, starttls, certfile, keyfile, cacertfile, cacertdir }
+** @return #1 Userdata with connection structure.
+*/
+static int lualdap_open_simple(lua_State *L)
+{
+ char *uri = NULL;
+ const char *who = NULL;
+ const char *password = NULL;
+ int starttls = 0;
+ const char *certfile = NULL;
+ const char *keyfile = NULL;
+ const char *cacertfile = NULL;
+ const char *cacertdir = NULL;
+
+ if (lua_istable(L, 1)) {
+ /* New API */
+ lua_settop(L, 1);
+ luaL_checktype(L, 1, LUA_TTABLE);
+ lua_getfield(L, 1, "uri");
+ lua_getfield(L, 1, "who");
+ lua_getfield(L, 1, "password");
+ lua_getfield(L, 1, "starttls");
+ lua_getfield(L, 1, "certfile");
+ lua_getfield(L, 1, "keyfile");
+ lua_getfield(L, 1, "cacertfile");
+ lua_getfield(L, 1, "cacertdir");
+
+ uri = (char *)luaL_checkstring(L, -8);
+ who = luaL_optstring(L, -7, NULL);
+ password = luaL_optstring(L, -6, NULL);
+ starttls = lua_toboolean(L, -5);
+ certfile = luaL_optstring(L, -4, NULL);
+ keyfile = luaL_optstring(L, -3, NULL);
+ cacertfile = luaL_optstring(L, -2, NULL);
+ cacertdir = luaL_optstring(L, -1, NULL);
+
+ /* Does popping here cause a use-after-free for those strings? */
+ lua_pop(L, 8);
+ } else {
+ /* Old API */
+ const char *hostname = luaL_checkstring(L, 1);
+ size_t hostname_len = strlen(hostname);
+
+ if (hostname_len > 248)
+ return faildirect(L, LUALDAP_PREFIX "Hostname is too large");
+ uri = alloca(hostname_len + 8);
+ strcpy(uri, "ldap://");
+ strcat(uri, hostname);
+
+ who = luaL_optstring(L, 2, NULL);
+ password = luaL_optstring(L, 3, NULL);
+ starttls = lua_toboolean(L, 4);
+ }
+
+ conn_data *conn = (conn_data *)lua_newuserdata(L, sizeof(conn_data));
+ struct berval cred = { password ? strlen(password) : 0, (char *)password };
+ int err, val;
+
+ lualdap_setmeta(L, LUALDAP_CONNECTION_METATABLE);
+ err = ldap_initialize(&conn->ld, uri);
+ if (err != LDAP_SUCCESS)
+ return faildirect(L, LUALDAP_PREFIX "Error connecting to server");
+
+ val = LDAP_VERSION3;
+ if (ldap_set_option(conn->ld, LDAP_OPT_PROTOCOL_VERSION, &val) != LDAP_OPT_SUCCESS)
+ return faildirect(L, LUALDAP_PREFIX "Error setting LDAP version");
+
+ if (certfile)
+ ldap_set_option(conn->ld, LDAP_OPT_X_TLS_CERTFILE, certfile);
+ if (keyfile)
+ ldap_set_option(conn->ld, LDAP_OPT_X_TLS_KEYFILE, keyfile);
+ if (cacertfile)
+ ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, cacertfile); /* The ca cert must be set globally */
+ if (cacertdir)
+ ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR, cacertfile); /* The ca cert must be set globally */
+
+ if (starttls) {
+ err = ldap_start_tls_s(conn->ld, NULL, NULL);
+ if (err != LDAP_SUCCESS)
+ return faildirect(L, ldap_err2string(err));
+ }
+
+ err = ldap_sasl_bind_s(conn->ld, who, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
+ if (err != LDAP_SUCCESS)
+ return faildirect(L, ldap_err2string(err));
+
+ return 1;
+}
+
+
+/*
+** Assumes the table is on top of the stack.
+*/
+static void set_info(lua_State *L)
+{
+ lua_pushliteral(L, "_COPYRIGHT");
+ lua_pushliteral(L, "Copyright (C) 2003-2007 Kepler Project, 2015 Jason A. Donenfeld <Jason@zx2c4.com>");
+ lua_settable(L, -3);
+ lua_pushliteral(L, "_DESCRIPTION");
+ lua_pushliteral(L, "LuaLDAP is a simple interface from Lua to an LDAP client");
+ lua_settable(L, -3);
+ lua_pushliteral(L, "_VERSION");
+ lua_pushliteral(L, "LuaLDAP 1.2.0");
+ lua_settable(L, -3);
+}
+
+
+/*
+** Create ldap table and register the open method.
+*/
+int luaopen_lualdap(lua_State *L)
+{
+ struct luaL_reg lualdap[] = {
+ {"open_simple", lualdap_open_simple},
+ {NULL, NULL},
+ };
+
+ lualdap_createmeta(L);
+ luaL_register(L, LUALDAP_TABLENAME, lualdap);
+ set_info(L);
+
+ return 1;
+}
diff --git a/lualdap/Makefile b/lualdap/Makefile
deleted file mode 100755
index 6a4f06d..0000000
--- a/lualdap/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-# $Id: Makefile,v 1.30 2007-03-13 22:07:33 godinho Exp $
-
-T= lualdap
-V= 1.1.0
-CONFIG= ./config
-
-include $(CONFIG)
-
-ifeq "$(LUA_VERSION_NUM)" "500"
-COMPAT_O= $(COMPAT_DIR)/compat-5.1.o
-endif
-
-OBJS= src/lualdap.o $(COMPAT_O)
-
-
-src/$(LIBNAME): $(OBJS)
- export MACOSX_DEPLOYMENT_TARGET="10.3"; $(CC) $(CFLAGS) $(LIB_OPTION) -o src/$(LIBNAME) $(OBJS) $(OPENLDAP_LIB)
-
-$(COMPAT_DIR)/compat-5.1.o: $(COMPAT_DIR)/compat-5.1.c
- $(CC) -c $(CFLAGS) -o $@ $(COMPAT_DIR)/compat-5.1.c
-
-install: src/$(LIBNAME)
- mkdir -p $(LUA_LIBDIR)
- cp src/$(LIBNAME) $(LUA_LIBDIR)
- cd $(LUA_LIBDIR); ln -f -s $(LIBNAME) $T.so
-
-clean:
- rm -f $(OBJS) src/$(LIBNAME)
diff --git a/lualdap/Makefile.win b/lualdap/Makefile.win
deleted file mode 100755
index 78d23a4..0000000
--- a/lualdap/Makefile.win
+++ /dev/null
@@ -1,22 +0,0 @@
-T= lualdap
-V= 1.1.0
-
-include config.win
-
-SRCS= src\$T.c
-OBJS= src\$T.obj
-
-lib: src\$(LIBNAME)
-
-.c.obj:
- $(CC) /c /Fo$@ $(CFLAGS) $<
-
-src\$(LIBNAME): $(OBJS)
- link /dll /def:src\$T.def /out:src\$(LIBNAME) $(OBJS) $(LUA_LIB) $(LDAP_LIB)
-
-install: src\$(LIBNAME)
- IF NOT EXIST $(LUA_LIBDIR) mkdir $(LUA_LIBDIR)
- copy src\$(LIBNAME) $(LUA_LIBDIR)
-
-clean:
- del src\$(LIBNAME) $(OBJS) src\$T.lib src\$T.exp
diff --git a/lualdap/README b/lualdap/README
deleted file mode 100755
index 0b748b6..0000000
--- a/lualdap/README
+++ /dev/null
@@ -1,28 +0,0 @@
-LuaLDAP
-(http://www.keplerproject.org/lualdap/)
-
-LuaLDAP is a simple interface from Lua to an LDAP client, in fact it is a bind to
-OpenLDAP or to ADSI. It enables a Lua program to:
-
- * Connect to an LDAP server;
- * Execute any operation (search, add, compare, delete, modify and rename);
- * Retrieve entries and references of the search result.
-
-LuaLDAP is free software and uses the same license as Lua 5.1.
-
-Current version is 1.1. It was developed for both Lua 5.0 and Lua 5.1,
-and both OpenLDAP 2.1 or newer and ADSI.
-
-Files in the distribution:
-
- /doc/us/*.html -- Documentation
- /src/* -- Source files
- /tests/* -- Test files
- /vc6/* -- Build files for MS Visual C 6 (deprecated)
- Makefile -- Makefile for Unix systems
- config -- Configurations to build on Unix systems
- Makefile.win -- Makefile for Windows systens with MS Visual C 8
- config.win -- Configurations to build on Windows systems
- README -- This file
-
-$Id: README,v 1.7 2007-12-14 15:14:54 carregal Exp $
diff --git a/lualdap/config b/lualdap/config
deleted file mode 100755
index 84543b3..0000000
--- a/lualdap/config
+++ /dev/null
@@ -1,26 +0,0 @@
-# Installation directories
-# System's libraries directory (where binary libraries are installed)
-LUA_LIBDIR= /usr/local/lib/lua/5.0
-# Lua includes directory
-LUA_INC= /usr/local/include
-# OpenLDAP includes directory
-OPENLDAP_INC= /usr/local/include
-# OpenLDAP library (an optional directory can be specified with -L<dir>)
-OPENLDAP_LIB= -lldap
-
-# OS dependent
-LIB_OPTION= -shared #for Linux
-#LIB_OPTION= -bundle -undefined dynamic_lookup #for MacOS X
-
-# Lua version number (first and second digits of target version)
-LUA_VERSION_NUM= 500
-LIBNAME= $T.so.$V
-COMPAT_DIR= ../compat/src
-
-# Compilation parameters
-WARN= -O2 -Wall -fPIC -W -Waggregate-return -Wcast-align -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings -ansi
-INCS= -I$(LUA_INC) -I$(OPENLDAP_INC) -I$(COMPAT_DIR)
-CFLAGS= $(WARN) $(INCS)
-CC= gcc
-
-# $Id: config,v 1.5 2006-07-24 01:42:06 tomas Exp $
diff --git a/lualdap/config.win b/lualdap/config.win
deleted file mode 100755
index 3b877f8..0000000
--- a/lualdap/config.win
+++ /dev/null
@@ -1,30 +0,0 @@
-# Installation directories
-# System's libraries directory (where binary libraries are installed)
-LUA_LIBDIR= c:\lua5.1
-
-# Lua includes directory
-LUA_INC= c:\lua5.1\include
-
-# OpenLDAP requires extra include. Comment this line if using ADSI (WinLDAP)
-#LDAP_INC=/IC:\openldap-2.1.17_bin\include
-
-# Lua library
-LUA_LIB= c:\lua5.1\lua5.1.lib
-
-# LDAP library
-#LDAP_LIB= C:\openldap-2.1.17_bin\DLLRelease\openldap.lib
-LDAP_LIB= Wldap32.lib
-
-LIBNAME= $T.dll
-
-# Compilation directives
-WARN= /O2
-
-INCS= /I$(LUA_INC) $(LDAP_INC)
-
-# CFLAGS should include -DWINLDAP to use native windows library instead of OpenLDAP
-#CFLAGS= $(WARN) $(INCS) -DWIN32
-CFLAGS= $(WARN) $(INCS) -DWIN32 -DWINLDAP
-
-CC= cl
-
diff --git a/lualdap/doc/us/index.html b/lualdap/doc/us/index.html
deleted file mode 100755
index f8bce95..0000000
--- a/lualdap/doc/us/index.html
+++ /dev/null
@@ -1,140 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-
-<head>
- <title>LuaLDAP: A Lua interface to an LDAP library</title>
- <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-</head>
-
-<body>
-
-<div id="container">
-
-<div id="product">
- <div id="product_logo">
- <a href="http://www.keplerproject.org">
- <img alt="LuaLDAP logo" width="128" height="128" src="lualdap.png"/>
- </a>
- </div>
- <div id="product_name"><big><strong>LuaLDAP</strong></big></div>
- <div id="product_description">A Lua interface to an LDAP library</div>
-</div> <!-- id="product" -->
-
-<div id="main">
-
-<div id="navigation">
-<h1>LuaLDAP</h1>
- <ul>
- <li><strong>Home</strong>
- <ul>
- <li><a href="index.html#over">Overview</a></li>
- <li><a href="index.html#status">Status</a></li>
- <li><a href="index.html#download">Download</a></li>
- <li><a href="index.html#history">History</a></li>
- <li><a href="index.html#credits">Credits</a></li>
- <li><a href="index.html#contact">Contact us</a></li>
- </ul>
- </li>
- <li><a href="manual.html">Manual</a>
- <ul>
- <li><a href="manual.html#introduction">Introduction</a></li>
- <li><a href="manual.html#building">Building</a></li>
- <li><a href="manual.html#installation">Installation</a></li>
- <li><a href="manual.html#attributes">Attributes</a></li>
- <li><a href="manual.html#dn">DN</a></li>
- <li><a href="manual.html#initialization">Initialization</a></li>
- <li><a href="manual.html#connection">Connection</a></li>
- <li><a href="manual.html#examples">Examples</a></li>
- </ul>
- </li>
- <li><a href="http://luaforge.net/projects/lualdap/">Project</a>
- <ul>
- <li><a href="http://luaforge.net/tracker/?group_id=14">Bug Tracker</a></li>
- <li><a href="http://luaforge.net/scm/?group_id=14">CVS</a></li>
- </ul>
- </li>
- <li><a href="license.html">License</a></li>
- </ul>
-</div> <!-- id="navigation" -->
-
-<div id="content">
-
-<h2><a name="over"></a>Overview</h2>
-
-<p>LuaLDAP is a simple interface from Lua to an LDAP client, in
-fact it is a bind to
-<a href="http://www.openldap.org">OpenLDAP</a> or to <a href="http://msdn2.microsoft.com/en-us/library/aa772161.aspx">ADSI</a>. It enables a Lua program to:</p>
-
-<ul>
- <li>Connect to an LDAP server;</li>
- <li>Execute any operation (search, add, compare, delete, modify and
- rename);</li>
- <li>Retrieve entries and references of the search result.</li>
-</ul>
-
-<p>LuaLDAP is free software and uses the same
-<a href="license.html">license</a> as Lua 5.1.</p>
-
-<h2><a name="status"></a>Status</h2>
-
-<p>Current version is 1.1. It was developed for both Lua 5.0 and Lua 5.1, and both
-<a href="http://www.openldap.org">OpenLDAP</a> 2.1 or newer and <a href="http://msdn2.microsoft.com/en-us/library/aa772161.aspx">ADSI</a>.</p>
-
-<h2><a name="download"></a>Download</h2>
-
-<p>LuaLDAP can be downloaded in source code from the
-<a href="http://luaforge.net/projects/lualdap/files">LuaForge</a>
-page. If you are using <a href="http://luabinaries.luaforge.net">LuaBinaries</a> a Windows binary
-version of LuaLDAP can be found at the same LuaForge page.</p>
-
-<h2><a name="history"></a>History</h2>
-
-<dl class="history">
- <dt><strong>Version 1.1</strong> [14/Dec/2007]</dt>
- <dd>Adapted to work on both Lua 5.0 and Lua 5.1 and to work with ADSI (WinLDAP). Thanks to Mark Edgar.</dd>
-
- <dt><strong><a href="http://www.keplerproject.org/lualdap/1.0/">Version 1.0.1</a></strong> [04/Apr/2006]</dt>
- <dd>Compatible with Compat-5.1 R5.</dd>
-
- <dt><strong>Version 1.0</strong> [10/Jun/2005]</dt>
- <dd />
-
- <dt><strong>Version 1.0 Alpha</strong> [10/Dec/2003]</dt>
- <dd />
-</dl>
-
-<h2><a name="credits"></a>Credits</h2>
-
-<p>LuaLDAP was designed by Roberto Ierusalimschy, Andr&eacute;
-Carregal and Tom&aacute;s Guisasola as part of the
-<a href="http://www.keplerproject.org">Kepler Project</a>
-which holds its copyright. It was implemented by Tom&aacute;s Guisasola and Leonardo Godinho with contributions by Mark Edgar.</p>
-
-<p>LuaLDAP development was sponsored by
-<a href="http://www.fabricadigital.com.br">F&aacute;brica Digital</a> and FINEP.</p>
-
-<h2><a name="contact"></a>Contact us</h2>
-
-<p>For further information please <a href=
-"mailto:info-NO-SPAM-THANKS@keplerproject.org">contact us</a>.
-Comments are welcome!</p>
-
-<p>You can also reach other Kepler developers and users on the Kepler Project
-<a href="http://luaforge.net/mail/?group_id=104">mailing list</a>.</p>
-
-</div> <!-- id="content" -->
-
-</div> <!-- id="main" -->
-
-<div id="about">
- <p><a href="http://validator.w3.org/check?uri=referer">
- <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
- <p><small>$Id: index.html,v 1.37 2007-12-14 17:06:57 carregal Exp $</small></p>
-</div> <!-- id="about" -->
-
-</div> <!-- id="container" -->
-</body>
-</html>
-
diff --git a/lualdap/doc/us/license.html b/lualdap/doc/us/license.html
deleted file mode 100755
index 5b9ea9f..0000000
--- a/lualdap/doc/us/license.html
+++ /dev/null
@@ -1,122 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-
-<head>
- <title>LuaLDAP: license</title>
- <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-</head>
-
-<body>
-
-<div id="container">
-
-<div id="product">
- <div id="product_logo"><a href="http://www.keplerproject.org">
- <img alt="LuaLDAP logo" width="128" height="128" src="lualdap.png"/>
- </a></div>
- <div id="product_name"><big><strong>LuaLDAP</strong></big></div>
- <div id="product_description">A Lua interface to the OpenLDAP library</div>
-</div> <!-- id="product" -->
-
-<div id="main">
-
-<div id="navigation">
-<h1>LuaLDAP</h1>
- <ul>
- <li><a href="index.html">Home</a>
- <ul>
- <li><a href="index.html#over">Overview</a></li>
- <li><a href="index.html#status">Status</a></li>
- <li><a href="index.html#download">Download</a></li>
- <li><a href="index.html#history">History</a></li>
- <li><a href="index.html#credits">Credits</a></li>
- <li><a href="index.html#contact">Contact us</a></li>
- </ul>
- </li>
- <li><a href="manual.html">Manual</a>
- <ul>
- <li><a href="manual.html#introduction">Introduction</a></li>
- <li><a href="manual.html#installation">Installation</a></li>
- <li><a href="manual.html#attributes">Attributes</a></li>
- <li><a href="manual.html#dn">DN</a></li>
- <li><a href="manual.html#initialization">Initialization</a></li>
- <li><a href="manual.html#connection">Connection</a></li>
- <li><a href="manual.html#examples">Examples</a></li>
- </ul>
- </li>
- <li><a href="http://luaforge.net/projects/lualdap/">Project</a>
- <ul>
- <li><a href="http://luaforge.net/tracker/?group_id=14">Bug Tracker</a></li>
- <li><a href="http://luaforge.net/scm/?group_id=14">CVS</a></li>
- </ul>
- </li>
- <li><strong>License</strong></li>
- </ul>
-</div> <!-- id="navigation" -->
-
-<div id="content">
-
-<h1>License</h1>
-
-<p>LuaLDAP is free software: it can be used for both academic and
-commercial purposes at absolutely no cost. There are no royalties
-or GNU-like "copyleft" restrictions. LuaLDAP qualifies as <a href=
-"http://www.opensource.org/docs/definition.html">Open Source</a>
-software. Its licenses are compatible with <a href=
-"http://www.gnu.org/licenses/gpl.html">GPL</a>. LuaLDAP is not in
-the public domain and the
-<a href="http://www.keplerproject.org">Kepler Project</a>
-keep its copyright. The legal details are below.</p>
-
-<p>The spirit of the license is that you are free to use LuaLDAP
-for any purpose at no cost without having to ask us. The only
-requirement is that if you do use LuaLDAP, then you should give us
-credit by including the appropriate copyright notice somewhere in
-your product or its documentation.</p>
-
-<p>The LuaLDAP library is designed and implemented by Roberto
-Ierusalimschy, Andr&eacute; Carregal and Tom&aacute;s Guisasola.
-The implementation is not derived from licensed software.</p>
-
-<!-- ===================================================================== -->
-
-<hr />
-Copyright &copy; 2003-2007 The Kepler Project.
-
-<p>Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use, copy,
-modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:</p>
-
-<p>The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.</p>
-
-<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.</p>
-
-</div> <!-- id="content" -->
-
-</div> <!-- id="main" -->
-
-<div id="about">
- <p><a href="http://validator.w3.org/check?uri=referer">
- <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
- <p><small>$Id: license.html,v 1.11 2007-12-14 16:46:15 carregal Exp $</small></p>
-</div> <!-- id="about" -->
-
-</div> <!-- id="container" -->
-
-</body>
-</html>
-
diff --git a/lualdap/doc/us/lualdap.png b/lualdap/doc/us/lualdap.png
deleted file mode 100755
index 8a45d88..0000000
--- a/lualdap/doc/us/lualdap.png
+++ /dev/null
Binary files differ
diff --git a/lualdap/doc/us/manual.html b/lualdap/doc/us/manual.html
deleted file mode 100755
index a9abd59..0000000
--- a/lualdap/doc/us/manual.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-
-<head>
- <title>LuaLDAP: A Lua interface to an LDAP library</title>
- <link rel="stylesheet" href="http://www.keplerproject.org/doc.css" type="text/css"/>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-</head>
-
-<body>
-
-<div id="container">
-
-<div id="product">
- <div id="product_logo"><a href="http://www.keplerproject.org">
- <img alt="LuaLDAP logo" width="128" height="128" src="lualdap.png"/>
- </a></div>
- <div id="product_name"><big><strong>LuaLDAP</strong></big></div>
- <div id="product_description">A Lua interface to an LDAP library</div>
-</div> <!-- id="product" -->
-
-<div id="main">
-
-<div id="navigation">
-<h1>LuaLDAP</h1>
- <ul>
- <li><a href="index.html">Home</a>
- <ul>
- <li><a href="index.html#over">Overview</a></li>
- <li><a href="index.html#status">Status</a></li>
- <li><a href="index.html#download">Download</a></li>
- <li><a href="index.html#history">History</a></li>
- <li><a href="index.html#credits">Credits</a></li>
- <li><a href="index.html#contact">Contact us</a></li>
- </ul>
- </li>
- <li><strong>Manual</strong>
- <ul>
- <li><a href="manual.html#introduction">Introduction</a></li>
- <li><a href="manual.html#building">Building</a></li>
- <li><a href="manual.html#installation">Installation</a></li>
- <li><a href="manual.html#attributes">Attributes</a></li>
- <li><a href="manual.html#dn">DN</a></li>
- <li><a href="manual.html#initialization">Initialization</a></li>
- <li><a href="manual.html#connection">Connection</a></li>
- <li><a href="manual.html#examples">Examples</a></li>
- </ul>
- </li>
- <li><a href="http://luaforge.net/projects/lualdap/">Project</a>
- <ul>
- <li><a href="http://luaforge.net/tracker/?group_id=14">Bug Tracker</a></li>
- <li><a href="http://luaforge.net/scm/?group_id=14">CVS</a></li>
- </ul>
- </li>
- <li><a href="license.html">License</a></li>
- </ul>
-</div> <!-- id="navigation" -->
-
-<div id="content">
-
-<h2><a name="introduction"></a>Introduction</h2>
-
-<p>LuaLDAP is a simple interface from Lua to an LDAP client, in
-fact it is a bind to <a href="http://www.openldap.org">OpenLDAP</a>
-client or <a href="http://msdn2.microsoft.com/en-us/library/aa772161.aspx">ADSI</a> client</p>
-
-<p>LuaLDAP defines one single global variable: a table called
-<code>lualdap</code>. This table holds the functions used to create an
-LDAP connection object.</p>
-
-<p>A connection object offers methods to perform any operation on
-the directory such as comparing values, adding new entries,
-modifying attributes on existing entries, removing entries, and the
-most common of all: searching. Entries are represented as Lua
-tables; attributes are its fields. The attribute values can be
-strings or tables of strings (used to represent multiple
-values).</p>
-
-<p>LuaLDAP is a bind to the
-<a href="http://www.openldap.org">OpenLDAP</a> library or to <a href="http://msdn2.microsoft.com/en-us/library/aa772161.aspx">ADSI</a> library and it
-depends on a previous installation of any of this libraries. You can
-download OpenLDAP from the
-<a href="http://www.openldap.org/software/download">OpenLDAP download</a>
-page. ADSI is included on Windows 2000 or newer. Windows NT/Me/98/95
-requires an <a href="http://msdn2.microsoft.com/en-us/library/aa772161.aspx">Active Directory Client Extension</a></p>
-<h2><a name="building"></a>Building</h2>
-
-<p>
-LuaLDAP could be built to Lua 5.0 or to Lua 5.1.
-In both cases,
-the language library and headers files for the target version
-must be installed properly.
-</p>
-<p>
-LuaLDAP offers a Makefile and a separate configuration file,
-<code>config</code>,
-which should be edited to suit your installation before runnig
-<code>make</code>.
-The file has some definitions like paths to the external libraries,
-compiler options and the like.
-One important definition is the version of Lua language,
-which is not obtained from the installed software.
-</p>
-
-<h2><a name="installation"></a>Installation</h2>
-
-<p>The LuaLDAP compiled binary should be copied to a directory in your
-<a href="http://www.lua.org/manual/5.1/manual.html#pdf-package.cpath">C path</a>.
-Lua 5.0 users should install <a href="http://www.keplerproject.org/compat">Compat-5.1</a> also.</p>
-
-<p>Windows users of ADSI can use the binary versions of LuaLDAP
-(<code>lualdap.dll</code>) available at
-<a href="http://luaforge.net/projects/lualdap/files">LuaForge</a>.</p>
-
-<h2><a name="attributes"></a>Representing attributes</h2>
-
-<p>Many LDAP operations manage sets of attributes and values.
-LuaLDAP provides a uniform way of representing them by using Lua
-tables. The table attributes can be Lua string, a binary string (a string of
-bits), or table of <em>n</em> values indexed from 1 to <em>n</em>.
-Some operations have different approaches that will be explained as necessary.</p>
-
-<p>Here is a simple example:</p>
-
-<pre class="example">
-entry = {
- an_attribute = "a value",
- other_attribute = {
- "first value of other attribute",
- "another value of other attribute",
- },
-}
-</pre>
-
-Attribute names cannot contain the <code>'\0'</code> character.
-
-<h2><a name="dn"></a>Distinguished names</h2>
-
-<p>The distinguished name (DN) is the term used to identify an
-entry on the directory information tree. It is formed by the
-relative distinguished name (RDN) of the entry and the
-distinguished name of its parent. LuaLDAP will always use a string
-to represent the DN of any entry.</p>
-
-<p>A more precise definition can be found on the LDAP
-documentation. A list of some of these files can be found in
-<a href="#related_docs">Related documentation</a> section.</p>
-
-<h2><a name="initialization"></a>Initialization functions</h2>
-
-<p>LuaLDAP provides a single way to connect to an LDAP server:</p>
-
-<dl>
- <dt><strong><code>lualdap.open_simple (hostname, who, password,
- usetls)</code></strong></dt>
- <dd>Initializes a session with an LDAP server. This function requires a
- hostname, accordingly to the <a href="#related_docs">C LDAP API</a>
- definition (<em>"hostname contains a space-separated list of
- hostnames or dotted strings representing the IP address of hosts
- running an LDAP server to connect to. Each hostname in the list MAY
- include a port number which is separated from the host itself with
- a colon (:) character."</em>). The argument <code>who</code> should be
- the <a href="#dn">distinguished name</a> of the entry that has the
- password to be checked against the third argument,
- <code>password</code>. The optional argument <code>usetls</code> is a
- Boolean flag indicating if Transport Layer Security (TLS) should be
- used.<br/>
- Returns a connection object if the operation was successful. In case of
- error it returns <code>nil</code> followed by an error string.</dd>
-</dl>
-
-<h2><a name="connection"></a>Connection objects</h2>
-
-<p>A connection object offers methods which implement LDAP
-operations. Almost all of them need a
-<a href="#dn">distinguished name</a> to identify the entry on which the
-operation will be executed.</p>
-
-<p>These methods execute asynchronous operations and return a
-function that should be called to obtain the results. The called
-functions will return <code>true</code> indicating the success of the
-operation. The only exception is the <code>compare</code> function
-which can return either <code>true</code> or <code>false</code>
-(as the result of the comparison) on a successful operation.</p>
-
-<p>There are two types of errors: <em>API errors</em>, such as
-wrong parameters, absent connection etc.; and <em>LDAP errors</em>,
-such as malformed DN, unknown attribute etc. API errors will raise
-a Lua error, while LDAP errors will be reported by the
-function/method returning <code>nil</code> plus the error
-message provided by the OpenLDAP client.</p>
-
-<p>A connection object can be created by calling the <a href=
-"#initialization">Initialization function</a>.</p>
-
-<h4>Methods</h4>
-
-<dl>
- <dt><strong><code>conn:add (distinguished_name,
- table_of_attributes)</code></strong></dt>
- <dd>Adds a new entry to the directory with the given attributes and
- values. <a name="conn_close"></a></dd>
-
- <dt><strong><code>conn:close()</code></strong></dt>
- <dd>Closes the connection <code>conn</code>.</dd>
-
- <dt><strong><code>conn:compare (distinguished_name, attribute,
- value)</code></strong></dt>
- <dd>Compares a value to an entry.</dd>
-
- <dt><strong><code>conn:delete (distinguished_name)</code></strong></dt>
- <dd>Deletes an entry from the directory.</dd>
-
- <dt><strong><code>conn:modify (distinguished_name,
- table_of_operations*)</code></strong></dt>
- <dd>Changes the values of attributes in the given entry. The tables of
- operations are <a href="#attributes">tables of attributes</a>
- with the value on index <code>1</code> indicating the operation to be
- performed. The valid operations are:
- <ul>
- <li><strong><code>'+'</code></strong> to add the values to the attributes</li>
- <li><strong><code>'-'</code></strong> to delete the values of the attributes</li>
- <li><strong><code>'='</code></strong> to replace the values of the attributes</li>
- </ul>
- Any number of tables of operations will be used in a single LDAP modify
- operation.</dd>
-
- <dt><strong><code>conn:rename (distinguished_name, new_relative_dn,
- new_parent)</code></strong></dt>
- <dd>Changes an entry name (i.e. change its <a href="#dn">distinguished name</a>).</dd>
-
- <dt><strong><code>conn:search (table_of_search_parameters)</code></strong></dt>
- <dd>Performs a search operation on the directory. The parameters are
- described below:<br/><br/>
- <dl>
- <dt><strong><code>attrs</code></strong></dt>
- <dd>a string or a list of attribute names to
- be retrieved (default is to retrieve all attributes).</dd>
-
- <dt><strong><code>attrsonly</code></strong></dt>
- <dd>a Boolean value that must be either
- <em>false</em> (default) if both attribute names and values are to be
- retrieved, or <em>true</em> if only names are wanted.</dd>
-
- <dt><strong><code>base</code></strong></dt>
- <dd>The <a href="#dn">distinguished name</a>
- of the entry at which to start the search.</dd>
-
- <dt><strong><code>filter</code></strong></dt>
- <dd>A string representing the search filter
- as described in <a href="http://www.ietf.org/rfc/rfc2254.txt">The
- String Representation of LDAP Search Filters (RFC 2254)</a>.</dd>
-
- <dt><strong><code>scope</code></strong></dt>
- <dd>A string indicating the scope of the
- search. The valid strings are: "base", "onelevel" and "subtree".
- The empty string ("") and <code>nil</code> will be treated as the
- default scope.</dd>
-
- <dt><strong><code>sizelimit</code></strong></dt>
- <dd>The maximum number of entries to
- return (default is no limit).</dd>
-
- <dt><strong><code>timeout</code></strong></dt>
- <dd>The timeout in seconds (default is no
- timeout). The precision is microseconds.</dd>
- </dl>
- <br/>
- The search method will return a <em>search iterator</em> which is a
- function that requires no arguments. The search iterator is used to
- get the search result and will return a string representing the <a
- href="#dn">distinguished name</a> and a <a href="#attributes">table
- of attributes</a> as returned by the search request.</dd>
-</dl>
-
-<h2><a name="examples"></a>Example</h2>
-
-<p>here is a some sample code that demonstrate the basic use of the library.</p>
-
-<pre class="example">
-require "lualdap"
-
-ld = assert (lualdap.open_simple ("ldap.server",
- "mydn=manoeljoaquim,ou=people,dc=ldap,dc=world",
- "mysecurepassword"))
-
-for dn, attribs in ld:search { base = "ou=people,dc=ldap,dc=world" } do
- io.write (string.format ("\t[%s]\n", dn))
- for name, values in pairs (attribs) do
- io.write ("["..name.."] : ")
- if type (values) == "string" then
- io.write (values)
- elseif type (values) == "table" then
- local n = table.getn(values)
- for i = 1, (n-1) do
- io.write (values[i]..",")
- end
- io.write (values[n])
- end
- io.write ("\n")
- end
-end
-
-ld:add ("mydn=newuser,ou=people,dc=ldap,dc=world", {
- objectClass = { "", "", },
- mydn = "newuser",
- abc = "qwerty",
- tel = { "123456758", "98765432", },
- givenName = "New User",
-})()
-
-ld:modify {"mydn=newuser,ou=people,dc=ldp,dc=world",
- { '=', givenName = "New", cn = "New", sn = "User", },
- { '+', o = { "University", "College", },
- mail = "newuser@university.edu", },
- { '-', abc = true, tel = "123456758", },
- { '+', tel = "13579113", },
-}()
-
-ld:delete ("mydn=newuser,ou=people,dc=ldp,dc=world")()
-
-</pre>
-
-<h2><a name="related_docs"></a>Related documentation</h2>
-
-<ul>
- <li><a href="http://www.ietf.org/rfc/rfc2251.txt">Lightweight
- Directory Access Protocol (v3)</a></li>
- <li><a href="http://www.ietf.org/rfc/rfc3377.txt">LDAPv3 Technical
- Specification</a></li>
- <li><a href="http://www.ietf.org/rfc/rfc2254.txt">The String
- Representation of LDAP Search Filters (RFC 2254)</a></li>
- <li><a href=
- "http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-ldapext-ldap-c-api-05.txt">
- The C LDAP Application Program Interface</a></li>
-</ul>
-
-</div> <!-- id="content" -->
-
-</div> <!-- id="main" -->
-
-<div id="about">
- <p><a href="http://validator.w3.org/check?uri=referer">
- <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p>
- <p><small>$Id: manual.html,v 1.34 2007-12-14 16:46:15 carregal Exp $</small></p>
-</div> <!-- id="about" -->
-
-</div> <!-- id="container" -->
-</body>
-</html>
-
diff --git a/lualdap/src/lualdap.c b/lualdap/src/lualdap.c
deleted file mode 100755
index b3a56be..0000000
--- a/lualdap/src/lualdap.c
+++ /dev/null
@@ -1,1000 +0,0 @@
-/*
-** LuaLDAP
-** See Copyright Notice in license.html
-** $Id: lualdap.c,v 1.48 2007-12-14 15:11:22 carregal Exp $
-*/
-
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef WIN32
-#include <Winsock2.h>
-#else
-#include <sys/time.h>
-#endif
-
-#ifdef WINLDAP
-#include "open2winldap.h"
-#else
-#include "ldap.h"
-#endif
-
-#include "lua.h"
-#include "lauxlib.h"
-#if ! defined (LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
-#include "compat-5.1.h"
-#endif
-
-#ifdef WINLDAPAPI
-#define timeval l_timeval
-typedef ULONG ldap_int_t;
-typedef PCHAR ldap_pchar_t;
-#else
-typedef int ldap_int_t;
-typedef const char * ldap_pchar_t;
-#endif
-
-#define LUALDAP_PREFIX "LuaLDAP: "
-#define LUALDAP_TABLENAME "lualdap"
-#define LUALDAP_CONNECTION_METATABLE "LuaLDAP connection"
-#define LUALDAP_SEARCH_METATABLE "LuaLDAP search"
-
-#define LUALDAP_MOD_ADD (LDAP_MOD_ADD | LDAP_MOD_BVALUES)
-#define LUALDAP_MOD_DEL (LDAP_MOD_DELETE | LDAP_MOD_BVALUES)
-#define LUALDAP_MOD_REP (LDAP_MOD_REPLACE | LDAP_MOD_BVALUES)
-#define LUALDAP_NO_OP 0
-
-/* Maximum number of attributes manipulated in an operation */
-#ifndef LUALDAP_MAX_ATTRS
-#define LUALDAP_MAX_ATTRS 100
-#endif
-
-/* Size of buffer of NULL-terminated arrays of pointers to struct values */
-#ifndef LUALDAP_ARRAY_VALUES_SIZE
-#define LUALDAP_ARRAY_VALUES_SIZE (2 * LUALDAP_MAX_ATTRS)
-#endif
-
-/* Maximum number of values structures */
-#ifndef LUALDAP_MAX_VALUES
-#define LUALDAP_MAX_VALUES (LUALDAP_ARRAY_VALUES_SIZE / 2)
-#endif
-
-
-/* LDAP connection information */
-typedef struct {
- int version; /* LDAP version */
- LDAP *ld; /* LDAP connection */
-} conn_data;
-
-
-/* LDAP search context information */
-typedef struct {
- int conn; /* conn_data reference */
- int msgid;
-} search_data;
-
-
-/* LDAP attribute modification structure */
-typedef struct {
- LDAPMod *attrs[LUALDAP_MAX_ATTRS + 1];
- LDAPMod mods[LUALDAP_MAX_ATTRS];
- int ai;
- BerValue *values[LUALDAP_ARRAY_VALUES_SIZE];
- int vi;
- BerValue bvals[LUALDAP_MAX_VALUES];
- int bi;
-} attrs_data;
-
-
-int luaopen_lualdap (lua_State *L);
-
-
-/*
-** Typical error situation.
-*/
-static int faildirect (lua_State *L, const char *errmsg) {
- lua_pushnil (L);
- lua_pushstring (L, errmsg);
- return 2;
-}
-
-
-/*
-** Get a connection object from the first stack position.
-*/
-static conn_data *getconnection (lua_State *L) {
- conn_data *conn = (conn_data *)luaL_checkudata (L, 1, LUALDAP_CONNECTION_METATABLE);
- luaL_argcheck(L, conn!=NULL, 1, LUALDAP_PREFIX"LDAP connection expected");
- luaL_argcheck(L, conn->ld, 1, LUALDAP_PREFIX"LDAP connection is closed");
- return conn;
-}
-
-
-/*
-** Get a search object from the first upvalue position.
-*/
-static search_data *getsearch (lua_State *L) {
- /* don't need to check upvalue's integrity */
- search_data *search = (search_data *)lua_touserdata (L, lua_upvalueindex (1));
- luaL_argcheck (L,search->conn!=LUA_NOREF,1,LUALDAP_PREFIX"LDAP search is closed");
- return search;
-}
-
-
-/*
-** Set metatable of userdata on top of the stack.
-*/
-static void lualdap_setmeta (lua_State *L, const char *name) {
- luaL_getmetatable (L, name);
- lua_setmetatable (L, -2);
-}
-
-
-/*
-** Error on option.
-*/
-static int option_error (lua_State *L, const char *name, const char *type) {
- return luaL_error (L, LUALDAP_PREFIX"invalid value on option `%s': %s expected, got %s", name, type, lua_typename (L, lua_type (L, -1)));
-}
-
-
-/*
-** Get the field called name of the table at position 2.
-*/
-static void strgettable (lua_State *L, const char *name) {
- lua_pushstring (L, name);
- lua_gettable (L, 2);
-}
-
-
-/*
-** Get the field named name as a string.
-** The table MUST be at position 2.
-*/
-static const char *strtabparam (lua_State *L, const char *name, char *def) {
- strgettable (L, name);
- if (lua_isnil (L, -1))
- return def;
- else if (lua_isstring (L, -1))
- return lua_tostring (L, -1);
- else {
- option_error (L, name, "string");
- return NULL;
- }
-}
-
-
-/*
-** Get the field named name as an integer.
-** The table MUST be at position 2.
-*/
-static long longtabparam (lua_State *L, const char *name, int def) {
- strgettable (L, name);
- if (lua_isnil (L, -1))
- return def;
- else if (lua_isnumber (L, -1))
- return (long)lua_tonumber (L, -1);
- else
- return option_error (L, name, "number");
-}
-
-
-/*
-** Get the field named name as a double.
-** The table MUST be at position 2.
-*/
-static double numbertabparam (lua_State *L, const char *name, double def) {
- strgettable (L, name);
- if (lua_isnil (L, -1))
- return def;
- else if (lua_isnumber (L, -1))
- return lua_tonumber (L, -1);
- else
- return option_error (L, name, "number");
-}
-
-
-/*
-** Get the field named name as a boolean.
-** The table MUST be at position 2.
-*/
-static int booltabparam (lua_State *L, const char *name, int def) {
- strgettable (L, name);
- if (lua_isnil (L, -1))
- return def;
- else if (lua_isboolean (L, -1))
- return lua_toboolean (L, -1);
- else
- return option_error (L, name, "boolean");
-}
-
-
-/*
-** Error on attribute's value.
-*/
-static void value_error (lua_State *L, const char *name) {
- luaL_error (L, LUALDAP_PREFIX"invalid value of attribute `%s' (%s)",
- name, lua_typename (L, lua_type (L, -1)));
-}
-
-
-/*
-** Initialize attributes structure.
-*/
-static void A_init (attrs_data *attrs) {
- attrs->ai = 0;
- attrs->attrs[0] = NULL;
- attrs->vi = 0;
- attrs->values[0] = NULL;
- attrs->bi = 0;
-}
-
-
-/*
-** Store the string on top of the stack on the attributes structure.
-** Increment the bvals counter.
-*/
-static BerValue *A_setbval (lua_State *L, attrs_data *a, const char *n) {
- BerValue *ret = &(a->bvals[a->bi]);
- if (a->bi >= LUALDAP_MAX_VALUES) {
- luaL_error (L, LUALDAP_PREFIX"too many values");
- return NULL;
- } else if (!lua_isstring (L, -1)) {
- value_error (L, n);
- return NULL;
- }
- a->bvals[a->bi].bv_len = lua_strlen (L, -1);
- a->bvals[a->bi].bv_val = (char *)lua_tostring (L, -1);
- a->bi++;
- return ret;
-}
-
-
-/*
-** Store a pointer to the value on top of the stack on the attributes structure.
-*/
-static BerValue **A_setval (lua_State *L, attrs_data *a, const char *n) {
- BerValue **ret = &(a->values[a->vi]);
- if (a->vi >= LUALDAP_ARRAY_VALUES_SIZE) {
- luaL_error (L, LUALDAP_PREFIX"too many values");
- return NULL;
- }
- a->values[a->vi] = A_setbval (L, a, n);
- a->vi++;
- return ret;
-}
-
-
-/*
-** Store a NULL pointer on the attributes structure.
-*/
-static BerValue **A_nullval (lua_State *L, attrs_data *a) {
- BerValue **ret = &(a->values[a->vi]);
- if (a->vi >= LUALDAP_ARRAY_VALUES_SIZE) {
- luaL_error (L, LUALDAP_PREFIX"too many values");
- return NULL;
- }
- a->values[a->vi] = NULL;
- a->vi++;
- return ret;
-}
-
-
-/*
-** Store the value of an attribute.
-** Valid values are:
-** true => no values;
-** string => one value; or
-** table of strings => many values.
-*/
-static BerValue **A_tab2val (lua_State *L, attrs_data *a, const char *name) {
- int tab = lua_gettop (L);
- BerValue **ret = &(a->values[a->vi]);
- if (lua_isboolean (L, tab) && (lua_toboolean (L, tab) == 1)) /* true */
- return NULL;
- else if (lua_isstring (L, tab)) /* string */
- A_setval (L, a, name);
- else if (lua_istable (L, tab)) { /* list of strings */
- int i;
- int n = luaL_getn (L, tab);
- for (i = 1; i <= n; i++) {
- lua_rawgeti (L, tab, i); /* push table element */
- A_setval (L, a, name);
- }
- lua_pop (L, n);
- } else {
- value_error (L, name);
- return NULL;
- }
- A_nullval (L, a);
- return ret;
-}
-
-
-/*
-** Set a modification value (which MUST be on top of the stack).
-*/
-static void A_setmod (lua_State *L, attrs_data *a, int op, const char *name) {
- if (a->ai >= LUALDAP_MAX_ATTRS) {
- luaL_error (L, LUALDAP_PREFIX"too many attributes");
- return;
- }
- a->mods[a->ai].mod_op = op;
- a->mods[a->ai].mod_type = (char *)name;
- a->mods[a->ai].mod_bvalues = A_tab2val (L, a, name);
- a->attrs[a->ai] = &a->mods[a->ai];
- a->ai++;
-}
-
-
-/*
-** Convert a Lua table into an array of modifications.
-** An array of modifications is a NULL-terminated array of LDAPMod's.
-*/
-static void A_tab2mod (lua_State *L, attrs_data *a, int tab, int op) {
- lua_pushnil (L); /* first key for lua_next */
- while (lua_next (L, tab) != 0) {
- /* attribute must be a string and not a number */
- if ((!lua_isnumber (L, -2)) && (lua_isstring (L, -2)))
- A_setmod (L, a, op, lua_tostring (L, -2));
- /* pop value and leave last key on the stack as next key for lua_next */
- lua_pop (L, 1);
- }
-}
-
-
-/*
-** Terminate the array of attributes.
-*/
-static void A_lastattr (lua_State *L, attrs_data *a) {
- if (a->ai >= LUALDAP_MAX_ATTRS) {
- luaL_error (L, LUALDAP_PREFIX"too many attributes");
- return;
- }
- a->attrs[a->ai] = NULL;
- a->ai++;
-}
-
-
-/*
-** Copy a string or a table of strings from Lua to a NULL-terminated array
-** of C-strings.
-*/
-static int table2strarray (lua_State *L, int tab, char *array[], int limit) {
- if (lua_isstring (L, tab)) {
- if (limit < 2)
- return luaL_error (L, LUALDAP_PREFIX"too many arguments");
- array[0] = (char *)lua_tostring (L, tab);
- array[1] = NULL;
- } else if (lua_istable (L, tab)) {
- int i;
- int n = luaL_getn (L, tab);
- if (limit < (n+1))
- return luaL_error (L, LUALDAP_PREFIX"too many arguments");
- for (i = 0; i < n; i++) {
- lua_rawgeti (L, tab, i+1); /* push table element */
- if (lua_isstring (L, -1))
- array[i] = (char *)lua_tostring (L, -1);
- else {
- return luaL_error (L, LUALDAP_PREFIX"invalid value #%d", i+1);
- }
- }
- array[n] = NULL;
- } else
- return luaL_error (L, LUALDAP_PREFIX"bad argument #%d (table or string expected, got %s)", tab, lua_typename (L, lua_type (L, tab)));
- return 0;
-}
-
-
-/*
-** Get the result message of an operation.
-** #1 upvalue == connection
-** #2 upvalue == msgid
-** #3 upvalue == result code of the message (ADD, DEL etc.) to be received.
-*/
-static int result_message (lua_State *L) {
- struct timeval *timeout = NULL; /* ??? function parameter ??? */
- LDAPMessage *res;
- int rc;
- conn_data *conn = (conn_data *)lua_touserdata (L, lua_upvalueindex (1));
- int msgid = (int)lua_tonumber (L, lua_upvalueindex (2));
- /*int res_code = (int)lua_tonumber (L, lua_upvalueindex (3));*/
-
- luaL_argcheck (L, conn->ld, 1, LUALDAP_PREFIX"LDAP connection is closed");
- rc = ldap_result (conn->ld, msgid, LDAP_MSG_ONE, timeout, &res);
- if (rc == 0)
- return faildirect (L, LUALDAP_PREFIX"result timeout expired");
- else if (rc < 0) {
- ldap_msgfree (res);
- return faildirect (L, LUALDAP_PREFIX"result error");
- } else {
- int err, ret = 1;
- char *mdn, *msg;
- rc = ldap_parse_result (conn->ld, res, &err, &mdn, &msg, NULL, NULL, 1);
- if (rc != LDAP_SUCCESS)
- return faildirect (L, ldap_err2string (rc));
- switch (err) {
- case LDAP_SUCCESS:
- case LDAP_COMPARE_TRUE:
- lua_pushboolean (L, 1);
- break;
- case LDAP_COMPARE_FALSE:
- lua_pushboolean (L, 0);
- break;
- default:
- lua_pushnil (L);
- lua_pushliteral (L, LUALDAP_PREFIX);
- lua_pushstring (L, msg);
- lua_pushliteral (L, " ");
- lua_pushstring (L, ldap_err2string(err));
- lua_concat (L, 4);
- ret = 2;
- }
- ldap_memfree (mdn);
- ldap_memfree (msg);
- return ret;
- }
-}
-
-
-/*
-** Push a function to process the LDAP result.
-*/
-static int create_future (lua_State *L, ldap_int_t rc, int conn, ldap_int_t msgid, int code) {
- if (rc != LDAP_SUCCESS)
- return faildirect (L, ldap_err2string (rc));
- lua_pushvalue (L, conn); /* push connection as #1 upvalue */
- lua_pushnumber (L, msgid); /* push msgid as #2 upvalue */
- lua_pushnumber (L, code); /* push code as #3 upvalue */
- lua_pushcclosure (L, result_message, 3);
- return 1;
-}
-
-
-/*
-** Unbind from the directory.
-** @param #1 LDAP connection.
-** @return 1 in case of success; nothing when already closed.
-*/
-static int lualdap_close (lua_State *L) {
- conn_data *conn = (conn_data *)luaL_checkudata (L, 1, LUALDAP_CONNECTION_METATABLE);
- luaL_argcheck(L, conn!=NULL, 1, LUALDAP_PREFIX"LDAP connection expected");
- if (conn->ld == NULL) /* already closed */
- return 0;
- ldap_unbind (conn->ld);
- conn->ld = NULL;
- lua_pushnumber (L, 1);
- return 1;
-}
-
-
-/*
-** Add a new entry to the directory.
-** @param #1 LDAP connection.
-** @param #2 String with new entry's DN.
-** @param #3 Table with new entry's attributes and values.
-** @return Function to process the LDAP result.
-*/
-static int lualdap_add (lua_State *L) {
- conn_data *conn = getconnection (L);
- ldap_pchar_t dn = (ldap_pchar_t) luaL_checkstring (L, 2);
- attrs_data attrs;
- ldap_int_t rc, msgid;
- A_init (&attrs);
- if (lua_istable (L, 3))
- A_tab2mod (L, &attrs, 3, LUALDAP_MOD_ADD);
- A_lastattr (L, &attrs);
- rc = ldap_add_ext (conn->ld, dn, attrs.attrs, NULL, NULL, &msgid);
- return create_future (L, rc, 1, msgid, LDAP_RES_ADD);
-}
-
-
-/*
-** Compare a value against an entry.
-** @param #1 LDAP connection.
-** @param #2 String with entry's DN.
-** @param #3 String with attribute's name.
-** @param #4 String with attribute's value.
-** @return Function to process the LDAP result.
-*/
-static int lualdap_compare (lua_State *L) {
- conn_data *conn = getconnection (L);
- ldap_pchar_t dn = (ldap_pchar_t) luaL_checkstring (L, 2);
- ldap_pchar_t attr = (ldap_pchar_t) luaL_checkstring (L, 3);
- BerValue bvalue;
- ldap_int_t rc, msgid;
- bvalue.bv_val = (char *)luaL_checkstring (L, 4);
- bvalue.bv_len = lua_strlen (L, 4);
- rc = ldap_compare_ext (conn->ld, dn, attr, &bvalue, NULL, NULL, &msgid);
- return create_future (L, rc, 1, msgid, LDAP_RES_COMPARE);
-}
-
-
-/*
-** Delete an entry.
-** @param #1 LDAP connection.
-** @param #2 String with entry's DN.
-** @return Boolean.
-*/
-static int lualdap_delete (lua_State *L) {
- conn_data *conn = getconnection (L);
- ldap_pchar_t dn = (ldap_pchar_t) luaL_checkstring (L, 2);
- ldap_int_t rc, msgid;
- rc = ldap_delete_ext (conn->ld, dn, NULL, NULL, &msgid);
- return create_future (L, rc, 1, msgid, LDAP_RES_DELETE);
-}
-
-
-/*
-** Convert a string into an internal LDAP_MOD operation code.
-*/
-static int op2code (const char *s) {
- if (!s)
- return LUALDAP_NO_OP;
- switch (*s) {
- case '+':
- return LUALDAP_MOD_ADD;
- case '-':
- return LUALDAP_MOD_DEL;
- case '=':
- return LUALDAP_MOD_REP;
- default:
- return LUALDAP_NO_OP;
- }
-}
-
-
-/*
-** Modify an entry.
-** @param #1 LDAP connection.
-** @param #2 String with entry's DN.
-** @param #3, #4... Tables with modifications to apply.
-** @return True on success or nil, error message otherwise.
-*/
-static int lualdap_modify (lua_State *L) {
- conn_data *conn = getconnection (L);
- ldap_pchar_t dn = (ldap_pchar_t) luaL_checkstring (L, 2);
- attrs_data attrs;
- ldap_int_t rc, msgid;
- int param = 3;
- A_init (&attrs);
- while (lua_istable (L, param)) {
- int op;
- /* get operation ('+','-','=' operations allowed) */
- lua_rawgeti (L, param, 1);
- op = op2code (lua_tostring (L, -1));
- if (op == LUALDAP_NO_OP)
- return luaL_error (L, LUALDAP_PREFIX"forgotten operation on argument #%d", param);
- /* get array of attributes and values */
- A_tab2mod (L, &attrs, param, op);
- param++;
- }
- A_lastattr (L, &attrs);
- rc = ldap_modify_ext (conn->ld, dn, attrs.attrs, NULL, NULL, &msgid);
- return create_future (L, rc, 1, msgid, LDAP_RES_MODIFY);
-}
-
-
-/*
-** Change the distinguished name of an entry.
-*/
-static int lualdap_rename (lua_State *L) {
- conn_data *conn = getconnection (L);
- ldap_pchar_t dn = (ldap_pchar_t) luaL_checkstring (L, 2);
- ldap_pchar_t rdn = (ldap_pchar_t) luaL_checkstring (L, 3);
- ldap_pchar_t par = (ldap_pchar_t) luaL_optlstring (L, 4, NULL, NULL);
- const int del = luaL_optnumber (L, 5, 0);
- ldap_int_t msgid;
- ldap_int_t rc = ldap_rename (conn->ld, dn, rdn, par, del, NULL, NULL, &msgid);
- return create_future (L, rc, 1, msgid, LDAP_RES_MODDN);
-}
-
-
-/*
-** Push an attribute value (or a table of values) on top of the stack.
-** @param L lua_State.
-** @param ld LDAP Connection.
-** @param entry Current entry.
-** @param attr Name of entry's attribute to get values from.
-** @return 1 in case of success.
-*/
-static int push_values (lua_State *L, LDAP *ld, LDAPMessage *entry, char *attr) {
- int i, n;
- BerValue **vals = ldap_get_values_len (ld, entry, attr);
- n = ldap_count_values_len (vals);
- if (n == 0) /* no values */
- lua_pushboolean (L, 1);
- else if (n == 1) /* just one value */
- lua_pushlstring (L, vals[0]->bv_val, vals[0]->bv_len);
- else { /* Multiple values */
- lua_newtable (L);
- for (i = 0; i < n; i++) {
- lua_pushlstring (L, vals[i]->bv_val, vals[i]->bv_len);
- lua_rawseti (L, -2, i+1);
- }
- }
- ldap_value_free_len (vals);
- return 1;
-}
-
-
-/*
-** Store entry's attributes and values at the given table.
-** @param entry Current entry.
-** @param tab Absolute stack index of the table.
-*/
-static void set_attribs (lua_State *L, LDAP *ld, LDAPMessage *entry, int tab) {
- char *attr;
- BerElement *ber = NULL;
- for (attr = ldap_first_attribute (ld, entry, &ber);
- attr != NULL;
- attr = ldap_next_attribute (ld, entry, ber))
- {
- lua_pushstring (L, attr);
- push_values (L, ld, entry, attr);
- lua_rawset (L, tab); /* tab[attr] = vals */
- ldap_memfree (attr);
- }
- ber_free (ber, 0); /* don't need to test if (ber == NULL) */
-}
-
-
-/*
-** Get the distinguished name of the given entry and pushes it on the stack.
-*/
-static void push_dn (lua_State *L, LDAP *ld, LDAPMessage *entry) {
- char *dn = ldap_get_dn (ld, entry);
- lua_pushstring (L, dn);
- ldap_memfree (dn);
-}
-
-
-/*
-** Release connection reference.
-*/
-static void search_close (lua_State *L, search_data *search) {
- luaL_unref (L, LUA_REGISTRYINDEX, search->conn);
- search->conn = LUA_NOREF;
-}
-
-
-/*
-** Retrieve next message...
-** @return #1 entry's distinguished name.
-** @return #2 table with entry's attributes and values.
-*/
-static int next_message (lua_State *L) {
- search_data *search = getsearch (L);
- conn_data *conn;
- struct timeval *timeout = NULL; /* ??? function parameter ??? */
- LDAPMessage *res;
- int rc;
- int ret;
-
- lua_rawgeti (L, LUA_REGISTRYINDEX, search->conn);
- conn = (conn_data *)lua_touserdata (L, -1); /* get connection */
-
- rc = ldap_result (conn->ld, search->msgid, LDAP_MSG_ONE, timeout, &res);
- if (rc == 0)
- return faildirect (L, LUALDAP_PREFIX"result timeout expired");
- else if (rc == -1)
- return faildirect (L, LUALDAP_PREFIX"result error");
- else if (rc == LDAP_RES_SEARCH_RESULT) { /* last message => nil */
- /* close search object to avoid reuse */
- search_close (L, search);
- ret = 0;
- } else {
- LDAPMessage *msg = ldap_first_message (conn->ld, res);
- switch (ldap_msgtype (msg)) {
- case LDAP_RES_SEARCH_ENTRY: {
- LDAPMessage *entry = ldap_first_entry (conn->ld, msg);
- push_dn (L, conn->ld, entry);
- lua_newtable (L);
- set_attribs (L, conn->ld, entry, lua_gettop (L));
- ret = 2; /* two return values */
- break;
- }
-/*No reference to LDAP_RES_SEARCH_REFERENCE on MSDN. Maybe there is a replacement to it?*/
-#ifdef LDAP_RES_SEARCH_REFERENCE
- case LDAP_RES_SEARCH_REFERENCE: {
- LDAPMessage *ref = ldap_first_reference (conn->ld, msg);
- push_dn (L, conn->ld, ref); /* is this supposed to work? */
- lua_pushnil (L);
- ret = 2; /* two return values */
- break;
- }
-#endif
- case LDAP_RES_SEARCH_RESULT:
- /* close search object to avoid reuse */
- search_close (L, search);
- ret = 0;
- break;
- default:
- ldap_msgfree (res);
- return luaL_error (L, LUALDAP_PREFIX"error on search result chain");
- }
- }
- ldap_msgfree (res);
- return ret;
-}
-
-
-/*
-** Convert a string to one of the possible scopes of the search.
-*/
-static int string2scope (lua_State *L, const char *s) {
- if ((s == NULL) || (*s == '\0'))
- return LDAP_SCOPE_DEFAULT;
- switch (*s) {
- case 'b':
- return LDAP_SCOPE_BASE;
- case 'o':
- return LDAP_SCOPE_ONELEVEL;
- case 's':
- return LDAP_SCOPE_SUBTREE;
- default:
- return luaL_error (L, LUALDAP_PREFIX"invalid search scope `%s'", s);
- }
-}
-
-
-/*
-** Close the search object.
-*/
-static int lualdap_search_close (lua_State *L) {
- search_data *search = (search_data *)luaL_checkudata (L, 1, LUALDAP_SEARCH_METATABLE);
- luaL_argcheck (L, search!=NULL, 1, LUALDAP_PREFIX"LDAP search expected");
- if (search->conn == LUA_NOREF)
- return 0;
- search_close (L, search);
- lua_pushnumber (L, 1);
- return 1;
-}
-
-
-/*
-** Create a search object and leaves it on top of the stack.
-*/
-static void create_search (lua_State *L, int conn_index, int msgid) {
- search_data *search = (search_data *)lua_newuserdata (L, sizeof (search_data));
- lualdap_setmeta (L, LUALDAP_SEARCH_METATABLE);
- search->conn = LUA_NOREF;
- search->msgid = msgid;
- lua_pushvalue (L, conn_index);
- search->conn = luaL_ref (L, LUA_REGISTRYINDEX);
-}
-
-
-/*
-** Fill in the attrs array, according to the attrs parameter.
-*/
-static int get_attrs_param (lua_State *L, char *attrs[]) {
- lua_pushstring (L, "attrs");
- lua_gettable (L, 2);
- if (lua_isstring (L, -1)) {
- attrs[0] = (char *)lua_tostring (L, -1);
- attrs[1] = NULL;
- } else if (!lua_istable (L, -1))
- attrs[0] = NULL;
- else
- if (table2strarray (L, lua_gettop (L), attrs, LUALDAP_MAX_ATTRS))
- return 0;
- return 1;
-}
-
-
-/*
-** Fill in the struct timeval, according to the timeout parameter.
-*/
-static struct timeval *get_timeout_param (lua_State *L, struct timeval *st) {
- double t = numbertabparam (L, "timeout", 0);
- st->tv_sec = (long)t;
- st->tv_usec = (long)(1000000 * (t - st->tv_sec));
- if (st->tv_sec == 0 && st->tv_usec == 0)
- return NULL;
- else
- return st;
-}
-
-
-/*
-** Perform a search operation.
-** @return #1 Function to iterate over the result entries.
-** @return #2 nil.
-** @return #3 nil as first entry.
-** The search result is defined as an upvalue of the iterator.
-*/
-static int lualdap_search (lua_State *L) {
- conn_data *conn = getconnection (L);
- ldap_pchar_t base;
- ldap_pchar_t filter;
- char *attrs[LUALDAP_MAX_ATTRS];
- int scope, attrsonly, msgid, rc, sizelimit;
- struct timeval st, *timeout;
-
- if (!lua_istable (L, 2))
- return luaL_error (L, LUALDAP_PREFIX"no search specification");
- if (!get_attrs_param (L, attrs))
- return 2;
- /* get other parameters */
- attrsonly = booltabparam (L, "attrsonly", 0);
- base = (ldap_pchar_t) strtabparam (L, "base", NULL);
- filter = (ldap_pchar_t) strtabparam (L, "filter", NULL);
- scope = string2scope (L, strtabparam (L, "scope", NULL));
- sizelimit = longtabparam (L, "sizelimit", LDAP_NO_LIMIT);
- timeout = get_timeout_param (L, &st);
-
- rc = ldap_search_ext (conn->ld, base, scope, filter, attrs, attrsonly,
- NULL, NULL, timeout, sizelimit, &msgid);
- if (rc != LDAP_SUCCESS)
- return luaL_error (L, LUALDAP_PREFIX"%s", ldap_err2string (rc));
-
- create_search (L, 1, msgid);
- lua_pushcclosure (L, next_message, 1);
- return 1;
-}
-
-
-/*
-** Return the name of the object's metatable.
-** This function is used by `tostring'.
-*/
-static int lualdap_conn_tostring (lua_State *L) {
- char buff[100];
- conn_data *conn = (conn_data *)lua_touserdata (L, 1);
- if (conn->ld == NULL)
- strcpy (buff, "closed");
- else
- sprintf (buff, "%p", conn);
- lua_pushfstring (L, "%s (%s)", LUALDAP_CONNECTION_METATABLE, buff);
- return 1;
-}
-
-
-/*
-** Return the name of the object's metatable.
-** This function is used by `tostring'.
-*/
-static int lualdap_search_tostring (lua_State *L) {
- char buff[100];
- search_data *search = (search_data *)lua_touserdata (L, 1);
- luaL_argcheck (L,search->conn!=LUA_NOREF,1,LUALDAP_PREFIX"LDAP search is closed");
- if (search->conn == LUA_NOREF)
- strcpy (buff, "closed");
- else
- sprintf (buff, "%p", search);
- lua_pushfstring (L, "%s (%s)", LUALDAP_SEARCH_METATABLE, buff);
- return 1;
-}
-
-
-/*
-** Create a metatable.
-*/
-static int lualdap_createmeta (lua_State *L) {
- const luaL_reg methods[] = {
- {"close", lualdap_close},
- {"add", lualdap_add},
- {"compare", lualdap_compare},
- {"delete", lualdap_delete},
- {"modify", lualdap_modify},
- {"rename", lualdap_rename},
- {"search", lualdap_search},
- {NULL, NULL}
- };
-
- if (!luaL_newmetatable (L, LUALDAP_CONNECTION_METATABLE))
- return 0;
-
- /* define methods */
- luaL_openlib (L, NULL, methods, 0);
-
- /* define metamethods */
- lua_pushliteral (L, "__gc");
- lua_pushcfunction (L, lualdap_close);
- lua_settable (L, -3);
-
- lua_pushliteral (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushliteral (L, "__tostring");
- lua_pushcfunction (L, lualdap_conn_tostring);
- lua_settable (L, -3);
-
- lua_pushliteral (L, "__metatable");
- lua_pushliteral(L,LUALDAP_PREFIX"you're not allowed to get this metatable");
- lua_settable (L, -3);
-
- if (!luaL_newmetatable (L, LUALDAP_SEARCH_METATABLE))
- return 0;
-
- lua_pushliteral (L, "__gc");
- lua_pushcfunction (L, lualdap_search_close);
- lua_settable (L, -3);
-
- lua_pushliteral (L, "__tostring");
- lua_pushcclosure (L, lualdap_search_tostring, 1);
- lua_settable (L, -3);
-
- lua_pushliteral (L, "__metatable");
- lua_pushliteral(L,LUALDAP_PREFIX"you're not allowed to get this metatable");
- lua_settable (L, -3);
-
- return 0;
-}
-
-
-/*
-** Open and initialize a connection to a server.
-** @param #1 String with hostname.
-** @param #2 String with username.
-** @param #3 String with password.
-** @param #4 Boolean indicating if TLS must be used.
-** @return #1 Userdata with connection structure.
-*/
-static int lualdap_open_simple (lua_State *L) {
- ldap_pchar_t host = (ldap_pchar_t) luaL_checkstring (L, 1);
- ldap_pchar_t who = (ldap_pchar_t) luaL_optstring (L, 2, NULL);
- const char *password = luaL_optstring (L, 3, NULL);
- int use_tls = lua_toboolean (L, 4);
- conn_data *conn = (conn_data *)lua_newuserdata (L, sizeof(conn_data));
- int err;
-
- /* Initialize */
- lualdap_setmeta (L, LUALDAP_CONNECTION_METATABLE);
- conn->version = 0;
- conn->ld = ldap_init (host, LDAP_PORT);
- if (conn->ld == NULL)
- return faildirect(L,LUALDAP_PREFIX"Error connecting to server");
- /* Set protocol version */
- conn->version = LDAP_VERSION3;
- if (ldap_set_option (conn->ld, LDAP_OPT_PROTOCOL_VERSION, &conn->version)
- != LDAP_OPT_SUCCESS)
- return faildirect(L, LUALDAP_PREFIX"Error setting LDAP version");
- /* Use TLS */
- if (use_tls) {
- int rc = ldap_start_tls_s (conn->ld, NULL, NULL);
- if (rc != LDAP_SUCCESS)
- return faildirect (L, ldap_err2string (rc));
- }
- /* Bind to a server */
- err = ldap_bind_s (conn->ld, who, password, LDAP_AUTH_SIMPLE);
- if (err != LDAP_SUCCESS)
- return faildirect (L, ldap_err2string (err));
-
- return 1;
-}
-
-
-/*
-** Assumes the table is on top of the stack.
-*/
-static void set_info (lua_State *L) {
- lua_pushliteral (L, "_COPYRIGHT");
- lua_pushliteral (L, "Copyright (C) 2003-2007 Kepler Project");
- lua_settable (L, -3);
- lua_pushliteral (L, "_DESCRIPTION");
- lua_pushliteral (L, "LuaLDAP is a simple interface from Lua to an LDAP client");
- lua_settable (L, -3);
- lua_pushliteral (L, "_VERSION");
- lua_pushliteral (L, "LuaLDAP 1.1.1");
- lua_settable (L, -3);
-}
-
-
-/*
-** Create ldap table and register the open method.
-*/
-int luaopen_lualdap (lua_State *L) {
- struct luaL_reg lualdap[] = {
- {"open_simple", lualdap_open_simple},
- {NULL, NULL},
- };
-
- lualdap_createmeta (L);
- luaL_openlib (L, LUALDAP_TABLENAME, lualdap, 0);
- set_info (L);
-
- return 1;
-}
diff --git a/lualdap/src/lualdap.def b/lualdap/src/lualdap.def
deleted file mode 100755
index 40fe17c..0000000
--- a/lualdap/src/lualdap.def
+++ /dev/null
@@ -1,6 +0,0 @@
-LIBRARY lualdap.dll
-DESCRIPTION "LuaLDAP"
-VERSION 1.1.1
-EXPORTS
-luaopen_lualdap
-
diff --git a/lualdap/src/open2winldap.h b/lualdap/src/open2winldap.h
deleted file mode 100755
index ad592d8..0000000
--- a/lualdap/src/open2winldap.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <winldap.h>
-
-/* For some reason MSDN mentions LDAP_RES_MODDN, but not LDAP_RES_MODRDN. */
-#ifndef LDAP_RES_MODDN
-#define LDAP_RES_MODDN LDAP_RES_MODRDN
-#endif
-
-/* MSDN doesn't mention LDAP_OPT_SUCCESS, it uses LDAP_SUCCESS intead */
-#ifndef LDAP_OPT_SUCCESS
-#define LDAP_OPT_SUCCESS LDAP_SUCCESS
-#endif
-
-/* MSDN doesn't mention LDAP_SCOPE_DEFAULT, so default will be LDAP_SCOPE_SUBTREE */
-#ifndef LDAP_SCOPE_DEFAULT
-#define LDAP_SCOPE_DEFAULT LDAP_SCOPE_SUBTREE
-#endif
-
-/* MSDN doesn't mention this function at all. Unfortunately, LDAPMessage an opaque type. */
-#define ldap_msgtype(m) ((m)->lm_msgtype)
-
-#define ldap_first_message ldap_first_entry
-
-/* The WinLDAP API allows comparisons against either string or binary values */
-#undef ldap_compare_ext
-
-/* The WinLDAP API uses ULONG seconds instead of a struct timeval. */
-#undef ldap_search_ext
-
-/* The WinLDAP API has a different number of arguments for this */
-#undef ldap_start_tls_s
-
-#ifdef UNICODE
-#define ldap_compare_ext(ld,dn,a,v,sc,cc,msg) \
- ldap_compare_extW(ld,dn,a,0,v,sc,cc,msg)
-#define ldap_search_ext(ld,base,scope,f,a,o,sc,cc,t,s,msg) \
- ldap_search_extW(ld,base,scope,f,a,o,sc,cc,(t)?(t)->tv_sec:0,s,msg)
-#define ldap_start_tls_s(ld,sc,cc) \
- ldap_start_tls_sW(ld,0,0,sc,cc)
-#else
-#define ldap_compare_ext(ld,dn,a,v,sc,cc,msg) \
- ldap_compare_extA(ld,dn,a,0,v,sc,cc,msg)
-#define ldap_search_ext(ld,base,scope,f,a,o,sc,cc,t,s,msg) \
- ldap_search_extA(ld,base,scope,f,a,o,sc,cc,(t)?(t)->tv_sec:0,s,msg)
-#define ldap_start_tls_s(ld,sc,cc) \
- ldap_start_tls_sA(ld,0,0,sc,cc)
-#endif
-
diff --git a/lualdap/vc6/lualdap.def b/lualdap/vc6/lualdap.def
deleted file mode 100755
index 3ef26ac..0000000
--- a/lualdap/vc6/lualdap.def
+++ /dev/null
@@ -1,5 +0,0 @@
-LIBRARY lualdap.dll
-DESCRIPTION "LuaLDAP"
-VERSION 1.0
-EXPORTS
-luaopen_lualdap
diff --git a/lualdap/vc6/lualdap.dsw b/lualdap/vc6/lualdap.dsw
deleted file mode 100755
index 4a34054..0000000
--- a/lualdap/vc6/lualdap.dsw
+++ /dev/null
@@ -1,78 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
-
-###############################################################################
-
-Project: "liblber"="..\..\external-src\openldap-2.1.30\libraries\liblber\liblber.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "libldap"="..\..\external-src\openldap-2.1.30\libraries\libldap\libldap.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name liblber
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name libsasl
- End Project Dependency
-}}}
-
-###############################################################################
-
-Project: "libsasl"="..\..\external-src\cyrus-sasl-1.5.28\win32\libsasl\libsasl.dsp" - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Project: "lualdap_dll"=.\lualdap_dll.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
- begin source code control
- lualdap_dll
- ..
- end source code control
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name libldap
- End Project Dependency
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
diff --git a/lualdap/vc6/lualdap.rc b/lualdap/vc6/lualdap.rc
deleted file mode 100755
index b0dbc1a..0000000
--- a/lualdap/vc6/lualdap.rc
+++ /dev/null
@@ -1,109 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// Portuguese (Brazil) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PTB)
-#ifdef _WIN32
-LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,0
- PRODUCTVERSION 1,0,0,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x21L
-#else
- FILEFLAGS 0x20L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "000004b0"
- BEGIN
- VALUE "Comments", "OpenLDAP 2.1.30\0"
- VALUE "CompanyName", "Ideais\0"
- VALUE "FileDescription", "lualdap\0"
- VALUE "FileVersion", "1, 0, 0, 0\0"
- VALUE "InternalName", "lualdap\0"
- VALUE "LegalCopyright", "Copyright © 2005\0"
- VALUE "LegalTrademarks", "\0"
- VALUE "OriginalFilename", "lualdap.dll\0"
- VALUE "PrivateBuild", "\0"
- VALUE "ProductName", "Ideais lualdap\0"
- VALUE "ProductVersion", "1, 0, 0, 0\0"
- VALUE "SpecialBuild", "Kepler Project\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x0, 1200
- END
-END
-
-#endif // !_MAC
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE
-BEGIN
- "#include ""afxres.h""\r\n"
- "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-#endif // Portuguese (Brazil) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
-
diff --git a/lualdap/vc6/lualdap_dll.dsp b/lualdap/vc6/lualdap_dll.dsp
deleted file mode 100755
index d7b24bc..0000000
--- a/lualdap/vc6/lualdap_dll.dsp
+++ /dev/null
@@ -1,127 +0,0 @@
-# Microsoft Developer Studio Project File - Name="lualdap_dll" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=lualdap_dll - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "lualdap_dll.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "lualdap_dll.mak" CFG="lualdap_dll - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "lualdap_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "lualdap_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName "lualdap_dll"
-# PROP Scc_LocalPath ".."
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "lualdap_dll - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "../lib/vc6"
-# PROP Intermediate_Dir "lualdap_dll/Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUALDAP_DLL_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../external-src/lua50/include" /I "../../external-src/openldap-2.1.30/include" /I "../../compat/src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUALDAP_DLL_EXPORTS" /FR /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x416 /d "NDEBUG"
-# ADD RSC /l 0x416 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 lua50.lib wsock32.lib oldap32.lib olber32.lib libsasl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../bin/vc6/lualdap.dll" /libpath:"../../external-src/lua50/lib/dll" /libpath:"../../external-src/openldap-2.1.30/Release" /libpath:"../../external-src/cyrus-sasl-1.5.28/win32/libsasl/Release"
-# Begin Special Build Tool
-SOURCE="$(InputPath)"
-PostBuild_Cmds=cd ../bin/vc6 zip.exe lualdap-1.0-win32.zip lualdap.dll zip.exe -j lualdap-1.0-win32.zip ../../../external-src/cyrus-sasl-1.5.28/win32/libsasl/Release/libsasl.dll
-# End Special Build Tool
-
-!ELSEIF "$(CFG)" == "lualdap_dll - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "../lib/vc6"
-# PROP Intermediate_Dir "lualdap_dll/Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUALDAP_DLL_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../external-src/lua50/include" /I "../../external-src/openldap-2.1.30/include" /I "../../compat/src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUALDAP_DLL_EXPORTS" /YX /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x416 /d "_DEBUG"
-# ADD RSC /l 0x416 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 lua50.lib oldap32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"../bin/vc6/lualdapd.dll" /pdbtype:sept /libpath:"../../external-src/lua50/lib/dll" /libpath:"../../external-src/openldap-2.1.30/Debug" /libpath:"../../external-src/cyrus-sasl-1.5.28/win32/libsasl/Debug"
-
-!ENDIF
-
-# Begin Target
-
-# Name "lualdap_dll - Win32 Release"
-# Name "lualdap_dll - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE="..\..\compat\src\compat-5.1.c"
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\lualdap.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lualdap.def
-# End Source File
-# Begin Source File
-
-SOURCE=.\lualdap.rc
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE="..\..\compat\src\compat-5.1.h"
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/lualdap/vc6/resource.h b/lualdap/vc6/resource.h
deleted file mode 100755
index 39ebbdf..0000000
--- a/lualdap/vc6/resource.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by lualdap.rc
-//
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 101
-#define _APS_NEXT_COMMAND_VALUE 40001
-#define _APS_NEXT_CONTROL_VALUE 1000
-#define _APS_NEXT_SYMED_VALUE 101
-#endif
-#endif
diff --git a/lualdap/tests/test.lua b/unit-tests.lua
index 2dce95b..11dfcef 100755..100644
--- a/lualdap/tests/test.lua
+++ b/unit-tests.lua
@@ -1,12 +1,9 @@
-#!/usr/local/bin/lua5.1
+#!/usr/bin/lua
---------------------------------------------------------------------
-- LuaLDAP test file.
-- This test will create a copy of an existing entry on the
-- directory to work on. This new entry will be modified,
-- renamed and deleted at the end.
---
--- See Copyright Notice in license.html
--- $Id: test.lua,v 1.15 2006-07-24 01:36:51 tomas Exp $
---------------------------------------------------------------------
--
@@ -96,7 +93,7 @@ end
-- basic checking test.
---------------------------------------------------------------------
function basic_test ()
- local ld = CONN_OK (lualdap.open_simple (HOSTNAME, WHO, PASSWORD))
+ local ld = CONN_OK (lualdap.open_simple { uri = HOSTNAME, who = WHO, password = PASSWORD })
assert2 (1, ld:close(), "couldn't close connection")
-- trying to close without a connection.
assert2 (false, pcall (ld.close))
@@ -109,14 +106,14 @@ function basic_test ()
-- it is ok to close a closed object, but nil is returned instead of 1.
assert2 (nil, ld:close())
-- trying to connect to an invalid host.
- assert2 (nil, lualdap.open_simple ("unknown-server"), "this should be an error")
+ assert2 (nil, lualdap.open_simple {uri = "unknown-server"}, "this should be an error")
-- reopen the connection.
-- first, try using TLS
- local ok = lualdap.open_simple (HOSTNAME, WHO, PASSWORD, true)
+ local ok = lualdap.open_simple {uri = HOSTNAME, who = WHO, password = PASSWORD, starttls = true }
if not ok then
-- second, try without TLS
io.write ("\nWarning! Couldn't connect with TLS. Trying again without it.")
- ok = lualdap.open_simple (HOSTNAME, WHO, PASSWORD, false)
+ ok = lualdap.open_simple {uri = HOSTNAME, who = WHO, password = PASSWORD, starttls = false }
end
LD = CONN_OK (ok)
CLOSED_LD = ld