7b086a80 |
1 | <?php |
2 | |
35586184 |
3 | /** |
4 | * plugin.php |
5 | * |
35586184 |
6 | * This file provides the framework for a plugin architecture. |
7 | * |
8 | * Documentation on how to write plugins might show up some time. |
9 | * |
47ccfad4 |
10 | * @copyright © 1999-2006 The SquirrelMail Project Team |
4b4abf93 |
11 | * @license http://opensource.org/licenses/gpl-license.php GNU Public License |
31841a9e |
12 | * @version $Id$ |
d6c32258 |
13 | * @package squirrelmail |
35586184 |
14 | */ |
15 | |
d6c32258 |
16 | /** |
17 | * This function adds a plugin. |
18 | * @param string $name Internal plugin name (ie. delete_move_next) |
19 | * @return void |
20 | */ |
0606ca1f |
21 | function use_plugin ($name) { |
bd9c880b |
22 | if (file_exists(SM_PATH . "plugins/$name/setup.php")) { |
23 | include_once(SM_PATH . "plugins/$name/setup.php"); |
0606ca1f |
24 | $function = "squirrelmail_plugin_init_$name"; |
25 | if (function_exists($function)) { |
26 | $function(); |
2d367c68 |
27 | } |
2d367c68 |
28 | } |
0606ca1f |
29 | } |
2d367c68 |
30 | |
d6c32258 |
31 | /** |
32 | * This function executes a hook. |
33 | * @param string $name Name of hook to fire |
34 | * @return mixed $data |
35 | */ |
31524bcd |
36 | function do_hook ($name) { |
eb1f02bc |
37 | global $squirrelmail_plugin_hooks, $currentHookName; |
0606ca1f |
38 | $data = func_get_args(); |
eb1f02bc |
39 | $currentHookName = $name; |
a3439b27 |
40 | |
0606ca1f |
41 | if (isset($squirrelmail_plugin_hooks[$name]) |
42 | && is_array($squirrelmail_plugin_hooks[$name])) { |
43 | foreach ($squirrelmail_plugin_hooks[$name] as $function) { |
44 | /* Add something to set correct gettext domain for plugin. */ |
45 | if (function_exists($function)) { |
31524bcd |
46 | $function($data); |
47 | } |
48 | } |
49 | } |
50 | |
eb1f02bc |
51 | $currentHookName = ''; |
52 | |
31524bcd |
53 | /* Variable-length argument lists have a slight problem when */ |
54 | /* passing values by reference. Pity. This is a workaround. */ |
55 | return $data; |
56 | } |
57 | |
8b096f0a |
58 | /** |
59 | * This function executes a hook and allows for parameters to be passed. |
60 | * |
61 | * @param string name the name of the hook |
62 | * @param mixed param the parameters to pass to the hook function |
63 | * @return mixed the return value of the hook function |
64 | */ |
31524bcd |
65 | function do_hook_function($name,$parm=NULL) { |
eb1f02bc |
66 | global $squirrelmail_plugin_hooks, $currentHookName; |
31524bcd |
67 | $ret = ''; |
eb1f02bc |
68 | $currentHookName = $name; |
31524bcd |
69 | |
70 | if (isset($squirrelmail_plugin_hooks[$name]) |
71 | && is_array($squirrelmail_plugin_hooks[$name])) { |
72 | foreach ($squirrelmail_plugin_hooks[$name] as $function) { |
73 | /* Add something to set correct gettext domain for plugin. */ |
74 | if (function_exists($function)) { |
75 | $ret = $function($parm); |
dd389be5 |
76 | } |
2d367c68 |
77 | } |
2d367c68 |
78 | } |
7b086a80 |
79 | |
eb1f02bc |
80 | $currentHookName = ''; |
81 | |
0606ca1f |
82 | /* Variable-length argument lists have a slight problem when */ |
83 | /* passing values by reference. Pity. This is a workaround. */ |
2586d588 |
84 | return $ret; |
0606ca1f |
85 | } |
7b086a80 |
86 | |
8b096f0a |
87 | /** |
7edd8ad6 |
88 | * This function executes a hook, allows for parameters to be passed, |
89 | * and looks for an array returned from each plugin: each array is |
90 | * then merged into one and returned to the core hook location. |
91 | * |
92 | * Note that unlike PHP's array_merge function, matching array keys |
93 | * will not overwrite each other, instead, values under such keys |
94 | * will be concatenated if they are both strings, or merged if they |
95 | * are arrays (in the same (non-overwrite) manner recursively). |
96 | * |
97 | * Plugins returning non-arrays (strings, objects, etc) will have |
98 | * their output added to the end of the ultimate return array, |
99 | * unless ALL values returned are strings, in which case one string |
100 | * with all returned strings concatenated together is returned. |
8b096f0a |
101 | * |
102 | * @param string name the name of the hook |
7edd8ad6 |
103 | * @param mixed param the parameters to pass to the hook function |
104 | * |
105 | * @return mixed the merged return arrays or strings of each |
106 | * plugin on this hook |
107 | * |
8b096f0a |
108 | */ |
09ac2863 |
109 | function concat_hook_function($name,$parm=NULL) { |
eb1f02bc |
110 | global $squirrelmail_plugin_hooks, $currentHookName; |
7edd8ad6 |
111 | // $ret = ''; |
112 | $ret = array(); |
eb1f02bc |
113 | $currentHookName = $name; |
31524bcd |
114 | |
09ac2863 |
115 | if (isset($squirrelmail_plugin_hooks[$name]) |
116 | && is_array($squirrelmail_plugin_hooks[$name])) { |
117 | foreach ($squirrelmail_plugin_hooks[$name] as $function) { |
7edd8ad6 |
118 | /* Add something to set correct gettext domain for plugin. */ |
09ac2863 |
119 | if (function_exists($function)) { |
7edd8ad6 |
120 | // $ret .= $function($parm); |
918fcc1d |
121 | $ret = sqm_array_merge($ret, $function($parm)); |
09ac2863 |
122 | } |
123 | } |
124 | } |
125 | |
eb1f02bc |
126 | $currentHookName = ''; |
127 | |
09ac2863 |
128 | /* Variable-length argument lists have a slight problem when */ |
129 | /* passing values by reference. Pity. This is a workaround. */ |
8266f7af |
130 | // FIXME: empty return array breaks legacy use of this hook, so |
131 | // as a workaround, return empty string (let's fix the |
132 | // hook calls so we can pull this out) |
133 | if (empty($ret)) return ''; |
09ac2863 |
134 | return $ret; |
135 | } |
cd7fc9e6 |
136 | |
5576644b |
137 | /** |
138 | * This function is used for hooks which are to return true or |
139 | * false. If $priority is > 0, any one or more trues will override |
140 | * any falses. If $priority < 0, then one or more falses will |
141 | * override any trues. |
8b096f0a |
142 | * Priority 0 means majority rules. Ties will be broken with $tie |
143 | * |
144 | * @param string name the hook name |
145 | * @param mixed parm the parameters for the hook function |
146 | * @param int priority |
147 | * @param bool tie |
148 | * @return bool the result of the function |
149 | */ |
5576644b |
150 | function boolean_hook_function($name,$parm=NULL,$priority=0,$tie=false) { |
eb1f02bc |
151 | global $squirrelmail_plugin_hooks, $currentHookName; |
5576644b |
152 | $yea = 0; |
153 | $nay = 0; |
154 | $ret = $tie; |
155 | |
156 | if (isset($squirrelmail_plugin_hooks[$name]) && |
157 | is_array($squirrelmail_plugin_hooks[$name])) { |
158 | |
159 | /* Loop over the plugins that registered the hook */ |
eb1f02bc |
160 | $currentHookName = $name; |
5576644b |
161 | foreach ($squirrelmail_plugin_hooks[$name] as $function) { |
162 | if (function_exists($function)) { |
163 | $ret = $function($parm); |
164 | if ($ret) { |
165 | $yea++; |
166 | } else { |
167 | $nay++; |
168 | } |
169 | } |
170 | } |
eb1f02bc |
171 | $currentHookName = ''; |
5576644b |
172 | |
173 | /* Examine the aftermath and assign the return value appropriately */ |
174 | if (($priority > 0) && ($yea)) { |
175 | $ret = true; |
176 | } elseif (($priority < 0) && ($nay)) { |
177 | $ret = false; |
178 | } elseif ($yea > $nay) { |
179 | $ret = true; |
180 | } elseif ($nay > $yea) { |
181 | $ret = false; |
182 | } else { |
183 | // There's a tie, no action needed. |
184 | } |
185 | return $ret; |
186 | } |
187 | // If the code gets here, there was a problem - no hooks, etc. |
188 | return NULL; |
189 | } |
190 | |
cd7fc9e6 |
191 | /** |
192 | * This function checks whether the user's USER_AGENT is known to |
193 | * be broken. If so, returns true and the plugin is invisible to the |
194 | * offending browser. |
7349fa12 |
195 | * *** THIS IS A TEST FOR JAVASCRIPT SUPPORT *** |
94ba79ce |
196 | * FIXME: This function needs to have its name changed! |
8b096f0a |
197 | * |
198 | * @return bool whether this browser properly supports JavaScript |
ccacde36 |
199 | * @deprecated use checkForJavascript() since 1.5.1 |
cd7fc9e6 |
200 | */ |
201 | function soupNazi(){ |
7349fa12 |
202 | return !checkForJavascript(); |
cd7fc9e6 |
203 | } |
fe0aa536 |
204 | |
205 | /** |
206 | * Check if plugin is enabled |
207 | * @param string $plugin_name plugin name |
208 | * @since 1.5.1 |
209 | * @return boolean |
210 | */ |
211 | function is_plugin_enabled($plugin_name) { |
212 | global $plugins; |
213 | |
e83cfcef |
214 | /** |
202bcbcc |
215 | * check if variable is empty. if var is not set, php empty |
e495bd68 |
216 | * returns true without error notice. |
217 | * |
218 | * then check if it is an array |
e83cfcef |
219 | */ |
e495bd68 |
220 | if (empty($plugins) || ! is_array($plugins)) |
fe0aa536 |
221 | return false; |
222 | |
223 | if ( in_array($plugin_name,$plugins) ) { |
224 | return true; |
225 | } else { |
226 | return false; |
227 | } |
228 | } |
d99b6c56 |
229 | |
230 | /** |
231 | * Check a plugin's version. |
232 | * |
233 | * Returns TRUE if the given plugin is installed, |
234 | * activated and is at minimum version $a.$b.$c. |
235 | * If any one of those conditions fails, FALSE |
236 | * will be returned (careful of plugins that are |
237 | * sufficiently versioned but are not activated). |
238 | * |
239 | * By overriding the default value of $force_inclusion, |
240 | * this function will attempt to grab versioning |
241 | * information from the given plugin even if it |
242 | * is not activated (plugin still has to be |
243 | * unpackaged and set in place in the plugins |
244 | * directory). Use with care - some plugins |
245 | * might break SquirrelMail when this is used. |
246 | * |
247 | * Note that this function assumes plugin |
248 | * versioning is consistently applied in the same |
249 | * fashion that SquirrelMail versions are, with the |
250 | * exception that an applicable SquirrelMail |
251 | * version may be appended to the version number |
252 | * (which will be ignored herein). That is, plugin |
253 | * version number schemes are expected in the following |
254 | * format: 1.2.3, or 1.2.3-1.4.0. |
255 | * |
256 | * Any characters after the third number are discarded, |
257 | * so formats such as the following will also work, |
258 | * although extra information about beta versions can |
259 | * possibly confuse the desired results of the version |
260 | * check: 1.2.3-beta4, 1.2.3.RC2, and so forth. |
261 | * |
b2a6a14c |
262 | * @since 1.5.2 |
d99b6c56 |
263 | * |
264 | * @param string plugin_name name of the plugin to |
265 | * check; must precisely |
266 | * match the plugin |
267 | * directory name |
268 | * @param int a major version number |
269 | * @param int b minor version number |
270 | * @param int c release number |
271 | * @param bool force_inclusion try to get version info |
272 | * for plugins not activated? |
273 | * (default FALSE) |
274 | * |
275 | * @return bool |
276 | * |
277 | */ |
278 | function check_plugin_version($plugin_name, |
279 | $a = 0, $b = 0, $c = 0, |
280 | $force_inclusion = FALSE) |
281 | { |
282 | |
6b6bcf00 |
283 | $info_function = $plugin_name . '_info'; |
d99b6c56 |
284 | $version_function = $plugin_name . '_version'; |
6b6bcf00 |
285 | $plugin_info = array(); |
d99b6c56 |
286 | $plugin_version = FALSE; |
287 | |
288 | |
6b6bcf00 |
289 | // first attempt to find the plugin info function, wherein |
290 | // the plugin version should be available |
d99b6c56 |
291 | // |
6b6bcf00 |
292 | if (function_exists($info_function)) |
293 | $plugin_info = $info_function(); |
d99b6c56 |
294 | else if ($force_inclusion |
295 | && file_exists(SM_PATH . 'plugins/' . $plugin_name . '/setup.php')) |
296 | { |
297 | include_once(SM_PATH . 'plugins/' . $plugin_name . '/setup.php'); |
6b6bcf00 |
298 | if (function_exists($info_function)) |
299 | $plugin_info = $info_function(); |
d99b6c56 |
300 | } |
6b6bcf00 |
301 | if (!empty($plugin_info['version'])) |
302 | $plugin_version = $plugin_info['version']; |
303 | |
304 | |
305 | // otherwise, look for older version function |
306 | // |
307 | if (!$plugin_version && function_exists($version_function)) |
308 | $plugin_version = $version_function(); |
309 | |
d99b6c56 |
310 | |
311 | if (!$plugin_version) return FALSE; |
312 | |
313 | |
314 | // now massage version number into something we understand |
315 | // |
316 | $plugin_version = trim(preg_replace(array('/[^0-9.]+.*$/', '/[^0-9.]/'), |
317 | '', $plugin_version), |
318 | '.'); |
319 | $plugin_version = explode('.', $plugin_version); |
320 | if (!isset($plugin_version[0])) $plugin_version[0] = 0; |
321 | if (!isset($plugin_version[1])) $plugin_version[1] = 0; |
322 | if (!isset($plugin_version[2])) $plugin_version[2] = 0; |
323 | // sm_print_r($plugin_version); |
324 | |
325 | |
326 | // now test the version number |
327 | // |
328 | if ($plugin_version[0] < $a || |
329 | ($plugin_version[0] == $a && $plugin_version[1] < $b) || |
330 | ($plugin_version[0] == $a && $plugin_version[1] == $b && $plugin_version[2] < $c)) |
331 | return FALSE; |
332 | |
333 | |
334 | return TRUE; |
335 | |
336 | } |
337 | |