001: /*
002: * LDAPTemplate.java
003: *
004: * Brazil project web application Framework,
005: * export version: 1.1
006: * Copyright (c) 2001 Sun Microsystems, Inc.
007: *
008: * Sun Public License Notice
009: *
010: * The contents of this file are subject to the Sun Public License Version
011: * 1.0 (the "License"). You may not use this file except in compliance with
012: * the License. A copy of the License is included as the file "license.terms",
013: * and also available at http://www.sun.com/
014: *
015: * The Original Code is from:
016: * Brazil project web application Framework release 1.1.
017: * The Initial Developer of the Original Code is: cstevens.
018: * Portions created by cstevens are Copyright (C) Sun Microsystems, Inc.
019: * All Rights Reserved.
020: *
021: * Contributor(s): cstevens, suhler.
022: *
023: * Version: 1.4
024: * Created by cstevens on 01/01/11
025: * Last modified by suhler on 01/01/14 14:54:40
026: */
027:
028: package sunlabs.brazil.ldap;
029:
030: import java.util.Enumeration;
031: import java.util.Properties;
032: import java.util.StringTokenizer;
033:
034: import sunlabs.brazil.template.Template;
035: import sunlabs.brazil.template.RewriteContext;
036: import sunlabs.brazil.util.Format;
037:
038: import netscape.ldap.LDAPAttribute;
039: import netscape.ldap.LDAPConnection;
040: import netscape.ldap.LDAPEntry;
041: import netscape.ldap.LDAPException;
042: import netscape.ldap.LDAPSearchConstraints;
043: import netscape.ldap.LDAPSearchResults;
044: import netscape.ldap.LDAPv2;
045:
046: /**
047: * The <code>LDAPTemplate</code> is invoked to process LDAP tags embedded in
048: * a document. This version requires the "ldap40.jar" file from the
049: * Netscape Navigator distribution.
050: * <p>
051: * The LDAPTemplate uses the following special tag: <ul>
052: * <li> <code><ldap></code>
053: * </ul>
054: * <p>
055: * When an LDAP tag is seen, the LDAP database is searched and the results
056: * are used to populate the request properties.
057: * <p>
058: * The following configuration parameters are used to perform the search.
059: * The parameters may appear either in the request properties (preceded by
060: * the prefix of this template as specified in the configuration file) or as
061: * named arguments in the LDAP tag.
062: * <dl class=props>
063: * <dt> <code>prefix</code>
064: * <dd> The string prefix for the property names that will be stored
065: * in the request properties to hold the results. If not specified,
066: * defaults to the prefix of this template as specified in the
067: * configuration file.<p>
068: *
069: * <dt> <code>dn</code>
070: * <dd> The Distinguished Name (DN) to lookup in the LDAP server. The format
071: * of a DN is described in RFC-1779. The "dn" and "search" options are
072: * mutually exclusive. When "dn" is specified, only zero or one result
073: * will be returned from the LDAP database. The result (if any) will be
074: * stored in the request properties as follows:
075: * <pre>
076: * <ldap dn="uid=6105,ou=people,o=WebAuth" prefix=<i>name</i>>
077: * <property <i>name</i>.dn>
078: * <property <i>name</i>.cn>
079: * <property <i>name</i>.sn>
080: * <property <i>name</i>.objectclass></pre>
081: * etc. The property <code><i>name</i>.dn</code> is the DN that was
082: * found. Other properties will be defined as shown, based on the
083: * attributes present in the LDAP record. <p>
084: *
085: * <dt> <code>search</code>
086: * <dd> The search filter to use when searching the LDAP server. The format
087: * of a search filter is described in RFC-1558. The "search" and "dn"
088: * options are mutually exclusive. When "search" is specified, zero or
089: * more results will be returned from the LDAP database. The results
090: * will be stored in the request properties as follows:
091: * <pre>
092: * <ldap search="(givenname=scott)" prefix=<i>name</i>>
093: * <property <i>name</i>.rows>
094: *
095: * <property <i>name</i>.0.dn>
096: * <property <i>name</i>.0.cn>
097: * <property <i>name</i>.0.mail>
098: *
099: * <property <i>name</i>.1.dn>
100: * <property <i>name</i>.1.cn>
101: * <property <i>name</i>.1.pager></pre>
102: * etc. The property <code><i>name</i>.rows</code> is set to the list
103: * of record indices found, and can be used by the BSL tag
104: * <code><foreach name=<i>x</i> property=<i>name</i>.rows></code> to
105: * iterate over all records. Other properties will be defined for
106: * each of the records found as shown, based on the attributes present
107: * in the each of the LDAP records. <p>
108: *
109: * <dt> <code>base</code>
110: * <dd> The Distinguished Name of the base record that forms the root of the
111: * search tree in the LDAP database. Used only with the "search" option.
112: * Defaults to "". This would be a good option to specify in the
113: * configuration file rather than in the LDAP tag. <p>
114: *
115: * <dt> <code>scope</code>
116: * <dd> The scope of the LDAP search, one of <ul>
117: * <li> "base" Search only in base record (specified by the "base" option).
118: * <li> "one" Search only records one level below the base record.
119: * <li> "sub" Search the entire subtree below the base record. </ul>
120: * Used only with the "search" option. Defaults to "sub". This would
121: * be a good option to specify in the configuration file rather than in
122: * the LDAP tag. <p>
123: *
124: * <dt> <code>attributes</code>
125: * <dd> The space-delimited list of attribute names to return from the
126: * LDAP "dn" or "search" operation. If empty or unspecified, all
127: * attributes for the record are returned. Not all records in the
128: * LDAP database have the same attributes. Defaults to "". <p>
129: *
130: * <dt> <code>host</code>
131: * <dd> The hostname of the LDAP server, of the form <code>"host"</code>
132: * or <code>"host:port"</code> if the server is not running on the
133: * standard LDAP port. Defaults to "". This would be a good option to
134: * specify in the configuration file rather than in the LDAP tag. <p>
135: *
136: * <dt> <code>authenticate</code>
137: * <dd> The Distinguished Name used for authenticating to the LDAP server,
138: * if necessary. Defaults to "". This would be a good option to specify
139: * in the configuration file rather than in the LDAP tag. <p>
140: *
141: * <dt> <code>password</code>
142: * <dd> The password sent when the "authenticate" option is used. Defaults
143: * to "".
144: * </dl>
145: *
146: * @author Colin Stevens (colin.stevens@sun.com)
147: * @version 1.4, 01/01/14
148: */
149:
150: public class LDAPTemplate extends Template {
151: String[] split(String str) {
152: if (str == null) {
153: return null;
154: }
155: StringTokenizer st = new StringTokenizer(str);
156: int n = st.countTokens();
157: String[] strs = new String[n];
158: for (int i = 0; i < n; i++) {
159: strs[i] = st.nextToken();
160: }
161: return strs;
162: }
163:
164: private static String subst(RewriteContext hr, String name) {
165: return Format.subst(hr.request.props, hr.get(name));
166: }
167:
168: String get(RewriteContext hr, String key) {
169: String result = hr.get(key);
170: if (result == null) {
171: Properties props = hr.request.props;
172: result = props.getProperty(hr.prefix + key);
173: if (result == null) {
174: result = props.getProperty(key);
175: }
176: }
177: result = Format.subst(hr.request.props, result);
178: return result;
179: }
180:
181: /**
182: * Process <ldap> tags.
183: */
184:
185: public void tag_ldap(RewriteContext hr) {
186: hr.killToken();
187:
188: String host = get(hr, "host");
189: String auth = get(hr, "authenticate");
190: String password = get(hr, "password");
191: String name = get(hr, "prefix");
192: name = (name == null) ? hr.prefix : name;
193: if (name.endsWith(".") == false) {
194: name += ".";
195: }
196:
197: String[] attrs = split(get(hr, "attributes"));
198:
199: LDAPConnection ld = new LDAPConnection();
200: try {
201: ld.connect(host, LDAPv2.DEFAULT_PORT, auth, password);
202:
203: String dn = subst(hr, "dn");
204: if (dn != null) {
205: LDAPEntry entry = ld.read(dn, attrs);
206: if (entry != null) {
207: shove(hr.request.props, name, entry);
208: }
209: return;
210: }
211:
212: String base = get(hr, "base");
213: String str = get(hr, "scope");
214: int scope = LDAPv2.SCOPE_SUB;
215: if ("base".equals(str)) {
216: scope = LDAPv2.SCOPE_BASE;
217: } else if ("one".equals(str)) {
218: scope = LDAPv2.SCOPE_ONE;
219: }
220:
221: String search = subst(hr, "search");
222:
223: LDAPSearchConstraints sc = ld.getSearchConstraints();
224: /* sc.setMaxResults( 0 );*/
225: /*
226: try {
227: ld.setOption(LDAPv2.SIZELIMIT, Integer.decode(get(hr, "limit")));
228: } catch (Exception e) {}*/
229:
230: StringBuffer sb = new StringBuffer();
231:
232: LDAPSearchResults results = ld.search(base, scope, search,
233: attrs, false, sc);
234: for (int i = 0; results.hasMoreElements(); i++) {
235: sb.append(i).append(' ');
236: shove(hr.request.props, name + i + ".", results.next());
237: }
238:
239: hr.request.props.put(name + "rows", sb.toString().trim());
240: ld.disconnect();
241: } catch (LDAPException e) {
242: hr.request.props.put(name + "error", e.errorCodeToString());
243: e.printStackTrace();
244: }
245: }
246:
247: void shove(Properties props, String prefix, LDAPEntry entry) {
248: props.put(prefix + "dn", entry.getDN());
249: Enumeration attrs = entry.getAttributeSet().getAttributes();
250: while (attrs.hasMoreElements()) {
251: LDAPAttribute attr = (LDAPAttribute) attrs.nextElement();
252: String name = attr.getName();
253: StringBuffer sb = new StringBuffer();
254: Enumeration e = attr.getStringValues();
255: while (e.hasMoreElements()) {
256: sb.append(e.nextElement()).append('|');
257: }
258: if (sb.length() > 0) {
259: sb.setLength(sb.length() - 1);
260: }
261: props.put(prefix + name, sb.toString());
262: }
263: }
264: }
|