1<?php
2/*
3 * This plugin finds phpbb links to a thread or Topic from a speceficboard
4 * and if there is no title set it adds the thread title
5 *
6 * @author     Dominik Eckelmann <deckelmann@gmail.com>
7 */
8
9if(!defined('DOKU_INC')) die();
10if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
11if(!defined('DOKU_DATA')) define('DOKU_DATA',DOKU_INC.'data/');
12
13
14require_once(DOKU_PLUGIN.'action.php');
15
16class action_plugin_phpbblinks extends DokuWiki_Action_Plugin
17{
18
19	var $con;
20	var $pre;
21
22    /**
23     * return some info
24     */
25    function getInfo()
26	{
27        return confToHash(dirname(__FILE__).'/info.txt');
28    }
29
30    function register(&$controller)
31	{
32        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE',  $this, 'replace', array());
33    }
34
35    function replace(&$event, $param)
36	{
37
38		// if the action is not save or preview -> we are not interested
39		if (!is_array($event->data)) return false;
40		if ( !isset($event->data['preview']) && !isset($event->data['save']))
41		{
42			return false;
43		}
44
45		// ignore admin interface
46		global $ACT;
47		if ($ACT == 'admin')
48		{
49			return false;
50		}
51
52		// if not enabled -> return
53		if (!$this->getConf('enable'))
54		{
55			return false;
56		}
57
58		// get the board url
59		$url = $this->_getUrl();
60
61		// no url given and the plugin has nothing to do
62		if (!$url)
63		{
64			$this->admMsg('No BoardURL is set',-1);
65			return;
66		}
67
68		// no db connection
69		if (!$this->_connect())
70		{
71			return false;
72		}
73
74		global $TEXT;
75
76		// we take the requested text and split it into pices
77		$text = $TEXT;
78		$textpice = preg_split('/[\s]/',$text);
79
80		// prepare some stuff
81		$urlc = strlen($url);
82		$urla = parse_url($url);
83		$search = array();
84		$replace = array();
85
86		// start to check every word
87		foreach ($textpice as $word)
88		{
89			// ignore empty lines
90			if (empty($word))
91			{
92				continue;
93			}
94
95			// prepare some more stuff
96			$args = array();
97			$enclose = false;
98			$org = $word;
99
100			// if the word is a link
101			if (substr($word,0,2) == '[[' && substr($word,-2) == ']]' )
102			{
103				$enclose = true;
104				if (strpos($word,'|'))
105				{
106					// link has already a title - ignore
107					continue;
108				}
109				$word = substr($word,2,-2);
110				if (strlen($word) <= $urlc)
111				{
112					// word is to short to be a real interesting url
113					continue;
114				}
115				if (substr($word,0,$urlc) != $url)
116				{
117					// not the right url
118					continue;
119				}
120				// get url args
121				$pices = parse_url($word);
122
123
124				if (!$pices['query'])
125				{
126					continue; // no args are given
127				}
128
129				// get the args
130				parse_str($pices['query'],$args);
131			} else {
132				$wu = parse_url($word);
133
134				// compare links
135				$same = true;
136				foreach (array('scheme','host','port','user','pass','path') as $k)
137				{
138					if (!isset($urla[$k]))
139					{
140						if (isset($wu[$k]))
141						{
142							$same = false;
143							break;
144						}
145						continue;
146					}
147					if ($wu[$k] != $urla[$k])
148					{
149						// links are not the same
150						$same = false;
151						break;
152					}
153				}
154				if (!$same)
155				{
156
157					continue;
158				}
159
160				// get the url args
161				parse_str($wu['query'],$args);
162			}
163
164			// args make smbting
165
166			if (isset($args['p']))
167			{
168				// get post title
169				$p = $args['p'];
170				$txt = $this->_getTopicByPostId($p);
171				if (!$txt) continue;
172				$txt = $this->getConf('linktxt') . $txt;
173				$search[]  = '/(\s)?'.str_replace('/','\\/',preg_quote($org)).'(\s)?/';
174				$replace[] = "\\1[[$url?p=$p#$p|$txt]]\\2";
175			}
176			elseif (isset($args['t']))
177			{
178				// get thread title
179				$t = $args['t'];
180				$txt = $this->_getTopicByTopicId($t);
181				if (!$txt) continue;
182				$txt = $this->getConf('linktxt') . $txt;
183				$search[]  = '/(\s)?'.str_replace('/','\\/',preg_quote($org)).'(\s)?/';
184				$replace[] = "\\1[[$url?t=$t|$txt]]\\2";
185			}
186			else continue;
187		}
188		ksort($search);
189		ksort($replace);
190		$TEXT = preg_replace($search,$replace,$TEXT);
191
192		$this->_disconnect();
193    }
194
195	function _getUrl() {
196		$url = $this->getConf('boardurl');
197		if (empty($url)) return false;
198
199		// add a final /
200
201		if (substr($url,-1) != '/') {
202			$url .= '/';
203		}
204
205		// add the viewtopic file
206		$url .= 'viewtopic.php';
207		return $url;
208	}
209
210	function _getTopicByTopicId($id) {
211		if (!$this->con) return '';
212		$q = sprintf(
213			'SELECT topic_title FROM %1$stopics WHERE topic_id=%2$d
214			',$this->pre,intval($id));
215		$r = $this->_query($q);
216		if (!$r) return false;
217		$r = $r['topic_title'];
218		return $r;
219	}
220	function _getTopicByPostId($id) {
221		if (!$this->con) return '';
222		$q = sprintf('
223			SELECT
224				%1$stopics.topic_title
225			FROM
226				%1$sposts , %1$stopics
227			WHERE
228				%1$sposts.post_id=%2$d AND
229				%1$sposts	.topic_id = %1$stopics.topic_id
230			',$this->pre,intval($id));
231		$r = $this->_query($q);
232		if (!$r) return false;
233		$r = $r['topic_title'];
234		return $r;
235	}
236	function _connect() {
237		$host = '';
238		$user = '';
239		$pass = '';
240		$dbu   = '';
241		$pre  = '';
242		if ($this->getConf('integration'))
243		{
244			global $conf;
245			global $table_prefix;
246			$host = $conf['auth']['mysql']['server'];
247			$user = $conf['auth']['mysql']['user'];
248			$pass = $conf['auth']['mysql']['password'];
249			$dbu  = $conf['auth']['mysql']['database'];
250			$pre  = $table_prefix;
251		}
252		else
253		{
254			$host = $this->getConf('host');
255			$user = $this->getConf('user');
256			$pass = $this->getConf('pass');
257			$dbu  = $this->getConf('db');
258			$pre  = $this->getConf('pre');
259		}
260		$this->pre = $pre;
261		$con = @mysql_connect( $host , $user , $pass) or $err = @mysql_error();
262		if (!$con)
263		{
264			$this->admMsg('Database connection failed '.$err,-1);
265			return false;
266		}
267		$this->con = $con;
268		$db = @mysql_select_db($dbu,$this->con);
269		if ($db)
270		{
271			return true;
272		}
273		$this->admMsg('Database selection failed '.@mysql_error($this->con),-1);
274		return false;
275	}
276	function _disconnect() {
277		mysql_close($this->con);
278	}
279	function _query($q) {
280		$r = @mysql_query($q,$this->con);
281		if (!$r)
282		{
283			$this->admMsg('Database Error '.@mysql_error($this->con),-1);
284			return array();
285		}
286		$r = mysql_fetch_assoc($r);
287		return $r;
288	}
289	function _esc($s) {
290		return mysql_real_escape_string($s,$this->con);
291	}
292
293	function admMsg($msg,$type=0)
294	{
295		global $INFO;
296		if (!$INFO['isadmin'] && !$INFO['ismanager'])
297		{
298			return;
299		}
300		msg("PHPBBLinks: $msg",$type);
301	}
302}
303
304
305
306?>
307