.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "DBD::LDAP 3pm" .TH DBD::LDAP 3pm "2011-10-07" "perl v5.12.4" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" .Vb 3 \& DBD::LDAP \- Perl extension for DBI, providing an SQL/Perl DBI interface \& to Ldap databases. LDAP stands for the "Lightweight Directory Access \& Protocol". For more information, see: http://www.ogre.com/ldap/docs.html .Ve .SH "AUTHOR" .IX Header "AUTHOR" .Vb 1 \& This module is Copyright (C) 2000\-2009 by \& \& Jim Turner \& \& Email: turnerjw784 .att. yahoo.com \& \& All rights reserved Without Prejudice. \& \& You may distribute this module under the same terms as Perl itself. .Ve .SH "PREREQUISITES" .IX Header "PREREQUISITES" .Vb 4 \& Convert::ANS1 (required by Net::LDAP) \& Net::LDAP \& DBI \& \- an LDAP database to connect to. .Ve .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& use DBI; \& $dbh = DBI\->connect("DBI:LDAP:ldapdb",\*(Aquser\*(Aq,\*(Aqpassword\*(Aq) #USER LOGIN. \& or die "Cannot connect as user: " . $DBI::errstr; \& \& $dbh = DBI\->connect("DBI:LDAP:ldapdb") #ANONYMOUS LOGIN (Read\-only). \& or die "Cannot connect as guest (readonly): " . $DBI::errstr; \& \& $sth = $dbh\->prepare("select * from people where (cn like \*(AqSmith%\*(Aq)") \& or die "Cannot prepare: " . $dbh\->errstr(); \& $sth\->execute() or die "Cannot execute: " . $sth\->errstr(); \& while ((@results) = $sth\->fetchrow_array) \& { \& print "\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\en"; \& ++$cnt; \& while (@results) \& { \& print "\-\-\-\-\-\->".join(\*(Aq|\*(Aq,split(/\e0/, shift(@results)))."\en"; \& } \& } \& $sth\->finish(); \& $dbh\->disconnect(); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\s-1DBD::LDAP\s0 is a \s-1DBI\s0 extension module adding an \s-1SQL\s0 database interface to standard \s-1LDAP\s0 databases to Perl's database-independent database interface. You will need access to an existing \s-1LDAP\s0 database or set up your own using an \s-1LDAP\s0 server, ie. \*(L"OpenLDAP\*(R", see (http://www.openldap.org). .PP The main advantage of \s-1DBD::LDAP\s0 is the ability to query \s-1LDAP\s0 databases via standard \s-1SQL\s0 queries in leu of cryptic \s-1LDAP\s0 \*(L"filters\*(R". \s-1LDAP\s0 is optimized for quick lookup of existing data, but \s-1DBD::LDAP\s0 does support entry inserts, updates, and deletes with commit/rollback via the standard \s-1SQL\s0 commands! .PP \&\s-1LDAP\s0 databases are \*(L"heirarchical\*(R" in structure, whereas other DBD-supported databases are \*(L"relational\*(R" and there is no LDAP-equivalent to \s-1SQL\s0 \*(L"tables\*(R", so \&\s-1DBD::LDAP\s0 maps a \*(L"table\*(R" interface over the \s-1LDAP\s0 \*(L"tree\*(R" via a configuration file you must set up. Each \*(L"table\*(R" is mapped to a common \*(L"base \s-1DN\s0\*(R". For example, consider a typical \s-1LDAP\s0 database of employees within different departments within a company. You might have a \*(L"company\*(R" names \*(L"Acme\*(R" and the root \*(L"dn\*(R" of \*(L"dc=Acme, dc=com\*(R" (Acme.com). Below the company level, are divisions, ie. \*(L"Widgets\*(R", and \*(L"Blivets\*(R". Each division would have an entry with a \*(L"dn\*(R" of \*(L"ou=Widgets, dc=Acme, dc=com\*(R". Employees within each division could have a \*(L"dn\*(R" of \*(L"cn=John Doe, ou=Widgets, dc=Acme, dc=com\*(R". With \s-1DBD::LDAP\s0, we could create tables to access these different levels, ie. \*(L"top\*(R", which would have a \*(L"\s-1DN\s0\*(R" of \*(L"dc=Acme, dc=com\*(R", \*(L"WidgetDivision\*(R" for \&\*(L"dc=Acme, dc=com\*(R". Tables can also be constained by additional attribute specifications (filters), ie constraining by \*(L"objectclass\*(R", ie. \&\*(L"(objectclass=person)\*(R". Then, doing a \*(L"select * from WidgetDivision\*(R" would display all \*(L"person\*(R"s with a \*(L"dn\*(R" containing "\*(L"ou=Widgets, dc=Acme, dc=com\*(R". .SH "INSTALLATION" .IX Header "INSTALLATION" .Vb 2 \& Installing this module (and the prerequisites from above) is quite \& simple. You just fetch the archive, extract it with \& \& gzip \-cd DBD\-LDAP\-####.tar.gz | tar xf \- \& \& \-or\- \& \& tar \-xzvf DBD\-LDAP\-####.tar.gz \& \& (this is for Unix users, Windows users would prefer WinZip or something \& similar) and then enter the following: \& \& cd DBD\-LDAP\-#.### \& perl Makefile.PL \& make \& make test \& \& If any tests fail, let me know. Otherwise go on with \& \& make install \& \& Note that you almost definitely need root or administrator permissions. \& If you don\*(Aqt have them, read the ExtUtils::MakeMaker man page for \& details on installing in your own directories. .Ve .SH "GETTING STARTED:" .IX Header "GETTING STARTED:" .Vb 2 \& 1) Create a "database", ie. "foo" by creating a text file "foo.ldb". The \& general format of this file is: .Ve .PP \&\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- hostname[;port][:[root\-dn][:[loginrule]]] tablename1:[basedn]:[basefilter]:dnattrs:[visableattrs]:[insertattrs]: \e\e [ldap_options] tablename2:[basedn]:[basefilter]:dnattrs:[visableattrs]:[insertattrs]: \e\e [ldap_options] \&... \&\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- .PP .Vb 6 \& represents the ldap server host name. \& represents the server\*(Aqs port, default is 389. \& if specified, is appended to the end of each tablename\*(Aqs \& base\-dn. \& if specified, converts single word "usernames" to the \& appropriate DN, ie: \& \& "cn=*," would convert user name "foo" to "cn=foo, " and \& append the "" onto that. The asterisk is converted to \& the user\-name specified in the "connect" method. If not specified, \& the username specified in the "connect" method must be a full DN. \& If the "" is not specified, then the "" would \& need to be a full DN. \& \& tablename \- represents the name to be used in SQL statements for a given \& set of entries which make up a virtual "table". \& basedn \- if specified, is appended to the "" to make up the \& common base DN for all entries in this table. If "" is \& not specified, then a full DN must be specified; otherwise, the \& default is the root\-dn. \& basefilter \- if specified, specifies a filter to be used if no "where"\- \& clause is specified in SQL queries. If a "where"\-clause is \& specified, the resulting filter is "and"\-ed with this one. The \& default is "(objectclass=*)". \& dnattrs \- specifies which attributes that values for which are to be \& appended to the left of the basedn to create DNs for new entries \& being inserted into the table. \& visableattrs \- if specified, one or more attributes separated by commas \& which will be sought when the SQL statement does not specify \& attributes, ie. "select * from tablename". If not specified, the \& attributes of the first matching entry are returned and used for \& all entries matching a given query. \& insertattrs \- if specified, one or more attribute/value combinations to be \& added to any new entry inserted into the table, usually needed for \& objectclass values. The attributes and values usually correspond \& to those specivied in the "". The general format is: \& attr1=value1[|value2...],attr2=value1...,... \& These attributes and values will be joined with any user\-specified \& values for these attributes. \& ldap_options \- if specified, can be any one or more of the following: \& \& ldap_sizelimit \- Limit the number of entries fetch by a query to this \& number (0 = no limit) \- default: 0. \& ldap_timelimit \- Limit the search to this number of seconds per query. \& (0 = no limit) \- default: 0. \& ldap_scope \- specify the "scope" of the search. Values are: "base", \& "one", and "sub", see Net::LDAP docs. Default is "one", \& meaning the set of records one level below the basedn. "base" \& means search only the basedn, and "sub" means the union \& of entries at the "base" level and "one" level below. \& ldap_inseparator \- specify the separator character/string to be used \& in queries to separate multiple values being specified for \& a given attribute. Default is "|". \& ldap_outseparator \- specify the separator character/string to be used \& in queryies to separate multiple values displayed as a result \& of a query. Default is "|". \& ldap_firstonly \- only display the 1st value fetched for each attribute \& per entry. This makes "ldap_outseparator" unnecessary. \& \& 2) write your script to use DBI, ie: \& \& #!/usr/bin/perl \& use DBI; \& \& $dbh = DBI\->connect(\*(AqDBD:LDAP:mydb\*(Aq,\*(Aqme\*(Aq,\*(Aqmypassword\*(Aq) || \& die "Could not connect (".$DBI\->err.\*(Aq:\*(Aq.$DBI\->errstr.")!"; \& ... \& #CREATE A TABLE, INSERT SOME RECORDS, HAVE SOME FUN! \& \& 3) get your application working. .Ve .SH "INSERTING, FETCHING AND MODIFYING DATA" .IX Header "INSERTING, FETCHING AND MODIFYING DATA" .Vb 2 \& 1st, we\*(Aqll create a database called "ldapdb" with the tables previously \& mentioned in the example in the DESCRIPTION section: .Ve .PP \&\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- file \*(L"ldapdb.ldb\*(R" \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- ldapserver:dc=Acme, dc=com:cn=*,<\s-1ROOT\s0> top:::dc WidgetDivision:ou=Widgets, :&(objectclass=top)(objectclass=person): \e\e cn:cn,sn,ou,title,telephonenumber,description,objectclass,dn: \e\e objectclass=top|person|organizationalPerson:ldap_outseparator => \*(L":\*(R" \&\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- .PP .Vb 2 \& The following examples insert some data in a table and fetch it back: \& First all data in the string: \& \& $dbh\->do(<do("INSERT INTO WidgetDivision (cn,sn,title,telephonenumber) VALUES (?, ?, ?, ?)", \& \*(AqJohn Doe\*(Aq,\*(AqDoeJ\*(Aq,\*(AqManager\*(Aq,\*(Aq123\-1111\*(Aq); \&END_SQL \& $dbh\->commit(); \& \& NOTE: Unlike most other DBD modules which support transactions, changes \& made do NOT show up until the "commit" function is called, unless \& "AutoCommit" is set. This is due to the fact that fetches are done \& from the LDAP server and changes do not take effect there until the \& Net::LDAP "update" function is called, which is called by "commit". \& \& NOTE: The "dn" field is generated automatically from the base "dn" and the \& dn component fields specified by "dnattrs", If you try to insert a \& value directly into it, it will be ignored. Also, if not specified, \& any attribute/value combinations specified in the "insertattrs" \& option will be added automatically. \& \& To retrieve data, you can use the following: \& \& my($query) = "SELECT * FROM WidgetDivision WHERE cn like \*(AqJohn%\*(Aq ORDER BY cn"; \& my($sth) = $dbh\->prepare($query); \& $sth\->execute(); \& while (my $entry = $sth\->fetchrow_hashref) { \& print("Found result record: cn = ", $entry\->{\*(Aqcn\*(Aq}, \& ", phone = ", $row\->{\*(Aqtelephonenumber\*(Aq}); \& } \& $sth\->finish(); \& \& The SQL "SELECT" statement above (combined with the table information \& in the "ldapdb.ldb" database file would generate and execute the following \& equivalent LDAP Search: \& \& base => \*(Aqou=Widgets, dc=Acme, dc=com\*(Aq, \& filter => \*(Aq(&(&(objectclass=top)(objectclass=person))(cn=John*))\*(Aq, \& scope => \*(Aqone\*(Aq, \& attrs => \*(Aqcn,sn,ou,title,telephonenumber,description,objectclass,dn\*(Aq \& \& See the DBI(3) manpage for details on these methods. See the \& \& Data rows are modified with the UPDATE statement: \& \& $dbh\->do("UPDATE WidgetDivision SET description = \*(AqOutstanding Employee\*(Aq WHERE cn = \*(AqJohn Doe\*(Aq"); \& \& NOTE: You can NOT change the "dn" field directly \- direct changes will be \& ignored. You change the "rdn" component of the "dn" field by changing \& the value of the other field(s) which are appended to the base "dn". \& Also, if not specified, any attribute/value combinations specified in \& the "insertattrs" option will be added automatically. \& \& Likewise you use the DELETE statement for removing entries: \& \& $dbh\->do("DELETE FROM WidgetDivision WHERE description = \*(AqOutstanding Employee\*(Aq"); .Ve .SH "METADATA" .IX Header "METADATA" .Vb 2 \& The following attributes are handled by DBI itself and not by DBD::LDAP, \& thus they should all work as expected. \& \& PrintError \& RaiseError \& Warn \& \& The following DBI attributes are handled by DBD::LDAP: \& \& AutoCommit \& Works \& \& NUM_OF_FIELDS \& Valid after \*(Aq$sth\->execute\*(Aq \& \& NUM_OF_PARAMS \& Valid after \*(Aq$sth\->prepare\*(Aq \& \& NAME \& Valid after \*(Aq$sth\->execute\*(Aq; undef for Non\-Select statements. \& \& NULLABLE \& Not really working. Always returns an array ref of one\*(Aqs, as \& DBD::LDAP always allows NULL (handled as an empty string). \& Valid after \`$sth\->execute\*(Aq. \& \& LongReadLen \& Should work \& \& LongTruncOk \& Should work \& \& These attributes and methods are not supported: \& \& bind_param_inout \& CursorName \& \& In addition to the DBI attributes, you can use the following dbh \& attributes. These attributes are read\-only after "connect". \& \& ldap_dbuser \& Current database user. \& \& ldap_HOME \& Environment variable specifying a path to search for LDAP \& databases (*.sdb) files. .Ve .SH "DRIVER PRIVATE METHODS" .IX Header "DRIVER PRIVATE METHODS" .Vb 4 \& DBI\->data_sources() \& The \`data_sources\*(Aq method returns a list of "databases" (.ldb files) \& found in the current directory and, if specified, the path in \& the ldap_HOME environment variable. \& \& $dbh\->tables() \& This method returns a list of table names specified in the current \& database. \& Example: \& \& my($dbh) = DBI\->connect("DBI:LDAP:mydatabase",\*(Aqme\*(Aq,\*(Aqmypswd\*(Aq); \& my(@list) = $dbh\->func(\*(Aqtables\*(Aq); .Ve .SH "OTHER SUPPORTING UTILITIES" .IX Header "OTHER SUPPORTING UTILITIES" .SH "RESTRICTIONS" .IX Header "RESTRICTIONS" .Vb 2 \& DBD::LDAP currently treats all data as strings and all fields as \& VARCHAR(255). \& \& Currently, you must define tables manually in the ".ldb" file \& using your favorite text editor. I hope to add support for the SQL \& "Create Table", "Alter Table", and "Drop Table" functions to handle this \& eventually. .Ve .SH "TODO" .IX Header "TODO" .Vb 3 \& "Create Table", "Alter Table", and "Drop Table" SQL functions for \& creating, altering, and deleting the tables defined in the \& ".ldb" file. \& \& Some kind of datatype support, ie. numeric (for sorting), CHAR for padding, \& Long/Blob \- for >255 chars per field, etc. .Ve .SH "KNOWN BUGS" .IX Header "KNOWN BUGS" .Vb 1 \& none \- (yet). .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" .Vb 1 \& Net::LDAP(3), DBI(3), perl(1) .Ve