<?php
/*
Plugin Name: Shoutbox
Version: 1.7
Plugin URI: http://waikay.net/2005/03/plugin-shoutbox/
Author: Leong Wai Kay
Author URI: http://waikay.net
Description: Adds a shoutbox to your blog

Change log:
1.8
 - Fixed error display bug.
 - Post to the shoutbox now truely sends the shout messages through the WP comment approval system, making it work with any spam plugins.

1.7
 - Fixed the bug of email not being saved.
 - Updated the verification process to comply with Wordpress 1.5.2 so shouts will be verified with comment plugins as well.

1.6
 - Fixed the bug of message disappearing when editing a shout.

1.5
 - Created an installation script so there is no need to manually run the initial SQL to create the tables.

1.4
 - Added in duplication post detection.
 - Option to display a number of shouts.
 - Added style to the header to put the shoutbox into a div frame. Remove it if you have your own CSS.

1.3
 - Fixed with updating cookies after headers are sent.

1.2
 - Form is now hidden and floats.
 - Shout entries can be completely managed thru the admin panel.

1.1b
 - Added new field to the database to allow hiding of entries
 - Administration added to edit or delete entries
 - Fixed bug when no entries in table

0.1
 - Initial release

INSTALLATION AND USUAGE
 Place the file as is into your plugin directory. Do not rename it.
 Under your wordpress admin panel, go to Manage > Shoutbox and click to install.
 To display the shoutbox on your blog simply place <?php shout_box() ?> where you want it to appear.
 You might want to edit the CSS to suit your layout.

*/

$tableshout $table_prefix.'shoutbox';

if (
is_plugin_page())
{
  require_once(
ABSPATH 'wp-config.php');

  
// check tables exist
  
$query "SELECT COUNT(*) FROM $tableshout";
  
$se $wpdb->show_errors;
  
$wpdb->hide_errors();
  
$exist $wpdb->get_var($query);
  
$wpdb->show_errors $se;

  if (
'' == $exist)
  {
    
// install tables
    
if (isset($_GET['install'])) {
      
$query "CREATE TABLE IF NOT EXISTS $tableshout (
        shout_ID int(11) NOT NULL auto_increment,
        shout_date datetime NOT NULL default '0000-00-00 00:00:00',
        shout_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
        author_name tinytext NOT NULL,
        author_email varchar(100) NOT NULL default '',
        author_url varchar(200) NOT NULL default '',
        author_IP varchar(15) NOT NULL default '',
        shout_content text NOT NULL,
        shout_status enum('normal','deleted') NOT NULL default 'normal',
        PRIMARY KEY  (shout_ID)
      ) TYPE=MyISAM"
;
      
$wpdb->query($query);
      
$wpdb->query("INSERT INTO $tableshout VALUES (1, '".current_time('mysql')."', '".current_time('mysql'1)."', 'Wai Kay', '', 'http://www.waikay.net', '', 'Hi! Your shoutbox is working fine!', '')");
      echo 
"<div class='wrap'><h2>Installation Completed</h2>
        <p>To display the shoutbox simply place <?php shout_box() ?> where you want it to appear. You might want to edit the CSS to suit your layout.</p>
        </div>"
;
    }
    else
      echo 
"<div class='wrap'>
        <h2>Install Shoutbox</h2>
        <p>Shoutbox has not been installed. <a href='admin.php?page=wp-shoutbox.php&install=yes'>Click to install shoutbox</a>.</p>
        </div>"
;
  }

  
// edit request
  
else if (isset($_GET['editshout'])) {
    
$shout_id $_GET['editshout'];

    if (isset(
$_POST['submit'])) {
      
$ss_name trim(strip_tags($_POST['ss_name']));
            
$ss_email trim(strip_tags($_POST['ss_email']));
      
$ss_url trim(strip_tags($_POST['ss_url']));
      
$ss_url = ((!stristr($ss_url'://')) && ($ss_url != '')) ? 'http://'.$ss_url $ss_url;
      
$ss_content trim($_POST['ss_content']);
      
$ss_content balanceTags($ss_content1);
      
$ss_content format_to_post($ss_content);
      
$ss_content apply_filters('post_comment_text'$ss_content);
      
$ss_status $_POST['ss_status'];

      
$query "UPDATE $tableshout SET author_name='$ss_name', author_email='$ss_email', author_url='$ss_url', shout_content='$ss_content', shout_status='$ss_status'
          WHERE shout_ID = '$shout_id' LIMIT 1"
;
      
$wpdb->query($query);
      echo 
'<div class="updated"><p>Shout <strong>edited</strong>.</p></div>';
    }

    
$query "SELECT author_name, author_email, author_url, author_ip, shout_content, shout_status FROM $tableshout WHERE shout_ID='$shout_id'";
    
$shouts $wpdb->get_results($query);
    if (
$shouts)
    {
      
$ss_name $shouts[0]->author_name;
      
$ss_email $shouts[0]->author_email;
      
$ss_url $shouts[0]->author_url;
      
$ss_ip $shouts[0]->author_ip;
      
$ss_content $shouts[0]->shout_content;
      if (
$shouts[0]->shout_status == "deleted")
      {
        
$ss_show '';
        
$ss_hidden 'checked="checked"';
      }
      else
      {
        
$ss_show 'checked="checked"';
        
$ss_hidden '';
      }

      
// display the form
      
?>
      <form method="POST" action="admin.php?page=wp-shoutbox.php&editshout=<?=$shout_id?>" name="shoutbox">
      <div class="wrap">
        <h2>Edit Shoutbox Entry</h2>
        <p>

          <fieldset id="namediv">
              <legend>Name:</legend>
            <div>
              <input type="text" name="ss_name" size="22" value="<?=$ss_name?>" tabindex="1"/>
              </div>
          </fieldset>
          <fieldset id="emaildiv">
                  <legend>E-mail:</legend>

              <div>
                <input type="text" name="ss_email" size="30" value="<?=$ss_email?>" tabindex="2"/>
              </div>
          </fieldset>
          <fieldset id="uridiv">
                  <legend>URI:</legend>
              <div>
                <input type="text" name="ss_url" size="35" value="<?=$ss_url?>" tabindex="3">
              </div>

          </fieldset>
          <fieldset style="clear: both;">
                  <legend>Message</legend>
              <textarea name ="ss_content" rows="9" cols="40" tabindex="4" tabindex="5" style="width: 99%"><?=$ss_content?></textarea></br>
          </fieldset>

          <p class="submit"><input type="submit" name="submit" value="Edit &raquo;" style="font-weight: bold;" tabindex="6" /></p>
        </p>
      </div>
      <div class="wrap">
        <h2>Advanced</h2>
        <table width="100%" cellspacing="2" cellpadding="5" class="editform">
          <tr>
            <th scope="row" valign="top">Entry Status:</th>
            <td><label for="entry_show" class="selectit"><input name="ss_status" type="radio" value="normal" <?=$ss_show?>/> Shown</label><br />
            <label for="entry_hide" class="selectit"><input name="ss_status" type="radio" value="deleted" <?=$ss_hidden?>/> Hidden</label><br />
          </tr>
<!--
          <tr>
            <th scope="row">Edit time:</th>
            <td><fieldset><legend><input type="checkbox" class="checkbox" name="edit_date" value="1" id="timestamp"  /> <label for="timestamp">Edit timestamp</label></legend><select name="mm">
              <option value="1">January</option>
              <option value="2">February</option>

              <option value="3">March</option>
              <option value="4" selected='selected'>April</option>
              <option value="5">May</option>
              <option value="6">June</option>
              <option value="7">July</option>
              <option value="8">August</option>

              <option value="9">September</option>
              <option value="10">October</option>
              <option value="11">November</option>
              <option value="12">December</option>
        </select>
        <input type="text" name="jj" value="05" size="2" maxlength="2" />
        <input type="text" name="aa" value="2005" size="4" maxlength="5" /> @
        <input type="text" name="hh" value="19" size="2" maxlength="2" /> :

        <input type="text" name="mn" value="09" size="2" maxlength="2" />
        <input type="hidden" name="ss" value="39" size="2" maxlength="2" /> Existing timestamp: April 05, 2005 @ 19:09</fieldset>
          </td>
          </tr>
-->
          <tr>
            <th scope="row">Delete:</th>
            <td><p><a class="delete" href="admin.php?page=wp-shoutbox.php&deleteshout=<?=$shout_id?>">Delete entry</a></p></td>

          </tr>
        </table>
      </div>
    </form>
    <?
    
}
    else
    {
      
?>
      <div class="wrap">
        <h2>Edit Shoutbox Entry</h2>
        <p>Invalid entry ID</p>
      </div>
      <?
    
}
  }
  else
  {
    if (isset(
$_GET['deleteshout']))
    {
      
$shout_id $_GET['deleteshout'];
      
$query "DELETE FROM $tableshout WHERE shout_ID = '$shout_id' LIMIT 1";
      
$done $wpdb->query($query);
      if (
$done) echo '<div class="updated"><h2>Delete Shoutbox Entry</h2><p>Entry deleted!</p></div>';
      else echo 
'<div class="updated"><h2>Delete Shoutbox Entry</h2><p>No such entry!</p></div>';
    }

    if (isset(
$_GET['noofshout']))
    {
      
update_option('shoutbox_shouts'$_GET['noofshout']);
      echo 
'<div class="updated"><p>Shouts to display <strong>updated</strong></p></div>';
    }

    unset(
$where);
    
$limit "LIMIT 0,20";
    echo 
"<div class='wrap'>";
    if(isset(
$_GET['m']))
    {
      
$_GET['m'] = (int) $_GET['m'];
      echo 
'<h2>' $month[substr$_GET['m'], 4)]." ".substr$_GET['m'], 0)."</h2>";
      
$where "WHERE MONTH(shout_date) = '".substr($_GET['m'], 42)."'";
      
$limit '';
    }
    else
      echo 
"<h2>Last 20 Shouts</h2>";
?>
<form name="viewmonth" action="" method="get" style="float: left; width: 20em;">
    <fieldset>
    <legend><?php _e('Show Posts From Month of...'?></legend>
    <select name='m'>
    <?php
        $arc_result
=$wpdb->get_results("SELECT DISTINCT YEAR(shout_date) AS yyear, MONTH(shout_date) AS mmonth FROM $tableshout ORDER BY shout_date DESC");
        foreach (
$arc_result as $arc_row) {
            
$arc_year  $arc_row->yyear;
            
$arc_month $arc_row->mmonth;

            if( isset(
$_GET['m']) && $arc_year zeroise($arc_month2) == $_GET['m'] )
                
$default 'selected="selected"';
            else
                
$default null;

            echo 
"<option $default value=\"" $arc_year.zeroise($arc_month2) . '">';
            echo 
$month[zeroise($arc_month2)] . " $arc_year";
            echo 
"</option>\n";
        }
    
?>
    </select>
        <input type="submit" name="submit" value="<?php _e('Show Month'?>"  />
    </fieldset>
  <input type="hidden" name="page" value="wp-shoutbox.php"/>
</form>
<form name="showshouts" action="" method="get" style="float: left; width: 10em;">
  <fieldset>
  <legend># of shouts displayed...</legend>
  <input type="text" name="noofshout" value="<?php echo get_option('shoutbox_shouts'); ?>" size="3" /> <input type="submit" name="submit" value="Update" />
  <input type="hidden" name="page" value="wp-shoutbox.php"/>
  </fieldset>
</form>
<br style='clear:both;' />
<?php
    
// load the last 20 shouts
    
$shouts $wpdb->get_results("SELECT * FROM $tableshout $where ORDER BY shout_date DESC $limit");
    if (
$shouts)
    {
      echo 
"<ol class='commentlist'>";
      
$i 0;
      foreach (
$shouts as $shout)
      {
        
$shout_datetime mysql2date('j M y, H:i'$shout->shout_date);
        
$shout_content apply_filters('comment_text'$shout->shout_content);
        
?>
        <li class="<?php echo ($i++ % == 'alternate' '').($shout->shout_status == "deleted" ' unapproved' :'');?>">
        <p><strong><?php _e('Name:'?></strong> <?php echo $shout->author_name; if ($shout->author_email) { ?>| <strong><?php _e('Email:'?></strong> <?=$shout->author_email?> <?php } if ($shout->author_url) { ?> | <strong><?php _e('URI:'?></strong> <?=$shout->author_url?> <?php ?>| <strong><?php _e('IP:'?></strong> <a href="http://ws.arin.net/cgi-bin/whois.pl?queryinput=<?=$shout->author_IP?>"><?=$shout->author_IP ?></a></p>
        <?=$shout_content?>
        <p><?php _e('Posted'); echo " $shout_datetime"?> | <a href='admin.php?page=wp-shoutbox.php&editshout=<?=$shout->shout_ID?>'>Edit</a> | <a href="admin.php?page=wp-shoutbox.php&deleteshout=<?=$shout->shout_ID?>">Delete</a></p>
        </li>
        <?php
      
}
      echo 
'</ol>';
    }
    else
      echo 
'<p>There are currently no entries</p>';

    echo 
"</div>";
  }
}
else
{
  
// config variables
  // $tableshout = $table_prefix.'shoutbox_test';
  // Check for post processing here
  
$spam_time 20;

  
// Process input if any
  
function shoutbox_init()
  {
    global 
$wpdb$tableshout$table_prefix$sb_error_text;

        
// Sometimes the comment plugins will kill the process before we can post the shout
        // So here we seach in the comment table and extract out any approved shouts we find and for now delete the rest
        
$wpdb->query("DELETE FROM $wpdb->comments WHERE comment_type = 'shoutbox' AND comment_post_ID = '-1' AND comment_approved = 'spam'");

        
//$result = $wpdb->query("SELECT comment_author, comment_author_email, comment_author_url, comment_author_IP, comment_date, comment_date_gmt, comment_content, comment_approved FROM $wpdb->comments WHERE comment_type = 'shoutbox' AND comment_approved = '1'");


    
if (isset($_POST['doshout']))
    {
      
$error false;
      
$sb_error_text "";

      
$ss_name trim(strip_tags($_POST['ss_name']));
      
$ss_url trim(strip_tags($_POST['ss_url']));
      
$ss_url = ((!stristr($ss_url'://')) && ($ss_url != '')) ? 'http://'.$ss_url $ss_url;
      if (
strlen($ss_url) < 7)
          
$ss_url '';
      
$ss_email trim($_POST['ss_email']);
      
$ss_content trim($_POST['ss_content']);
      
$ss_ip $_SERVER['REMOTE_ADDR'];

      if (empty(
$ss_name))
      {
        
$error true;
        
$sb_error_text "Name Required!<br/>";
      }

      if (empty(
$ss_content))
      {
        
$error true;
        
$sb_error_text .= "Message is Empty!</br>";
      }

      
// no errors found.
      
if (!$error)
      {
        
$now current_time('mysql');
        
$now_gmt current_time('mysql'1);
        
// Simple flood-protection
        
$lasttime $wpdb->get_var("SELECT shout_date FROM $tableshout WHERE author_IP = '$ss_ip' ORDER BY shout_date DESC LIMIT 1");
        if (!empty(
$lasttime)) {
          
$time_lastcommentmysql2date('U'$lasttime);
          
$time_newcommentmysql2date('U'$now);
          if ((
$time_newcomment $time_lastcomment) < $spam_time)
          {
            
$error true;
            
$sb_error_text "Spam prevention! You can only post after $spam_time seconds";
          }
        }
      }

      if (!
$error)
      {
        
// format the post
        
$ss_content balanceTags($ss_content1);
        
$ss_content format_to_post($ss_content);
        
$ss_content apply_filters('post_comment_text'$ss_content);

        
// Check for duplicate posts
        
$duplicate $wpdb->get_var("SELECT shout_date FROM $tableshout WHERE author_name = '$ss_name' AND author_url = '$ss_url' AND author_email = '$ss_email' AND shout_content LIKE '$ss_content'  ORDER BY shout_date DESC LIMIT 0,1");
        if (!empty(
$duplicate)) {
          
$time_lastcommentmysql2date('U'$duplicate);
          
$time_newcommentmysql2date('U'$now);
          if ((
$time_newcomment $time_lastcomment) < 86400)
          {
            
$error true;
            
$sb_error_text "Message already posted!";
          }
        }
      }

      if (!
$error)
      {
        
// check of approval
        
$shoutdata = array(
          
'comment_author' => $ss_name,
          
'comment_author_email' => $ss_email,
          
'comment_author_url' => $ss_url,
          
'comment_content' => $ss_content
        
);

        
$shoutdata apply_filters('preprocess_comment'$shoutdata);
        
extract($shoutdata);

        
$user_id apply_filters('pre_user_id'$user_ID);
        
$ss_name  apply_filters('pre_comment_author_name'$comment_author);
        
$ss_email   apply_filters('pre_comment_author_email'$comment_author_email);
        
$ss_url     apply_filters('pre_comment_author_url'$comment_author_url);
        
$ss_content apply_filters('pre_comment_content'$comment_content);
        
$ss_ip     apply_filters('pre_comment_user_ip'$ss_ip);
                
$user_agent  apply_filters('pre_comment_user_agent'$_SERVER['HTTP_USER_AGENT']);

/*
        if(!check_comment($ss_name, $ss_email, $ss_url, $ss_content, $ss_ip, '', '')) {
          $error = true;
          $sb_error_text .= "Post not approved! Please contact administrator";
        }
*/

                //spam protection
                
if ( $userdata && ( $user_id == $post_author || $userdata->user_level >= ) ) {
                    
$approved 1;
                } else {
                    if ( 
check_comment($ss_name$ss_email$ss_url$ss_content$ss_ip'''') )
                        
$approved 1;
                    else
                        
$approved 0;
                    if ( 
wp_blacklist_check($ss_name$ss_email$ss_url$ss_content$ss_ip$user_agent) )
                        
$approved 'spam';
                }

                
$approved apply_filters('pre_comment_approved'$approved);

                
$result $wpdb->query("INSERT INTO $wpdb->comments
                (comment_post_ID, comment_author, comment_author_email, comment_author_url, comment_author_IP, comment_date, comment_date_gmt, comment_content, comment_approved, comment_agent, comment_type, user_id)
                VALUES
                ('-1', '$ss_name', '$ss_email', '$ss_url', '$ss_ip', '$now', '$now_gmt', '$ss_content', '$approved', '$user_agent', 'shoutbox', '$user_id')
                "
);

                
// we insert the shoutbox comment as a real comment in WP to a fake postID.
                // This way we make use of any existing anti-spam plugin being used.
                
$comment_id $wpdb->insert_id;
                
do_action('comment_post'$comment_id$approved);

                
// because some plugins do not update the $approved correctly, we need to check the database
                
$approved $wpdb->get_var("SELECT comment_approved FROM $wpdb->comments WHERE comment_ID = '$comment_id' LIMIT 1");

                if (
'spam' == $approved ) { // If it's spam then void the post
                    
$error true;
          
$sb_error_text .= "Shout not approved or marked as spam! Please contact the administrator!";
                }
                else if (
'0' == $approved )
                {
                    
$error true;
                    
$sb_error_text .= "Your shout appears suspicious is flagged for moderation.";
                    
$ss_status 'spam';
                }
                else
                    
$ss_status 'normal';

                
// delete the extra comment
                
$wpdb->query("DELETE FROM $wpdb->comments WHERE comment_id = $comment_id");

                
// end spam protection
      
}

      
// no errors found. submit the post
      
if (!$error)
      {

        
$query "INSERT INTO $tableshout (shout_date, shout_date_gmt, author_name, author_email, author_url, author_IP, shout_content, shout_status)
                  VALUES ('$now', '$now_gmt', '$ss_name', '$ss_email', '$ss_url', '$ss_ip', '$ss_content', '$ss_status')"
;
        
$wpdb->query($query);
        
$ss_content "";

        
// Update comment cookies
        
setcookie('comment_author_' COOKIEHASHstripslashes($ss_name), time() + 30000000COOKIEPATH);
        
setcookie('comment_author_email_' COOKIEHASHstripslashes($ss_email), time() + 30000000COOKIEPATH);
        
setcookie('comment_author_url_' COOKIEHASHstripslashes($ss_url), time() + 30000000COOKIEPATH);
      }
    }
  }

  function 
shoutbox_admin_menu()
  {
    if (
function_exists('add_options_page')) {
      
add_management_page('Shoutbox''Shoutbox'5basename(__FILE__));
        }
  }


  function 
shout_box ()
  {
    global 
$wpdb$tableshout$user_level$sb_error_text;
    global 
$cookiehash;

    
$ss_name = (isset($_COOKIE['comment_author_'.$cookiehash])) ? trim($_COOKIE['comment_author_'.$cookiehash]) : '';
    
$ss_email = (isset($_COOKIE['comment_author_email_'.$cookiehash])) ? trim($_COOKIE['comment_author_email_'.$cookiehash]) : '';
    
$ss_url = (isset($_COOKIE['comment_author_url_'.$cookiehash])) ? trim($_COOKIE['comment_author_url_'.$cookiehash]) : '';

    
// Get the shouts
    
$limit get_option('shoutbox_shouts');
    
$limit = ($limit == '' "LIMIT 0, $limit");
    
$query "SELECT * FROM $tableshout ORDER BY shout_date DESC $limit";
    
$shouts $wpdb->get_results($query);

    
get_currentuserinfo();

    echo 
'<div id="shoutbox">';
    if (
$shouts)
      foreach (
$shouts as $shout)
      {
        if ((
$shout->shout_status == 'deleted') && $user_level 10) continue;
        
$shout_content apply_filters('comment_text'$shout->shout_content);
        if (
$shout->author_url == '')
          
$shout_author $shout->author_name;
        else
          
$shout_author '<a href="'.$shout->author_url.'">'.$shout->author_name.'</a>';
        
// set the time properly
        /*
        $timestamp = (strtotime($shout->shout_date));
        $shout_datetime = date('n M y, g:ia', $timestamp + (8 * 3600));
        */
        
$shout_datetime mysql2date('j M y, H:i'$shout->shout_date);

        
//display the shouts
        
echo '<div class="shoutentry"'.($shout->shout_status == 'deleted' ' style="color:#CCC;" >' '>');
        echo 
'<p class="author">'.$shout_author.'</p>';
        echo 
$shout_content;
        echo 
'<p class="date">on '.$shout_datetime.($user_level >= 10 ' <a href="'.get_settings('siteurl') . '/wp-admin/admin.php?page=wp-shoutbox.php&editshout='.$shout->shout_ID.'">edit</a>' '').'</p>';
        echo 
'</div>';
      }
    else
      echo 
'<p>There are currently no entries</p>';
    echo 
'</div>';

    if (!empty(
$sb_error_text)) echo "<div class='error'><b>Error!</b><br/>$sb_error_text</div>";
    
// display the form
    
?>
    <a href="javascript:void(null);" onclick="s_toggleDisplay(document.getElementById('shoutform'), this, 'Show Form &#9660;', 'Hide Form &#9650;');">Show Form &#9660;</a>
    <div id="shoutform" class="shoutform">
      <form method="post" action="<?=$_SERVER[PHP_SELF]?>" name="shoutbox">
      <p>Name</p><input type="text" name="ss_name" size="20" value="<?=$ss_name?>" />
      <p>Email</p><input type="text" name="ss_email" size="20" value="<?=$ss_email?>" />
      <p>URL</p><input type="text" name="ss_url" size="20" value="<?=$ss_url?>" />
      <p>Message</p><textarea name ="ss_content" rows="2" cols="22"><?=$ss_content?></textarea>
      <div style="text-align: right;"><input type="submit" name="doshout" value="Post!" class="button" /> <input type="reset" value="Clear" class="button" /></div>
      </form>
    </div>

  <?php
  
}

  function 
add_shoutbox_header($text)
  {
    echo    
"<script  type='text/javascript' language='Javascript'>
      function s_toggleDisplay(his, me, showtext, hidetext) {
        if (his.style.display != 'none') {
          his.style.display = 'none';
          me.innerHTML = showtext;
        } else {
          his.style.display = 'block';
          me.innerHTML = hidetext;
        }
      }
      </script>
      <style type='text/css' media='screen'>
      /* CSS for shoutbox */
      div #shoutbox {
        overflow: auto;
        height: 30em;
        border-top:         1px solid #999999;
        border-left:        1px solid #999999;
        border-right:       1px solid #ccc;
        border-bottom:      1px solid #ccc;
        margin-top: .5em;
        margin-bottom: .5em;
      }
    </style>"
;
    return 
$text;
  }

  
add_action('admin_menu''shoutbox_admin_menu');
  
add_action('wp_head''add_shoutbox_header');
  
add_action('init''shoutbox_init');
}
?>