plugins/Linkchomper.php
changeset 0 df77b4db90d7
child 1 1666d776fa27
equal deleted inserted replaced
-1:000000000000 0:df77b4db90d7
       
     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 ) ? '&lt;Raw HTML block&gt;' : '<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'] . ']">&uarr;</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'] . ']">&darr;</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 ?>