1<?php
2/**
3 * Wiki farm manager
4 *
5 * @license  GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author   Etienne MELEARD <etienne.meleard@cru.fr>
7 * @desc     Process and renders farm config related requests
8 */
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');
13if(!defined('DOKU_FARM_PLUGIN')) define('DOKU_FARM_PLUGIN', DOKU_PLUGIN.'farm/');
14
15if(!defined('DOKU_FARMPLUGINLOADED')) define('DOKU_FARMPLUGINLOADED', true);
16
17require_once DOKU_FARM_PLUGIN.'animal.class.php';
18
19class dokuwiki_farm_config {
20	var $data = array();
21	var $manager = null;
22	var $errors = array();
23	private $ref = array();
24	private $conf = array();
25
26	/**
27	 * @param $manager object that must handle error(), success(), nicesize(), getLang() ... calls
28	 */
29	function __construct($manager) {
30		$this->manager = & $manager;
31		$farmconf = array();
32		include DOKU_FARM_PLUGIN.'config.php';
33		$this->data = $farmconf;
34	}
35
36	/**
37	 * Process requests
38	 */
39	function process() {
40		if(isset($this->manager->opt['save'])) {
41			// Security check
42			if(!checkSecurityToken()) {
43				$this->manager->error('system_errors', 'system_badtoken_failure');
44				return;
45			}
46			if(!$this->save()) {
47				$this->manager->error('config_errors', 'config_save_failure');
48				return;
49			}
50		}
51	}
52
53	/**
54	 * Renders
55	 */
56	function html() {
57		ptln('<div class="farm_cmd_title">'.$this->manager->getLang('config_title').'</div>');
58		ptln('<div class="farm_cmd_info">'.$this->manager->getLang('config_info').'</div>');
59		$this->form();
60	}
61
62	/**
63	 * Tells whether a configuration parameter is editable
64	 * @param $f parameter identifier
65	 * @return boolean
66	 */
67	function allowed($f) {
68		if(
69			$f == 'farmwebroot' ||
70			$f == 'farmfsroot' ||
71			$f == 'farmer' ||
72			$f == 'barn'
73		) return false;
74		return true;
75	}
76
77	/**
78	 * Outputs a form to edit the farm configuration
79	 */
80	function form($install = false) {
81		$cnf = array();
82		foreach(explode("\n", @file_get_contents(DOKU_FARM_PLUGIN.'config.php')) as $l) {
83			if(preg_match('`^\$farmconf\[[\'"]([a-z0-9_-]+)[\'"]\]\s*=\s*([^;]+);$`i', trim($l), $m)) {
84				$id = trim($m[1]);
85				if(!$this->allowed($id)) continue;
86				$d = trim($m[2]);
87				if(preg_match('`^[\'"].*[\'"]$`', $d)) $d = substr($d, 1, -1);
88				if(in_array(strtolower($d), array('true', 'false'))) $d = (strtolower($d) == 'true');
89				$cnf[$id] = $d;
90			}
91		}
92
93		$this->manager->formHead(array('farm_cmd' => 'farmconfig'));
94		foreach($cnf as $id => $d) {
95			ptln('	<fieldset>');
96			$l = '		'.$this->manager->getLang('config_field_name_'.$id).' : ';
97			if(is_bool($d)) {
98				$l .= '<input type="checkbox" name="config_field_'.$id.'"';
99				if($d) $l .= ' checked="checked"';
100				$l .= '/>';
101			}else{
102				$l .= '<input type="text" name="config_field_'.$id.'" value="'.$d.'"/>';
103			}
104			ptln($l.'<br />');
105			ptln('<small>'.$this->manager->getLang('config_field_desc_'.$id).'</small>');
106			ptln('	</fieldset>');
107		}
108
109		ptln('	<fieldset class="save">');
110		ptln('		<input type="submit" class="button" name="farm_opt[save]" value="'.$this->manager->getLang('btn_save').'" />');
111		ptln('	</fieldset>');
112		ptln('</form>');
113	}
114
115	/**
116	 * Saves the farm configuration
117	 * @return success as boolean
118	 */
119	function save() {
120		$this->conf = explode("\n", @file_get_contents(DOKU_FARM_PLUGIN.'config.php'));
121		if(!count($this->conf)) return false;
122
123		for($i=0; $i<count($this->conf); $i++) {
124			if(preg_match('`^\$farmconf\[[\'"]([a-z0-9_-]+)[\'"]\]\s*=\s*([^;]+);$`i', trim($this->conf[$i]), $m)) {
125				$id = trim($m[1]);
126				$this->ref[$id] = $i;
127			}
128		}
129
130		foreach($this->ref as $id => $n) {
131			if(!$this->allowed($id)) continue;
132			if(preg_match('`^\$farmconf\[[\'"]([a-z0-9_-]+)[\'"]\]\s*=\s*([^;]+);$`i', trim($this->conf[$n]), $m)) {
133				$d = trim($m[2]);
134				if(preg_match('`^[\'"].*[\'"]$`', $d)) $d = substr($d, 1, -1);
135				if(in_array(strtolower($d), array('true', 'false'))) {
136					$d = (strtolower($d) == 'true');
137					if($this->triggerChange($id, $d, isset($_POST['config_field_'.$id]))) $this->conf[$n] = '$farmconf[\''.$id.'\'] = '.(isset($_POST['config_field_'.$id]) ? 'true' : 'false').';';
138				}elseif(preg_match('`^[0-9]+(\s*[+/*-]\s*[0-9]+)*$`', $d)) {
139					if(!isset($_POST['config_field_'.$id])) continue;
140					$fb = create_function('', 'try{ return '.$d.'; }catch(Exception $e) { return null; }');
141					$fa = create_function('', 'try{ return '.(!empty($_POST['config_field_'.$id]) ? $_POST['config_field_'.$id] : '0').'; }catch(Exception $e) { return 0; }');
142					if(is_null($fa())) continue;
143					if($this->triggerChange($id, $fb(), $fa())) $this->conf[$n] = '$farmconf[\''.$id.'\'] = '.$_POST['config_field_'.$id].';';
144				}else{
145					if(!isset($_POST['config_field_'.$id])) continue;
146					if($this->triggerChange($id, $d, $_POST['config_field_'.$id])) $this->conf[$n] = '$farmconf[\''.$id.'\'] = \''.str_replace('\'', '\\\'', $_POST['config_field_'.$id]).'\';';
147				}
148			}
149		}
150		if($fp = fopen(DOKU_FARM_PLUGIN.'config.php', 'w')) {
151			fwrite($fp, implode("\n", $this->conf));
152			fclose($fp);
153			return true;
154		}else return false;
155	}
156
157	/**
158	 * Copy .htaccess replacing some tags
159	 * @param $src source file
160	 * @param $dest destination file
161	 */
162	function copyHtaccess($src, $dest, $more = array()) {
163		$c = @file_get_contents($src);
164		if(!$c) return false;
165
166		$farm = $this->manager->conf['farmwebroot'];
167		if(preg_match('`^([^:]+://)?([^/]+)?/?(.*)$`i', $farm, $m)) $farm = $m[3];
168		if(substr($farm, -1) != '/') $farm .= '/';
169		$c = str_replace('{farm}', $farm, $c);
170		$c = str_replace('{farmer}', $this->manager->conf['farmer'], $c);
171		$c = str_replace('{barn}', $this->manager->conf['barn'], $c);
172
173		foreach($more as $k => $v) $c = str_replace('{'.$k.'}', $v, $c);
174
175		$fp = fopen($dest, 'w');
176		if(!$fp) return false;
177		fwrite($fp, $c);
178		fclose($fp);
179		return true;
180	}
181
182	/**
183	 * Handles some specific parameters changes
184	 * @param $id parameter identifier
185	 * @param $before value before change
186	 * @param $after value after change
187	 * @return boolean telling wheter the change is acepted or not
188	 */
189	function triggerChange($id, $before, $after) {
190		if($after === $before) return true;
191
192		if($id == 'farmrewrite') {
193			if($after) {
194				if(realpath($this->manager->conf['farmfsroot'].$this->manager->conf['barn']) == realpath($this->manager->conf['farmfsroot'])) return true;
195
196				if($this->copyHtaccess(DOKU_FARM_PLUGIN.'install/farm.htaccess', $this->manager->conf['farmfsroot'].'.htaccess')) {
197					if($this->triggerChange('userewrite', false, true)) {
198						$_POST['config_field_userewrite'] = 1; // to keep integrity
199						$this->conf[$this->ref['userewrite']] = '$farmconf[\'userewrite\'] = true;';
200						return true;
201					}
202					return false;
203				}else{
204					$this->manager->error('config_errors', 'config_createfarmrewritefile_failure');
205					return false;
206				}
207			}elseif(@file_exists($this->manager->conf['farmfsroot'].'.htaccess')) {
208				if(realpath($this->manager->conf['farmfsroot'].$this->manager->conf['barn']) == realpath($this->manager->conf['farmfsroot'])) return true;
209				if(!unlink($this->manager->conf['farmfsroot'].'.htaccess')) {
210					$this->manager->error('config_errors', 'config_deletefarmrewritefile_failure');
211					return false;
212				}
213			}
214			return true;
215		}
216
217		if($id == 'userewrite') {
218			if($after) {
219				$src = (realpath($this->manager->conf['farmfsroot'].$this->manager->conf['barn']) != realpath($this->manager->conf['farmfsroot'])) ? 'barn.htaccess' : 'barnatroot.htaccess';
220				if($this->copyHtaccess(DOKU_FARM_PLUGIN.'install/'.$src, $this->manager->conf['farmfsroot'].$this->manager->conf['barn'].'.htaccess')) {
221					return true;
222				}else{
223					$this->manager->error('config_errors', 'config_createrewritefile_failure');
224					return false;
225				}
226			}else{
227				if(@file_exists($this->manager->conf['farmfsroot'].'.htaccess')) {
228					if(!unlink($this->manager->conf['farmfsroot'].'.htaccess')) {
229						$this->manager->error('config_errors', 'config_deletefarmrewritefile_failure');
230					}else{
231						$_POST['config_field_farmrewrite'] = 0; // to keep integrity
232						$this->conf[$this->ref['barnrewrite']] = '$farmconf[\'farmrewrite\'] = false;';
233					}
234				}
235				if(@file_exists($this->manager->conf['farmfsroot'].$this->manager->conf['barn'].'.htaccess')) {
236					if(!unlink($this->manager->conf['farmfsroot'].$this->manager->conf['barn'].'.htaccess')) {
237						$this->manager->error('config_errors', 'config_deleterewritefile_failure');
238						return false;
239					}
240				}
241				return true;
242			}
243		}
244
245		if($id == 'virtual') {
246			if($after) {
247				if(!@file_exists(DOKU_FARM_PLUGIN.'virtual_hosts.php')) {
248					if(!copy(DOKU_FARM_PLUGIN.'install/virtual_hosts.php', DOKU_FARM_PLUGIN.'virtual_hosts.php')) {
249						$this->manager->error('config_errors', 'config_copyvirtualhostfile_failure');
250						return false;
251					}
252				}
253
254				if(!$this->copyHtaccess(DOKU_FARM_PLUGIN.'install/virtual.htaccess', $this->manager->conf['farmfsroot'].'.htaccess', array('farmerhost' => $this->manager->conf['farmerhost']))) {
255					$this->manager->error('config_errors', 'config_createrewritefile_failure');
256					return false;
257				}
258			}else{
259				if($this->manager->conf['userewrite']) {
260					if($this->triggerChange('userewrite', false, true)) {
261						$_POST['config_field_userewrite'] = 1; // to keep integrity
262						$this->conf[$this->ref['userewrite']] = '$farmconf[\'userewrite\'] = true;';
263					}
264				}
265				if($this->manager->conf['farmrewrite']) {
266					if($this->triggerChange('farmrewrite', false, true)) {
267						$_POST['config_field_farmrewrite'] = 1; // to keep integrity
268						$this->conf[$this->ref['farmrewrite']] = '$farmconf[\'farmrewrite\'] = true;';
269					}
270				}
271			}
272			$this->manager->conf['virtual'] = $after;
273			return true;
274		}
275
276		if($id == 'farmerhost') {
277			if(!$this->manager->conf['virtual']) return true;
278			if($this->copyHtaccess(DOKU_FARM_PLUGIN.'install/virtual.htaccess', $this->manager->conf['farmfsroot'].'.htaccess', array('farmerhost' => $after))) {
279				return true;
280			}else{
281				$this->manager->error('config_errors', 'config_createrewritefile_failure');
282				return false;
283			}
284		}
285
286		if($id == 'animaltemplate') {
287			if(!dokuwiki_farm_animal::exists($after)) {
288				$this->manager->error('config_errors', 'animal_unknownanimal_failure');
289				return false;
290			}else return true;
291		}
292
293		if($id == 'enablesoap') {
294			if($after) {
295				if(!@file_exists($this->manager->conf['farmfsroot'].'farm.wsdl')) {
296					$wsdl = @file_get_contents(DOKU_FARM_PLUGIN.'install/wsdl.base');
297					if(!$wsdl) {
298						$this->manager->error('config_errors', 'config_createwsdl_failure');
299						return false;
300					}
301					$file = $this->manager->conf['farmwebroot'].'farm.wsdl';
302					$wsdl = str_replace('{wsdl}', $file, $wsdl);
303					$wsdl = str_replace('{location}', $this->manager->conf['farmwebroot'].$this->manager->conf['farmer'].'lib/plugins/farm/soapserver.php', $wsdl);
304					if($fp = fopen($this->manager->conf['farmfsroot'].'farm.wsdl', 'w')) {
305						fwrite($fp, $wsdl);
306						fclose($fp);
307					}else{
308						$this->manager->error('config_errors', 'config_createwsdl_failure');
309						return false;
310					}
311				}
312
313				if(!@file_exists(DOKU_FARM_PLUGIN.'trusted_apps.php')) {
314					if(!copy(DOKU_FARM_PLUGIN.'install/trusted_apps.php', DOKU_FARM_PLUGIN.'trusted_apps.php')) {
315						$this->manager->error('config_errors', 'config_copytrustedappsfile_failure');
316						return false;
317					}
318				}
319			}else{
320				if(@file_exists($this->manager->conf['farmfsroot'].'farm.wsdl')) {
321					if(!unlink($this->manager->conf['farmfsroot'].'farm.wsdl')) {
322						$this->manager->error('config_errors', 'config_deletewsdl_failure');
323						return false;
324					}
325				}
326			}
327			$this->manager->conf['enablesoap'] = $after;
328			return true;
329		}
330
331		return true;
332	}
333}
334?>
335