001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.tag; 020 021import java.io.IOException; 022 023import javax.naming.NamingException; 024import javax.naming.directory.DirContext; 025import javax.naming.directory.SearchControls; 026 027import lucee.commons.lang.ClassException; 028import lucee.runtime.exp.ApplicationException; 029import lucee.runtime.exp.PageException; 030import lucee.runtime.ext.tag.TagImpl; 031import lucee.runtime.net.ldap.LDAPClient; 032import lucee.runtime.op.Caster; 033import lucee.runtime.tag.util.DeprecatedUtil; 034import lucee.runtime.type.Query; 035import lucee.runtime.type.util.ArrayUtil; 036import lucee.runtime.type.util.ListUtil; 037 038// TODO tag ldap 039// attr rebind 040 041/** 042* Provides an interface to LDAP Lightweight Directory Access Protocol 043* directory servers like the Netscape Directory Server. 044*/ 045public final class Ldap extends TagImpl { 046 047 private String delimiter=";"; 048 private String server; 049 private int port=389; 050 private short secureLevel=LDAPClient.SECURE_NONE; 051 private String[] returnAsBinary=new String[0]; 052 private String attributes=null; 053 private String username; 054 private String password; 055 private String action="query"; 056 private String[] sort=new String[0]; 057 private String dn; 058 private int referral; 059 private int scope=SearchControls.SUBTREE_SCOPE; 060 061 private int sortType=LDAPClient.SORT_TYPE_CASE; 062 private int sortDirection=LDAPClient.SORT_DIRECTION_ASC; 063 064 private int startrow=1; 065 private int timeout=60000; 066 private int maxrows; 067 private String name; 068 private String start; 069 private String separator=","; 070 private String filter="objectclass = *"; 071 private int modifyType=DirContext.REPLACE_ATTRIBUTE; 072 private boolean rebind; 073 074 075 @Override 076 public void release() { 077 action="query"; 078 delimiter=";"; 079 port=389; 080 secureLevel=LDAPClient.SECURE_NONE; 081 returnAsBinary=new String[0]; 082 username=null; 083 password=null; 084 referral=0; 085 attributes=null; 086 sort=new String[0]; 087 dn=null; 088 name=null; 089 scope=SearchControls.SUBTREE_SCOPE; 090 091 startrow=1; 092 timeout=60000; 093 maxrows=-1; 094 095 sortType=LDAPClient.SORT_TYPE_CASE; 096 sortDirection=LDAPClient.SORT_DIRECTION_ASC; 097 098 start=null; 099 separator=","; 100 filter="objectclass = *"; 101 modifyType=DirContext.REPLACE_ATTRIBUTE; 102 rebind=false; 103 104 super.release(); 105 106 } 107 108 109 /** 110 * @param filterfile The filterfile to set. 111 * @throws ApplicationException 112 */ 113 public void setFilterfile(String filterfile) { 114 DeprecatedUtil.tagAttribute(pageContext,"LDAP", "filterfile"); 115 } 116 117 /** Specifies the character that cfldap uses to separate multiple 118 * attribute name/value pairs when more than one attribute is specified 119 * in the attribute attribute or the attribute that you want to use has 120 * the default delimiter character, which is the semicolon (;), 121 * such as mgrpmsgrejecttext;lang-en. The delimiter character is used by the query, 122 * add, and modify action attributes, and is used by cfldap to output multi-value attributes 123 * @param delimiter delimiter to set 124 */ 125 public void setDelimiter(String delimiter) { 126 this.delimiter = delimiter; 127 } 128 129 /** 130 * Used in conjunction with action = "Query". Specifies the first row of the LDAP query to insert 131 * into the query. The default is 1. 132 * @param startrow The startrow to set. 133 */ 134 public void setStartrow(double startrow) { 135 this.startrow = (int)startrow; 136 } 137 138 /** 139 * Specifies the maximum number of entries for LDAP queries. 140 * @param maxrows The maxrows to set. 141 */ 142 public void setMaxrows(double maxrows) { 143 this.maxrows = (int)maxrows; 144 } 145 146 /** 147 * Specifies the maximum amount of time, in seconds, to wait for LDAP processing. Defaults to 148 * 60 seconds. 149 * @param timeout The timeout to set. 150 */ 151 public void setTimeout(double timeout) { 152 this.timeout = (int)timeout; 153 } 154 155 /** 156 * @param password The password to set. 157 */ 158 public void setPassword(String password) { 159 this.password = password; 160 } 161 162 163 /** 164 * Port defaults to the standard LDAP port, 389. 165 * @param port The port to set. 166 */ 167 public void setPort(double port) { 168 this.port = (int) port; 169 } 170 171 172 /** 173 * Identifies the type of security to employ, CFSSL_BASIC or CFSSL_CLIENT_AUTH, 174 * and additional information that is required by the specified security type. 175 * @param referral The referral to set. 176 */ 177 public void setReferral(double referral) { 178 this.referral = (int) referral; 179 } 180 181 182 /** 183 * Host name "biff.upperlip.com" or IP address "192.1.2.225" of the LDAP server. 184 * @param server The server to set. 185 */ 186 public void setServer(String server) { 187 this.server = server; 188 } 189 190 191 /** 192 * If no user name is specified, the LDAP connection is anonymous. 193 * @param username The username to set. 194 */ 195 public void setUsername(String username) { 196 this.username = username; 197 } 198 199 200 /** 201 * @param secure The secureLevel to set. 202 * @throws ApplicationException 203 */ 204 public void setSecure(String secure) throws ApplicationException { 205 secure=secure.trim().toUpperCase(); 206 if(secure.equals("CFSSL_BASIC")) secureLevel=LDAPClient.SECURE_CFSSL_BASIC; 207 else if(secure.equals("CFSSL_CLIENT_AUTH")) secureLevel=LDAPClient.SECURE_CFSSL_CLIENT_AUTH; 208 else throw new ApplicationException("invalid value for attribute secure ["+secure+"], valid values are [CFSSL_BASIC, CFSSL_CLIENT_AUTH]"); 209 } 210 /** 211 * Specifies the scope of the search from the entry specified in the Start attribute 212 * for action = "Query". 213 * @param strScope The scope to set. 214 * @throws ApplicationException 215 */ 216 public void setScope(String strScope) throws ApplicationException { 217 strScope=strScope.trim().toLowerCase(); 218 if(strScope.equals("onelevel")) scope=SearchControls.ONELEVEL_SCOPE; 219 else if(strScope.equals("base")) scope=SearchControls.OBJECT_SCOPE; 220 else if(strScope.equals("subtree")) scope=SearchControls.SUBTREE_SCOPE; 221 else throw new ApplicationException("invalid value for attribute scope ["+strScope+"], valid values are [oneLevel,base,subtree]"); 222 } 223 224 /** 225 * Indicates whether to add, delete, or replace an attribute 226 * in a multi-value list of attributes. 227 * @param modifyType The modifyType to set. 228 * @throws ApplicationException 229 */ 230 public void setModifytype(String modifyType) throws ApplicationException { 231 modifyType=modifyType.trim().toLowerCase(); 232 if(modifyType.equals("add")) this.modifyType=DirContext.ADD_ATTRIBUTE; 233 else if(modifyType.equals("delete")) this.modifyType=DirContext.REMOVE_ATTRIBUTE; 234 else if(modifyType.equals("replace")) this.modifyType=DirContext.REPLACE_ATTRIBUTE; 235 else throw new ApplicationException("invalid value for attribute modifyType ["+modifyType+"], valid values are [add,replace,delete]"); 236 } 237 238 /** 239 * @param returnAsBinary The returnAsBinary to set. 240 * @throws PageException 241 */ 242 public void setReturnasbinary(String returnAsBinary) throws PageException { 243 this.returnAsBinary = ArrayUtil.trim(ListUtil.toStringArray(ListUtil.listToArrayRemoveEmpty(returnAsBinary,','))); 244 } 245 246 /** 247 * Indicates the attribute or attributes by which to sort query results. 248 * Use a comma [,] to separate attributes. 249 * @param sort The sort to set. 250 * @throws PageException 251 */ 252 public void setSort(String sort) throws PageException { 253 this.sort = ArrayUtil.trim(ListUtil.toStringArray(ListUtil.listToArrayRemoveEmpty(sort,','))); 254 } 255 256 /** 257 * Specifies how to sort query results. 258 * @param sortControl sortControl to set 259 * @throws PageException 260 */ 261 public void setSortcontrol(String sortControl) throws PageException { 262 String[] sortControlArr = ArrayUtil.trim(ListUtil.toStringArray(ListUtil.listToArrayRemoveEmpty(sortControl,','))); 263 for(int i=0;i<sortControlArr.length;i++) { 264 String scs=sortControlArr[i].trim().toLowerCase(); 265 266 if(scs.equals("asc"))sortDirection=LDAPClient.SORT_DIRECTION_ASC; 267 else if(scs.equals("desc")) sortDirection=LDAPClient.SORT_DIRECTION_DESC; 268 else if(scs.equals("case"))sortType=LDAPClient.SORT_TYPE_CASE; 269 else if(scs.equals("nocase"))sortType=LDAPClient.SORT_TYPE_NOCASE; 270 else throw new ApplicationException("invalid value for attribute sortControl ["+sortControl+"], " + 271 "valid values are [asc,desc,case,nocase]"); 272 } 273 } 274 275 /** 276 * @param strAttributes 277 */ 278 public void setAttributes(String strAttributes) { 279 attributes = strAttributes; 280 } 281 282 /** 283 * Specifies the LDAP action. 284 * @param action The action to set. 285 */ 286 public void setAction(String action) { 287 this.action=action.trim().toLowerCase(); 288 } 289 290 291 /** 292 * Specifies the distinguished name for update actions. 293 * @param dn The dn to set. 294 */ 295 public void setDn(String dn) { 296 this.dn = dn; 297 } 298 299 300 /** 301 * The name you assign to the LDAP query. 302 * @param name The name to set. 303 */ 304 public void setName(String name) { 305 this.name = name; 306 } 307 308 309 /** 310 * Specifies the character that cfldap uses to separate attribute values in multi-value attributes. 311 * This character is used by the query, add, and modify action attributes, and 312 * by cfldap to output multi-value attributes. The default character is the comma (,). 313 * @param separator The separator to set. 314 */ 315 public void setSeparator(String separator) { 316 this.separator = separator; 317 } 318 319 320 /** 321 * Specifies the distinguished name of the entry to be used to start the search. 322 * @param start The start to set. 323 */ 324 public void setStart(String start) { 325 this.start = start; 326 } 327 328 329 /** 330 * @param filter The filter to set. 331 */ 332 public void setFilter(String filter) { 333 this.filter = filter; 334 } 335 336 /** 337 * If you set rebind to Yes, cfldap attempts to rebind the referral callback and reissue the query 338 * by the referred address using the original credentials. The default is No, which means referred 339 * connections are anonymous. 340 * @param rebind The rebind to set. 341 */ 342 public void setRebind(boolean rebind) { 343 this.rebind = rebind; 344 } 345 346 347 348 349 @Override 350 public int doStartTag() throws PageException { 351 try { 352 return _doStartTag(); 353 } 354 catch (Exception e) { 355 throw Caster.toPageException(e); 356 } 357 } 358 private int _doStartTag() throws NamingException, PageException, IOException, ClassException { 359 360 //LDAPClient client=new LDAPClient(server,port,secureLevel,returnAsBinary,username,password,referral); 361 LDAPClient client=new LDAPClient(server,port,returnAsBinary); 362 if(secureLevel!=LDAPClient.SECURE_NONE)client.setSecureLevel(secureLevel); 363 if(username!=null)client.setCredential(username,password); 364 if(referral>0) client.setReferral(referral); 365 366 if(action.equals("add")) { 367 required("LDAP",action,"attributes",attributes); 368 required("LDAP",action,"dn",dn); 369 client.add(dn,attributes,delimiter,separator); 370 } 371 else if(action.equals("delete")) { 372 required("LDAP",action,"dn",dn); 373 client.delete(dn); 374 } 375 else if(action.equals("modifydn")) { 376 required("LDAP",action,"attributes",attributes); 377 required("LDAP",action,"dn",dn); 378 client.modifydn(dn,attributes); 379 } 380 else if(action.equals("modify")) { 381 required("LDAP",action,"attributes",attributes); 382 required("LDAP",action,"dn",dn); 383 client.modify(dn,modifyType,attributes,delimiter,separator); 384 } 385 else if(action.equals("query")) { 386 required("LDAP",action,"start",start); 387 required("LDAP",action,"attributes",attributes); 388 required("LDAP",action,"name",name); 389 Query qry = client.query(attributes,scope,startrow,maxrows, 390 timeout,sort,sortType,sortDirection,start,separator,filter); 391 pageContext.setVariable(name,qry); 392 393 } 394 else throw new ApplicationException("invalid value for attribute action ["+action+"], valid values are [add,delete,modifydn,modify,query]"); 395 396 return SKIP_BODY; 397 } 398 399 400 401 402}