r3303 - in trunk/libmnetutil: . include include/libmnetutil m4 source

mikaelsv at minisip.org mikaelsv at minisip.org
Tue Jun 12 10:48:39 CEST 2007


Author: mikaelsv
Date: 2007-06-12 10:48:39 +0200 (Tue, 12 Jun 2007)
New Revision: 3303

Added:
   trunk/libmnetutil/include/libmnetutil/Downloader.h
   trunk/libmnetutil/include/libmnetutil/HttpDownloader.h
   trunk/libmnetutil/include/libmnetutil/LdapConnection.h
   trunk/libmnetutil/include/libmnetutil/LdapCredentials.h
   trunk/libmnetutil/include/libmnetutil/LdapDirectoryLocator.h
   trunk/libmnetutil/include/libmnetutil/LdapEntry.h
   trunk/libmnetutil/include/libmnetutil/LdapException.h
   trunk/libmnetutil/source/Downloader.cxx
   trunk/libmnetutil/source/HttpDownloader.cxx
   trunk/libmnetutil/source/LdapConnection.cxx
   trunk/libmnetutil/source/LdapEntry.cxx
   trunk/libmnetutil/source/LdapException.cxx
Modified:
   trunk/libmnetutil/Makefile.am
   trunk/libmnetutil/configure.ac
   trunk/libmnetutil/include/Makefile.am
   trunk/libmnetutil/m4/libmnetutil.m4
Log:
Three new features have been added:

 * Basic LDAP support
   - This support is optional and included by adding the --enable-ldap command
     when configuring the compilation.
   - Requires OpenLDAP
   - Supports strings and binary attribute values
 * Downloading files using HTTP
   - Does not support HTTPS, but since a StreamSocket can be used to tunnel
     the HTTP messages (the StreamSocket is then supplied as an argument to
     the HttpDownloader constructor) encryption can be achieved using such
     work-around.
 * The Downloader::create(std::string uri) function can be used to create
   "downloaders" for any given URI (but right now only HTTP URIs are supported)



Modified: trunk/libmnetutil/Makefile.am
===================================================================
--- trunk/libmnetutil/Makefile.am	2007-06-11 14:24:32 UTC (rev 3302)
+++ trunk/libmnetutil/Makefile.am	2007-06-12 08:48:39 UTC (rev 3303)
@@ -11,7 +11,7 @@
 lib_LTLIBRARIES = libmnetutil.la
 # libmnetutil_la_CPPFLAGS = 
 libmnetutil_la_LDFLAGS = $(MINISIP_LIBRARY_LDFLAGS)
-libmnetutil_la_LIBADD = udns/libudns.la  $(LTLIBOBJS) $(MINISIP_LIBS)
+libmnetutil_la_LIBADD = udns/libudns.la  $(LTLIBOBJS) $(MINISIP_LIBS) $(LDAP_LIBS)
 libmnetutil_la_DEPENDENCIES = $(LTLIBOBJS)
 
 libmnetutil_la_SOURCES = $(mnetutil_src)
@@ -32,6 +32,14 @@
 		    source/IP6ServerSocket.cxx
 endif
 
+ldap_src =
+if ENABLE_LDAP
+ldap_src += \
+		    source/LdapConnection.cxx \
+                    source/LdapEntry.cxx \
+                    source/LdapException.cxx
+endif
+
 mnetutil_src = \
 		    source/init.cxx \
 		    source/DnsNaptr.cxx \
@@ -39,6 +47,7 @@
 		    source/IP4Address.cxx \
 		    source/IP4ServerSocket.cxx \
 		    $(ipv6_src) \
+		    $(ldap_src) \
 		    source/NetworkException.cxx \
 		    source/NetworkFunctions.cxx \
 		    source/ServerSocket.cxx \
@@ -49,7 +58,9 @@
 		    source/UDPSocket.cxx \
 		    source/DatagramSocket.cxx \
 		    $(win32_src) \
-		    source/StreamSocket.cxx
+		    source/StreamSocket.cxx \
+		    source/Downloader.cxx \
+		    source/HttpDownloader.cxx
 
 # maintainer rules
 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}

Modified: trunk/libmnetutil/configure.ac
===================================================================
--- trunk/libmnetutil/configure.ac	2007-06-11 14:24:32 UTC (rev 3302)
+++ trunk/libmnetutil/configure.ac	2007-06-12 08:48:39 UTC (rev 3303)
@@ -27,6 +27,19 @@
 AC_CHECK_HEADERS([ifaddrs.h netdb.h sys/socket.h])
 AM_MINISIP_CHECK_IPV6
 
+AC_ARG_ENABLE(ldap,
+    AS_HELP_STRING([--enable-ldap],
+        [enables LDAP support]),
+    [ if test "${enable_ldap}" = "yes"
+      then
+	AM_MINISIP_CHECK_LDAP
+        AC_DEFINE(ENABLE_LDAP, [], [LDAP support is enabled])
+	ENABLE_LDAP="yes"
+      fi  
+      ])
+AM_CONDITIONAL(ENABLE_LDAP, test "${ENABLE_LDAP}" = "yes" )
+AC_SUBST(LDAP_LIBS)
+
 AG_CHECK_POSIX_REGCOMP
 AM_CONDITIONAL(HAVE_POSIX_REGCOMP, test "${ag_cv_posix_regcomp}" = "yes")
 

Modified: trunk/libmnetutil/include/Makefile.am
===================================================================
--- trunk/libmnetutil/include/Makefile.am	2007-06-11 14:24:32 UTC (rev 3302)
+++ trunk/libmnetutil/include/Makefile.am	2007-06-12 08:48:39 UTC (rev 3303)
@@ -1,4 +1,15 @@
+ldap_src =
+if ENABLE_LDAP
+ldap_src += \
+			libmnetutil/LdapConnection.h \
+			libmnetutil/LdapCredentials.h \
+			libmnetutil/LdapDirectoryLocator.h \
+			libmnetutil/LdapEntry.h \
+			libmnetutil/LdapException.h
+endif
+
 pkginclude_HEADERS =    \
+			$(ldap_src) \
 			libmnetutil/init.h \
 			libmnetutil/DnsNaptr.h \
 			libmnetutil/IPAddress.h \
@@ -12,7 +23,9 @@
 			libmnetutil/NetUtil.h \
 			libmnetutil/UDPSocket.h \
 			libmnetutil/DatagramSocket.h \
-			libmnetutil/libmnetutil_config.h
+			libmnetutil/libmnetutil_config.h \
+			libmnetutil/Downloader.h \
+			libmnetutil/HttpDownloader.h
 
 noinst_HEADERS = 	\
 			config.h \

Added: trunk/libmnetutil/include/libmnetutil/Downloader.h
===================================================================
--- trunk/libmnetutil/include/libmnetutil/Downloader.h	                        (rev 0)
+++ trunk/libmnetutil/include/libmnetutil/Downloader.h	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,64 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef DOWNLOADER_H
+#define DOWNLOADER_H
+
+#include <libmutil/MemObject.h>
+#include <string>
+
+using namespace std;
+
+/**
+ * Creates objects for downloading documents specified by and URI.
+ *
+ * This class provides an easy interface for fetching files over the Internet
+ * using a variety of protocols. This class does not fetch any data but only
+ * creates an object that later can be used for fetching the actual data.
+ *
+ * The class is very generic, hence very limited and since it is abstract it
+ * cannot be instantiated by itself.
+ *
+ */
+class Downloader : public MObject {
+
+	public:
+		/**
+		 * Uses the protocol portion of the specified URI to determine
+		 * what type of object should be created to handle the download.
+		 *
+		 * Currently only supports HTTP download using the HttpDownloader class.
+		 *
+		 * @param	uri	Full URI for a remote document (e.g. "http://www.kth.se/index.html")
+		 */
+		static MRef<Downloader*> create(string const uri);
+
+		virtual std::string getMemObjectType() const {return "Downloader";};
+
+		/**
+		 * Returns the document in question. In order to support both
+		 * textual and binary documents there is no function for
+		 * retrieving the remote document as a string (this would not
+		 * work well with binary data).
+		 */
+		virtual const char* getChars() = 0;
+
+};
+
+
+#endif

Added: trunk/libmnetutil/include/libmnetutil/HttpDownloader.h
===================================================================
--- trunk/libmnetutil/include/libmnetutil/HttpDownloader.h	                        (rev 0)
+++ trunk/libmnetutil/include/libmnetutil/HttpDownloader.h	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,212 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _HTTPDOWNLOAD_H_
+#define _HTTPDOWNLOAD_H_
+
+#include <libmutil/MemObject.h>
+#include <libmnetutil/StreamSocket.h>
+#include <libmnetutil/TCPSocket.h>
+#include <libmnetutil/Downloader.h>
+#include <string>
+#include <vector>
+#include <map>
+
+#define HTTP_METHOD_1_0 			"HTTP/1.0"
+
+#define HTTP_RESPONSECODE_OK 			200
+#define HTTP_RESPONSECODE_NOTFOUND 		404
+#define HTTP_RESPONSECODE_MOVEDPERMANENTLY 	301
+#define HTTP_RESPONSECODE_MOVEDTEMPORARILY 	302
+#define HTTP_RESPONSECODE_SERVERERROR 		500
+
+#define HTTP_HEADER_FROM 			"From"
+#define HTTP_HEADER_USERAGENT 			"User-Agent"
+#define HTTP_HEADER_SERVER 			"Server"
+#define HTTP_HEADER_HOST 			"Host"
+#define HTTP_HEADER_ACCEPTS 			"Accepts"
+#define HTTP_HEADER_CONTENTTYPE 		"Content-Type"
+#define HTTP_HEADER_CONTENTLENGTH 		"Content-Length"
+#define HTTP_HEADER_LASTMODIFIED 		"Last-Modified"
+
+#define HTTP_HEADER_CRLF			"\r\n"
+
+using namespace std;
+
+/**
+ * This class is a very simple HTTP user agent that fetches web pages using the HTTP 1.0 (not 1.1) protocol.
+ *
+ * The implementation is, as mentioned, very simplified and has the following limitations:
+ *  - The entire requested document is stored in memory, thus exhausting the available system memory if large files are fetched
+ *  - The above limitation is however not relevant as only the first 32 KiB of the requested document are fetched
+ *  - Cannot cope with multi-line headers
+ *  - Cannot handle password protected resources
+ *  - Only handles HTTP (not HTTPS)
+ *
+ * Usage:
+ *  # Initialize the class instance by calling the constructor
+ *  # Call either downloadToFile(string), downloadToString() or requestHeaders()
+ *  # Work with the document using the functions getHeader(string), getBody() and getResponseCode()
+ *
+ * Constructors and descructors are defined in HEADER FILE!
+ *
+ * @author	Mikael Svensson
+ */
+class HttpDownloader : public Downloader {
+	public:
+		/**
+		 * Connects to HTTP server but does not fetch file.
+		 *
+		 * @param	url	File/document to fetch.
+		 */
+		HttpDownloader(string url) : url (url), remotePort(80), respCode(-1), followRedirect(true), sock(NULL), internalSocketObject(false) {
+			parseUrl();
+			if (remotePort > 0 && remoteHostname != "") {
+				sock = new TCPSocket(remoteHostname, remotePort);
+				internalSocketObject = true;
+			}
+		}
+
+		/**
+		 * This constructor is useful when tunneling HTTP over other protocols than pure TCP.
+		 *
+		 * Since the constructor HttpDownload(string) opens up an new TCP connection directly it is not
+		 * useful when encryption is needed (e.g. when using the TlsSrpSocket). In these cases
+		 * a StreamSocket object can be created outside the HttpDownloader object and passed to this
+		 * constructor for use by the download functions later on.
+		 *
+		 * @note	The StreamSocket sock will *not* be closed after usage, even though this is not an HTTP 1.1 compatible client.
+		 * @param	url	File/document to fetch.
+		 * @param	sock	Pre-existing socket to use for communicating with HTTP server.
+		 */
+		HttpDownloader(string url, StreamSocket * sock): url (url), remotePort(80), respCode(-1), followRedirect(true), sock(sock), internalSocketObject(false) {
+			parseUrl();
+		}
+
+		/**
+		 * The default constructor deallocates memory, if allocated.
+		 */
+		~HttpDownloader() {
+			if (internalSocketObject)
+				delete sock;
+		}
+
+
+		const char*	getChars();
+		/**
+		 * Fetch remote file and save as file on local computer.
+		 */
+		bool 	downloadToFile(string filename);
+
+		/**
+		 * Fetch remote file and return it as a single string
+		 */
+		string 	downloadToString();
+
+		/**
+		 * Fetch only HTTP headers for remote file.
+		 *
+		 * @return	True on success, false otherwise.
+		 */
+		bool 	downloadHeaders();
+
+		/**
+		 * Return value of HTTP header.
+		 *
+		 * @note	This function relies on that either downloadHeaders(), downloadToFile() or downloadToString() has been called prior.
+		 * @param	header	Name of header to fetch.
+		 */
+		string 	getHeader(string header);
+
+		/**
+		 * Returns the response code.
+		 *
+		 * @note	This function relies on that either downloadHeaders(), downloadToFile() or downloadToString() has been called prior.
+		 */
+		int 	getResponseCode() const;
+
+		/**
+		 * Sets whether or not redirection responses should be followed automatically.
+		 *
+		 * To prevent circular redirections (loops) a maximum of three redirections will be followed.
+		 */
+		void 	setFollowRedirects(bool const val);
+		bool 	getFollowRedirects() const;
+
+		virtual std::string getMemObjectType() const {return "HttpDownloader";};
+
+	private:
+		// Variables
+		string 	url;
+		string 	remoteHostname;
+		string 	remoteProtocol;
+		string 	remoteFile;
+		int 	remotePort;
+		map<string, string> headers;
+		int 	respCode;
+		bool	followRedirect;
+		StreamSocket * sock;
+		bool 	internalSocketObject;
+
+		// Functions
+		int 	fetch(string request, ostream & bodyStream);
+
+		/**
+		 * Parse a line of the HTTP response and store the line as a key/value pair in the map of headers.
+		 *
+		 * Note that the header value is trimmed for white-space both from the right and left.
+		 */
+		void 	parseHeader(string line);
+
+		/**
+		 * Does not take into account the following things:
+		 * - Header values might be split into multiple lines
+		 * - Header lines can end with \\n instead of \\r\\n
+		 */
+		int 	parseHeaders(stringstream & headers);
+
+		/**
+		 * Used to parse the URL supplied in the constructor.
+		 *
+		 * The purpose is to pick out address, port and so on.
+		 *
+		 * Can probably not handle "Location: /index.php" but only "Location: http://full-server-name/index.php"
+		 */
+		void 	parseUrl();
+
+		/**
+		 * @deprecated	Use the very similar split() from libmutil/stringutils.h instead.
+		 * @param	data		String to be split
+		 * @param	token		Separator
+		 * @param	res		The string vector where the strings found will be stored
+		 * @param	maxChars	The maximum number of characters of data that will be scanned (-1 disables feature and entire string is scanned).
+		 * @author	Erik Ehrlund
+		 * @author	Mikael Svensson
+		 */
+		void	split(string data, string token, vector<string> &res, int maxChars = -1); // Copyright Erik Ehrlund
+
+		/**
+		 * This function removes any spaces, line feeds, carrige returns and tabs from the beginning and end of the specified string.
+		 *
+		 * @deprecated	Use the very similar trim() from libmutil/stringutils.h instead.
+		 */
+		string	trim(string s);
+		string	buildRequestString(string method, string file);
+};
+
+#endif

Added: trunk/libmnetutil/include/libmnetutil/LdapConnection.h
===================================================================
--- trunk/libmnetutil/include/libmnetutil/LdapConnection.h	                        (rev 0)
+++ trunk/libmnetutil/include/libmnetutil/LdapConnection.h	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,110 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef LDAPCONNECTION_H_
+#define LDAPCONNECTION_H_
+
+#include <ldap.h>
+
+#include <libmutil/MemObject.h>
+#include <libmnetutil/LdapException.h>
+#include <libmnetutil/LdapCredentials.h>
+#include <libmnetutil/LdapEntry.h>
+
+#include <ldap.h>
+#include <string>
+#include <vector>
+
+/**
+ * Manages one connection to one LDAP server.
+ *
+ * @author	Mikael Svensson
+ */
+class LdapConnection : public MObject {
+	public:
+		LdapConnection(std::string host, int port);
+		LdapConnection(std::string host, int port, MRef<LdapCredentials*> cred);
+		LdapConnection(std::string host);
+		LdapConnection(std::string host, MRef<LdapCredentials*> cred);
+		~LdapConnection();
+
+		/**
+		 * Connects AND binds to the specified server. Automatically disconnects
+		 * any existing connection.
+		 */
+		void 			connect() throw (LdapException);
+
+		/**
+		 * Tests if a connection has been set up.
+		 *
+		 * @param	alsoCheckBind	If set the function checks both if a connection has been established and if the client is "bound".
+		 */
+		bool 			isConnected(bool alsoCheckBind = false);
+
+		/**
+		 * Disconnect from server (unbind).
+		 */
+		bool 			disconnect();
+
+		/**
+		 * Sends a query to the LDAP server and blocks until the entire response has been returned.
+		 *
+		 * @param	baseDn	The root path on the server where the search should commence.
+		 * @param	query	The LDAP query filter to be used to select entries/objects.
+		 * @param	attrs	String vector containing the attribute names to return.
+		 * @param	scope	The scope of the search. Possible values: LDAP_SCOPE_SUBTREE, LDAP_SCOPE_BASE or LDAP_SCOPE_ONE.
+		 * @return	A vector containing LdapEntry instances. Each LdapEntry represents a returned object and each instance is already populated with the appropriate values when returned.
+		 */
+		std::vector<MRef<LdapEntry*> > find(std::string baseDn, std::string query, std::vector<std::string> & attrs, int scope = LDAP_SCOPE_SUBTREE) throw (LdapNotConnectedException, LdapException);
+
+		/**
+		 * Determine the base DN of the connected server.
+		 *
+		 * This is done by requesting the namingContexts attribute of all objects in the directory root.
+		 * This is, obviously, not a query that includes sub-folder in the LDAP tree.
+		 *
+		 * This feature is not supported by all servers. If the method cannot determine the base DN
+		 * of the directory it will throw an LdapUnsupportedException.
+		 */
+		std::string 		getBaseDn() throw (LdapNotConnectedException, LdapUnsupportedException);
+
+		/**
+		 * Set the credentials to use. Currently only simple authentication with a username and password is supported.
+		 */
+		void			setCredentials(MRef<LdapCredentials*> cred);
+
+		MRef<LdapCredentials*>	getCredentials();
+
+		/**
+		 * Return raw LDAP object pointer.
+		 */
+		//LDAP*			getLdapObject();
+	private:
+		LDAP* 			ld;
+		std::string 		hostname;
+		int 			port;
+		MRef<LdapCredentials*> 	cred;
+
+		/**
+		 * Used internally to determine whether or not the client has executed a bind operation.
+		 */
+		bool			isBound;
+
+};
+
+#endif

Added: trunk/libmnetutil/include/libmnetutil/LdapCredentials.h
===================================================================
--- trunk/libmnetutil/include/libmnetutil/LdapCredentials.h	                        (rev 0)
+++ trunk/libmnetutil/include/libmnetutil/LdapCredentials.h	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,42 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef LDAPCREDENTIALS_H_
+#define LDAPCREDENTIALS_H_
+
+#include <libmutil/MemObject.h>
+#include <libmcrypto/cert.h>
+
+#include <string>
+
+/**
+ * Simple data class for storing credentials.
+ *
+ * @author	Mikael Svensson
+ */
+class LdapCredentials : public MObject {
+	public:
+		MRef<certificate*> cert;
+		std::string username;
+		std::string password;
+
+		LdapCredentials(std::string usr,std::string pw) : username(usr), password(pw) {
+		}
+};
+
+#endif

Added: trunk/libmnetutil/include/libmnetutil/LdapDirectoryLocator.h
===================================================================
--- trunk/libmnetutil/include/libmnetutil/LdapDirectoryLocator.h	                        (rev 0)
+++ trunk/libmnetutil/include/libmnetutil/LdapDirectoryLocator.h	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef LDAPDIRECTORYLOCATOR_H_
+#define LDAPDIRECTORYLOCATOR_H_
+
+#include <libmutil/MemObject.h>
+
+/**
+ * Provides a selection of methods for locating LDAP servers. NOT IMPLEMENTED!
+ *
+ * @author	Mikael Svensson
+ */
+class LdapDirectoryLocator : public MObject {
+	public:
+		static std::string findDnsSrv();
+		static std::string findDnsAlias();
+		static std::string findUserConfig();
+		static std::string findUserCache();
+		static std::string find();
+};
+#endif

Added: trunk/libmnetutil/include/libmnetutil/LdapEntry.h
===================================================================
--- trunk/libmnetutil/include/libmnetutil/LdapEntry.h	                        (rev 0)
+++ trunk/libmnetutil/include/libmnetutil/LdapEntry.h	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,108 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef LDAPENTRY_H_
+#define LDAPENTRY_H_
+
+#include <ldap.h>
+#include <lber.h>
+#include <libmnetutil/LdapException.h>
+#include <libmutil/MemObject.h>
+
+#include <string>
+#include <map>
+#include <vector>
+
+class certificate_pair {}; //Dummy entry
+
+/**
+ * Class used internally by LdapEntry
+ *
+ * @author	Mikael Svensson
+ */
+class LdapEntryBinaryValue : public MObject {
+	public:
+		LdapEntryBinaryValue(char* v, int l) : length(l) {
+			value = new char[length];
+			memcpy(value, v, length);
+		}
+		~LdapEntryBinaryValue() {
+			delete[] value;
+		}
+		char* value;
+		int length;
+};
+
+/**
+ * Represents one object in the LDAP directory, including its attribute values.
+ *
+ * When the class instance is created it read an entire entry from an LDAP repsonse message
+ * and stores all information internally. This means that once all the LdapEntry objects
+ * have been created it is safe to free the memory allocated by the response message itself.
+ *
+ * The class differentiates between binary and non-binary attribute values (anything that is
+ * not binary is stored as strings). The separation is made based on the returned attribute
+ * names as it is assumed that all binary attributes have name which end with ";binary".
+ *
+ * Binary attribute values are stored in LdapEntryBinaryValue object whereas all other values
+ * are stored as strings.
+ *
+ * @author	Mikael Svensson
+ */
+class LdapEntry : public MObject {
+	public:
+		LdapEntry(LDAP* ld, LDAPMessage* entry);
+		//~LdapEntry();
+
+		/**
+		 * Return THE FIRST string value for a given attribute.
+		 */
+		std::string			getAttrValueString(std::string attr) throw (LdapAttributeNotFoundException);
+
+		/**
+		 * Return all binary values for a given attribute.
+		 */
+
+		std::vector< MRef<LdapEntryBinaryValue*> > getAttrValuesBinary(std::string attr) throw (LdapAttributeNotFoundException);
+		/**
+		 * Return ALL string values for a given attribute.
+		 */
+		std::vector<std::string>	getAttrValuesStrings(std::string attr) throw (LdapAttributeNotFoundException);
+
+		/**
+		 * Specialized method that returns all certificate pair attribute values (given a specific attribute name).
+		 */
+		std::vector<MRef<certificate_pair*> >	getAttrValuesCertificatePairs(std::string attr) throw (LdapAttributeNotFoundException);
+
+		//std::string 			getDn();
+
+		/**
+		 * Returns list of all attribute names.
+		 */
+		std::vector<std::string> 	getAttrNames();
+
+		/**
+		 * Tests if the directory entry/object has a specific attribute.
+		 */
+		bool 				hasAttribute(std::string attr);
+	private:
+		std::map<std::string, std::vector<MRef<LdapEntryBinaryValue*> > > valuesBinary;
+		std::map<std::string, std::vector<std::string> > valuesStrings;
+};
+
+#endif

Added: trunk/libmnetutil/include/libmnetutil/LdapException.h
===================================================================
--- trunk/libmnetutil/include/libmnetutil/LdapException.h	                        (rev 0)
+++ trunk/libmnetutil/include/libmnetutil/LdapException.h	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2005, 2004 Erik Eliasson, Johan Bilien
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef LDAPEXCEPTION_H_
+#define LDAPEXCEPTION_H_
+
+#include <libmutil/Exception.h>
+#include <libmnetutil/libmnetutil_config.h>
+#include <string>
+
+/**
+ * @author	Mikael Svensson
+ * @author	Erik Eliasson <eliasson at it.kth.se>
+ * @author	Johan Bilien <jobi at via.ecp.fr>
+ */
+class LIBMNETUTIL_API LdapException : public Exception {
+	public:
+		LdapException();
+		LdapException(std::string message);
+		virtual ~LdapException() throw() {};
+		virtual const char *what() const throw();
+	protected:
+		std::string msg;
+};
+
+class LIBMNETUTIL_API LdapAttributeNotFoundException : public LdapException {
+	public:
+		LdapAttributeNotFoundException(std::string message);
+};
+
+class LIBMNETUTIL_API LdapNotConnectedException : public LdapException {
+	public:
+		LdapNotConnectedException();
+};
+
+class LIBMNETUTIL_API LdapUnsupportedException : public LdapException {
+	public:
+		LdapUnsupportedException(std::string feature);
+};
+
+#endif

Modified: trunk/libmnetutil/m4/libmnetutil.m4
===================================================================
--- trunk/libmnetutil/m4/libmnetutil.m4	2007-06-11 14:24:32 UTC (rev 3302)
+++ trunk/libmnetutil/m4/libmnetutil.m4	2007-06-12 08:48:39 UTC (rev 3303)
@@ -1,3 +1,16 @@
+# AM_MINISIP_CHECK_LDAP
+#-----------------------
+AC_DEFUN([AM_MINISIP_CHECK_LDAP], [
+	# PKG_CHECK_MODULES([LDAP], [libldap], [liblber])
+
+	mnetutil_save_LIBS="${LIBS}"
+	LDAP_LIBS="-lldap -llber"
+	LIBS="${LDAP_LIBS} ${LIBS}"
+	AC_CHECK_FUNCS([ldap_init],,[AC_MSG_ERROR([OpenLDAP not found])])
+	LIBS="${mnetutil_save_LIBS}"
+])
+
+
 # AM_MINISIP_ENABLE_IPV6(VERSION)
 # -------------------------------
 AC_DEFUN([AM_MINISIP_ENABLE_IPV6],[ 

Added: trunk/libmnetutil/source/Downloader.cxx
===================================================================
--- trunk/libmnetutil/source/Downloader.cxx	                        (rev 0)
+++ trunk/libmnetutil/source/Downloader.cxx	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,15 @@
+#include <libmnetutil/Downloader.h>
+#include <libmnetutil/HttpDownloader.h>
+#include <string>
+
+using namespace std;
+
+MRef<Downloader*> Downloader::create(string const uri) {
+	int pos = uri.find("://");
+	if (string::npos != pos) {
+		string protocol = uri.substr(0, pos);
+		if (protocol == "http")
+			return MRef<Downloader*>(dynamic_cast<Downloader*>(new HttpDownloader(uri)));
+	}
+	return MRef<Downloader*>();
+}

Added: trunk/libmnetutil/source/HttpDownloader.cxx
===================================================================
--- trunk/libmnetutil/source/HttpDownloader.cxx	                        (rev 0)
+++ trunk/libmnetutil/source/HttpDownloader.cxx	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,366 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <libmutil/MemObject.h>
+#include <libmnetutil/HttpDownloader.h>
+#include <libmnetutil/StreamSocket.h>
+
+#include <fstream>
+#include <sstream>
+
+#include <string>
+#include <vector>
+#include <map>
+#include <iostream>
+
+/**
+ * The buffer size is set to a constant value to simplify the implementation. A production version of this class cannot have this limitation.
+ */
+#define BUFFERSIZE 4096
+
+using namespace std;
+
+const char* HttpDownloader::getChars() {
+	int tries = 3;
+	while (tries) {
+		ostringstream body;
+		int fetchRes = fetch(buildRequestString("GET ", remoteFile), body);
+		if (fetchRes == HTTP_RESPONSECODE_MOVEDPERMANENTLY || respCode == HTTP_RESPONSECODE_MOVEDTEMPORARILY) {
+			url = getHeader("Location");
+			parseUrl();
+			if (!followRedirect) {
+				return "";
+			}
+		} else if (fetchRes == HTTP_RESPONSECODE_OK) {
+			return body.str().c_str();
+		} else {
+			return "";
+		}
+		tries--;
+	}
+	return "";
+}
+
+
+int HttpDownloader::getResponseCode() const {
+	return respCode;
+}
+
+void HttpDownloader::setFollowRedirects(bool const val) {
+	followRedirect = val;
+}
+
+bool HttpDownloader::getFollowRedirects() const {
+	return followRedirect;
+}
+
+int HttpDownloader::fetch(string request, ostream & bodyStream) {
+
+	cerr << "(FETCH)" << endl;
+
+	if (sock == NULL) {
+		// TODO: Error check for socket object
+	}
+
+	stringstream headerStream;
+	int fp = 0;
+	unsigned int bytesWritten = 0, bytesRead = 0;
+	struct sockaddr_in remoteAddr;
+	/*
+	This is what the hostent struct looks like:
+
+	struct  hostent
+	{
+	char    *h_name;        // official name of host
+	char    **h_aliases;    // alias list
+	int     h_addrtype;     // host address type
+	int     h_length;       // length of address
+	char    **h_addr_list;  // list of addresses from name server
+	#define h_addr  h_addr_list[0]  // address, for backward compatiblity
+	};
+	*/
+	struct hostent *remoteHost;
+
+	/* Buffer for holding data read from the network stream */
+	char buffer[BUFFERSIZE];
+	memset(buffer, 0, sizeof(buffer)); // Zero out the buffer used when recieving data
+
+	/* Create socket */
+	fp = socket(AF_INET, SOCK_STREAM, 0);
+	if (fp == -1) {
+		cerr << "Error: Could not create socket" << endl;
+		return false;
+	}
+	//memset(remoteAddr, 0, sizeof(remoteAddr)); // Zero the data structure containing information about the remote host
+
+	/* Fetch information about the remote host */
+	remoteHost = gethostbyname(remoteHostname.c_str()); // Use host name stored in class instance
+	if (remoteHost == NULL) {
+		cerr << "Error: Could not resolve host name" << endl;
+		return false;
+	}
+	remoteAddr.sin_family = AF_INET;
+	remoteAddr.sin_port = htons(remotePort); // Use port number stored in class instance
+
+	// Copy information about remote host's IP address from one structure to another (to the one used by "connect()")
+	bcopy((char *)remoteHost->h_addr, (char *)&remoteAddr.sin_addr.s_addr, sizeof(remoteHost->h_length));
+
+	/* Send request */
+	bytesWritten = sock->write(request.c_str(), request.length());
+	if (bytesWritten < 0) {
+		cerr << "Error: Could not send request" << endl;
+		return false;
+	} else if (bytesWritten < request.length()) {
+		return false;
+	}
+
+
+	/* Read response */
+	bool headerMode = true;
+	int headerParseResult = 0;
+	while ((bytesRead = sock->read(buffer, BUFFERSIZE)) > 0) {
+		if (headerMode) {
+			// Search for headers/body boundary in lastly fetched data
+			char* bodyStr = strstr(buffer, "\r\n\r\n");
+			int bodyLen = buffer + bytesRead - bodyStr;
+
+			if (bodyStr != NULL) {
+				// Found boundary
+				headerStream.write(buffer, bodyStr - buffer);
+				// Error checking!
+				if (headerStream.fail()) {
+					return 0;
+				}
+
+				bodyStream.write(bodyStr+4, bodyLen-4);
+				// Error checking!
+				if (bodyStream.fail()) {
+					return 0;
+				}
+
+				headerMode = false;
+
+				headerParseResult = parseHeaders(headerStream);
+				switch (headerParseResult) {
+					case HTTP_RESPONSECODE_OK:
+						break;
+					default:
+						close(fp);
+						return headerParseResult;
+						break;
+
+				}
+			} else {
+				headerStream.write(buffer, bytesRead);
+				// Error checking!
+				if (headerStream.fail()) {
+					return 0;
+				}
+			}
+		} else {
+			bodyStream.write(buffer, bytesRead);
+			// Error checking!
+			if (bodyStream.fail()) {
+				return 0;
+			}
+		}
+	}
+	if (internalSocketObject)
+		sock->close();
+
+	if (bytesRead < 0) {
+		cerr << "Error: Could not receive response" << endl;
+		return 0;
+	}
+
+	return HTTP_RESPONSECODE_OK;
+}
+
+void HttpDownloader::parseUrl() {
+	int pos = 0;
+	int lastPos = 0;
+	// Find protocol
+	if ((pos = url.find("://", 0)) != string::npos) {
+		remoteProtocol = url.substr(lastPos, pos - lastPos);
+		lastPos = pos + 3;
+	}
+	// Find host (and possibly file on remote host, e.g. "index.html")
+	if ((pos = url.find("/", lastPos)) != string::npos) {
+		// At least the root of the webserver should be fetched (e.g. "http://www.sunet.se/", but more likely "http://www.sunet.se/index.html")
+		remoteHostname = url.substr(lastPos, pos - lastPos);
+		lastPos = pos;
+		remoteFile = url.substr(lastPos);
+	} else {
+		//Only host part specified (e.g. "http://www.sunet.se")
+		remoteHostname = url.substr(lastPos);
+	}
+	// Find remote port
+	if ((pos = remoteHostname.find(":", 0)) != string::npos) {
+		remoteHostname = remoteHostname.substr(0, pos);
+		remotePort = atoi(remoteHostname.substr(pos + 1).c_str());
+	}
+}
+
+void HttpDownloader::split(string data, string token, vector<string> &res, int maxChars)
+{
+	int count = 0;
+	int lastpos = 0;
+	int tokenlen = token.length();
+	int pos = data.find(token,lastpos);
+	while(string::npos != pos && ((maxChars > 0 && pos < maxChars) || maxChars <= 0))
+	{
+		count = pos - lastpos;
+		res.push_back(data.substr(lastpos,count));
+		lastpos = pos + tokenlen;
+		pos = data.find(token,lastpos);
+	}
+	/**
+	 * If the entire string is to be scanned then we want to add the last part of the string/data
+	 * to the result list. This splitis not necessary is there is an upper limit when no more characters
+	 * are of interest.
+	 */
+	if (maxChars <= 0) {
+		res.push_back(data.substr(lastpos));
+	}
+}
+
+string HttpDownloader::trim(string s) {
+	int trimLeftPos = s.find_first_not_of(" \n\t\r");
+	int trimRightPos = s.find_last_not_of(" \n\t\r");
+	int pos = 0;
+	int len = 0;
+
+	if (trimLeftPos != string::npos)
+		pos = trimLeftPos;
+
+	if (trimRightPos != string::npos)
+		len = trimRightPos + 1 - pos;
+	else
+		len = s.length() - pos;
+
+	return s.substr(pos, len);
+}
+bool HttpDownloader::downloadHeaders() {
+	int tries = 3;
+	while (tries) {
+		ostringstream body;
+		int fetchRes = fetch(buildRequestString("HEAD ", remoteFile), body);
+		if (fetchRes == HTTP_RESPONSECODE_MOVEDPERMANENTLY || respCode == HTTP_RESPONSECODE_MOVEDTEMPORARILY) {
+			url = getHeader("Location");
+			parseUrl();
+			if (!followRedirect) {
+				return false;
+			}
+		} else if (fetchRes == HTTP_RESPONSECODE_OK) {
+			return true;
+		} else {
+			return false;
+		}
+		tries--;
+	}
+	return false;
+}
+
+string HttpDownloader::downloadToString() {
+
+	int tries = 3;
+	while (tries) {
+		ostringstream body;
+		int fetchRes = fetch(buildRequestString("GET ", remoteFile), body);
+		if (fetchRes == HTTP_RESPONSECODE_MOVEDPERMANENTLY || respCode == HTTP_RESPONSECODE_MOVEDTEMPORARILY) {
+			url = getHeader("Location");
+			parseUrl();
+			if (!followRedirect) {
+				return "";
+			}
+		} else if (fetchRes == HTTP_RESPONSECODE_OK) {
+			return body.str();
+		} else {
+			return "";
+		}
+		tries--;
+	}
+	return "";
+}
+bool HttpDownloader::downloadToFile(string filename) {
+
+	int tries = 3;
+	while (tries) {
+
+		ofstream file(filename.c_str(), ios_base::out | ios_base::trunc);
+		if (!file) {
+			return false;
+		}
+
+		int fetchRes = fetch(buildRequestString("GET ", remoteFile), file);
+		if (fetchRes == HTTP_RESPONSECODE_MOVEDPERMANENTLY || respCode == HTTP_RESPONSECODE_MOVEDTEMPORARILY) {
+			url = getHeader("Location");
+			parseUrl();
+			if (!followRedirect) {
+				return false;
+			}
+		} else if (fetchRes == HTTP_RESPONSECODE_OK) {
+			return !file.fail();
+		} else {
+			return false;
+		}
+		tries--;
+	}
+	return false;
+}
+
+int HttpDownloader::parseHeaders(stringstream & headers) {
+	vector<string> lines;
+	vector<string> initialLine;
+	string bodySep = HTTP_HEADER_CRLF;
+	bodySep += HTTP_HEADER_CRLF;
+
+	split(headers.str(), HTTP_HEADER_CRLF, lines);
+	split(lines[0], " ", initialLine);
+
+	respCode = atoi(initialLine[1].c_str());
+
+	for (int i=1; i<lines.size(); i++) {
+		parseHeader(lines.at(i));
+	}
+
+	return respCode;
+}
+
+void HttpDownloader::parseHeader(string line) {
+	int pos = line.find(':');
+	if (pos != string::npos) {
+		cout << "Found header: [" << line.substr(0, pos) << " = " << trim(line.substr(pos+1)) << "]" << endl;
+		headers[line.substr(0, pos)] = trim(line.substr(pos+1));
+	} else {
+		cerr << "ERROR: Header \"" << line << "\" is not valid!" << endl;
+	}
+}
+
+string HttpDownloader::getHeader(string header) {
+	map<string, string>::iterator iter = headers.find(header);
+	if (iter != headers.end()) {
+		return iter->second;
+	} else {
+		return "";
+	}
+}
+string HttpDownloader::buildRequestString(string method, string file) {
+	string res = method + " " + file + " " + HTTP_METHOD_1_0;
+	res.append(HTTP_HEADER_CRLF);
+
+	res.append(HTTP_HEADER_FROM);
+	res.append(": anonymous at minisip.org");
+	res.append(HTTP_HEADER_CRLF);
+
+	res.append(HTTP_HEADER_USERAGENT);
+	res.append(": Minisip-FileDownloader/0.1");
+	res.append(HTTP_HEADER_CRLF);
+
+	res.append(HTTP_HEADER_CRLF);
+	//res.append(HTTP_HEADER_CRLF);
+
+	return res;
+}

Added: trunk/libmnetutil/source/LdapConnection.cxx
===================================================================
--- trunk/libmnetutil/source/LdapConnection.cxx	                        (rev 0)
+++ trunk/libmnetutil/source/LdapConnection.cxx	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,150 @@
+#include <libmnetutil/LdapConnection.h>
+
+LdapConnection::LdapConnection(std::string host, int port) : hostname(host), port(port), ld(NULL), isBound(false) {
+}
+LdapConnection::LdapConnection(std::string host) : hostname(host), port(LDAP_PORT), ld(NULL), isBound(false) {
+}
+LdapConnection::LdapConnection(std::string host, int port, MRef<LdapCredentials*> cred) : hostname(host), port(port), ld(NULL), isBound(false) {
+	setCredentials(cred);
+	try {
+		connect();
+	} catch (LdapException & e) {
+		//std::cerr << e.what() << std::endl;
+	}
+}
+LdapConnection::LdapConnection(std::string host, MRef<LdapCredentials*> cred) : hostname(host), port(LDAP_PORT), ld(NULL), isBound(false) {
+	setCredentials(cred);
+	try {
+		connect();
+	} catch (LdapException & e) {
+		//std::cerr << e.what() << std::endl;
+	}
+}
+LdapConnection::~LdapConnection() {
+	disconnect();
+}
+
+bool LdapConnection::isConnected(bool alsoCheckBind) {
+	if (NULL == ld)
+		return false;
+	if (alsoCheckBind && !isBound)
+		return false;
+	return true;
+}
+void LdapConnection::setCredentials(MRef<LdapCredentials*> cred) {
+	this->cred = cred;
+}
+MRef<LdapCredentials*> LdapConnection::getCredentials() {
+	return cred;
+}
+/**
+ * Some of this code has been copied from an unknown source.
+ */
+void LdapConnection::connect() throw (LdapException) {
+	int auth_method = LDAP_AUTH_SIMPLE;
+	int desired_version = LDAP_VERSION3;
+
+	if (isConnected()) {
+		disconnect();
+	}
+	if (cred.isNull()) {
+		throw LdapException("Could not connect since no credentials have been specified");
+	}
+
+	// Initialize LDAP library and open connection
+	if ((ld = ldap_init(hostname.c_str(), port)) == NULL ) {
+		throw LdapException("Could not connect to server");
+	}
+
+	// Set protocol version
+	if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &desired_version) != LDAP_OPT_SUCCESS) {
+		throw LdapException("Could not set connection options after setting up connection");
+	}
+
+	// Create LDAP bind
+	if (ldap_bind_s(ld, cred->username.c_str(), cred->password.c_str(), auth_method) != LDAP_SUCCESS) {
+		throw LdapException("Could not bind to connected server");
+	}
+
+	isBound = true;
+}
+
+bool LdapConnection::disconnect() {
+	if (isBound) {
+		ldap_unbind(ld);
+	}
+}
+
+/**
+ * Some of this code has been copied from an unknown source.
+ */
+std::vector<MRef<LdapEntry*> > LdapConnection::find(std::string baseDn, std::string query, std::vector<std::string> & attrs, int scope) throw (LdapNotConnectedException, LdapException) {
+	LDAPMessage* msg;
+	std::vector<MRef<LdapEntry*> > entries = std::vector<MRef<LdapEntry*> >();
+	char* searchAttrs[attrs.size()+1];
+	LDAPMessage* entry;
+	char* attr;
+	int i=0;
+
+	// Test if client is connected
+	if (!isConnected()) {
+		throw LdapNotConnectedException();
+	}
+
+	// Convert vector of C++ strings to array of C-style strings
+	for(i = 0; i < attrs.size(); i++ ) {
+		searchAttrs[i] = const_cast<char*>(attrs.at(i).c_str());
+	}
+
+	// OpenLDAP requires that the last entry is NULL (my guess is to avoid needing an additional "length variable")
+	searchAttrs[attrs.size()] = NULL;
+
+	// Send query (note that it is blocking!)
+	if (ldap_search_s(ld, baseDn.c_str(), scope, query.c_str(), searchAttrs, 0, &msg) != LDAP_SUCCESS)
+	{
+		// Return empty list
+		throw LdapException("LdapException: Could not execute query");
+	}
+
+
+	// Push each returned object (entry) onto the result vector
+	for( entry = ldap_first_entry(ld, msg);entry != NULL; entry = ldap_next_entry(ld,entry))
+	{
+		// Parse the returned entry directly (don't wait until the user actually "needs" it)
+		entries.push_back(MRef<LdapEntry*>(new LdapEntry(ld, entry)));
+
+	}
+
+	// Clear up some memory
+	ldap_msgfree(msg);
+
+	return std::vector<MRef<LdapEntry*> >(entries);
+}
+
+std::string LdapConnection::getBaseDn() throw (LdapNotConnectedException, LdapUnsupportedException) {
+
+	if (!isConnected()) {
+		throw LdapNotConnectedException();
+	}
+
+	std::vector<MRef<LdapEntry*> > entries;
+	std::vector<std::string> attrs;
+
+	attrs.push_back("namingContexts");
+	entries = find("", "(objectclass=*)", attrs, LDAP_SCOPE_BASE);
+
+	if (0 == entries.size()) {
+		throw LdapUnsupportedException("Retrieving base DN");
+	} else {
+		try {
+			return entries.at(0)->getAttrValueString("namingContexts");
+		} catch (LdapAttributeNotFoundException & e) {
+			throw LdapUnsupportedException("Retrieving base DN");
+		}
+	}
+}
+/*
+LDAP* LdapConnection::getLdapObject() {
+	return ld;
+}
+*/

Added: trunk/libmnetutil/source/LdapEntry.cxx
===================================================================
--- trunk/libmnetutil/source/LdapEntry.cxx	                        (rev 0)
+++ trunk/libmnetutil/source/LdapEntry.cxx	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,94 @@
+#include <libmnetutil/LdapEntry.h>
+#include <libmutil/stringutils.h>
+
+LdapEntry::LdapEntry(LDAP* ld, LDAPMessage* entry) {
+	BerElement* ber;
+	struct berval** binaries;
+	char* attr;
+	char** strings;
+	int i=0;
+
+	valuesBinary.clear();
+	valuesStrings.clear();
+
+	for( attr = ldap_first_attribute(ld, entry, &ber); attr != NULL; attr = ldap_next_attribute(ld, entry, ber)) {
+
+		std::string attrName(attr);
+
+		// Separate binary attributes from the rest simply to testing what the returned attribute is called. Simple and effective.
+		if (stringEndsWith(attr, ";binary")) {
+			// Process binary attributes
+			if ((binaries = ldap_get_values_len(ld, entry, attr)) != NULL) {
+				for (i=0; binaries[i] != NULL; i++) {
+					valuesBinary[attrName].push_back(MRef<LdapEntryBinaryValue*>(new LdapEntryBinaryValue(binaries[i]->bv_val, binaries[i]->bv_len)));
+				}
+				ldap_value_free_len(binaries);
+			}
+		} else {
+			// Process string attributes
+			if ((strings = ldap_get_values(ld, entry, attr)) != NULL) {
+				for (i = 0; strings[i] != NULL; i++) {
+					valuesStrings[attrName].push_back(std::string(strings[i]));
+				}
+				ldap_value_free(strings);
+			}
+		}
+		ldap_memfree(attr);
+	}
+	if (ber != NULL) {
+		ber_free(ber,0);
+	}
+}
+
+bool LdapEntry::hasAttribute(std::string attr) {
+	std::map<std::string, std::vector<MRef<LdapEntryBinaryValue*> > >::iterator binaryIter = valuesBinary.find(attr);
+	std::map<std::string, std::vector<std::string> >::iterator stringIter = valuesStrings.find(attr);
+
+	if( binaryIter != valuesBinary.end() || stringIter != valuesStrings.end() ) {
+		return true;
+	}
+
+	return false;
+}
+
+std::string LdapEntry::getAttrValueString(std::string attr) throw (LdapAttributeNotFoundException) {
+	std::map<std::string, std::vector<std::string> >::iterator stringIter = valuesStrings.find(attr);
+
+	if (stringIter != valuesStrings.end()) {
+		return valuesStrings[attr].at(0);
+	}
+
+	throw LdapAttributeNotFoundException(attr);
+}
+std::vector<std::string> LdapEntry::getAttrValuesStrings(std::string attr) throw (LdapAttributeNotFoundException) {
+	std::map<std::string, std::vector<std::string> >::iterator i = valuesStrings.find(attr);
+
+	if (i != valuesStrings.end()) {
+		return valuesStrings[attr];
+	}
+
+	throw LdapAttributeNotFoundException(attr);
+}
+std::vector< MRef<LdapEntryBinaryValue*> > LdapEntry::getAttrValuesBinary(std::string attr) throw (LdapAttributeNotFoundException) {
+	std::map<std::string, std::vector<MRef<LdapEntryBinaryValue*> > >::iterator i = valuesBinary.find(attr);
+
+	if (i != valuesBinary.end()) {
+		return valuesBinary[attr];
+	}
+
+	throw LdapAttributeNotFoundException(attr);
+
+}
+std::vector<std::string> LdapEntry::getAttrNames() {
+	std::vector<std::string> res;
+	std::map<std::string, std::vector<std::string> >::iterator i;
+	std::map<std::string, std::vector<MRef<LdapEntryBinaryValue*> > >::iterator j;
+
+	for (i = valuesStrings.begin(); i != valuesStrings.end(); i++)
+		res.push_back(i->first);
+
+	for (j = valuesBinary.begin(); j != valuesBinary.end(); j++)
+		res.push_back(j->first);
+
+	return res;
+}

Added: trunk/libmnetutil/source/LdapException.cxx
===================================================================
--- trunk/libmnetutil/source/LdapException.cxx	                        (rev 0)
+++ trunk/libmnetutil/source/LdapException.cxx	2007-06-12 08:48:39 UTC (rev 3303)
@@ -0,0 +1,29 @@
+#include <libmnetutil/LdapException.h>
+
+/**
+ * @author	Mikael Svensson
+ * @author	Erik Eliasson <eliasson at it.kth.se>
+ * @author	Johan Bilien <jobi at via.ecp.fr>
+ */
+
+LdapException::LdapException() {
+	msg = "LdapException";
+};
+
+LdapException::LdapException(std::string msg) {
+	this->msg = "LdapException: " + msg;
+};
+
+const char* LdapException::what()const throw(){
+	return msg.c_str();
+}
+
+LdapAttributeNotFoundException::LdapAttributeNotFoundException(std::string message) {
+	msg = "LdapAttributeNotFoundException: Could not find attribute " + message;
+}
+LdapNotConnectedException::LdapNotConnectedException() {
+	msg = "LdapNotConnectedException: Not connected to server";
+}
+LdapUnsupportedException::LdapUnsupportedException(std::string feature) {
+	msg = "LdapUnsupportedException: Feature " + feature + " not supported";
+}



More information about the Minisip-devel mailing list