Aquarionics

/home/a/aquarion/sites/www.aquarionics.com/epistula/chapters/comment.inc.php

All my code (That is, anything not in the "Others" list on the right) is BSD licenced.

You can also view this page as text/plain or colour-coded source


<?PHP
/*******************************************************************************
    Chapter - Comment
********************************************************************************

    Attach a comment to an item, View recent comments or all comments by
    author/site/IP

    TODO: ability to switch off comments for items
    TODO: TypeKey Authentication
    TODO: GPG signed comments
    TODO: Distributed Authentication Architecture

    $Id: comment.inc.php,v 1.4 2004/08/17 19:59:35 aquarion Exp $

    $log$

*******************************************************************************/



$page->content .= $page->subheading("Comments");

class comment {
    var $author;
    var $email;
    var $url;
    var $attachment;
    var $attachid;
    var $threadid;
    var $status;
    var $mailevent;
    var $maileventitem;

    var $ip;

    var $options;

    var $debug;

    function comment(){
        $this->status = "Open";
        $this->mailevent = "never";
        $this->ip = $_SERVER['REMOTE_ADDR'];
    }

    
    /**
        string filter ($content)
    
        Filters a Comment for inappropriate stuff
    */
    function filter ($content)
    {
        return $content;
    } // end func

    function CommentForm(){
        $out = "<form method=post action=\"/comment\" class=\"commentform\"><div>\n"
             ."<label for=\"author\">Name</label><input type=\"text\" name=\"author\" id=\"author\" value=\"".$this->author."\" size=\"30\"> (Shown)<br>\n"
             ."<label for=\"url\">URL</label><input type=\"text\" name=\"url\" id=\"url\" value=\"".$this->url."\" size=\"30\"> (Linked to)<br>\n"
             ."<label for=\"email\">Email</label><input type=\"text\" name=\"email\" id=\"email\" value=\"".$this->email."\" size=\"30\"> (Not shown, see below)<br>\n"
             ."<label for=\"maileventbox\">Email me on reply...</label></div>\n"
             ."<div id=\"maileventbox\" class=\"formBox\">";

        if ($this->mailevent == true){
            $out .= "<input type=\"checkbox\" name=\"mailevent\" id=\"mailevent\" checked> to this comment  \n";
        } else {
            $out .= "<input type=\"checkbox\" name=\"mailevent\" id=\"mailevent\"> to this comment<br>\n";
        }

        if ($this->maileventitem == true){
                $out .= "<input type=\"checkbox\" name=\"maileventitem\" id=\"maileventitem\" checked> to this thread";
        } else {
                $out .= "<input type=\"checkbox\" name=\"maileventitem\" id=\"maileventitem\"> to this thread";
        }

        /*$selected = array($this->mailevent => ' selected="selected"');

        $out .= '<label style="display: block;" for="maileventComment" '.$selected['commment'].'><input '.$style.' type="radio" name="mailevent" id="maileventComment" value="commment">...to this comment</label><br>'

        .'<label style="display: block;" for="maileventThread" '.$selected['thread'].'><input type="radio" name="mailevent" id="maileventThread" value="thread">...to this comment</label><br>'

        .'<label style="display: block;" for="maileventNever" '.$selected['never'].'><input type="radio" name="mailevent" id="maileventNever" value="never">...never</label><br>';*/

        $out .= "</div><div id=\"otheroptions\">\n"
             ."<label for=\"options\">Other Options</label>\n"
            
             ."<div id=\"options\" class=\"formBox\">";

        if ($this->options['savethis'] == true || $_COOKIE['whoami']){
                $selected = " checked";
        } else {
                $selected = "";
        }
            
        $out .= "<input type=\"checkbox\" name=\"savethis\"".$selected.">Save identity information as a cookie\n";

        if ($_COOKIE['whoami']){
        $out .= "<script type=\"text/javascript\">\n"
             ."<!-- \n"
             ."writeKillCookie();\n"
             ."//-->\n"
             ."</script>\n";
        }

        if ($this->options['typekey'] == true){
                $selected = " checked";
        } else {
                $selected = "";
        }
            
        #$out .= "<br><input type=\"checkbox\" name=\"pgpsign\"".$selected." DISABLED> <A HREF=\"http://www.gnupg.org\">GPG</A> Sign comment (Coming Soon)\n";
        #$out .= "<br><input type=\"checkbox\" name=\"typekey\"".$selected." DISABLED> Verify me with <A HREF=\"http://www.typekey.com/\">Typekey</A> [<A HREF=\"https://www.typekey.com/t/typekey/login\">Sign In</A>]  (Coming Sooner)\n";
        #$out .= "<br><input type=\"checkbox\" name=\"passport\"".$selected." DISABLED> Verify me with <A HREF=\"http://www.passport.com/\">Passport</A> [<A HREF=\"https://www.hotmail.com\">Sign In</A>]  (Coming when hell freezes over)\n";
        #$out .= "<br><input type=\"checkbox\" name=\"lap\"".$selected." DISABLED> Verify me with <A HREF=\"http://www.projectliberty.org//\">Project Liberty</A> (Coming when shortly after that)\n";


        $out .= "</div>\n"

        #     ."<label for=\"attachment\">Attached to </label><span name=\"attachment\">"
        #            .$this->attachment." #".$this->attachid."<br>\n"
             ."<input type=\"hidden\" name=\"attachment\" value=\"".$this->attachment."\">\n"
             ."<input type=\"hidden\" name=\"attachid\" value=\"".$this->attachid."\">\n"

             .'<strong style="color: red">NOTICE: New commenter\'s submissions will be passed though <a href="http://www.akismet.com">Akismet</a> for spam detection [<a href="/journal/2006/09/23/Akismet_Spam_Checking">Why?</a>]</strong><br>'

             ."<label for=\"content\">Comment</label>\n"
                    #."<h2>Comment formatting has changed as of 6<sup>th</sup> June. <a href=\"#formatting\">details</a></h2>"
                    ."<textarea name=\"content\" rows=\"16\" cols=\"50\">".htmlentities(stripslashes($this->content))."</textarea><br>";
            


        $out .= "<input type=\"submit\" value=\"Preview\" name=\"submit\">\n"
             ."<input type=\"submit\" value=\"Post\" name=\"submit\">\n"
             #."<input type=\"submit\" value=\"Post as Private Comment\" name=\"submit\"><br><br>\n"
             ."<div class=\"hidden\"><input type=\"submit\" value=\"Post this Comment to the Trashcan\" name=\"submit\">\n"
             .'(<a href="/journal/2004/10/26/Spammed">Why?</a>)'
             ."</div></div></form>\n";


        $out .= "<h3>Notes:</h3>\n"
             ."<ul>\n"
             ."\t<li>No form element is required apart from the content of your comment, "
                    ."but the system reserves the right to make fun of you if you don't give a name.</li>"
             ."\t<li>Obviously, if you ask for an email when your comment is replied to, then you'll need to supply an email address</li>\n"
             ."\t<li>Email will never be displayed on site, it's purely so the site can contact you.</li>\n"
             ."\t<li>If you enter a URL, your name will become a link to that URL.</li>\n"
             ."\t<li>By posting this, you agree to let me display it on the site. </li>"
             ."\t<li>Site policy is not to delete comments unless they are both inflammatory and unfunny. Or (in the admins opinion) spam.</li>"
             ."\t<li>...nor to edit them unless they would spoil other peoples enjoyment of the site or a movie, or something. And then only if I like the movie.</li>\n"
             ."\t<li>I am not bound to obey the above two rules, but you can expect me to have a damn good reason if I don't. The hidden email address rule, however, is both hard and fast. I hate spam as much as you do, probably more.</li>"
             ."\t<li>Your posting IP will be recorded in the database, though never shown. ".
                    "This is part of [E]'s anti-moron system.</li>\n"
             ."\t<li name=\"pagerank\">Your first comments to the site will be marked 'Untrusted' until the admin checks them over. Untrusted means any links you post get the \"<a href=\"http://www.google.com/googleblog/2005/01/preventing-comment-spam.html\">nofollow</a>\" tag added (Google, MSN, Yahoo etc. won't ever follow them). After that you become a 'Trusted' user and your links aren't modified in any way.</li>"
             ."</ul>\n\n"
        
             ."<h3 id=\"formatting\">Formatting Options:</h3>\n"
            # ."<strong>Note, These have changed (2004-06-06)</strong>\n"

            /* ."\t<li>Formatting Options:\n"
             ."\t<ul>\n"
             ."\t\t<li>[strong]text like this[/strong] becomes <strong>text like this</strong></li>\n"
             ."\t\t<li>[em]text like this[/em] becomes <em>text like this</em></li>\n"
             ."\t\t<li>A set of lines prefixed by stars (*) will become an unordered list.</li>\n"
             ."\t</ul>\n"*/

             ."\t<ul>\n"
             ."\t\t<li>Formatting is textile based. For example:</li>\n"
             ."\t\t<li>*text like this* becomes <strong>text like this</strong></li>\n"
             ."\t\t<li>_text like this_ becomes <em>text like this</em></li>\n"
             ."\t\t<li>A set of lines prefixed by stars (*) will become an unordered list.</li>\n"
             ."\t\t<li>A set of lines prefixed by hashes (#) will become an ordered list.</li>\n"
             ."\t\t<li>HTML will be stripped, erradicated and locked in a dungeon where I shall laugh at it and occasionally poke it with sticks. Prevent cruelty to HTML: Don't use it in my comments system.</li>\n"

             //."\t<li>All HTML will be <span style=\"color: red\">encoded and displayed</span>.</li>\n"
             ."\t<li>All urls (Anything starting http://) will be turned into links.</li>\n"
             ."</ul>\n";
             return $out;
    }

    function TestTrust(){
        $q = "select count(*) from comment where email = '".$this->email."' and status != 'Untrusted' ";
        $row = mysql_fetch_row(safequery($q));
        
        

        if ($row[0] > 2){
            return true;
        } else {
            return false;
        }
    }

    function Validate(){
        global $_EP;
        $output = array();
        $spammer = 0;


        // Check IP...
        if (isItSpam("ip",$this->ip)){$spammer++;}

        // Check Author...
        $this->author = strip_tags($this->author);
        $test[0] = "Name";
        $test[1] = "Stripped HTML";
        $test[2] = true;
        if (isItSpam("author", $this->author)){$spammer++;$test[2] = false;}
        //$output[] = $test;

        // Check Email...
        $this->email = strip_tags($this->email);
        if (isItSpam("email", $this->email)){$spammer++;}
        $test[0] = "Email";
        $test[1] = "Stripped HTML";
        $test[2] = true;
        //$output[] = $test;


        // Check MailEvent
        if ($this->mailevent){
            unset($test);
            $test[0] = "Mail On Reply";
            if(!check_trigger($this->email,'email')){
                $test[1] = "Emailing to this address is banned.";
                $test[2] = false;
            } elseif ($this->email == ""){
                $test[1] = "If you're going to be emailed, I need an email address";
                $test[2] = false;
            } else {
                $test[1] = "I will email you when someone replies to this thread";
                $test[2] = true;
            }
            $output[] = $test;
        }

        if ($this->maileventitem){
                unset($test);
                $test[0] = "Mail On Reply to Item";
                if(!check_trigger($this->email,'email')){
                        $test[1] = "Emailing to this address is banned.";
                        $test[2] = false;
                } elseif ($this->email == ""){
                        $test[1] = "If you're going to be emailed, I need an email address";
                        $test[2] = false;
                } else {
                        $test[1] = "I will email you when someone replies to this comment";
                        $test[2] = true;
                }
                $output[] = $test;
        }


        // Check Trust...
        unset($test);
        
        $trusted = $this->testTrust();

        $test[0] = "Trust Level";

        if ($trusted){
            $test[1] = "You're fine.";
            $test[2] = true;
        } else {
            $test[1] = "I Haven't seen you before, so your links will be marked 'nofollow' until the admin moderates them.";
            $test[2] = true;
            $this->status = "Untrusted";
            $output[] = $test;
        }
        if (isItSpam("url", $this->url)){$spammer++;$test[2] = false;}
        


        // Check URL...
        unset($test);
        $this->url = strip_tags($this->url);
        $test[0] = "URL";

        if ((!ereg("^http://.*", $this->url)) && $this->url != ""){
            $test[1] = "Home pages have to start 'http://', otherwise the links are broken";
            $test[2] = false;
            $output[] = $test;    
        } else {
            $test[1] = "URL appears to be valid or blank";
            $test[2] = true;
        }
        if (isItSpam("url", $this->url)){$spammer++;$test[2] = false;}
        

        // Check Content
        unset($test);
        $test[0] = "Comment";
        if (strlen(trim($this->content))<2){
            $test[1] = "Um, With all due respect, comments sorta need content :-)";
            $test[2] = false;
        } else {
            $comment_format = comment_format($this->content);
            if (count($comment_format[1]) != 0){
                foreach ($comment_format[1] as $problem => $message){
                    $test[1] .= $message."<br>\n"; 
                }
                $test[2] = false;
                $output[] = $test;    
            } elseif(!checkCaps($this->content)) {
                $test[1] = "Step away from the caps-lock key with your hands where I can see them";
                $test[2] = false;
                $output[] = $test;    
            } else {
                $test[1] = "Encoded content";
                $test[2] = true;
            }

        }
        
    
        //Attachment
        unset($test);
        if ($this->attachment and $this->attachid){
            $test[0] = "Checking existence of ".$this->attachment." #".$this->attachid;
            if (!checkExists($this->attachment, $this->attachid)){
                $test[1] = "Doesn't appear to exist, sorry.";
                $test[2] = false;
                $output[] = $test;
                
            }
            
            
            $threadid = getThread($this->attachment, $this->attachid);
            if ($threadid != $this->attachment."-".$this->attachid) {
                $threadBang = explode("-", $threadid);
                $test[0] = "Checking existence of ".$threadBang[0]." #".$threadBang[1];
                if (!checkexists($threadBang[0], $threadBang[1])){
                    $test[1] = "Doesn't appear to exist, sorry.";
                    $test[2] = false;
                } else {
                    #$test[1] = "Found it.";
                    #$test[2] = true;
                    #$output[] = $test;
                    
                    $test = $this->allowsComments($threadBang[0], $threadBang[1]);
                    $test ? $output[] = $test : false;
                }                
            } else {
                $test = $this->allowsComments($this->attachment, $this->attachid);
                $test ? $output[] = $test : false;
            }
            
            
            
        } else {
            $test[0] = "Variables set";
            $test[1] = "I've no idea what to attach it to!";
            $test[2] = false;
            $output[] = $test;    
        }

        // Check Akismet

        if (!$trusted && isset($_EP['use_akismet']) && $_EP['use_akismet']){
                $test[0] = '<a href="http://www.akismet.com">Akismet</a> Spam Check';
                $test[1] = "(Incomplete)";
                $test[2] = true;
            if (!isset($_EP['Secrets']['wordpressAPI'])){
                $test[1] = " No Wordpress API Key specified in config, skipping this test and whining...";
                mailAdmin("Comments", "Couldn't check spam with Akismet: No API key");
                break;
            }
            include("include/Akismet.class.php");
            $akismet = new Akismet($_EP['url'], $_EP['Secrets']['wordpressAPI']);

            $akismet->setAuthor($this->author);
            $akismet->setAuthorEmail($this->email);
            $akismet->setAuthorURL($this->url);
            $akismet->setPermalink(getPermaLink($this->attachment, $this->attachid));
            $akismet->setContent($this->content);

            if($akismet->isSpam()) {
                $test[1] = "... thinks you're a spammer. Go Away.";
                #mailAdmin("Akismet Check: Spammer", print_r($this, 1));
                keepTrack("akismet");
                $test[2] = false;
            } else {
                $test[1] =  "... is inclined to trust you.";
            }
            #echo "Hello Akismet";
            $output[] = $test;
        }

        #if ($spammer){
        #    $test[0] = "Spam check";
        #    $test[1] = "I think you're a spammer, Go away.";
        #    $test[2] = false;
        #    $output[] = $test;    
        #}
        
        return $output;
    }

    function Post(){

        $this->ip = $_SERVER['REMOTE_ADDR'];
        $threadid = getThread($this->attachment, $this->attachid);
        $threadBang = explode("-", $threadid);
        if (!checkexists($threadBang[0], $threadBang[1])){
            panic("Fatality","Original Post doesn't exist",$threadid." in 'Failed to exist' error 404");
        }

        /*------------+-------------+------+-----+-----------+----------------+
        | Field       | Type        | Null | Key | Default   | Extra          |
        +-------------+-------------+------+-----+-----------+----------------+
        | id          | bigint(20)  |      | PRI | NULL      | auto_increment |
        | author      | tinytext    | YES  |     | NULL      |                |
        | email       | tinytext    | YES  |     | NULL      |                |
        | url         | tinytext    | YES  |     | NULL      |                |
        | attachment  | tinytext    | YES  |     | NULL      |                |
        | attach_id   | bigint(20)  | YES  |     | NULL      |                |
        | content     | mediumtext  | YES  |     | NULL      |                |
        | status      | tinytext    | YES  |     | NULL      |                |
        | thread_id   | tinytext    | YES  |     | NULL      |                |
        | date_created| datetime    | YES  |     | NULL      |                |
        | postip      | varchar(20) |      |     | 127.0.0.1 |                |
        +-------------+-------------+------+-----+-----------+---------------*/
        $magicslashes = false;

        if ($magicslashes){
            $query = "insert into comment (author, email, url, attachment, attach_id, content, status, thread_id, date_created, postip) values (\"".$this->author."\", \"".$this->email."\", \"".$this->url."\", \"".$this->attachment."\", ".$this->attachid.", \"".$this->content."\", \"".$this->status."\", \"".$threadid."\", NOW(), \"".$this->ip."\")";
        } else {
            $query = "insert into comment (author, email, url, attachment, attach_id, content, status, thread_id, date_created, postip) values (\"".addslashes($this->author)."\", \"".addslashes($this->email)."\", \"".addslashes($this->url)."\", \"".$this->attachment."\", ".$this->attachid.", \"".addslashes($this->content)."\", \"".$this->status."\", \"".$threadid."\", NOW(), \"".$this->ip."\")";
        }

        safequery($query);

        $preview = $this->author.":\n".$this->content;

        trigger($this->attachment, $this->attachid, "comment", getPermalink($threadBang[0],$threadBang[1]), $preview);

        if ($threadid != $this->attachment."-".$this->attachid){
            trigger($threadBang[0], $threadBang[1], "comment");
        }
        
        if ($this->mailevent){
            new_trigger('comment',mysql_insert_id(), 'comment', $this->email,'email');
        }

                if ($this->maileventitem){
                        new_trigger($threadBang[0],$threadBang[1], 'comment', $this->email,'email');
                }        


        deleteCache($threadBang[1],$threadBang[0]);
        deleteCache(mysql_insert_id(),"comment");

        return ("Comment Posted Sucessfully. <a href=\"".getPermalink($threadBang[0],$threadBang[1])."\">Go take a look</a>, or return to the <a href=\"/\">front page</a>");

    }

    function Email($address, $private = false){
        $threadid = getThread($this->attachment, $this->attachid);
        $threadBang = explode("-", $threadid);
        if (!checkexists($threadBang[0], $threadBang[1])){
            panic("Fatality","Original Post doesn't exist",$threadid." in 'Failed to exist' error 404");
        }
        
        #$ref = mysql_fetch_assoc(safequery("select * from ".$threadBang[0]." where id = ".$threadBang[1]));
        $index = getIndex(array($threadBang[0]),"full",1, "where ".$threadBang[0].".id = ".$threadBang[1]);
        $ref = $index[0];

        //Find the author of the original article, hardcoded to Aquarion until the
        // User system is done.

        if ($private){
            $sub = "Private";
        } else {
            $sub = "New";
        }

        #$sendto = "aquarion@suespammers.org";
        if (!$address){
            $sendto = $ref['email'];
        } else {
            $sendto = $address;
        }
        $subject = "[E] $sub Message re ".$ref['title'];

        $message = "URL: ".getPermaLink($threadBang[0], $threadBang[1])."\n\n";

        #safequery("insert into comment (author, email, url, attachment, attach_id, content, status, thread_id, date_created, postip) values (\"".$this->author."\", \"".$this->email."\", \"".$this->url."\", \"".$this->attachment."\", ".$this->attachid.", \"".nl2br($this->content)."\", \"".$this->status."\", \"".$threadid."\", NOW(), \"".$this->ip."\")");

        $message .= wordwrap(stripslashes($this->content));
        $message .= "\n\nFrom: ".$this->author;
        $message .= "\nURL: ".$this->url;
        $message .= "\nEmail: ".$this->email;
        $message .= "\nSubject: ".$_POST['submit'];
        $message .= "\nStatus: ".$this->status;
        if (!$address){
            $message .= "\nIP: ".$this->ip;
        }
        $message .= "\n-- \nSent from Epistula";

        mail($sendto, $subject, $message,
            "From: epistula@aquarionics.com (".$this->author.")\r\n"
           ."Reply-To: ".$this->email."\r\n"
           ."X-Mailer: PHP/" . phpversion());
          
        @jabber("aquarion@jabber.org",$message);

        return ("Comment Emailed Sucessfully. <a href=\"/".$threadBang[0]."/id/".$threadBang[1]."\">Go back to page</a>, or return to the <a href=\"/\">front page</a>");
    }
    
    
        
    function allowsComments($type, $id){
        
        if(!allowsComments($type, $id)){
                $test = array();
                $test[0] = "Commenting on old items";
                $test[2] = false;
                $test[1] = "Sorry, Item is too old to be commented on.";
                return $test;
            
        }
    }
    
};

$localnav = array(
    array('name' => "Top commenters", "link" => "/comment/top")
    );

$page->localnav = $page->subheading("More Comments:").$page->menu($localnav);
$page->localnav .= $page->ulink("/meta/comment.rss2", $page->image("/assets/images/buttons/rss2.gif", "[RSS Icon]"), "Aquarionics ".$page->chapter." RSS Feed")."<br>";
$page->localnav .= $page->ulink("/meta/comment.esf", $page->image("/assets/images/buttons/esf.gif", "[ESF Icon]"), "Aquarionics ".$page->chapter." ESF Feed")."<br>";
$page->localnav .= $page->ulink("/meta/journal.cdf", $page->image("/assets/images/buttons/cdf.gif", "[CDF Icon]"), "Aquarionics ".$page->chapter." CDF Channel");

function getThread($attach, $attachid){
    if ($attach == "comment"){
        $q = "select thread_id from comment where id = ".$attachid;
        $res = safequery($q);
        if (mysql_num_rows($res) == 0){
            panic("ThreadID Error", "Thread ID Empty!" ,$q);
        }
        $row = mysql_fetch_assoc($res);
        $return = $row['thread_id'];
    } else {
        $return = $attach."-".$attachid;
    }
    return $return;
};

function commentsByCrit($crit = false){
    global $wanted;
    global $page;
    global $_SECRET;

    if(!is_numeric($_GET['skip'])){
        $limit = 0;
    } else {
        $limit = $_GET['skip'];
    }
    

    $q = "select count(id) as count, max(date_created) as last, min(date_created) as first, 56 as digit from comment ";
    if($crit){
        $q .= "where ".$crit;
    }
    $q .= "group by digit";
    $row = mysql_fetch_assoc(safequery($q));


    $out = "Found ".$row['count']." comments between ".$row['first']." and ".$row['last'];


    $q = "select *, unix_timestamp(date_created) as epoch from comment ";
    if($crit){
        $q .= "where ".$crit;
    }
    $q .= " order by date_created desc limit $limit, ".($limit + 50);
    #$out .= $q;
    $r = safequery($q);

    $url = "/".$wanted[0]."/".$wanted[1]."/".$wanted[2];
    
    $nextprev = array();

    if ($limit != 0){
        $nextprev[] = array('link' => $url."?skip=".($limit-50), 'name' => "Previous 50");
    }

    if (mysql_num_rows($r) == ($limit + 50)){
        $nextprev[] = array('link' => $url."?skip=".($limit+50), 'name' => "Next 50");
    }
    
    if (count($nextprev) > 0){
        $nextprev = $page->menu($nextprev,"pipe");
    } else {
        $nextprev = "";
    }

    #$out = $q;
    $out .= $nextprev;
    #$out = array();
    while($comment = mysql_fetch_assoc($r)){
        $thread = explode("-",$comment['thread_id']);
        $link = getPermalink($thread[0], $thread[1]);
        $out .= "<div>Re: <a href=\"".$link."\">".$comment['thread_id']."</a> <a href=\"".$link."#".$comment['id']."\">Comment #".$comment['id']."</a> <br>\n";
        $out .= "On: ".date("Y-m-d@h:i",$comment['epoch'])."<br>\n";
        $out .= "From: ";
        
        
        if ($comment['url']){
            $out .= "\"<a href=\"".$comment['url']."\">".$comment['author']."</a>\"";
        } else {
            $out .= "\"".$comment['author']."\"";
        }

        $out .= "<br>\n";

        $more = array();
        
        $more[] = array(
            'link'  => "/".$wanted[0]."/author/".$comment['author'],
            'name'  => "author",
            'title' => "More from this given name"
        );
        
        if ($comment['email']){
            $more[] = array(
                'link'  => "/".$wanted[0]."/email/".md5($comment['email'].$_SECRET['hashSecret']),
                'name'  => "email",
                'title' => "More from this given email address"
            );
        }

        if ($comment['url']){
            $more[] = array(
                'link'  => "/".$wanted[0]."/url/".rawurlencode($comment['url']),
                'name'  => "url",
                'title' => "More from this given url address"
            );
        }

        $more[] = array(
            'link'  => "/".$wanted[0]."/postip/".md5($comment['postip'].$_SECRET['hashSecret']),
            'name'  => "IP",
            'title' => "More from this IP address"
        );

        
        #$out .= "More Comments: ".$page->menu($more,"pipe");
        $out .= " More Comments: |";
        foreach($more as $array){
            $out .= " <a href=\"".$array['link']."\" title=\"".$array['title']."\">".$array['name']."</a> |";
        }

        #$out .= "[<a href=\"/".$wanted[0]."/postip/".md5($comment['postip'])."\">IP</a>]";
        #$out .= "[<a href=\"/sysadmin/delete_comment?id=".$comment['id']."\">Delete</a>]";
        $comment = process(htmlspecialchars(strip_tags($comment['content'])),"textile");
        $out .= "<blockquote cite=\"".$link."\">".$comment."</blockquote></div>\n\n";
    }
    $out .= $nextprev;
    return $page->item($out,"comments", "item");
}

switch($wanted[1]){

case "top":
    $q = "select count(id) as theCount, max(date_created) as last, min(date_created) as first, author from comment group by author order by `theCount` desc;";
    
    $r = safequery($q);
    $page->content .= $page->subheading("Top Content");

    $out .= "<ol>\n";
    while ($row = mysql_fetch_assoc($r)){
        $out .= "\t<li><a href=\"/comment/by/".$row['author']."\">".$row['author']."</a> (".$row['theCount'].")</li>\n";
    }
    $out .= "</ol>\n";

    $page->content .= $page->item($out,"topcomment");

    break;


case "author":
case "by":
    $page->content .= $page->subheading("Comments by ".urldecode($wanted[2]));
    $page->content .= commentsByCrit("author = '".mysql_escape_string(urldecode($wanted[2]))."'");break;
case "postip": 
    $page->content .= $page->heading("Comments from this IP");
    $page->content .= commentsByCrit("md5(concat(postip,\"".$_SECRET['hashSecret']."\")) = \"".$wanted[2]."\"");break;
case "url":
    $page->content .= $page->heading("Comments linking to ".$wanted[2]);
    $page->content .= commentsByCrit("url = \"".rawurldecode($wanted[2])."\"");break;
case "email":
    $page->content .= $page->heading("Comments from this email address");
    $page->content .= commentsByCrit("md5(concat(email,\"".$_SECRET['hashSecret']."\")) = \"".$wanted[2]."\"");break;
case "index":
    $page->content .= $page->heading("Comments");
    $page->content .= commentsByCrit();break;


case "":
$message = new comment;

if ($_POST['savethis'] == true){
    $cookie = $_POST['author']."§".$_POST['url']."§".$_POST['email'];
    if ($_POST['mailevent']){
        $cookie .= "§mailme";
    } else {
        $cookie .= "§nomailme";
    }

        if ($_POST['maileventitem']){
                $cookie .= "§mailmeitem"