1<?php
2/**
3 * PHP Includes via Syntax
4 *
5 * Please create the directory "phpincludes" in your installation of
6 * DokuWiki. Now you can put there any HTML or PHP File you want to
7 * this directory.
8 *
9 * <phpinc=filename>
10 *
11 * The syntax includes the PHP file per include an puts the result into
12 * the wiki page.
13 *
14 * @license    GNU_GPL_v2
15 * @author     Darren Hemphill <contact [alt] rendezz [dlot] co [dlot] za>
16 * @adoptedby  Oliver Geisen <oliver [at-sign] rehkopf-geisen [dotsign] de>
17 */
18
19if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
20if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
21require_once(DOKU_PLUGIN.'syntax.php');
22
23
24class syntax_plugin_ldapsearch extends DokuWiki_Syntax_Plugin {
25
26	var $ldapsearch_conf;
27	function getInfo(){
28		return array(
29			'author' => 'Baseline IT',
30			'email'  => 'info@baseline-remove-this-it.co.za',
31			'date'   => '2017-03-01',
32			'name'   => 'LDAP Search',
33			'desc'   => 'Allows you to do an inline LDAP search using LDAP URL syntax or configured searches',
34			'url'    => 'https://www.dokuwiki.org/plugin:ldapsearch',
35		);
36	}
37
38
39	function getType(){ return 'substition'; }
40	function getSort(){ return 1; }
41
42	function connectTo($mode) {
43		$searchTriggerPattern = '\[ldapsearch .*?\]';
44		$this->Lexer->addSpecialPattern($searchTriggerPattern ,$mode,'plugin_ldapsearch');
45	}
46
47	function handle($match, $state, $pos, &$handler) {
48		$urlSyntax = 'ldap:\/\/([-\w.]+):([0-9]+)\/([^\?]*)\?([^\?]*)\?(base|one|sub)\?([^\]]+)';
49		$paramSyntax = ' (\w+)=("[^"]+"|[^\s\]]+)';
50		// build the ldapsearch_conf here only once
51		if(!$this->ldapsearch_conf) {
52			$this->build_ldapsearch_conf();
53		}
54		switch ($state) {
55			case DOKU_LEXER_SPECIAL : {
56				$matches = array();
57				if(preg_match("/$urlSyntax/",$match,$matches)) {
58					$ldapDetails = array(
59								'hostname' => $matches[1],
60								'port' => $matches[2],
61								'basedn' => $matches[3],
62								'attributes' => explode(",",$matches[4]),
63								'scope' => $matches[5],
64								'filter' => $matches[6],
65							);
66					$data = array( 'result' => null, 'ldapDetails' => $ldapDetails );
67					return array($state, $data);
68				} elseif(preg_match_all("/$paramSyntax/",$match,$matches, PREG_SET_ORDER)) {
69					$ldapDetails = array();
70					foreach($matches as $pair) {
71						$value = preg_replace('/^"(.*?)"$/','$1',$pair[2]);
72						$ldapDetails[$pair[1]] = $value;
73					}
74					// return null if no name specified
75					if(!$ldapDetails['search']) { return null; }
76					if($this->getConf('allow_overrides')) {
77						// allow overrides
78						foreach (array('hostname','port','basedn','attributes','scope','binddn','bindpassword') as $key) {
79							if(!$ldapDetails[$key])
80							{
81								$ldapDetails[$key] = $this->ldapsearch_conf[$ldapDetails['search']][$key];
82							}
83						}
84					}
85					// explode attributes
86					$ldapDetails['attributes'] = explode(',',$ldapDetails['attributes']);
87					// on its way
88					$data = array( 'result' => null, 'ldapDetails' => $ldapDetails );
89					return array($state, $data);
90				} else {
91					return null;
92				}
93			}
94
95			default:
96				return array($state);
97		}
98	}
99
100	function build_ldapsearch_conf() {
101		$set_index = array();
102		foreach(explode('|',$this->getConf('name')) as $name) {
103			$this->ldapsearch_conf[$name] = array();
104			array_push($set_index,$name);
105		}
106		foreach(array('hostname','port','basedn','attributes','scope','binddn','bindpassword') as $param) {
107			$count = 0;
108			foreach(explode('|',$this->getConf($param)) as $value) {
109				$this->ldapsearch_conf[$set_index[$count]][$param] = $value;
110				$count++;
111			}
112		}
113		//print_r($this->ldapsearch_conf);
114	}
115
116	function ldapsearch_search($ldapDetails) {
117		//print_r($ldapDetails);
118		if(!$ldapDetails['port']) { $ldapDetails['port'] = 389; }
119		if($ldap_handle = ldap_connect($ldapDetails['hostname'],$ldapDetails['port'])) {
120			ldap_set_option($ldap_handle, LDAP_OPT_PROTOCOL_VERSION, 3) ;
121			if(ldap_bind($ldap_handle,$ldapDetails['binddn'],$ldapDetails['bindpassword'])) {
122				$value = "";
123				if($ldapDetails['scope'] == 'sub') {
124					$results = ldap_search($ldap_handle,$ldapDetails['basedn'],$ldapDetails['filter'],$ldapDetails['attributes']);
125					$info = ldap_get_entries($ldap_handle, $results);
126					$value = $info[0][strtolower($ldapDetails['attributes'][0])][0];
127				} elseif($ldapDetails['scope'] == 'one') {
128					$results = ldap_list($ldap_handle, $ldapDetails['basedn'], $ldapDetails['filter'],$ldapDetails['attributes']);
129					$info = ldap_get_entries($ldap_handle, $results);
130					$value = $info[0][strtolower($ldapDetails['attributes'][0])][0];
131				} elseif($ldapDetails['scope'] == 'base') {
132					$results = ldap_read($ldap_handle, $ldapDetails['basedn'], $ldapDetails['filter'],$ldapDetails['attributes']);
133					$info = ldap_get_entries($ldap_handle, $results);
134					$value = $info[strtolower($ldapDetails['attributes'][0])][0];
135				} else {
136					$value = "Unknown scope ".$ldapDetails['scope']."\n";
137				}
138				ldap_unbind($ldap_handle);
139				return $value;
140			} else {
141				return "Failed to bind to LDAP on ".$ldapDetails['hostname'].":".$ldapDetails['port']."\n";
142			}
143		} else {
144			return "Failed to connect to LDAP on ".$ldapDetails['hostname'].":".$ldapDetails['port']."\n";
145		}
146	}
147
148	function render($mode, &$renderer, $indata) {
149		if($mode == 'xhtml'){
150			list($state, $data) = $indata;
151			$result = $date['result'];
152			$ldapDetails = $data['ldapDetails'];
153
154			switch ($state) {
155				case DOKU_LEXER_SPECIAL : {
156					error_log("render $match\n",3,"/tmp/mylog.txt");
157					$content = $this->ldapsearch_search($ldapDetails);
158					$renderer->doc .= $content;
159					break;
160				}
161
162			}
163			return true;
164		}
165
166		// unsupported $mode
167		return false;
168	}
169}
170
171?>
172