|
1 <?php |
|
2 /* |
|
3 Plugin Name: Linkchomper |
|
4 Plugin URI: http://enanocms.org/Linkchomper |
|
5 Description: Allows you to add custom links to the Links section of the sidebar. Includes click-tracking functionality. |
|
6 Author: Dan Fuhry |
|
7 Version: 0.1 beta 1 |
|
8 Author URI: http://enanocms.org/ |
|
9 */ |
|
10 |
|
11 /* |
|
12 * Linkchomper for Enano CMS |
|
13 * Version 0.1 beta 1 |
|
14 * Copyright (C) 2006-2007 Dan Fuhry |
|
15 * |
|
16 * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License |
|
17 * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. |
|
18 * |
|
19 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied |
|
20 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. |
|
21 */ |
|
22 |
|
23 global $db, $session, $paths, $template, $plugins; // Common objects |
|
24 |
|
25 // Constants |
|
26 |
|
27 define('LC_LINK_RAW', 1); |
|
28 define('LC_LINK_TRACK_CLICKS', 2); |
|
29 define('LC_LINK_DISABLED', 4); |
|
30 define('LC_LINK_INNER_IMAGE', 8); |
|
31 |
|
32 define('LC_EDIT', 1); |
|
33 define('LC_CREATE', 2); |
|
34 |
|
35 if ( !$version = getConfig('linkchomper_version') ) |
|
36 { |
|
37 // Install the table |
|
38 $q = $db->sql_query('CREATE TABLE '.table_prefix.'linkchomper( |
|
39 link_id mediumint(8) NOT NULL auto_increment, |
|
40 link_name varchar(255) NOT NULL, |
|
41 link_href text NOT NULL, |
|
42 link_inner_html text NOT NULL, |
|
43 link_before_html text NOT NULL, |
|
44 link_after_html text NOT NULL, |
|
45 link_flags tinyint(1) NOT NULL DEFAULT 0, |
|
46 link_clicks bigint(15) NOT NULL DEFAULT 0, |
|
47 link_order mediumint(8) NOT NULL DEFAULT 0, |
|
48 PRIMARY KEY ( link_id ) |
|
49 );'); |
|
50 if ( !$q ) |
|
51 { |
|
52 // Prevent Linkchomper from loading again |
|
53 $plugin_key = 'plugin_' . basename(__FILE__); |
|
54 setConfig($plugin_key, '0'); |
|
55 $db->_die('The error occurred during an attempt to create the table for Linkchomper. For your site\'s protection, Linkchomper has disabled itself. It can be re-enabled in the administration panel.'); |
|
56 } |
|
57 setConfig('linkchomper_version', '0.1b1'); |
|
58 } |
|
59 |
|
60 // Hook into the template compiler |
|
61 |
|
62 $plugins->attachHook('links_widget', 'linkchomper_generate_html($ob);'); |
|
63 |
|
64 // Add our link tracking page |
|
65 |
|
66 $plugins->attachHook('base_classes_initted', ' |
|
67 global $paths; |
|
68 $paths->add_page(Array( |
|
69 \'name\'=>\'LinkChomper click tracker\', |
|
70 \'urlname\'=>\'LCClick\', |
|
71 \'namespace\'=>\'Special\', |
|
72 \'special\'=>0,\'visible\'=>0,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\', |
|
73 )); |
|
74 $paths->add_page(Array( |
|
75 \'name\'=>\'Administration\', |
|
76 \'urlname\'=>\'Linkchomper\', |
|
77 \'namespace\'=>\'Admin\', |
|
78 \'special\'=>0,\'visible\'=>0,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\', |
|
79 )); |
|
80 $paths->addAdminNode(\'Plugin configuration\', \'Linkchomper manager\', \'Linkchomper\'); |
|
81 '); |
|
82 |
|
83 |
|
84 // Function to generate HTML for the sidebar widget |
|
85 |
|
86 function linkchomper_generate_html(&$links_array) |
|
87 { |
|
88 global $db, $session, $paths, $template, $plugins; // Common objects |
|
89 |
|
90 $q = $db->sql_query('SELECT link_id, link_name, link_href, link_inner_html, link_before_html, link_after_html, link_flags FROM '.table_prefix.'linkchomper ORDER BY link_order ASC;'); |
|
91 if ( !$q ) |
|
92 $db->_die(); |
|
93 |
|
94 if ( $row = $db->fetchrow() ) |
|
95 { |
|
96 do { |
|
97 |
|
98 // Get flags |
|
99 $flags =& $row['link_flags']; |
|
100 |
|
101 // Is this link disabled? If so, skip the whole painful process |
|
102 if ( $flags & LC_LINK_DISABLED ) |
|
103 continue; |
|
104 |
|
105 // First check to see if the inner_html is an image URL. If so, generate a nice img tag for the inner HTML. |
|
106 if ( $flags & LC_LINK_INNER_IMAGE ) |
|
107 { |
|
108 $row['link_inner_html'] = '<img alt="' . htmlspecialchars($row['link_name']) . '" src="' . htmlentities($row['link_inner_html']) . '" style="border-width: 0px;" />'; |
|
109 } |
|
110 |
|
111 // If it's raw HTML, just send it through |
|
112 if ( $flags & LC_LINK_RAW ) |
|
113 { |
|
114 $links_array[] = $row['link_before_html'] . $row['link_inner_html'] . $row['link_after_html']; |
|
115 } |
|
116 // If we're supposed to track clicks, send a deceptive anchor |
|
117 else if ( $flags & LC_LINK_TRACK_CLICKS ) |
|
118 { |
|
119 $url = makeUrlNS('Special', 'LCClick/' . $row['link_id'], false, true); |
|
120 // Escape target URL for Javascript-safety |
|
121 $real_url = htmlspecialchars(str_replace(array('\\', '\'', '"'), array('\\\\', '\\\'', '\\"'), $row['link_href'])); |
|
122 $link = $row['link_before_html'] . '<a href="' . $url . '" title="' . htmlspecialchars($row['link_href']) . '" onmouseover="void(window.status=\'' . $real_url . '\');" onmouseout="void(window.status=\'\');">' . $row['link_inner_html'] . '</a>' . $row['link_after_html']; |
|
123 $links_array[] = $link; |
|
124 } |
|
125 // None of those? OK just send a normal link |
|
126 else |
|
127 { |
|
128 $url = htmlspecialchars($row['link_href']); |
|
129 $link = $row['link_before_html'] . '<a href="' . $url . '">' . $row['link_inner_html'] . '</a>' . $row['link_after_html']; |
|
130 $links_array[] = $link; |
|
131 } |
|
132 |
|
133 } while ( $row = $db->fetchrow() ); |
|
134 } |
|
135 |
|
136 $db->free_result(); |
|
137 |
|
138 } |
|
139 |
|
140 // Special page handler for click tracker |
|
141 |
|
142 function page_Special_LCClick() |
|
143 { |
|
144 global $db, $session, $paths, $template, $plugins; // Common objects |
|
145 |
|
146 $link_id = ( $xx = $paths->getParam(0) ) ? intval($xx) : false; |
|
147 |
|
148 if ( !$link_id ) |
|
149 die_friendly('Nice try', '<p>Hacking attempt</p>'); |
|
150 |
|
151 $q = $db->sql_query('SELECT link_href,link_flags FROM '.table_prefix.'linkchomper WHERE link_id=' . $link_id . ';'); |
|
152 |
|
153 if ( !$q ) |
|
154 $db->_die(); |
|
155 |
|
156 $row = $db->fetchrow(); |
|
157 $db->free_result(); |
|
158 |
|
159 if ( ! ( $row['link_flags'] & LC_LINK_TRACK_CLICKS ) ) |
|
160 { |
|
161 die_friendly('Nice try', '<p>This ain\'t no tracker link...</p>'); |
|
162 } |
|
163 |
|
164 $q = $db->sql_query('UPDATE '.table_prefix.'linkchomper SET link_clicks=link_clicks+1 WHERE link_id=' . $link_id . ';'); |
|
165 |
|
166 if ( !$q ) |
|
167 $db->_die(); |
|
168 |
|
169 redirect($row['link_href'], 'Redirecting', 'Thanks for clicking the link, you are now being transferred to the destination.', 0); |
|
170 |
|
171 } |
|
172 |
|
173 function linkchomper_admin_redirect_home($message = 'Your changes have been saved, and you will now be transferred back to the administration panel.') |
|
174 { |
|
175 global $db, $session, $paths, $template, $plugins; // Common objects |
|
176 $url = makeUrlComplete('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'Linkchomper'); |
|
177 redirect($url, 'Linkchomper changes saved', $message, 2); |
|
178 } |
|
179 |
|
180 function page_Admin_Linkchomper() |
|
181 { |
|
182 |
|
183 //@ini_set('display_errors', 'On') or die('Can\'t set display_errors'); |
|
184 //error_reporting(E_ALL); |
|
185 |
|
186 global $db, $session, $paths, $template, $plugins; // Common objects |
|
187 if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN ) |
|
188 { |
|
189 echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>'; |
|
190 return; |
|
191 } |
|
192 |
|
193 if ( isset($_POST['action']) ) |
|
194 { |
|
195 if ( isset($_POST['action']['move_up']) || isset($_POST['action']['move_down']) ) |
|
196 { |
|
197 $direction = ( isset($_POST['action']['move_up']) ) ? 'up' : 'down'; |
|
198 $ordering = ( isset($_POST['action']['move_up']) ) ? 'ASC' : 'DESC'; |
|
199 |
|
200 // Move an item up in the list |
|
201 // First step: Get IDs of the item to move and the item above it |
|
202 $id = array_keys($_POST['action']['move_' . $direction]); |
|
203 $id = intval( $id[0] ); |
|
204 if ( !$id ) |
|
205 { |
|
206 echo 'Hacking attempt'; |
|
207 return false; |
|
208 } |
|
209 |
|
210 $q = $db->sql_query('SELECT link_id, link_name, link_order FROM '.table_prefix.'linkchomper ORDER BY link_order ' . $ordering . ';'); |
|
211 |
|
212 if ( !$q ) |
|
213 $db->_die(); |
|
214 |
|
215 $last_id = false; |
|
216 $this_id = false; |
|
217 |
|
218 $last_order = false; |
|
219 $this_order = false; |
|
220 |
|
221 $id_to = false; |
|
222 $id_from = false; |
|
223 |
|
224 $order_to = false; |
|
225 $order_from = false; |
|
226 |
|
227 while ( $row = $db->fetchrow() ) |
|
228 { |
|
229 $this_id = $row['link_id']; |
|
230 $this_order = $row['link_order']; |
|
231 if ( $this_id == $id && $last_id === false ) |
|
232 { |
|
233 linkchomper_admin_redirect_home('This item is already at the top or bottom of the list.'); |
|
234 } |
|
235 else if ( $this_id == $id ) |
|
236 { |
|
237 $id_from = $last_id; |
|
238 $id_to = $this_id; |
|
239 $order_from = $this_order; |
|
240 $order_to = $last_order; |
|
241 break; |
|
242 } |
|
243 $last_id = $this_id; |
|
244 $last_order = $this_order; |
|
245 } |
|
246 |
|
247 unset($this_id, $this_order, $last_id, $last_order); |
|
248 |
|
249 if ( $last_order === false || $this_order === false ) |
|
250 { |
|
251 linkchomper_admin_redirect_home('Sanity check failed.'); |
|
252 } |
|
253 |
|
254 $sql1 = 'UPDATE '.table_prefix.'linkchomper SET link_order=' . $order_to . ' WHERE link_id=' . $id_to . ';'; |
|
255 $sql2 = 'UPDATE '.table_prefix.'linkchomper SET link_order=' . $order_from . ' WHERE link_id=' . $id_from . ';'; |
|
256 |
|
257 if ( !$db->sql_query($sql1) ) |
|
258 { |
|
259 $db->_die(); |
|
260 } |
|
261 |
|
262 if ( !$db->sql_query($sql2) ) |
|
263 { |
|
264 $db->_die(); |
|
265 } |
|
266 |
|
267 linkchomper_admin_redirect_home('The item "' . $row['link_name'] . '" has been moved ' . $direction . '.'); |
|
268 |
|
269 } |
|
270 else if ( isset($_POST['action']['delete']) ) |
|
271 { |
|
272 // Delete a link |
|
273 $id = array_keys($_POST['action']['delete']); |
|
274 $id = intval( $id[0] ); |
|
275 if ( !$id ) |
|
276 { |
|
277 echo 'Hacking attempt'; |
|
278 return false; |
|
279 } |
|
280 $q = $db->sql_query('DELETE FROM '.table_prefix."linkchomper WHERE link_id=$id;"); |
|
281 if ( !$q ) |
|
282 $db->_die(); |
|
283 |
|
284 linkchomper_admin_redirect_home('The selected link has been deleted.'); |
|
285 } |
|
286 |
|
287 linkchomper_admin_redirect_home('Invalid or no action defined'); |
|
288 } |
|
289 |
|
290 else if ( isset($_POST['stage2']) ) |
|
291 { |
|
292 $_GET['module'] = $paths->page; |
|
293 $_POST['stage2_real'] = $_POST['stage2']; |
|
294 unset($_POST['stage2']); |
|
295 page_Special_Administration(); |
|
296 return true; |
|
297 } |
|
298 |
|
299 else if ( isset($_POST['stage2_real']) ) |
|
300 { |
|
301 /* |
|
302 |
|
303 TODO: |
|
304 The idea here is to build a template-based unified edit form that will be used both for creating and editing links. Make it have |
|
305 intelligent auto-hiding/auto-(un)checking elements and make it use the standard flags field. |
|
306 |
|
307 */ |
|
308 // allow breaking out |
|
309 switch(true){case true: |
|
310 $stage2 =& $_POST['stage2_real']; |
|
311 $err_and_revert = array( |
|
312 'error' => false |
|
313 ); |
|
314 if ( isset($stage2['delete']) ) |
|
315 { |
|
316 $id = array_keys($stage2['delete']); |
|
317 $id = intval( $id[0] ); |
|
318 if ( !$id ) |
|
319 { |
|
320 echo 'Hacking attempt'; |
|
321 return false; |
|
322 } |
|
323 echo '<form action="' . makeUrlNS('Admin', 'Linkchomper') . '" method="post" enctype="multipart/form-data">'; |
|
324 echo '<div class="tblholder"> |
|
325 <table border="0" cellspacing="1" cellpadding="4">'; |
|
326 echo ' <tr> |
|
327 <th>Confirm deletion</th> |
|
328 </tr> |
|
329 <td class="row1" style="text-align: center; line-height: 40px;"> |
|
330 Are you sure you want to permanently delete this link? |
|
331 </td> |
|
332 <tr> |
|
333 <th class="subhead"> |
|
334 <input type="submit" name="action[delete]['.$id.']" value="Yes, delete link" /> |
|
335 <input type="submit" name="stage2[cancel]" value="Cancel" /> |
|
336 </th> |
|
337 </tr>'; |
|
338 |
|
339 echo ' </table> |
|
340 </div>'; |
|
341 echo '</form>'; |
|
342 } |
|
343 else if ( isset($stage2['create_new']) ) |
|
344 { |
|
345 $editor = new LinkchomperFormGenerator(); |
|
346 $editor->echo_html(); |
|
347 } |
|
348 else if ( isset($stage2['edit']) ) |
|
349 { |
|
350 $id = array_keys($stage2['edit']); |
|
351 $id = intval( $id[0] ); |
|
352 if ( !$id ) |
|
353 { |
|
354 echo 'Hacking attempt'; |
|
355 return false; |
|
356 } |
|
357 $q = $db->sql_query('SELECT * FROM '.table_prefix."linkchomper WHERE link_id=$id;"); |
|
358 if ( !$q ) |
|
359 $db->_die(); |
|
360 if ( $db->numrows() < 1 ) |
|
361 { |
|
362 echo "Can't find link: $id"; |
|
363 $db->free_result(); |
|
364 } |
|
365 else |
|
366 { |
|
367 $row = $db->fetchrow(); |
|
368 $db->free_result(); |
|
369 $editor = new LinkchomperFormGenerator(); |
|
370 $editor->track_clicks = ( $row['link_flags'] & LC_LINK_TRACK_CLICKS ); |
|
371 $editor->raw_html = ( $row['link_flags'] & LC_LINK_RAW ); |
|
372 $editor->link_flag_image = ( $row['link_flags'] & LC_LINK_INNER_IMAGE ); |
|
373 $editor->link_disabled = ( $row['link_flags'] & LC_LINK_DISABLED ); |
|
374 $editor->link_target = $row['link_href']; |
|
375 $editor->link_name = $row['link_name']; |
|
376 $editor->mode = LC_EDIT; |
|
377 $editor->inner_html = $row['link_inner_html']; |
|
378 $editor->before_html = $row['link_before_html']; |
|
379 $editor->after_html = $row['link_after_html']; |
|
380 $editor->link_id = $row['link_id']; |
|
381 $editor->echo_html(); |
|
382 } |
|
383 } |
|
384 else if ( isset($stage2['create_new_finish']) ) |
|
385 { |
|
386 $flags = 0; |
|
387 |
|
388 // Validation |
|
389 $errors = array(); |
|
390 |
|
391 $link_name = trim($_POST['link_name']); |
|
392 if ( empty($link_name) ) |
|
393 $errors[] = 'Please enter a name for your link.'; |
|
394 |
|
395 if ( isset($_POST['raw_html']) && isset($_POST['track_clicks']) ) |
|
396 $errors[] = 'Raw blocks cannot be used with clicktracking.'; |
|
397 |
|
398 $link_target = trim($_POST['link_target']); |
|
399 if ( empty($link_target) && !isset($_POST['raw_html']) ) |
|
400 $errors[] = 'Please enter a target for your link.'; |
|
401 |
|
402 if ( $_POST['link_flag_img'] == '1' ) |
|
403 { |
|
404 $inner_html = trim($_POST['link_img_path']); |
|
405 if ( empty($inner_html) ) |
|
406 $errors[] = 'Please enter a path or URL to an image file.'; |
|
407 } |
|
408 else |
|
409 { |
|
410 $inner_html = trim($_POST['link_inner_html']); |
|
411 if ( empty($inner_html) ) |
|
412 $errors[] = 'Please enter some content to go inside your link.'; |
|
413 } |
|
414 |
|
415 if ( count($errors) > 0 ) |
|
416 { |
|
417 $err_and_revert['error'] = true; |
|
418 $err_and_revert['message'] = implode("<br />\n ", $errors); |
|
419 } |
|
420 else |
|
421 { |
|
422 if ( isset($_POST['link_disabled']) ) |
|
423 $flags = $flags | LC_LINK_DISABLED; |
|
424 if ( $_POST['link_flag_img'] == '1' ) |
|
425 $flags = $flags | LC_LINK_INNER_IMAGE; |
|
426 if ( isset($_POST['raw_html']) ) |
|
427 $flags = $flags | LC_LINK_RAW; |
|
428 if ( isset($_POST['track_clicks']) ) |
|
429 $flags = $flags | LC_LINK_TRACK_CLICKS; |
|
430 |
|
431 $before_html = strval(trim($_POST['link_before_html'])); |
|
432 $after_html = strval(trim($_POST['link_after_html'])); |
|
433 |
|
434 if ( !$session->get_permissions('php_in_pages') ) |
|
435 { |
|
436 // Not allowed to embed PHP and Javascript |
|
437 $before_html = sanitize_html($before_html); |
|
438 $after_html = sanitize_html($after_html); |
|
439 $inner_html = sanitize_html($inner_html); |
|
440 } |
|
441 |
|
442 $sanitized = array( |
|
443 'link_name' => $db->escape($link_name), |
|
444 'link_target' => $db->escape($link_target), |
|
445 'link_inner_html' => $db->escape($inner_html), |
|
446 'link_before_html' => $db->escape($before_html), |
|
447 'link_after_html' => $db->escape($after_html) |
|
448 ); |
|
449 |
|
450 $sql = "INSERT INTO ".table_prefix."linkchomper(link_name, link_href, link_inner_html, link_before_html, link_after_html, link_flags, link_order) VALUES('{$sanitized['link_name']}','{$sanitized['link_target']}','{$sanitized['link_inner_html']}','{$sanitized['link_before_html']}','{$sanitized['link_after_html']}', $flags, ".LC_ADMIN_ORDER_LAST.");"; |
|
451 if ( !$db->sql_query($sql) ) |
|
452 $db->_die(); |
|
453 |
|
454 echo '<div class="info-box">Link created.</div>'; |
|
455 break; |
|
456 } |
|
457 } |
|
458 else if ( isset($stage2['edit_finish']) ) |
|
459 { |
|
460 $flags = 0; |
|
461 |
|
462 // Validation |
|
463 $errors = array(); |
|
464 |
|
465 $link_name = trim($_POST['link_name']); |
|
466 if ( empty($link_name) ) |
|
467 $errors[] = 'Please enter a name for your link.'; |
|
468 |
|
469 if ( isset($_POST['raw_html']) && isset($_POST['track_clicks']) ) |
|
470 $errors[] = 'Raw blocks cannot be used with clicktracking.'; |
|
471 |
|
472 $link_target = trim($_POST['link_target']); |
|
473 if ( empty($link_target) && !isset($_POST['raw_html']) ) |
|
474 $errors[] = 'Please enter a target for your link.'; |
|
475 |
|
476 if ( $_POST['link_flag_img'] == '1' ) |
|
477 { |
|
478 $inner_html = trim($_POST['link_img_path']); |
|
479 if ( empty($inner_html) ) |
|
480 $errors[] = 'Please enter a path or URL to an image file.'; |
|
481 } |
|
482 else |
|
483 { |
|
484 $inner_html = trim($_POST['link_inner_html']); |
|
485 if ( empty($inner_html) ) |
|
486 $errors[] = 'Please enter some content to go inside your link.'; |
|
487 } |
|
488 |
|
489 $link_id = intval($_POST['link_id']); |
|
490 if ( $link_id < 1 ) |
|
491 $errors[] = 'Unable to obtain link ID'; |
|
492 |
|
493 if ( count($errors) > 0 ) |
|
494 { |
|
495 $err_and_revert['error'] = true; |
|
496 $err_and_revert['message'] = implode("<br />\n ", $errors); |
|
497 } |
|
498 else |
|
499 { |
|
500 if ( isset($_POST['link_disabled']) ) |
|
501 $flags = $flags | LC_LINK_DISABLED; |
|
502 if ( $_POST['link_flag_img'] == '1' ) |
|
503 $flags = $flags | LC_LINK_INNER_IMAGE; |
|
504 if ( isset($_POST['raw_html']) ) |
|
505 $flags = $flags | LC_LINK_RAW; |
|
506 if ( isset($_POST['track_clicks']) ) |
|
507 $flags = $flags | LC_LINK_TRACK_CLICKS; |
|
508 |
|
509 $before_html = strval(trim($_POST['link_before_html'])); |
|
510 $after_html = strval(trim($_POST['link_after_html'])); |
|
511 |
|
512 if ( !$session->get_permissions('php_in_pages') ) |
|
513 { |
|
514 // Not allowed to embed PHP and Javascript |
|
515 $before_html = sanitize_html($before_html); |
|
516 $after_html = sanitize_html($after_html); |
|
517 $inner_html = sanitize_html($inner_html); |
|
518 } |
|
519 |
|
520 $sanitized = array( |
|
521 'link_name' => $db->escape($link_name), |
|
522 'link_target' => $db->escape($link_target), |
|
523 'link_inner_html' => $db->escape($inner_html), |
|
524 'link_before_html' => $db->escape($before_html), |
|
525 'link_after_html' => $db->escape($after_html) |
|
526 ); |
|
527 |
|
528 $sql = "UPDATE ".table_prefix."linkchomper SET link_name='{$sanitized['link_name']}',link_href='{$sanitized['link_target']}',link_inner_html='{$sanitized['link_inner_html']}',link_before_html='{$sanitized['link_before_html']}',link_after_html='{$sanitized['link_after_html']}',link_flags=$flags WHERE link_id=$link_id;"; |
|
529 if ( !$db->sql_query($sql) ) |
|
530 $db->_die(); |
|
531 |
|
532 echo '<div class="info-box">Your changes have been saved.</div>'; |
|
533 break; |
|
534 } |
|
535 } |
|
536 else if ( isset($stage2['cancel']) ) |
|
537 { |
|
538 break; |
|
539 } |
|
540 else |
|
541 { |
|
542 echo 'Undefined Superform handler:<pre>' . htmlspecialchars(print_r($stage2, true)) . '</pre>'; |
|
543 } |
|
544 if ( $err_and_revert['error'] ) |
|
545 { |
|
546 $editor = new LinkchomperFormGenerator(); |
|
547 $editor->error = $err_and_revert['message']; |
|
548 $editor->track_clicks = ( isset($_POST['track_clicks']) && !isset($_POST['raw_html']) ); |
|
549 $editor->raw_html = ( isset($_POST['raw_html']) && !isset($_POST['track_clicks']) ); |
|
550 $editor->link_flag_image = ( $_POST['link_flag_img'] == '1' ); |
|
551 $editor->link_disabled = ( isset($_POST['link_disabeld']) ); |
|
552 $editor->link_target = $_POST['link_target']; |
|
553 $editor->link_name = $_POST['link_name']; |
|
554 $editor->mode = ( isset($stage2['create_new_finish']) ) ? LC_CREATE : LC_EDIT; |
|
555 $editor->inner_html = $_POST['link_inner_html']; |
|
556 $editor->before_html = $_POST['link_before_html']; |
|
557 $editor->after_html = $_POST['link_after_html']; |
|
558 $editor->link_id = ( isset($stage2['create_new_finish']) ) ? -1 : intval($_POST['link_id']); |
|
559 $editor->echo_html(); |
|
560 } |
|
561 return true; |
|
562 } |
|
563 } |
|
564 |
|
565 echo <<<EOF |
|
566 <h3>Linkchomper link manager</h3> |
|
567 <p>Linkchomper is a plugin that allows you to add custom content to the "Links" block on your sidebar. You can add tracking links, raw HTML, or just normal links.</p> |
|
568 EOF; |
|
569 |
|
570 echo '<form name="main" action="'.makeUrlNS('Admin', 'Linkchomper').'" method="post">'; |
|
571 echo '<div class="tblholder"> |
|
572 <table border="0" cellspacing="1" cellpadding="4"> |
|
573 <tr> |
|
574 <th>Link name</th> |
|
575 <th>Link target</th> |
|
576 <th>Clicks</th> |
|
577 <th colspan="4" style="width: 50px;">Admin</th> |
|
578 </tr>'; |
|
579 |
|
580 $q = $db->sql_query('SELECT link_id, link_name, link_href, link_flags, link_clicks, link_order FROM '.table_prefix.'linkchomper ORDER BY link_order ASC;'); |
|
581 |
|
582 if ( !$q ) |
|
583 $db->_die(); |
|
584 |
|
585 $num_rows = $db->numrows(); |
|
586 $i = 0; |
|
587 |
|
588 if ( $row = $db->fetchrow() ) |
|
589 { |
|
590 do { |
|
591 echo '<tr>'; |
|
592 echo '<td class="row1">' . htmlspecialchars($row['link_name']) . '</td>'; |
|
593 echo '<td class="row2">' . ( ( $row['link_flags'] & LC_LINK_RAW ) ? '<Raw HTML block>' : '<a href="' . htmlspecialchars($row['link_href']) . '" onclick="window.open(this.href); return false;">' . htmlspecialchars($row['link_href']) . '</a>' ) . '</td>'; |
|
594 echo '<td class="row1" style="text-align: center;">' . ( ( $row['link_flags'] & LC_LINK_TRACK_CLICKS ) ? $row['link_clicks'] : '' ) . '</td>'; |
|
595 // Admin actions |
|
596 echo '<td class="row2" style="text-align: center;"><button ' . ( ( $i == 0 ) ? 'disabled="disabled"' : '' ) . ' name="action[move_up][' . $row['link_id'] . ']">↑</button></td>'; |
|
597 echo '<td class="row1" style="text-align: center;"><button ' . ( ( $i + 1 == $num_rows ) ? 'disabled="disabled"' : '' ) . ' name="action[move_down][' . $row['link_id'] . ']">↓</button></td>'; |
|
598 echo '<td class="row2" style="text-align: center;"><button name="stage2[edit][' . $row['link_id'] . ']">Edit</button></td>'; |
|
599 echo '<td class="row1" style="text-align: center;"><button name="stage2[delete][' . $row['link_id'] . ']">Delete</button></td>'; |
|
600 echo '</tr>'; |
|
601 $i++; |
|
602 } while ( $row = $db->fetchrow() ); |
|
603 } |
|
604 else |
|
605 { |
|
606 echo '<tr> |
|
607 <td class="row1" colspan="7"> |
|
608 You haven\'t created any links yet. |
|
609 </td> |
|
610 </tr>'; |
|
611 } |
|
612 |
|
613 echo '<tr style="text-align: center;"> |
|
614 <th class="subhead" colspan="7"> |
|
615 <button name="stage2[create_new]"><b>Create new link</b></button> |
|
616 </th> |
|
617 </tr>'; |
|
618 |
|
619 echo '</table></div>'; |
|
620 echo '</form>'; |
|
621 |
|
622 // */ |
|
623 |
|
624 } |
|
625 |
|
626 // Hopefully no one will ever get 4 billion links in their sidebar. |
|
627 define('LC_ADMIN_ORDER_LAST', ( pow(2, 33)-3 )); |
|
628 |
|
629 /** |
|
630 * Class to generate edit forms for Linkchomper links. |
|
631 * @package Enano |
|
632 * @subpackage Linkchomper |
|
633 * @license GNU General Public License <http://www.gnu.org/licenses/gpl.html> |
|
634 */ |
|
635 |
|
636 class LinkchomperFormGenerator |
|
637 { |
|
638 |
|
639 /** |
|
640 * What this editor instance does, create or edit. Should be LC_EDIT or LC_CREATE. |
|
641 * @var int |
|
642 */ |
|
643 |
|
644 var $mode = LC_CREATE; |
|
645 |
|
646 /** |
|
647 * The name of the link. |
|
648 * @var string |
|
649 */ |
|
650 |
|
651 var $link_name = ''; |
|
652 |
|
653 /** |
|
654 * Link ID - only used when editing |
|
655 * @var int |
|
656 */ |
|
657 |
|
658 var $link_id = -1; |
|
659 |
|
660 /** |
|
661 * Flag for raw HTML switch |
|
662 * @var bool |
|
663 */ |
|
664 |
|
665 var $raw_html = false; |
|
666 |
|
667 /** |
|
668 * Flag for inner HTML field is an image URL |
|
669 * @var bool |
|
670 */ |
|
671 |
|
672 var $image_url = false; |
|
673 |
|
674 /** |
|
675 * Flag to determine if clicks will be tracked |
|
676 * @var bool |
|
677 */ |
|
678 |
|
679 var $track_clicks = false; |
|
680 |
|
681 /** |
|
682 * "Appear after" (link order) |
|
683 * @var int The link ID to appear after |
|
684 */ |
|
685 |
|
686 var $appear_after = LC_ADMIN_ORDER_LAST; |
|
687 |
|
688 /** |
|
689 * Link target. |
|
690 * @var string |
|
691 */ |
|
692 |
|
693 var $link_target = 'http://www.example.com/'; |
|
694 |
|
695 /** |
|
696 * If the image flag is on, this should be set to true. Should only be used while editing. |
|
697 * @var bool |
|
698 */ |
|
699 |
|
700 var $link_flag_image = false; |
|
701 |
|
702 /** |
|
703 * Set to true if the link is disabled (hidden) |
|
704 * @var bool |
|
705 */ |
|
706 |
|
707 var $link_disabled = false; |
|
708 |
|
709 /** |
|
710 * The inner HTML (or image URL) |
|
711 * @var string |
|
712 */ |
|
713 |
|
714 var $inner_html = ''; |
|
715 |
|
716 /** |
|
717 * HTML shown before the link |
|
718 * @var string |
|
719 */ |
|
720 |
|
721 var $before_html = ''; |
|
722 |
|
723 /** |
|
724 * HTML shown after the link |
|
725 * @var string |
|
726 */ |
|
727 |
|
728 var $after_html = ''; |
|
729 |
|
730 /** |
|
731 * Unique identifier used for Javascript bits |
|
732 * @var string |
|
733 * @access private |
|
734 */ |
|
735 |
|
736 var $uuid = ''; |
|
737 |
|
738 /** |
|
739 * Error message to show at the top of the form. Default is false for no error. |
|
740 * @var string |
|
741 */ |
|
742 |
|
743 var $error = ''; |
|
744 |
|
745 /** |
|
746 * Constructor. |
|
747 */ |
|
748 |
|
749 function __construct() |
|
750 { |
|
751 $uuid = md5( mt_rand() . microtime() . @file_get_contents('/proc/uptime') /* That last one's just for fun ;-) */ ); |
|
752 if ( file_exists('/dev/urandom') ) |
|
753 { |
|
754 $f = @fopen('/dev/urandom', 'r'); |
|
755 if ( $f ) |
|
756 { |
|
757 $random = fread($f, 16); |
|
758 $random = hexencode($random, '', ''); |
|
759 fclose($f); |
|
760 $uuid = $random; |
|
761 } |
|
762 } |
|
763 $this->uuid = $uuid; |
|
764 } |
|
765 |
|
766 /** |
|
767 * PHP 4 constructor |
|
768 */ |
|
769 |
|
770 function LinkchomperFormGenerator() |
|
771 { |
|
772 $this->__construct(); |
|
773 } |
|
774 |
|
775 /** |
|
776 * Generates the ready to use HTML. |
|
777 * @return string |
|
778 */ |
|
779 |
|
780 function get_html() |
|
781 { |
|
782 global $db, $session, $paths, $template, $plugins; // Common objects |
|
783 |
|
784 if ( !empty($template->theme) && file_exists(ENANO_ROOT . '/themes/' . $template->theme . '/linkchomper_editor.tpl') ) |
|
785 { |
|
786 $parser = $template->makeParser('linkchomper_editor.tpl'); |
|
787 } |
|
788 else |
|
789 { |
|
790 $tpl_code = <<<EOF |
|
791 <!-- start of Linkchomper editor --> |
|
792 <script type="text/javascript"> |
|
793 // <![CDATA[ |
|
794 |
|
795 // Helper javascript code (uuid={UUID}) |
|
796 |
|
797 var check_box_raw_{UUID} = function() |
|
798 { |
|
799 var source = document.getElementById('raw_{UUID}'); |
|
800 if ( source.checked ) |
|
801 { |
|
802 var target = document.getElementById('trk_{UUID}'); |
|
803 target.checked = false; |
|
804 target.disabled = true; |
|
805 target = document.getElementById('lc_tr_url_{UUID}'); |
|
806 target.style.display = 'none'; |
|
807 target = document.getElementById('lc_tr_beforehtml_{UUID}'); |
|
808 target.style.display = 'none'; |
|
809 target = document.getElementById('lc_tr_afterhtml_{UUID}'); |
|
810 target.style.display = 'none'; |
|
811 } |
|
812 else |
|
813 { |
|
814 var target = document.getElementById('trk_{UUID}'); |
|
815 target.disabled = false; |
|
816 target = document.getElementById('lc_tr_url_{UUID}'); |
|
817 target.style.display = null; |
|
818 target = document.getElementById('lc_tr_beforehtml_{UUID}'); |
|
819 target.style.display = null; |
|
820 target = document.getElementById('lc_tr_afterhtml_{UUID}'); |
|
821 target.style.display = null; |
|
822 } |
|
823 } |
|
824 |
|
825 var check_box_trk_{UUID} = function() |
|
826 { |
|
827 var source = document.getElementById('trk_{UUID}'); |
|
828 if ( source.checked ) |
|
829 { |
|
830 var target = document.getElementById('raw_{UUID}'); |
|
831 target.checked = false; |
|
832 target.disabled = true; |
|
833 } |
|
834 else |
|
835 { |
|
836 var target = document.getElementById('raw_{UUID}'); |
|
837 target.disabled = false; |
|
838 } |
|
839 } |
|
840 |
|
841 var radio_set_image_{UUID} = function() |
|
842 { |
|
843 var source = document.getElementById('is_img_{UUID}'); |
|
844 if ( source.checked ) |
|
845 { |
|
846 var target; |
|
847 target = document.getElementById('inner_html_{UUID}'); |
|
848 target.style.display = 'none'; |
|
849 target = document.getElementById('inner_img_{UUID}'); |
|
850 target.style.display = 'block'; |
|
851 } |
|
852 else |
|
853 { |
|
854 var target; |
|
855 target = document.getElementById('inner_html_{UUID}'); |
|
856 target.style.display = 'block'; |
|
857 target = document.getElementById('inner_img_{UUID}'); |
|
858 target.style.display = 'none'; |
|
859 } |
|
860 } |
|
861 |
|
862 addOnloadHook(check_box_raw_{UUID}); |
|
863 addOnloadHook(check_box_trk_{UUID}); |
|
864 addOnloadHook(radio_set_image_{UUID}); |
|
865 |
|
866 // ]]> |
|
867 </script> |
|
868 <!-- BEGIN show_error --> |
|
869 <div class="error-box"> |
|
870 <b>The following error occurred while <!-- BEGIN mode_is_create -->creating the link<!-- BEGINELSE mode_is_create -->saving your changes<!-- END mode_is_create -->:</b><br /> |
|
871 {ERROR_MESSAGE} |
|
872 </div> |
|
873 <!-- END show_error --> |
|
874 <form action="{FORM_ACTION}" method="post" enctype="multipart/form-data"> |
|
875 <div class="tblholder"> |
|
876 <table border="0" cellspacing="1" cellpadding="4"> |
|
877 <tr> |
|
878 <th colspan="2"> |
|
879 <!-- BEGIN mode_is_create --> |
|
880 Create new link |
|
881 <!-- END mode_is_create --> |
|
882 <!-- BEGIN mode_is_edit --> |
|
883 Editing link: {LINK_NAME} |
|
884 <!-- END mode_is_edit --> |
|
885 </th> |
|
886 </tr> |
|
887 <tr> |
|
888 <td class="row1" style="width: 33%;"> |
|
889 <label for="ln_{UUID}">Link title:</label><br /> |
|
890 <small>This is only used "internally" for your convenience - the user never sees this value.</small> |
|
891 </td> |
|
892 <td class="row2"> |
|
893 <input id="ln_{UUID}" name="link_name" value="{LINK_NAME}" type="text" size="50" /> |
|
894 </td> |
|
895 </tr> |
|
896 <tr> |
|
897 <td class="row1" style="width: 33%;"> |
|
898 Link options: |
|
899 </td> |
|
900 <td class="row2"> |
|
901 <p><label><input type="checkbox" name="raw_html" id="raw_{UUID}" onclick="check_box_raw_{UUID}();" <!-- BEGIN raw_html -->checked="checked"<!-- END raw_html --> /> Use my own custom HTML here and bypass Linkchomper's processor</label></p> |
|
902 <p><label><input type="checkbox" name="track_clicks" id="trk_{UUID}" onclick="check_box_trk_{UUID}();" <!-- BEGIN track_clicks -->checked="checked"<!-- END track_clicks --> /> Track clicks</label></p> |
|
903 <p><label><input type="checkbox" name="link_disabled" <!-- BEGIN link_disabled -->checked="checked" <!-- END link_disabled -->/> Link is disabled</label></p> |
|
904 </td> |
|
905 </tr> |
|
906 <tr id="lc_tr_url_{UUID}"> |
|
907 <td class="row1"> |
|
908 Link target:<br /> |
|
909 <small>This should be in the format of http://url.</small> |
|
910 </td> |
|
911 <td class="row2"> |
|
912 <input type="text" name="link_target" value="{LINK_TARGET}" size="50" /> |
|
913 </td> |
|
914 </tr> |
|
915 <tr id="lc_tr_innerhtml_{UUID}"> |
|
916 <td class="row1"> |
|
917 Content inside link:<br /> |
|
918 <small>You may use HTML here.</small> |
|
919 </td> |
|
920 <td class="row2"> |
|
921 Use inside link: <label><input id="is_img_{UUID}" onclick="radio_set_image_{UUID}();" type="radio" name="link_flag_img" value="1" <!-- BEGIN link_flag_image -->checked="checked" <!-- END link_flag_image -->/> Image</label> <label><input type="radio" onclick="radio_set_image_{UUID}();" name="link_flag_img" value="0" <!-- BEGINNOT link_flag_image -->checked="checked" <!-- END link_flag_image -->/> Text or HTML</label> |
|
922 <div id="inner_img_{UUID}" style="margin-top: 10px;"> |
|
923 Path to image, relative or absolute:<br /> |
|
924 <input type="text" size="50" name="link_img_path" value="<!-- BEGIN link_flag_image -->{HTML_INNER}<!-- END link_flag_image -->" onblur="document.getElementById('link_img_preview_{UUID}').src = this.value;" /><br /> |
|
925 <br /> |
|
926 <img alt=" " src="about:blank" id="link_img_preview_{UUID}" /> |
|
927 </div> |
|
928 <div id="inner_html_{UUID}" style="margin-top: 10px;"> |
|
929 {TEXTAREA_HTML_INNER} |
|
930 </div> |
|
931 </td> |
|
932 </tr> |
|
933 <tr id="lc_tr_beforehtml_{UUID}"> |
|
934 <td class="row1"> |
|
935 Text <u>before</u> link:<br /> |
|
936 <small>You may use HTML here.</small> |
|
937 </td> |
|
938 <td class="row2"> |
|
939 {TEXTAREA_HTML_BEFORE} |
|
940 </td> |
|
941 </tr> |
|
942 <tr id="lc_tr_afterhtml_{UUID}"> |
|
943 <td class="row1"> |
|
944 Text <u>after</u> link:<br /> |
|
945 <small>You may use HTML here.</small> |
|
946 </td> |
|
947 <td class="row2"> |
|
948 {TEXTAREA_HTML_AFTER} |
|
949 </td> |
|
950 </tr> |
|
951 <tr> |
|
952 <th class="subhead" colspan="2"> |
|
953 <!-- BEGIN mode_is_create --> |
|
954 <input type="submit" name="stage2[create_new_finish]" value="Create link" /> |
|
955 <!-- END mode_is_create --> |
|
956 <!-- BEGIN mode_is_edit --> |
|
957 <input type="submit" name="stage2[edit_finish]" value="Save changes" /> |
|
958 <!-- END mode_is_edit --> |
|
959 <input type="submit" name="stage2[cancel]" value="Cancel" style="font-weight: normal;" /> |
|
960 </th> |
|
961 </tr> |
|
962 </table> |
|
963 </div> |
|
964 <!-- BEGIN mode_is_edit --> |
|
965 <input type="hidden" name="link_id" value="{LINK_ID}" /> |
|
966 <!-- END mode_is_edit --> |
|
967 </form> |
|
968 <!-- finish of Linkchomper editor --> |
|
969 EOF; |
|
970 $parser = $template->makeParserText($tpl_code); |
|
971 } |
|
972 |
|
973 $form_action = makeUrlNS('Admin', 'Linkchomper'); |
|
974 |
|
975 $sanitized = array( |
|
976 'name' => &$this->link_name, |
|
977 'target' => &$this->link_target, |
|
978 'inner' => &$this->inner_html, |
|
979 'before' => &$this->before_html, |
|
980 'after' => &$this->after_html |
|
981 ); |
|
982 |
|
983 foreach ( $sanitized as $id => $item ) |
|
984 { |
|
985 unset($sanitized[$id]); |
|
986 $sanitized[$id] = htmlspecialchars($item); |
|
987 } |
|
988 |
|
989 $textarea_html_inner = $template->tinymce_textarea('link_inner_html', $sanitized['inner'], 10, 60); |
|
990 $textarea_html_before = $template->tinymce_textarea('link_before_html', $sanitized['before'], 10, 60); |
|
991 $textarea_html_after = $template->tinymce_textarea('link_after_html', $sanitized['after'], 10, 60); |
|
992 |
|
993 if ( $this->mode == LC_EDIT ) |
|
994 { |
|
995 $parser->assign_vars(array( |
|
996 'LINK_ID' => $this->link_id |
|
997 )); |
|
998 } |
|
999 |
|
1000 $parser->assign_vars(array( |
|
1001 'UUID' => $this->uuid, |
|
1002 'FORM_ACTION' => $form_action, |
|
1003 'LINK_NAME' => $sanitized['name'], |
|
1004 'LINK_TARGET' => $sanitized['target'], |
|
1005 'HTML_INNER' => $sanitized['inner'], |
|
1006 'HTML_BEFORE' => $sanitized['before'], |
|
1007 'HTML_AFTER' => $sanitized['after'], |
|
1008 'TEXTAREA_HTML_INNER' => $textarea_html_inner, |
|
1009 'TEXTAREA_HTML_BEFORE' => $textarea_html_before, |
|
1010 'TEXTAREA_HTML_AFTER' => $textarea_html_after, |
|
1011 'ERROR_MESSAGE' => strval($this->error) |
|
1012 )); |
|
1013 $parser->assign_bool(array( |
|
1014 'raw_html' => $this->raw_html, |
|
1015 'track_clicks' => $this->track_clicks, |
|
1016 'mode_is_create' => ( $this->mode == LC_CREATE ), |
|
1017 'mode_is_edit' => ( $this->mode == LC_EDIT ), |
|
1018 'show_error' => ( !empty($this->error) ), |
|
1019 'link_flag_image' => $this->link_flag_image, |
|
1020 'link_disabled' => $this->link_disabled |
|
1021 )); |
|
1022 |
|
1023 $html = $parser->run(); |
|
1024 |
|
1025 return $html; |
|
1026 |
|
1027 } |
|
1028 |
|
1029 /** |
|
1030 * For convenience. Echoes out HTML. |
|
1031 */ |
|
1032 |
|
1033 function echo_html() |
|
1034 { |
|
1035 echo $this->get_html(); |
|
1036 } |
|
1037 |
|
1038 } |
|
1039 |
|
1040 ?> |