system/lib-comment.php
author Dirk Haun <dirk@haun-online.de>
Sat, 14 Nov 2009 18:51:37 +0100
branchHEAD
changeset 7471 60332a73eac2
parent 7399 5260a7fb13df
child 7511 5579e1ef3120
permissions -rw-r--r--
It's 'polls', not 'poll' (since Geeklog 1.4.0) and shouldn't really be referred to in non-plugin code
     1 <?php
     2 
     3 /* Reminder: always indent with 4 spaces (no tabs). */
     4 // +---------------------------------------------------------------------------+
     5 // | Geeklog 1.6                                                               |
     6 // +---------------------------------------------------------------------------+
     7 // | lib-comment.php                                                           |
     8 // |                                                                           |
     9 // | Geeklog comment library.                                                  |
    10 // +---------------------------------------------------------------------------+
    11 // | Copyright (C) 2000-2009 by the following authors:                         |
    12 // |                                                                           |
    13 // | Authors: Tony Bibbs        - tony AT tonybibbs DOT com                    |
    14 // |          Mark Limburg      - mlimburg AT users DOT sourceforge DOT net    |
    15 // |          Jason Whittenburg - jwhitten AT securitygeeks DOT com            |
    16 // |          Dirk Haun         - dirk AT haun-online DOT de                   |
    17 // |          Vincent Furia     - vinny01 AT users DOT sourceforge DOT net     |
    18 // |          Jared Wenerd      - wenerd87 AT gmail DOT com                    |
    19 // +---------------------------------------------------------------------------+
    20 // |                                                                           |
    21 // | This program is free software; you can redistribute it and/or             |
    22 // | modify it under the terms of the GNU General Public License               |
    23 // | as published by the Free Software Foundation; either version 2            |
    24 // | of the License, or (at your option) any later version.                    |
    25 // |                                                                           |
    26 // | This program is distributed in the hope that it will be useful,           |
    27 // | but WITHOUT ANY WARRANTY; without even the implied warranty of            |
    28 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             |
    29 // | GNU General Public License for more details.                              |
    30 // |                                                                           |
    31 // | You should have received a copy of the GNU General Public License         |
    32 // | along with this program; if not, write to the Free Software Foundation,   |
    33 // | Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.           |
    34 // |                                                                           |
    35 // +---------------------------------------------------------------------------+
    36 
    37 if (strpos(strtolower($_SERVER['PHP_SELF']), 'lib-comment.php') !== false) {
    38     die('This file can not be used on its own!');
    39 }
    40 
    41 if ($_CONF['allow_user_photo']) {
    42     /**
    43     * only needed for the USER_getPhoto function
    44     */
    45     require_once $_CONF['path_system'] . 'lib-user.php';
    46 }
    47 
    48 /**
    49 * This function displays the comment control bar
    50 *
    51 * Prints the control that allows the user to interact with Geeklog Comments
    52 *
    53 * @param    string  $sid    ID of item in question
    54 * @param    string  $title  Title of item
    55 * @param    string  $type   Type of item (i.e. article, photo, etc)
    56 * @param    string  $order  Order that comments are displayed in
    57 * @param    string  $mode   Mode (nested, flat, etc.)
    58 * @param    int     $ccode  Comment code: -1=no comments, 0=allowed, 1=closed
    59 * @return   string          HTML Formated comment bar
    60 * @see CMT_userComments
    61 *
    62 */
    63 function CMT_commentBar( $sid, $title, $type, $order, $mode, $ccode = 0 )
    64 {
    65     global $_CONF, $_TABLES, $_USER, $LANG01;
    66 
    67     $parts = explode( '/', $_SERVER['PHP_SELF'] );
    68     $page = array_pop( $parts );
    69     $nrows = DB_count( $_TABLES['comments'], array( 'sid', 'type' ),
    70                        array( $sid, $type ));
    71 
    72     $commentbar = new Template( $_CONF['path_layout'] . 'comment' );
    73     $commentbar->set_file( array( 'commentbar' => 'commentbar.thtml' ));
    74     $commentbar->set_var( 'xhtml', XHTML );
    75     $commentbar->set_var( 'site_url', $_CONF['site_url'] );
    76     $commentbar->set_var( 'site_admin_url', $_CONF['site_admin_url'] );
    77     $commentbar->set_var( 'layout_url', $_CONF['layout_url'] );
    78 
    79     $commentbar->set_var( 'lang_comments', $LANG01[3] );
    80     $commentbar->set_var( 'lang_refresh', $LANG01[39] );
    81     $commentbar->set_var( 'lang_reply', $LANG01[60] );
    82     $commentbar->set_var( 'lang_disclaimer', $LANG01[26] );
    83 
    84     if( $ccode == 0 ) {
    85         $commentbar->set_var( 'reply_hidden_or_submit', 'submit' );
    86     } else {
    87         $commentbar->set_var( 'reply_hidden_or_submit', 'hidden' );
    88     }
    89     $commentbar->set_var( 'num_comments', COM_numberFormat( $nrows ));
    90     $commentbar->set_var( 'comment_type', $type );
    91     $commentbar->set_var( 'sid', $sid );
    92 
    93     $cmt_title = stripslashes($title);
    94     $commentbar->set_var('story_title', $cmt_title);
    95     // Article's are pre-escaped.
    96     if ($type != 'article') {
    97         $cmt_title = htmlspecialchars($cmt_title);
    98     }
    99     $commentbar->set_var('comment_title', $cmt_title);
   100 
   101     if ($type == 'article') {
   102         $articleUrl = COM_buildUrl($_CONF['site_url']
   103                                    . "/article.php?story=$sid");
   104     } else { // for a plugin
   105         /**
   106         * Link to plugin defined link or lacking that a generic link
   107         * that the plugin should support (hopefully)
   108         */
   109         list($plgurl, $plgid) = PLG_getCommentUrlId($type);
   110         $articleUrl = "$plgurl?$plgid=$sid";
   111     }
   112 
   113     $commentbar->set_var('article_url', $articleUrl);
   114     if ($page == 'comment.php') {
   115         $link = COM_createLink($cmt_title, $articleUrl,
   116                                array('class' => 'non-ul b'));
   117         $commentbar->set_var('story_link', $link);
   118         $commentbar->set_var('start_storylink_anchortag',
   119                              '<a href="' . $articleUrl . '" class="non-ul">');
   120         $commentbar->set_var('end_storylink_anchortag', '</a>');
   121     } else {
   122         $commentbar->set_var('story_link', $articleUrl);
   123     }
   124 
   125     if( !empty( $_USER['uid'] ) && ( $_USER['uid'] > 1 )) {
   126         $username = $_USER['username'];
   127         $fullname = $_USER['fullname'];
   128     } else {
   129         $result = DB_query( "SELECT username,fullname FROM {$_TABLES['users']} WHERE uid = 1" );
   130         $N = DB_fetchArray( $result );
   131         $username = $N['username'];
   132         $fullname = $N['fullname'];
   133     }
   134     if( empty( $fullname )) {
   135         $fullname = $username;
   136     }
   137     $commentbar->set_var( 'user_name', $username );
   138     $commentbar->set_var( 'user_fullname', $fullname );
   139 
   140     if( !empty( $_USER['username'] )) {
   141         $author = COM_getDisplayName( $_USER['uid'], $username, $fullname );
   142         $commentbar->set_var( 'user_nullname', $author );
   143         $commentbar->set_var( 'author', $author );
   144         $commentbar->set_var( 'login_logout_url',
   145                               $_CONF['site_url'] . '/users.php?mode=logout' );
   146         $commentbar->set_var( 'lang_login_logout', $LANG01[35] );
   147     } else {
   148         $commentbar->set_var( 'user_nullname', '' );
   149         $commentbar->set_var( 'login_logout_url',
   150                               $_CONF['site_url'] . '/users.php?mode=new' );
   151         $commentbar->set_var( 'lang_login_logout', $LANG01[61] );
   152     }
   153 
   154     if( $page == 'comment.php' ) {
   155         $commentbar->set_var( 'parent_url',
   156                               $_CONF['site_url'] . '/comment.php' );
   157         $hidden = '';
   158         if( $_REQUEST['mode'] == 'view' ) {
   159             $hidden .= '<input type="hidden" name="cid" value="' . $_REQUEST['cid'] . '"' . XHTML . '>';
   160             $hidden .= '<input type="hidden" name="pid" value="' . $_REQUEST['cid'] . '"' . XHTML . '>';
   161         }
   162         else if( $_REQUEST['mode'] == 'display' ) {
   163             $hidden .= '<input type="hidden" name="pid" value="' . $_REQUEST['pid'] . '"' . XHTML . '>';
   164         }
   165         $commentbar->set_var( 'hidden_field', $hidden .
   166                 '<input type="hidden" name="mode" value="' . $_REQUEST['mode'] . '"' . XHTML . '>' );
   167     } else if( $type == 'article' ) {
   168         $commentbar->set_var( 'parent_url',
   169                               $_CONF['site_url'] . '/article.php' );
   170         $commentbar->set_var( 'hidden_field',
   171                 '<input type="hidden" name="story" value="' . $sid . '"' . XHTML . '>' );
   172     } else { // plugin
   173         // Link to plugin defined link or lacking that a generic link that the plugin should support (hopefully)
   174         list($plgurl, $plgid) = PLG_getCommentUrlId($type);
   175         $commentbar->set_var( 'parent_url', $plgurl );
   176         $commentbar->set_var( 'hidden_field',
   177                 '<input type="hidden" name="' . $plgid . '" value="' . $sid . '"' . XHTML . '>' );
   178     }
   179 
   180     // Order
   181     $selector = '<select name="order">' . LB
   182               . COM_optionList( $_TABLES['sortcodes'], 'code,name', $order )
   183               . LB . '</select>';
   184     $commentbar->set_var( 'order_selector', $selector);
   185 
   186     // Mode
   187     if( $page == 'comment.php' ) {
   188         $selector = '<select name="format">';
   189     } else {
   190         $selector = '<select name="mode">';
   191     }
   192     $selector .= LB
   193                . COM_optionList( $_TABLES['commentmodes'], 'mode,name', $mode )
   194                . LB . '</select>';
   195     $commentbar->set_var( 'mode_selector', $selector);
   196 
   197     return $commentbar->finish( $commentbar->parse( 'output', 'commentbar' ));
   198 }
   199 
   200 
   201 /**
   202 * This function prints &$comments (db results set of comments) in comment format
   203 * -For previews, &$comments is assumed to be an associative array containing
   204 *  data for a single comment.
   205 *
   206 * @param    array    &$comments Database result set of comments to be printed
   207 * @param    string   $mode      'flat', 'threaded', etc
   208 * @param    string   $type      Type of item (article, polls, etc.)
   209 * @param    string   $order     How to order the comments 'ASC' or 'DESC'
   210 * @param    boolean  $delete_option   if current user can delete comments
   211 * @param    boolean  $preview   Preview display (for edit) or not
   212 * @param    int      $ccode     Comment code: -1=no comments, 0=allowed, 1=closed
   213 * @return   string   HTML       Formated Comment
   214 *
   215 */
   216 function CMT_getComment( &$comments, $mode, $type, $order, $delete_option = false, $preview = false, $ccode = 0 )
   217 {
   218     global $_CONF, $_TABLES, $_USER, $LANG01, $LANG03, $MESSAGE, $_IMAGE_TYPE;
   219 
   220     $indent = 0;  // begin with 0 indent
   221     $retval = ''; // initialize return value
   222 
   223     $template = new Template( $_CONF['path_layout'] . 'comment' );
   224     $template->set_file( array( 'comment' => 'comment.thtml',
   225                                 'thread'  => 'thread.thtml'  ));
   226 
   227     // generic template variables
   228     $template->set_var( 'xhtml', XHTML );
   229     $template->set_var( 'site_url', $_CONF['site_url'] );
   230     $template->set_var( 'site_admin_url', $_CONF['site_admin_url'] );
   231     $template->set_var( 'layout_url', $_CONF['layout_url'] );
   232     $template->set_var( 'lang_authoredby', $LANG01[42] );
   233     $template->set_var( 'lang_on', $LANG01[36] );
   234     $template->set_var( 'lang_permlink', $LANG01[120] );
   235     $template->set_var( 'order', $order );
   236 
   237     if( $ccode == 0 ) {
   238         $template->set_var( 'lang_replytothis', $LANG01[43] );
   239         $template->set_var( 'lang_reply', $LANG01[25] );
   240     } else {
   241         $template->set_var( 'lang_replytothis', '' );
   242         $template->set_var( 'lang_reply', '' );
   243     }
   244 
   245     // Make sure we have a default value for comment indentation
   246     if (!isset($_CONF['comment_indent'])) {
   247         $_CONF['comment_indent'] = 25;
   248     }
   249 
   250     if ($preview) {
   251         $A = $comments;
   252         if (empty( $A['nice_date'])) {
   253             $A['nice_date'] = time();
   254         }
   255         if (!isset($A['cid'])) {
   256             $A['cid'] = 0;
   257         }
   258         if (!isset($A['photo'])) {
   259             if (isset($_USER['photo'])) {
   260                 $A['photo'] = $_USER['photo'];
   261             } else {
   262                 $A['photo'] = '';
   263             }
   264         }
   265         if (! isset($A['email'])) {
   266             if (isset($_USER['email'])) {
   267                 $A['email'] = $_USER['email'];
   268             } else {
   269                 $A['email'] = '';
   270             }
   271         }
   272         $mode = 'flat';
   273     } else {
   274         $A = DB_fetchArray( $comments );
   275     }
   276 
   277     if (empty($A)) {
   278         return '';
   279     }
   280 
   281     $token = '';
   282     if ($delete_option && !$preview) {
   283         $token = SEC_createToken();
   284     }
   285 
   286     // check for comment edit
   287 
   288     $row = 1;
   289     do {
   290         // check for comment edit
   291         $commentedit = DB_query("SELECT cid,uid,UNIX_TIMESTAMP(time) AS time FROM {$_TABLES['commentedits']} WHERE cid = {$A['cid']}");
   292         $B = DB_fetchArray($commentedit);
   293         if ($B) { //comment edit present
   294             // get correct editor name
   295             if ($A['uid'] == $B['uid']) {
   296                 $editname = $A['username'];
   297             } else {
   298                 $editname = DB_getItem($_TABLES['users'], 'username',
   299                                        "uid={$B['uid']}");
   300             }
   301             // add edit info to text
   302             $A['comment'] .= '<div class="comment-edit">' . $LANG03[30] . ' '
   303                           . strftime($_CONF['date'], $B['time']) . ' '
   304                           . $LANG03[31] . ' ' . $editname
   305                           . '</div><!-- /COMMENTEDIT -->';
   306         }
   307 
   308         // determines indentation for current comment
   309         if ($mode == 'threaded' || $mode == 'nested') {
   310             $indent = ($A['indent'] - $A['pindent']) * $_CONF['comment_indent'];
   311         }
   312 
   313         // comment variables
   314         $template->set_var('indent', $indent);
   315         $template->set_var('author_name', strip_tags($A['username']));
   316         $template->set_var('author_id', $A['uid']);
   317         $template->set_var('cid', $A['cid']);
   318         $template->set_var('cssid', $row % 2);
   319 
   320         if ($A['uid'] > 1) {
   321             $fullname = '';
   322             if (! empty($A['fullname'])) {
   323                 $fullname = $A['fullname'];
   324             }
   325             $fullname = COM_getDisplayName($A['uid'], $A['username'],
   326                                            $fullname);
   327             $template->set_var('author_fullname', $fullname);
   328             $template->set_var('author', $fullname);
   329             $alttext = $fullname;
   330 
   331             $photo = '';
   332             if ($_CONF['allow_user_photo']) {
   333                 if (isset ($A['photo']) && empty($A['photo'])) {
   334                     $A['photo'] = '(none)';
   335                 }
   336                 $photo = USER_getPhoto($A['uid'], $A['photo'], $A['email']);
   337             }
   338             if( !empty( $photo )) {
   339                 $template->set_var( 'author_photo', $photo );
   340                 $camera_icon = '<img src="' . $_CONF['layout_url']
   341                     . '/images/smallcamera.' . $_IMAGE_TYPE . '" alt=""' . XHTML . '>';
   342                 $template->set_var( 'camera_icon',
   343                     COM_createLink(
   344                         $camera_icon,
   345                         $_CONF['site_url'] . '/users.php?mode=profile&amp;uid=' . $A['uid']
   346                     )
   347                 );
   348             } else {
   349                 $template->set_var( 'author_photo', '' );
   350                 $template->set_var( 'camera_icon', '' );
   351             }
   352 
   353             $template->set_var( 'start_author_anchortag', '<a href="'
   354                     . $_CONF['site_url'] . '/users.php?mode=profile&amp;uid='
   355                     . $A['uid'] . '">' );
   356             $template->set_var( 'end_author_anchortag', '</a>' );
   357             $template->set_var( 'author_link',
   358                 COM_createLink(
   359                     $fullname,
   360                     $_CONF['site_url'] . '/users.php?mode=profile&amp;uid=' . $A['uid']
   361                 )
   362             );
   363 
   364         } else {
   365             //comment is from anonymous user
   366             if (isset($A['name'])) {
   367                 $A['username'] = strip_tags($A['name']);
   368             }
   369             $template->set_var( 'author', $A['username'] );
   370             $template->set_var( 'author_fullname', $A['username'] );
   371             $template->set_var( 'author_link', $A['username'] );
   372             $template->set_var( 'author_photo', '' );
   373             $template->set_var( 'camera_icon', '' );
   374             $template->set_var( 'start_author_anchortag', '' );
   375             $template->set_var( 'end_author_anchortag', '' );
   376         }
   377 
   378         // hide reply link from anonymous users if they can't post replies
   379         $hidefromanon = false;
   380         if( empty( $_USER['username'] ) && (( $_CONF['loginrequired'] == 1 )
   381                 || ( $_CONF['commentsloginrequired'] == 1 ))) {
   382             $hidefromanon = true;
   383         }
   384 
   385         // this will hide HTML that should not be viewed in preview mode
   386         if( $preview || $hidefromanon ) {
   387             $template->set_var( 'hide_if_preview', 'style="display:none"' );
   388         } else {
   389             $template->set_var( 'hide_if_preview', '' );
   390         }
   391 
   392         // for threaded mode, add a link to comment parent
   393         if( $mode == 'threaded' && $A['pid'] != 0 && $indent == 0 ) {
   394             $result = DB_query( "SELECT title,pid FROM {$_TABLES['comments']} WHERE cid = '{$A['pid']}'" );
   395             $P = DB_fetchArray( $result );
   396             if( $P['pid'] != 0 ) {
   397                 $plink = $_CONF['site_url'] . '/comment.php?mode=display&amp;sid='
   398                        . $A['sid'] . '&amp;title=' . urlencode( htmlspecialchars( $P['title'] ))
   399                        . '&amp;type=' . $type . '&amp;order=' . $order . '&amp;pid='
   400                        . $P['pid'] . '&amp;format=threaded';
   401             } else {
   402                 $plink = $_CONF['site_url'] . '/comment.php?mode=view&amp;sid='
   403                        . $A['sid'] . '&amp;title=' . urlencode( htmlspecialchars( $P['title'] ))
   404                        . '&amp;type=' . $type . '&amp;order=' . $order . '&amp;cid='
   405                        . $A['pid'] . '&amp;format=threaded';
   406             }
   407             $parent_link = COM_createLink($LANG01[44], $plink) . ' | ';
   408             $template->set_var('parent_link', $parent_link);
   409         } else {
   410             $template->set_var('parent_link', '');
   411         }
   412 
   413         $template->set_var( 'date', strftime( $_CONF['date'], $A['nice_date'] ));
   414         $template->set_var( 'sid', $A['sid'] );
   415         $template->set_var( 'type', $A['type'] );
   416 
   417         // COMMENT edit rights
   418         $edit_option = false;
   419         if (isset($A['uid']) && isset($_USER['uid'])
   420                 && ($_USER['uid'] == $A['uid']) && ($_CONF['comment_edit'] == 1)
   421                 && ((time() - $A['nice_date']) < $_CONF['comment_edittime'])
   422                 && (DB_getItem($_TABLES['comments'], 'COUNT(*)',
   423                                "pid = {$A['cid']}") == 0)) {
   424             $edit_option = true;
   425             if (empty($token)) {
   426                 $token = SEC_createToken();
   427             }
   428         } elseif (SEC_hasRights('comment.moderate')) { 
   429             $edit_option = true;
   430         }
   431         
   432         // edit link
   433         $edit = '';
   434         if ($edit_option) {
   435             $editlink = $_CONF['site_url'] . '/comment.php?mode=edit&amp;cid='
   436                 . $A['cid'] . '&amp;sid=' . $A['sid'] . '&amp;type=' . $type;
   437             $edit = COM_createLink($LANG01[4], $editlink) . ' | ';
   438         }
   439 
   440         // unsubscribe link
   441         $unsubscribe = '';
   442         if (($_CONF['allow_reply_notifications'] == 1) && !COM_isAnonUser()
   443                 && isset($A['uid']) && isset($_USER['uid'])
   444                 && ($_USER['uid'] == $A['uid'])) {
   445             $hash = DB_getItem($_TABLES['commentnotifications'], 'deletehash',
   446                                "cid = {$A['cid']} AND uid = {$_USER['uid']}");
   447             if (! empty($hash)) {
   448                 $unsublink = $_CONF['site_url']
   449                            . '/comment.php?mode=unsubscribe&amp;key=' . $hash;
   450                 $unsubattr = array('title' => $LANG03[43]);
   451                 $unsubscribe = COM_createLink($LANG03[42], $unsublink,
   452                                               $unsubattr) . ' | ';
   453             }
   454         }
   455 
   456         // if deletion is allowed, displays delete link
   457         if ($delete_option) {
   458             $deloption = '';
   459 
   460             // always place edit option first, if available
   461             if (! empty($edit)) {
   462                 $deloption .= $edit;
   463             }
   464 
   465             // actual delete option
   466             $dellink = $_CONF['site_url'] . '/comment.php?mode=delete&amp;cid='
   467                 . $A['cid'] . '&amp;sid=' . $A['sid'] . '&amp;type=' . $type
   468                 . '&amp;' . CSRF_TOKEN . '=' . $token;
   469             $delattr = array('onclick' => "return confirm('{$MESSAGE[76]}');");
   470             $deloption .= COM_createLink($LANG01[28], $dellink, $delattr) . ' | ';
   471 
   472             if (!empty($A['ipaddress'])) {
   473                 if (empty($_CONF['ip_lookup'])) {
   474                     $deloption .= $A['ipaddress'] . '  | ';
   475                 } else {
   476                     $iplookup = str_replace('*', $A['ipaddress'],
   477                                             $_CONF['ip_lookup']);
   478                     $deloption .= COM_createLink($A['ipaddress'], $iplookup) . ' | ';
   479                 }
   480             }
   481 
   482             if (! empty($unsubscribe)) {
   483                 $deloption .= $unsubscribe;
   484             }
   485 
   486             $template->set_var('delete_option', $deloption);
   487         } elseif ($edit_option) {
   488             $template->set_var('delete_option', $edit . $unsubscribe);
   489         } elseif (! COM_isAnonUser()) {
   490             $reportthis = '';
   491             if ($A['uid'] != $_USER['uid']) {
   492                 $reportthis_link = $_CONF['site_url']
   493                     . '/comment.php?mode=report&amp;cid=' . $A['cid']
   494                     . '&amp;type=' . $type;
   495                 $report_attr = array('title' => $LANG01[110]);
   496                 $reportthis = COM_createLink($LANG01[109], $reportthis_link,
   497                                              $report_attr) . ' | ';
   498             }
   499             $template->set_var('delete_option', $reportthis . $unsubscribe);
   500         } else {
   501             $template->set_var('delete_option', '');
   502         }
   503         
   504         //and finally: format the actual text of the comment, but check only the text, not sig or edit
   505         $text = str_replace('<!-- COMMENTSIG --><div class="comment-sig">', '',
   506                             $A['comment']);
   507         $text = str_replace('</div><!-- /COMMENTSIG -->', '', $text);
   508         $text = str_replace('<div class="comment-edit">', '', $text);
   509         $text = str_replace('</div><!-- /COMMENTEDIT -->', '', $text);
   510         if( preg_match( '/<.*>/', $text ) == 0 ) {
   511             $A['comment'] = nl2br( $A['comment'] );
   512         }
   513 
   514         // highlight search terms if specified
   515         if( !empty( $_REQUEST['query'] )) {
   516             $A['comment'] = COM_highlightQuery( $A['comment'],
   517                                                 $_REQUEST['query'] );
   518         }
   519 
   520         $A['comment'] = str_replace( '$', '&#36;',  $A['comment'] );
   521         $A['comment'] = str_replace( '{', '&#123;', $A['comment'] );
   522         $A['comment'] = str_replace( '}', '&#125;', $A['comment'] );
   523 
   524         // Replace any plugin autolink tags
   525         $A['comment'] = PLG_replaceTags( $A['comment'] );
   526 
   527         // create a reply to link
   528         $reply_link = '';
   529         if ($ccode == 0) {
   530             $reply_link = $_CONF['site_url'] . '/comment.php?sid=' . $A['sid']
   531                         . '&amp;pid=' . $A['cid'] . '&amp;title='
   532                         . urlencode($A['title']) . '&amp;type=' . $A['type'];
   533             $reply_option = COM_createLink($LANG01[43], $reply_link,
   534                                            array('rel' => 'nofollow')) . ' | ';
   535             $template->set_var('reply_option', $reply_option);
   536         } else {
   537             $template->set_var('reply_option', '');
   538         }
   539         $template->set_var('reply_link', $reply_link);
   540 
   541         // format title for display, must happen after reply_link is created
   542         $A['title'] = htmlspecialchars( $A['title'] );
   543         $A['title'] = str_replace( '$', '&#36;', $A['title'] );
   544 
   545         $template->set_var( 'title', $A['title'] );
   546         $template->set_var( 'comments', $A['comment'] );
   547 
   548         // parse the templates
   549         if( ($mode == 'threaded') && $indent > 0 ) {
   550             $template->set_var( 'pid', $A['pid'] );
   551             $retval .= $template->parse( 'output', 'thread' );
   552         } else {
   553             $template->set_var( 'pid', $A['cid'] );
   554             $retval .= $template->parse( 'output', 'comment' );
   555         }
   556         $row++;
   557     } while( $A = DB_fetchArray( $comments ));
   558 
   559     return $retval;
   560 }
   561 
   562 /**
   563 * This function displays the comments in a high level format.
   564 *
   565 * Begins displaying user comments for an item
   566 *
   567 * @param    string      $sid       ID for item to show comments for
   568 * @param    string      $title     Title of item
   569 * @param    string      $type      Type of item (article, polls, etc.)
   570 * @param    string      $order     How to order the comments 'ASC' or 'DESC'
   571 * @param    string      $mode      comment mode (nested, flat, etc.)
   572 * @param    int         $pid       id of parent comment
   573 * @param    int         $page      page number of comments to display
   574 * @param    boolean     $cid       true if $pid should be interpreted as a cid instead
   575 * @param    boolean     $delete_option   if current user can delete comments
   576 * @param    int         $ccode     Comment code: -1=no comments, 0=allowed, 1=closed
   577 * @return   string  HTML Formated Comments
   578 * @see CMT_commentBar
   579 *
   580 */
   581 function CMT_userComments( $sid, $title, $type='article', $order='', $mode='', $pid = 0, $page = 1, $cid = false, $delete_option = false, $ccode = 0 )
   582 {
   583     global $_CONF, $_TABLES, $_USER, $LANG01;
   584 
   585     if( !empty( $_USER['uid'] ) ) {
   586         $result = DB_query( "SELECT commentorder,commentmode,commentlimit FROM {$_TABLES['usercomment']} WHERE uid = '{$_USER['uid']}'" );
   587         $U = DB_fetchArray( $result );
   588         if( empty( $order ) ) {
   589             $order = $U['commentorder'];
   590         }
   591         if( empty( $mode ) ) {
   592             $mode = $U['commentmode'];
   593         }
   594         $limit = $U['commentlimit'];
   595     }
   596 
   597     if( $order != 'ASC' && $order != 'DESC' ) {
   598         $order = 'ASC';
   599     }
   600 
   601     if( empty( $mode )) {
   602         $mode = $_CONF['comment_mode'];
   603     }
   604 
   605     if( empty( $limit )) {
   606         $limit = $_CONF['comment_limit'];
   607     }
   608 
   609     if( !is_numeric($page) || $page < 1 ) {
   610         $page = 1;
   611     }
   612 
   613     $start = $limit * ( $page - 1 );
   614 
   615     $template = new Template( $_CONF['path_layout'] . 'comment' );
   616     $template->set_file( array( 'commentarea' => 'startcomment.thtml' ));
   617     $template->set_var( 'xhtml', XHTML );
   618     $template->set_var( 'site_url', $_CONF['site_url'] );
   619     $template->set_var( 'site_admin_url', $_CONF['site_admin_url'] );
   620     $template->set_var( 'layout_url', $_CONF['layout_url'] );
   621     $template->set_var( 'commentbar',
   622             CMT_commentBar( $sid, $title, $type, $order, $mode, $ccode ));
   623     $template->set_var( 'sid', $sid );
   624     $template->set_var( 'comment_type', $type );
   625 
   626     if( $mode == 'nested' || $mode == 'threaded' || $mode == 'flat' ) {
   627         // build query
   628         switch( $mode ) {
   629             case 'flat':
   630                 if( $cid ) {
   631                     $count = 1;
   632 
   633                     $q = "SELECT c.*, u.username, u.fullname, u.photo, u.email, "
   634                        . "UNIX_TIMESTAMP(c.date) AS nice_date "
   635                        . "FROM {$_TABLES['comments']} AS c, {$_TABLES['users']} AS u "
   636                        . "WHERE c.uid = u.uid AND c.cid = $pid AND type='{$type}'";
   637                 } else {
   638                     $count = DB_count( $_TABLES['comments'],
   639                                 array( 'sid', 'type' ), array( $sid, $type ));
   640 
   641                     $q = "SELECT c.*, u.username, u.fullname, u.photo, u.email, "
   642                        . "UNIX_TIMESTAMP(c.date) AS nice_date "
   643                        . "FROM {$_TABLES['comments']} AS c, {$_TABLES['users']} AS u "
   644                        . "WHERE c.uid = u.uid AND c.sid = '$sid' AND type='{$type}' "
   645                        . "ORDER BY date $order LIMIT $start, $limit";
   646                 }
   647                 break;
   648 
   649             case 'nested':
   650             case 'threaded':
   651             default:
   652                 if( $order == 'DESC' ) {
   653                     $cOrder = 'c.rht DESC';
   654                 } else {
   655                     $cOrder = 'c.lft ASC';
   656                 }
   657 
   658                 // We can simplify the query, and hence increase performance
   659                 // when pid = 0 (when fetching all the comments for a given sid)
   660                 if( $cid ) {  // pid refers to commentid rather than parentid
   661                     // count the total number of applicable comments
   662                     $q2 = "SELECT COUNT(*) "
   663                         . "FROM {$_TABLES['comments']} AS c, {$_TABLES['comments']} AS c2 "
   664                         . "WHERE c.sid = '$sid' AND (c.lft >= c2.lft AND c.lft <= c2.rht) "
   665                         . "AND c2.cid = $pid AND c.type='{$type}'";
   666                     $result = DB_query( $q2 );
   667                     list( $count ) = DB_fetchArray( $result );
   668 
   669                     $q = "SELECT c.*, u.username, u.fullname, u.photo, u.email, c2.indent AS pindent, "
   670                        . "UNIX_TIMESTAMP(c.date) AS nice_date "
   671                        . "FROM {$_TABLES['comments']} AS c, {$_TABLES['comments']} AS c2, "
   672                        . "{$_TABLES['users']} AS u "
   673                        . "WHERE c.sid = '$sid' AND (c.lft >= c2.lft AND c.lft <= c2.rht) "
   674                        . "AND c2.cid = $pid AND c.uid = u.uid AND c.type='{$type}' "
   675                        . "ORDER BY $cOrder LIMIT $start, $limit";
   676                 } else {    // pid refers to parentid rather than commentid
   677                     if( $pid == 0 ) {  // the simple, fast case
   678                         // count the total number of applicable comments
   679                         $count = DB_count( $_TABLES['comments'],
   680                                 array( 'sid', 'type' ), array( $sid, $type ));
   681 
   682                         $q = "SELECT c.*, u.username, u.fullname, u.photo, u.email, 0 AS pindent, "
   683                            . "UNIX_TIMESTAMP(c.date) AS nice_date "
   684                            . "FROM {$_TABLES['comments']} AS c, {$_TABLES['users']} AS u "
   685                            . "WHERE c.sid = '$sid' AND c.uid = u.uid  AND type='{$type}' "
   686                            . "ORDER BY $cOrder LIMIT $start, $limit";
   687                     } else {
   688                         // count the total number of applicable comments
   689                         $q2 = "SELECT COUNT(*) "
   690                             . "FROM {$_TABLES['comments']} AS c, {$_TABLES['comments']} AS c2 "
   691                             . "WHERE c.sid = '$sid' AND (c.lft > c2.lft AND c.lft < c2.rht) "
   692                             . "AND c2.cid = $pid AND c.type='{$type}'";
   693                         $result = DB_query($q2);
   694                         list($count) = DB_fetchArray($result);
   695 
   696                         $q = "SELECT c.*, u.username, u.fullname, u.photo, u.email, c2.indent + 1 AS pindent, "
   697                            . "UNIX_TIMESTAMP(c.date) AS nice_date "
   698                            . "FROM {$_TABLES['comments']} AS c, {$_TABLES['comments']} AS c2, "
   699                            . "{$_TABLES['users']} AS u "
   700                            . "WHERE c.sid = '$sid' AND (c.lft > c2.lft AND c.lft < c2.rht) "
   701                            . "AND c2.cid = $pid AND c.uid = u.uid AND c.type='{$type}' "
   702                            . "ORDER BY $cOrder LIMIT $start, $limit";
   703                     }
   704                 }
   705                 break;
   706         }
   707 
   708         $thecomments = '';
   709         $result = DB_query( $q );
   710         $thecomments .= CMT_getComment( $result, $mode, $type, $order,
   711                                         $delete_option, false, $ccode );
   712 
   713         // Pagination
   714         $tot_pages =  ceil($count / $limit);
   715         $pLink = $_CONF['site_url'] . "/article.php?story=$sid&amp;type=$type&amp;order=$order&amp;mode=$mode";
   716         $template->set_var('pagenav',
   717                            COM_printPageNavigation($pLink, $page, $tot_pages));
   718 
   719         $template->set_var('comments', $thecomments);
   720         $retval = $template->finish($template->parse('output', 'commentarea'));
   721     }
   722 
   723     return $retval;
   724 }
   725 
   726 /**
   727 * Displays the comment form
   728 *
   729 * @param    string  $title      Title of comment
   730 * @param    string  $comment    Text of comment
   731 * @param    string  $sid        ID of object comment belongs to
   732 * @param    int     $pid        ID of parent comment
   733 * @param    string  $type       Type of object comment is posted to
   734 * @param    string  $mode       Mode, e.g. 'preview'
   735 * @param    string  $postmode   Indicates if comment is plain text or HTML
   736 * @return   string  HTML for comment form
   737 *
   738 */
   739 function CMT_commentForm($title,$comment,$sid,$pid='0',$type,$mode,$postmode)
   740 {
   741     global $_CONF, $_TABLES, $_USER, $LANG03, $LANG12, $LANG_LOGIN,
   742            $LANG_ACCESS;
   743 
   744     $retval = '';
   745 
   746     // never trust $uid ...
   747     if (empty ($_USER['uid'])) {
   748         $uid = 1;
   749     } else {
   750         $uid = $_USER['uid'];
   751     }
   752 
   753     $commentuid = $uid;
   754     $table = $_TABLES['comments'];
   755     if (($mode == 'edit' || $mode == $LANG03[28]) && isset($_REQUEST['cid'])) {
   756         $cid = COM_applyFilter ($_REQUEST['cid']);
   757         $commentuid = DB_getItem ($_TABLES['comments'], 'uid', "cid = '$cid'");
   758     } elseif ($mode == 'editsubmission' || $mode == $LANG03[34]) {
   759         $cid = COM_applyFilter ($_REQUEST['cid']);
   760         $commentuid = DB_getItem ($_TABLES['commentsubmissions'], 'uid', "cid = '$cid'");
   761         $table = $_TABLES['commentsubmissions'];
   762     }
   763 
   764     if (COM_isAnonUser() &&
   765             (($_CONF['loginrequired'] == 1) || ($_CONF['commentsloginrequired'] == 1))) {
   766         $retval .= COM_startBlock ($LANG_LOGIN[1], '',
   767                            COM_getBlockTemplate ('_msg_block', 'header'));
   768         $loginreq = new Template($_CONF['path_layout'] . 'submit');
   769         $loginreq->set_file('loginreq', 'submitloginrequired.thtml');
   770         $loginreq->set_var( 'xhtml', XHTML );
   771         $loginreq->set_var('login_message', $LANG_LOGIN[2]);
   772         $loginreq->set_var('site_url', $_CONF['site_url']);
   773         $loginreq->set_var('site_admin_url', $_CONF['site_admin_url']);
   774         $loginreq->set_var('lang_login', $LANG_LOGIN[3]);
   775         $loginreq->set_var('lang_newuser', $LANG_LOGIN[4]);
   776         $loginreq->parse('errormsg', 'loginreq');
   777         $retval .= $loginreq->finish($loginreq->get_var('errormsg'));
   778         $retval .= COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
   779         return $retval;
   780     } else {
   781         COM_clearSpeedlimit ($_CONF['commentspeedlimit'], 'comment');
   782 
   783         $last = 0;
   784         if ($mode != 'edit' && $mode != 'editsubmission' 
   785                 && $mode != $LANG03[28] && $mode != $LANG03[34]) {
   786             // not edit mode or preview changes
   787             $last = COM_checkSpeedlimit ('comment');
   788         }
   789 
   790         if ($last > 0) {
   791             $retval .= COM_startBlock ($LANG12[26], '',
   792                                COM_getBlockTemplate ('_msg_block', 'header'))
   793                 . $LANG03[7]
   794                 . $last
   795                 . $LANG03[8]
   796                 . COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
   797         } else {
   798 
   799             if (($_CONF['advanced_editor'] == 1) && file_exists ($_CONF['path_layout'] . 'comment/commentform_advanced.thtml')) {
   800                 $postmode = 'html';
   801             } elseif (empty ($postmode)) {
   802                 $postmode = $_CONF['postmode'];
   803             }
   804 
   805             // Note:
   806             // $comment / $newcomment is what goes into the preview / is
   807             // actually stored in the database -> strip HTML
   808             // $commenttext is what the user entered and goes back into the
   809             // <textarea> -> don't strip HTML
   810 
   811             $commenttext = htmlspecialchars (COM_stripslashes ($comment));
   812 
   813             // Replace $, {, and } with special HTML equivalents
   814             $commenttext = str_replace('$','&#36;',$commenttext);
   815             $commenttext = str_replace('{','&#123;',$commenttext);
   816             $commenttext = str_replace('}','&#125;',$commenttext);
   817 
   818             $title = COM_checkWords (strip_tags (COM_stripslashes ($title)));
   819             // $title = str_replace('$','&#36;',$title); done in CMT_getComment
   820 
   821             $_POST['title'] = $title;
   822             $newcomment = $comment;
   823             if ($mode == $LANG03[28] ) { // for preview
   824                 $newcomment = CMT_prepareText($comment, $postmode, $type, true, $cid);
   825             } elseif ($mode == $LANG03[34]) {
   826                 $newcomment = CMT_prepareText($comment, $postmode, $type, true);
   827             } else {
   828                 $newcomment = CMT_prepareText($comment, $postmode, $type);
   829             }
   830             $_POST['comment'] = $newcomment;
   831 
   832             // Preview mode:
   833             if (($mode == $LANG03[14] || $mode == $LANG03[28] || $mode == $LANG03[34]) && !empty($title) && !empty($comment) ) {
   834                 $start = new Template( $_CONF['path_layout'] . 'comment' );
   835                 $start->set_file( array( 'comment' => 'startcomment.thtml' ));
   836                 $start->set_var( 'xhtml', XHTML );
   837                 $start->set_var( 'site_url', $_CONF['site_url'] );
   838                 $start->set_var( 'site_admin_url', $_CONF['site_admin_url'] );
   839                 $start->set_var( 'layout_url', $_CONF['layout_url'] );
   840                 $start->set_var( 'hide_if_preview', 'style="display:none"' );
   841 
   842                 // Clean up all the vars
   843                 $A = array();
   844                 foreach ($_POST as $key => $value) {
   845                     if (($key == 'pid') || ($key == 'cid')) {
   846                         $A[$key] = COM_applyFilter ($_POST[$key], true);
   847                     } else if (($key == 'title') || ($key == 'comment')) {
   848                         // these have already been filtered above
   849                         $A[$key] = $_POST[$key];
   850                     } else if ($key == 'username') {
   851                         $A[$key] = htmlspecialchars(COM_checkWords(strip_tags(
   852                                     COM_stripslashes($_POST[$key]))));
   853                     } else {
   854                         $A[$key] = COM_applyFilter ($_POST[$key]);
   855                     }
   856                 }
   857 
   858                 // correct time and username for edit preview
   859                 if (($mode == $LANG03[28]) || ($mode == $LANG03[34])) { 
   860                     $A['nice_date'] = DB_getItem($table, 'UNIX_TIMESTAMP(date)',
   861                                                  "cid = '$cid'");
   862                     if ($_USER['uid'] != $commentuid) {
   863                         $uresult = DB_query("SELECT username, fullname, email, photo FROM {$_TABLES['users']} WHERE uid = $commentuid");
   864                         $A = array_merge($A, DB_fetchArray($uresult));
   865                     }
   866                 } 
   867                 if (empty ($A['username'])) {
   868                     $A['username'] = DB_getItem ($_TABLES['users'], 'username',
   869                                                  "uid = $uid");
   870                 }
   871                 $thecomments = CMT_getComment ($A, 'flat', $type, 'ASC', false,
   872                                                true);
   873 
   874                 $start->set_var( 'comments', $thecomments );
   875                 $retval .= COM_startBlock ($LANG03[14])
   876                         . $start->finish( $start->parse( 'output', 'comment' ))
   877                         . COM_endBlock ();
   878             } else if ($mode == $LANG03[14]) {
   879                 $retval .= COM_startBlock ($LANG03[17], '',
   880                                COM_getBlockTemplate ('_msg_block', 'header'))
   881                     . $LANG03[12]
   882                     . COM_endBlock(COM_getBlockTemplate ('_msg_block', 'footer'));
   883                 $mode = 'error';
   884             }
   885 
   886             $comment_template = new Template($_CONF['path_layout'] . 'comment');
   887             if (($_CONF['advanced_editor'] == 1) && file_exists ($_CONF['path_layout'] . 'comment/commentform_advanced.thtml')) {
   888                 $comment_template->set_file('form','commentform_advanced.thtml');
   889             } else {
   890                 $comment_template->set_file('form','commentform.thtml');
   891             }
   892             $comment_template->set_var('xhtml', XHTML);
   893             $comment_template->set_var('site_url', $_CONF['site_url']);
   894             $comment_template->set_var('site_admin_url', $_CONF['site_admin_url']);
   895             $comment_template->set_var('layout_url', $_CONF['layout_url']);
   896             $comment_template->set_var('start_block_postacomment', COM_startBlock($LANG03[1]));
   897             if ($_CONF['show_fullname'] == 1) {
   898                 $comment_template->set_var('lang_username', $LANG_ACCESS['name']);
   899             } else {
   900                 $comment_template->set_var('lang_username', $LANG03[5]);
   901             }
   902             $comment_template->set_var('sid', $sid);
   903             $comment_template->set_var('pid', $pid);
   904             $comment_template->set_var('type', $type);
   905 
   906             $formurl = $_CONF['site_url'] . '/comment.php';
   907             if ($mode == 'edit' || $mode == $LANG03[28]) { //edit modes
   908             	$comment_template->set_var('start_block_postacomment',
   909                                            COM_startBlock($LANG03[32]));
   910             	$comment_template->set_var('cid', '<input type="hidden" name="cid" value="' . $cid . '"' . XHTML . '>');
   911             } else if ($mode == 'editsubmission' || $mode == $LANG03[34]) {
   912                 $comment_template->set_var('start_block_postacomment',
   913                                            COM_startBlock($LANG03[33]));
   914                 $comment_template->set_var('cid', '<input type="hidden" name="cid" value="' . $cid . '"' . XHTML . '>');
   915             } else {
   916                 $comment_template->set_var('start_block_postacomment',
   917                                            COM_startBlock($LANG03[1]));
   918             	$comment_template->set_var('cid', '');
   919             }
   920             $comment_template->set_var('form_url', $formurl);
   921 
   922             if (COM_isAnonUser()) {
   923                 // Anonymous user
   924                 $comment_template->set_var('uid', 1);
   925                 if (isset($A['username'])) {
   926                     $name = $A['username']; // for preview
   927                 } elseif (isset($_COOKIE[$_CONF['cookie_anon_name']])) {
   928                     // stored as cookie, name used before
   929                     $name = htmlspecialchars(COM_checkWords(strip_tags(
   930                         COM_stripslashes($_COOKIE[$_CONF['cookie_anon_name']]))));
   931                 } else {
   932                     $name = COM_getDisplayName(1); // anonymous user
   933                 }
   934                 $usernameblock = '<input type="text" name="username" size="16" value="' . 
   935                                  $name . '" maxlength="32"' . XHTML . '>';
   936                 $comment_template->set_var('username', $usernameblock);
   937 
   938                 $comment_template->set_var('action_url',
   939                     $_CONF['site_url'] . '/users.php?mode=new');
   940                 $comment_template->set_var('lang_logoutorcreateaccount',
   941                     $LANG03[04]);
   942             } else {
   943                 if ($commentuid != $_USER['uid']) {
   944                     $uresult = DB_query("SELECT username, fullname FROM {$_TABLES['users']} WHERE uid = $commentuid");
   945                     list($username, $fullname) = DB_fetchArray($uresult);
   946                 } else {
   947                     $username = $_USER['username'];
   948                     $fullname = $_USER['fullname'];
   949                 }
   950                 $comment_template->set_var('gltoken_name', CSRF_TOKEN);
   951                 $comment_template->set_var('gltoken', SEC_createToken());
   952                 $comment_template->set_var('uid', $commentuid);
   953                 $name = COM_getDisplayName($commentuid, $username, $fullname);
   954                 $comment_template->set_var('username', $name);
   955                 $comment_template->set_var('action_url',
   956                     $_CONF['site_url'] . '/users.php?mode=logout');
   957                 $comment_template->set_var('lang_logoutorcreateaccount',
   958                     $LANG03[03]);
   959             }
   960 
   961             if ($postmode == 'html') {
   962                 $comment_template->set_var ('show_texteditor', 'none');
   963                 $comment_template->set_var ('show_htmleditor', '');
   964             } else {
   965                 $comment_template->set_var ('show_texteditor', '');
   966                 $comment_template->set_var ('show_htmleditor', 'none');
   967             }
   968 
   969             $comment_template->set_var('lang_title', $LANG03[16]);
   970             $comment_template->set_var('title', htmlspecialchars($title));
   971             $comment_template->set_var('lang_comment', $LANG03[9]);
   972             $comment_template->set_var('comment', $commenttext);
   973             $comment_template->set_var('lang_postmode', $LANG03[2]);
   974             $comment_template->set_var('postmode_options',
   975                 COM_optionList($_TABLES['postmodes'], 'code,name', $postmode));
   976             $comment_template->set_var('allowed_html',
   977                 COM_allowedHTML($type == 'article'
   978                                 ? 'story.edit' : "$type.edit"));
   979             $comment_template->set_var('lang_importantstuff', $LANG03[18]);
   980             $comment_template->set_var('lang_instr_line1', $LANG03[19]);
   981             $comment_template->set_var('lang_instr_line2', $LANG03[20]);
   982             $comment_template->set_var('lang_instr_line3', $LANG03[21]);
   983             $comment_template->set_var('lang_instr_line4', $LANG03[22]);
   984             $comment_template->set_var('lang_instr_line5', $LANG03[23]);
   985 
   986             if ($mode == 'edit' || $mode == $LANG03[28]) {
   987                 //editing comment or preview changes
   988                 $comment_template->set_var('lang_preview', $LANG03[28]); 
   989             } elseif ($mode == 'editsubmission' || $mode == $LANG03[34]) {
   990                 $comment_template->set_var('lang_preview', $LANG03[34]);
   991             } else {
   992             	//new comment
   993                 $comment_template->set_var('lang_preview', $LANG03[14]);
   994             }
   995 
   996             PLG_templateSetVars('comment', $comment_template); 
   997             if ($mode == $LANG03[28] || ($mode == 'edit' && $_CONF['skip_preview'] == 1)) { 
   998                 // for editing
   999                 $comment_template->set_var('save_option',
  1000                     '<input type="submit" name="mode" value="' . $LANG03[29]
  1001                     . '"' . XHTML . '>');
  1002             } elseif ($mode == $LANG03[34] || ($mode == 'editsubmission' && $_CONF['skip_preview'] == 1))  {
  1003                 // editing submission comment
  1004                 $comment_template->set_var('save_option',
  1005                     '<input type="submit" name="mode" value="' . $LANG03[35]
  1006                     . '"' . XHTML . '>');
  1007             } elseif (($_CONF['skip_preview'] == 1) || ($mode == $LANG03[14])) {
  1008                 $comment_template->set_var('save_option',
  1009                     '<input type="submit" name="mode" value="' . $LANG03[11]
  1010                     . '"' . XHTML . '>');
  1011 
  1012             }
  1013             
  1014             if (($_CONF['allow_reply_notifications'] == 1 && $uid != 1) && 
  1015                     ($mode == '' || $mode == $LANG03[14] || $mode == 'error')) {
  1016                 $checked = '';
  1017                 if (isset($_POST['notify'])) {
  1018                     $checked = ' checked="checked"';
  1019                 }
  1020                 $comment_template->set_var('notification',
  1021                     '<p><input type="checkbox"' . ' name="notify"' . $checked
  1022                     . '>' . $LANG03[36] . '</p>');
  1023             }
  1024             
  1025             $comment_template->set_var('end_block', COM_endBlock());
  1026             $comment_template->parse('output', 'form');
  1027             $retval .= $comment_template->finish($comment_template->get_var('output'));
  1028         }
  1029     }
  1030 
  1031     return $retval;
  1032 }
  1033 
  1034 /**
  1035  * Save a comment
  1036  *
  1037  * @author   Vincent Furia, vinny01 AT users DOT sourceforge DOT net
  1038  * @param    string      $title      Title of comment
  1039  * @param    string      $comment    Text of comment
  1040  * @param    string      $sid        ID of object receiving comment
  1041  * @param    int         $pid        ID of parent comment
  1042  * @param    string      $type       Type of comment this is (article, polls, etc)
  1043  * @param    string      $postmode   Indicates if text is HTML or plain text
  1044  * @return   int         -1 == queued, 0 == comment saved, > 0 indicates error
  1045  *
  1046  */
  1047 function CMT_saveComment($title, $comment, $sid, $pid, $type, $postmode)
  1048 {
  1049     global $_CONF, $_TABLES, $_USER, $LANG03;
  1050 
  1051     $ret = 0;
  1052 
  1053     // Get a valid uid
  1054     if (empty ($_USER['uid'])) {
  1055         $uid = 1;
  1056     } else {
  1057         $uid = $_USER['uid'];
  1058     }
  1059 
  1060     // Sanity check
  1061     if (empty ($sid) || empty ($title) || empty ($comment) || empty ($type) ) {
  1062         COM_errorLog("CMT_saveComment: $uid from {$_SERVER['REMOTE_ADDR']} tried "
  1063                    . 'to submit a comment with one or more missing values.');
  1064         return $ret = 1;
  1065     }
  1066 
  1067     // Check that anonymous comments are allowed
  1068     if (($uid == 1) && (($_CONF['loginrequired'] == 1)
  1069             || ($_CONF['commentsloginrequired'] == 1))) {
  1070         COM_errorLog("CMT_saveComment: IP address {$_SERVER['REMOTE_ADDR']} "
  1071                    . 'attempted to save a comment with anonymous comments disabled for site.');
  1072         return $ret = 2;
  1073     }
  1074 
  1075     // Check for people breaking the speed limit
  1076     COM_clearSpeedlimit ($_CONF['commentspeedlimit'], 'comment');
  1077     $last = COM_checkSpeedlimit ('comment');
  1078     if ($last > 0) {
  1079         COM_errorLog("CMT_saveComment: $uid from {$_SERVER['REMOTE_ADDR']} tried "
  1080                    . 'to submit a comment before the speed limit expired');
  1081         return $ret = 3;
  1082     }
  1083 
  1084     // Let plugins have a chance to check for spam
  1085     $spamcheck = '<h1>' . $title . '</h1><p>' . $comment . '</p>';
  1086     $result = PLG_checkforSpam ($spamcheck, $_CONF['spamx']);
  1087     // Now check the result and display message if spam action was taken
  1088     if ($result > 0) {
  1089         // update speed limit nonetheless
  1090         COM_updateSpeedlimit ('comment');
  1091 
  1092         // then tell them to get lost ...
  1093         COM_displayMessageAndAbort ($result, 'spamx', 403, 'Forbidden');
  1094     }
  1095 
  1096     // Let plugins have a chance to decide what to do before saving the comment, return errors.
  1097     if ($someError = PLG_commentPreSave($uid, $title, $comment, $sid, $pid, $type, $postmode)) {
  1098         return $someError;
  1099     }
  1100 
  1101     $comment = addslashes(CMT_prepareText($comment, $postmode, $type));
  1102     $title = addslashes(COM_checkWords(strip_tags($title)));
  1103     if (($uid == 1) && isset($_POST['username'])) {
  1104         $anon = COM_getDisplayName(1);
  1105         if (strcmp($_POST['username'], $anon) != 0) {
  1106             $username = COM_checkWords(strip_tags(COM_stripslashes($_POST['username'])));
  1107             setcookie($_CONF['cookie_anon_name'], $username, time() + 31536000,
  1108                       $_CONF['cookie_path'], $_CONF['cookiedomain'],
  1109                       $_CONF['cookiesecure']);
  1110             $name = addslashes($username);
  1111         }
  1112     }
  1113 
  1114     // check for non-int pid's
  1115     // this should just create a top level comment that is a reply to the original item
  1116     if (!is_numeric($pid) || ($pid < 0)) {
  1117         $pid = 0;
  1118     }
  1119 
  1120     COM_updateSpeedlimit('comment');
  1121     if (empty($title) || empty($comment)) {
  1122         COM_errorLog("CMT_saveComment: $uid from {$_SERVER['REMOTE_ADDR']} tried "
  1123                    . 'to submit a comment with invalid $title and/or $comment.');
  1124         $ret = 5;
  1125     } elseif (($_CONF['commentsubmission'] == 1) &&
  1126             !SEC_hasRights('comment.submit')) {
  1127         // comment into comment submission table enabled
  1128         if (isset($name)) {
  1129             DB_save($_TABLES['commentsubmissions'],
  1130                     'sid,uid,name,comment,date,title,pid,ipaddress,type',
  1131                     "'$sid',$uid,'$name','$comment',NOW(),'$title',$pid,'{$_SERVER['REMOTE_ADDR']}','$type'");
  1132         } else {
  1133             DB_save($_TABLES['commentsubmissions'],
  1134                     'sid,uid,comment,date,title,pid,ipaddress,type',
  1135                     "'$sid',$uid,'$comment',NOW(),'$title',$pid,'{$_SERVER['REMOTE_ADDR']}','$type'");
  1136         }
  1137 
  1138         $ret = -1; // comment queued
  1139     } elseif ($pid > 0) {
  1140         DB_lockTable ($_TABLES['comments']);
  1141         
  1142         $result = DB_query("SELECT rht, indent FROM {$_TABLES['comments']} WHERE cid = $pid "
  1143                          . "AND sid = '$sid'");
  1144         list($rht, $indent) = DB_fetchArray($result);
  1145         if ( !DB_error() ) {
  1146             DB_query("UPDATE {$_TABLES['comments']} SET lft = lft + 2 "
  1147                    . "WHERE sid = '$sid' AND type = '$type' AND lft >= $rht");
  1148             DB_query("UPDATE {$_TABLES['comments']} SET rht = rht + 2 "
  1149                    . "WHERE sid = '$sid' AND type = '$type' AND rht >= $rht");
  1150             if (isset($name)) {
  1151                 DB_save ($_TABLES['comments'], 'sid,uid,comment,date,title,pid,lft,rht,indent,type,ipaddress,name',
  1152              "'$sid',$uid,'$comment',now(),'$title',$pid,$rht,$rht+1,$indent+1,'$type','{$_SERVER['REMOTE_ADDR']}','$name'");
  1153             } else {
  1154                 DB_save ($_TABLES['comments'], 'sid,uid,comment,date,title,pid,lft,rht,indent,type,ipaddress',
  1155              "'$sid',$uid,'$comment',now(),'$title',$pid,$rht,$rht+1,$indent+1,'$type','{$_SERVER['REMOTE_ADDR']}'");
  1156             }
  1157             
  1158         } else { //replying to non-existent comment or comment in wrong article
  1159             COM_errorLog("CMT_saveComment: $uid from {$_SERVER['REMOTE_ADDR']} tried "
  1160                        . 'to reply to a non-existent comment or the pid/sid did not match');
  1161             $ret = 4; // Cannot return here, tables locked!
  1162         }
  1163     } else {
  1164         $rht = DB_getItem($_TABLES['comments'], 'MAX(rht)', "sid = '$sid'");
  1165         if ( DB_error() ) {
  1166             $rht = 0;
  1167         }
  1168         if (isset($name)) {
  1169             DB_save ($_TABLES['comments'], 'sid,uid,comment,date,title,pid,lft,rht,indent,type,ipaddress,name',
  1170                 "'$sid',$uid,'$comment',now(),'$title',$pid,$rht+1,$rht+2,0,'$type','{$_SERVER['REMOTE_ADDR']}','$name'");
  1171         } else {
  1172             $rht = DB_getItem($_TABLES['comments'], 'MAX(rht)', "sid = '$sid'");
  1173             if ( DB_error() ) {
  1174                 $rht = 0;
  1175             }
  1176             DB_save ($_TABLES['comments'], 'sid,uid,comment,date,title,pid,lft,rht,indent,type,ipaddress',
  1177                 "'$sid',$uid,'$comment',now(),'$title',$pid,$rht+1,$rht+2,0,'$type','{$_SERVER['REMOTE_ADDR']}'");
  1178         }
  1179         
  1180     }
  1181 
  1182     $cid = DB_insertId();
  1183     DB_unlockTable($_TABLES['comments']);
  1184 
  1185     // notify of new comment 
  1186     if ($_CONF['allow_reply_notifications'] == 1 && $pid > 0 && $ret == 0) {
  1187         $result = DB_query("SELECT cid, uid, deletehash FROM {$_TABLES['commentnotifications']} WHERE cid = $pid");
  1188         $A = DB_fetchArray($result);
  1189         if ($A !== false) {
  1190             CMT_sendReplyNotification($A);
  1191         }
  1192     }
  1193 
  1194     // save user notification information
  1195     if (isset($_POST['notify']) && ($ret == -1 || $ret == 0) ) {
  1196         $deletehash = md5($title . $cid . $comment . rand());
  1197         if ($ret == -1) {
  1198             //null goes into cid, comment not published yet, set moderation queue id
  1199             DB_save($_TABLES['commentnotifications'], 'uid,deletehash,mid',"$uid,'$deletehash',$cid");
  1200         } else {
  1201             DB_save($_TABLES['commentnotifications'], 'cid,uid,deletehash',"$cid,$uid,'$deletehash'");
  1202         }
  1203     }
  1204 
  1205     // Send notification of comment if no errors and notifications enabled
  1206     // for comments
  1207     if ((($ret == -1) || ($ret == 0)) && isset($_CONF['notification']) &&
  1208             in_array('comment', $_CONF['notification'])) {
  1209         if ($ret == -1) {
  1210             $cid = 0; // comment went into the submission queue
  1211         }
  1212         if (($uid == 1) && isset($username)) {
  1213             CMT_sendNotification($title, $comment, $uid, $username,
  1214                                  $_SERVER['REMOTE_ADDR'], $type, $cid);
  1215         } else {
  1216             CMT_sendNotification($title, $comment, $uid, '',
  1217                                  $_SERVER['REMOTE_ADDR'], $type, $cid);
  1218         }
  1219     }
  1220     
  1221     return $ret;
  1222 }
  1223 
  1224 /**
  1225 * Send an email notification for a new comment submission.
  1226 *
  1227 * @param    $title      string      comment title
  1228 * @param    $comment    string      text of the comment
  1229 * @param    $uid        int         user id
  1230 * @param    $username   string      optional name of anonymous user
  1231 * @param    $ipaddress  string      poster's IP address
  1232 * @param    $type       string      type of comment ('article', 'polls', ...)
  1233 * @param    $cid        int         comment id (or 0 when in submission queue)
  1234 * @return               boolean     true if successfully sent, otherwise false
  1235 *
  1236 */
  1237 function CMT_sendNotification($title, $comment, $uid, $username, $ipaddress, $type, $cid)
  1238 {
  1239     global $_CONF, $_TABLES, $LANG01, $LANG03, $LANG08, $LANG09, $LANG29;
  1240 
  1241     // sanity check
  1242     if (($username == $_SERVER['REMOTE_ADDR']) &&
  1243             ($ipaddress != $_SERVER['REMOTE_ADDR'])) {
  1244         COM_errorLog("The API for CMT_sendNotification has changed ...");
  1245         return false;
  1246     }
  1247 
  1248     // we have to undo the addslashes() call from savecomment()
  1249     $title = stripslashes($title);
  1250     $comment = stripslashes($comment);
  1251 
  1252     // strip HTML if posted in HTML mode
  1253     if (preg_match('/<.*>/', $comment) != 0) {
  1254         $comment = strip_tags($comment);
  1255     }
  1256 
  1257     if ($uid < 1) {
  1258         $uid = 1;
  1259     }
  1260     if (($uid == 1) && !empty($username)) {
  1261         $author = $username;
  1262     } else {
  1263         $author = COM_getDisplayName($uid);
  1264     }
  1265     if (($uid == 1) && !empty($ipaddress)) {
  1266         // add IP address for anonymous posters
  1267         $author .= ' (' . $ipaddress . ')';
  1268     }
  1269 
  1270     $mailbody = "$LANG03[16]: $title\n"
  1271               . "$LANG03[5]: $author\n";
  1272 
  1273     if ($type != 'article') {
  1274         $mailbody .= "$LANG09[5]: $type\n";
  1275     }
  1276 
  1277     if ($_CONF['emailstorieslength'] > 0) {
  1278         if ($_CONF['emailstorieslength'] > 1) {
  1279             $comment = MBYTE_substr($comment, 0, $_CONF['emailstorieslength'])
  1280                      . '...';
  1281         }
  1282         $mailbody .= $comment . "\n\n";
  1283     }
  1284 
  1285     if ($cid == 0) {
  1286         $mailsubject = $_CONF['site_name'] . ' ' . $LANG29[41];
  1287         $mailbody .= $LANG01[10] . ' <' . $_CONF['site_admin_url']
  1288                   . "/moderation.php>\n\n";
  1289     } else {
  1290         $mailsubject = $_CONF['site_name'] . ' ' . $LANG03[9];
  1291         $mailbody .= $LANG03[39] . ' <' . $_CONF['site_url']
  1292                   . '/comment.php?mode=view&cid=' . $cid . ">\n\n";
  1293     }
  1294 
  1295     $mailbody .= "\n------------------------------\n";
  1296     $mailbody .= "\n$LANG08[34]\n";
  1297     $mailbody .= "\n------------------------------\n";
  1298 
  1299 
  1300     return COM_mail($_CONF['site_mail'], $mailsubject, $mailbody);
  1301 }
  1302 
  1303 /**
  1304  * Deletes a given comment
  1305  *
  1306  * The function expects the calling function to check to make sure the
  1307  * requesting user has the correct permissions and that the comment exits
  1308  * for the specified $type and $sid.
  1309  *
  1310  * @author  Vincent Furia, vinny01 AT users DOT sourceforge DOT net
  1311  * @param   string      $type   article, or plugin identifier
  1312  * @param   string      $sid    id of object comment belongs to
  1313  * @param   int         $cid    Comment ID
  1314  * @return  string      0 indicates success, >0 identifies problem
  1315  */
  1316 function CMT_deleteComment ($cid, $sid, $type)
  1317 {
  1318     global $_CONF, $_TABLES, $_USER;
  1319 
  1320     $ret = 0;  // Assume good status unless reported otherwise
  1321 
  1322     // Sanity check, note we return immediately here and no DB operations
  1323     // are performed
  1324     if (!is_numeric ($cid) || ($cid < 0) || empty ($sid) || empty ($type)) {
  1325         COM_errorLog("CMT_deleteComment: {$_USER['uid']} from {$_SERVER['REMOTE_ADDR']} tried "
  1326                    . 'to delete a comment with one or more missing/bad values.');
  1327         return $ret = 1;
  1328     }
  1329 
  1330     // Delete the comment from the DB and update the other comments to
  1331     // maintain the tree structure
  1332     // A lock is needed here to prevent other additions and/or deletions
  1333     // from happening at the same time. A transaction would work better,
  1334     // but aren't supported with MyISAM tables.
  1335     DB_lockTable ($_TABLES['comments']);
  1336     $result = DB_query("SELECT pid, lft, rht FROM {$_TABLES['comments']} "
  1337                      . "WHERE cid = $cid AND sid = '$sid' AND type = '$type'");
  1338     if ( DB_numRows($result) == 1 ) {
  1339         list($pid,$lft,$rht) = DB_fetchArray($result);
  1340         DB_change ($_TABLES['comments'], 'pid', $pid, 'pid', $cid);
  1341         DB_delete ($_TABLES['comments'], 'cid', $cid);
  1342         DB_query("UPDATE {$_TABLES['comments']} SET indent = indent - 1 "
  1343            . "WHERE sid = '$sid' AND type = '$type' AND lft BETWEEN $lft AND $rht");
  1344         DB_query("UPDATE {$_TABLES['comments']} SET lft = lft - 2 "
  1345            . "WHERE sid = '$sid' AND type = '$type'  AND lft >= $rht");
  1346         DB_query("UPDATE {$_TABLES['comments']} SET rht = rht - 2 "
  1347            . "WHERE sid = '$sid' AND type = '$type'  AND rht >= $rht");
  1348     } else {
  1349         COM_errorLog("CMT_deleteComment: {$_USER['uid']} from {$_SERVER['REMOTE_ADDR']} tried "
  1350                    . 'to delete a comment that doesn\'t exist as described.');
  1351         return $ret = 2;
  1352     }
  1353 
  1354     DB_unlockTable ($_TABLES['comments']);
  1355 
  1356     return $ret;
  1357 }
  1358 
  1359 /**
  1360 * Display form to report abusive comment.
  1361 *
  1362 * @param    string  $cid    comment id
  1363 * @param    string  $type   type of comment ('article', 'polls', ...)
  1364 * @return   string          HTML for the form (or error message)
  1365 *
  1366 */
  1367 function CMT_reportAbusiveComment ($cid, $type)
  1368 {
  1369     global $_CONF, $_TABLES, $_USER, $LANG03, $LANG12, $LANG_LOGIN;
  1370 
  1371     $retval = '';
  1372 
  1373     if (empty ($_USER['username'])) {
  1374         $retval .= COM_startBlock ($LANG_LOGIN[1], '',
  1375                            COM_getBlockTemplate ('_msg_block', 'header'));
  1376         $loginreq = new Template ($_CONF['path_layout'] . 'submit');
  1377         $loginreq->set_file ('loginreq', 'submitloginrequired.thtml');
  1378         $loginreq->set_var ('xhtml', XHTML);
  1379         $loginreq->set_var ('login_message', $LANG_LOGIN[2]);
  1380         $loginreq->set_var ('site_url', $_CONF['site_url']);
  1381         $loginreq->set_var ('lang_login', $LANG_LOGIN[3]);
  1382         $loginreq->set_var ('lang_newuser', $LANG_LOGIN[4]);
  1383         $loginreq->parse ('errormsg', 'loginreq');
  1384         $retval .= $loginreq->finish ($loginreq->get_var ('errormsg'));
  1385         $retval .= COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
  1386 
  1387         return $retval;
  1388     }
  1389 
  1390     COM_clearSpeedlimit ($_CONF['speedlimit'], 'mail');
  1391     $last = COM_checkSpeedlimit ('mail');
  1392     if ($last > 0) {
  1393         $retval .= COM_startBlock ($LANG12[26], '',
  1394                             COM_getBlockTemplate ('_msg_block', 'header'))
  1395                 . $LANG12[30] . $last . $LANG12[31]
  1396                 . COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
  1397 
  1398         return $retval;
  1399     }
  1400 
  1401     $start = new Template($_CONF['path_layout'] . 'comment');
  1402     $start->set_file(array('report' => 'reportcomment.thtml'));
  1403     $start->set_var('xhtml', XHTML);
  1404     $start->set_var('site_url', $_CONF['site_url']);
  1405     $start->set_var('layout_url', $_CONF['layout_url']);
  1406     $start->set_var('lang_report_this', $LANG03[25]);
  1407     $start->set_var('lang_send_report', $LANG03[10]);
  1408     $start->set_var('cid', $cid);
  1409     $start->set_var('type', $type);
  1410     $start->set_var('gltoken_name', CSRF_TOKEN);
  1411     $start->set_var('gltoken', SEC_createToken());
  1412 
  1413     $result = DB_query ("SELECT uid,sid,pid,title,comment,UNIX_TIMESTAMP(date) AS nice_date FROM {$_TABLES['comments']} WHERE cid = $cid AND type = '$type'");
  1414     $A = DB_fetchArray ($result);
  1415 
  1416     $result = DB_query ("SELECT username,fullname,photo,email FROM {$_TABLES['users']} WHERE uid = {$A['uid']}");
  1417     $B = DB_fetchArray ($result);
  1418 
  1419     // prepare data for comment preview
  1420     $A['cid'] = $cid;
  1421     $A['type'] = $type;
  1422     $A['username'] = $B['username'];
  1423     $A['fullname'] = $B['fullname'];
  1424     $A['photo'] = $B['photo'];
  1425     $A['email'] = $B['email'];
  1426     $A['indent'] = 0;
  1427     $A['pindent'] = 0;
  1428 
  1429     $thecomment = CMT_getComment ($A, 'flat', $type, 'ASC', false, true);
  1430     $start->set_var ('comment', $thecomment);
  1431     $retval .= COM_startBlock ($LANG03[15])
  1432             . $start->finish ($start->parse ('output', 'report'))
  1433             . COM_endBlock ();
  1434 
  1435     return $retval;
  1436 }
  1437 
  1438 /**
  1439 * Send report about abusive comment
  1440 *
  1441 * @param    string  $cid    comment id
  1442 * @param    string  $type   type of comment ('article', 'polls', ...)
  1443 * @return   string          Meta refresh or HTML for error message
  1444 *
  1445 */
  1446 function CMT_sendReport ($cid, $type)
  1447 {
  1448     global $_CONF, $_TABLES, $_USER, $LANG03, $LANG08, $LANG_LOGIN;
  1449 
  1450     if (empty ($_USER['username'])) {
  1451         $retval = COM_siteHeader ('menu', $LANG_LOGIN[1]);
  1452         $retval .= COM_startBlock ($LANG_LOGIN[1], '',
  1453                            COM_getBlockTemplate ('_msg_block', 'header'));
  1454         $loginreq = new Template ($_CONF['path_layout'] . 'submit');
  1455         $loginreq->set_file ('loginreq', 'submitloginrequired.thtml');
  1456         $loginreq->set_var ('xhtml', XHTML);
  1457         $loginreq->set_var ('login_message', $LANG_LOGIN[2]);
  1458         $loginreq->set_var ('site_url', $_CONF['site_url']);
  1459         $loginreq->set_var ('lang_login', $LANG_LOGIN[3]);
  1460         $loginreq->set_var ('lang_newuser', $LANG_LOGIN[4]);
  1461         $loginreq->parse ('errormsg', 'loginreq');
  1462         $retval .= $loginreq->finish ($loginreq->get_var ('errormsg'));
  1463         $retval .= COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
  1464         $retval .= COM_siteFooter ();
  1465 
  1466         return $retval;
  1467     }
  1468 
  1469     COM_clearSpeedlimit ($_CONF['speedlimit'], 'mail');
  1470     if (COM_checkSpeedlimit ('mail') > 0) {
  1471         return COM_refresh ($_CONF['site_url'] . '/index.php');
  1472     }
  1473 
  1474     $username = DB_getItem ($_TABLES['users'], 'username',
  1475                             "uid = {$_USER['uid']}");
  1476     $result = DB_query ("SELECT uid,title,comment,sid,ipaddress FROM {$_TABLES['comments']} WHERE cid = $cid AND type = '$type'");
  1477     $A = DB_fetchArray ($result);
  1478 
  1479     $title = stripslashes ($A['title']);
  1480     $comment = stripslashes ($A['comment']);
  1481 
  1482     // strip HTML if posted in HTML mode
  1483     if (preg_match ('/<.*>/', $comment) != 0) {
  1484         $comment = strip_tags ($comment);
  1485     }
  1486 
  1487     $author = COM_getDisplayName ($A['uid']);
  1488     if (($A['uid'] <= 1) && !empty ($A['ipaddress'])) {
  1489         // add IP address for anonymous posters
  1490         $author .= ' (' . $A['ipaddress'] . ')';
  1491     }
  1492 
  1493     $mailbody = sprintf ($LANG03[26], $username);
  1494     $mailbody .= "\n\n"
  1495               . "$LANG03[16]: $title\n"
  1496               . "$LANG03[5]: $author\n";
  1497 
  1498     if ($type != 'article') {
  1499         $mailbody .= "$LANG09[5]: $type\n";
  1500     }
  1501 
  1502     if ($_CONF['emailstorieslength'] > 0) {
  1503         if ($_CONF['emailstorieslength'] > 1) {
  1504             $comment = MBYTE_substr ($comment, 0, $_CONF['emailstorieslength'])
  1505                      . '...';
  1506         }
  1507         $mailbody .= $comment . "\n\n";
  1508     }
  1509 
  1510     $mailbody .= $LANG08[33] . ' <' . $_CONF['site_url']
  1511               . '/comment.php?mode=view&cid=' . $cid . ">\n\n";
  1512 
  1513     $mailbody .= "\n------------------------------\n";
  1514     $mailbody .= "\n$LANG08[34]\n";
  1515     $mailbody .= "\n------------------------------\n";
  1516 
  1517     $mailsubject = $_CONF['site_name'] . ' ' . $LANG03[27];
  1518 
  1519     if (COM_mail ($_CONF['site_mail'], $mailsubject, $mailbody)) {
  1520         $msg = 27; // message sent
  1521     } else {
  1522         $msg = 85; // problem sending the email
  1523     }
  1524     COM_updateSpeedlimit ('mail');
  1525 
  1526     return COM_refresh ($_CONF['site_url'] . "/index.php?msg=$msg");
  1527 }
  1528 
  1529 /**
  1530  * Handles a comment edit submission
  1531  *
  1532  * @copyright Jared Wenerd 2008
  1533  * @author Jared Wenerd, wenerd87 AT gmail DOT com
  1534  * @param  string $mode whether to store edited comment in the queue
  1535  * @return string HTML (possibly a refresh)
  1536  */
  1537 function CMT_handleEditSubmit($mode = null)
  1538 {
  1539     global $_CONF, $_TABLES, $_USER, $LANG03;
  1540 
  1541     $display = '';
  1542 
  1543     $type = COM_applyFilter($_POST['type']);
  1544     $sid = COM_applyFilter($_POST['sid']);
  1545     $cid = COM_applyFilter($_POST['cid']);
  1546     $postmode = COM_applyFilter($_POST['postmode']);
  1547     
  1548     $commentuid = DB_getItem ($_TABLES['comments'], 'uid', "cid = '$cid'");
  1549     if ( empty($_USER['uid'])) {
  1550         $uid = 1;
  1551     } else {
  1552         $uid = $_USER['uid'];
  1553     }
  1554         
  1555     // check for bad input
  1556     if (empty($sid) || empty($_POST['title']) || empty($_POST['comment']) ||
  1557             !is_numeric($cid) || ($cid < 1)) {
  1558         COM_errorLog("CMT_handleEditSubmit(): {{$_USER['uid']} from {$_SERVER['REMOTE_ADDR']} tried to edit a comment with one or more missing values.");
  1559         return COM_refresh($_CONF['site_url'] . '/index.php');
  1560     } elseif ( $uid != $commentuid && !SEC_hasRights( 'comment.moderate' ) ) {
  1561         //check permissions
  1562         COM_errorLog("CMT_handleEditSubmit(): {{$_USER['uid']} from {$_SERVER['REMOTE_ADDR']} tried "
  1563                    . 'to edit a comment without proper permission.');
  1564         return COM_refresh($_CONF['site_url'] . '/index.php');
  1565     }
  1566 
  1567     $comment = CMT_prepareText($_POST['comment'], $postmode, $type);
  1568     $title = COM_checkWords (strip_tags (COM_stripslashes ($_POST['title'])));
  1569     
  1570     if ($mode == $LANG03[35]) {
  1571         $table = $_TABLES['commentsubmissions'];
  1572     } else {
  1573         $table = $_TABLES['comments'];
  1574     }
  1575     
  1576     if (!empty ($title) && !empty ($comment)) {
  1577         COM_updateSpeedlimit ('comment');
  1578         $title = addslashes ($title);
  1579         $comment = addslashes ($comment);
  1580   
  1581         // save the comment into the table
  1582         DB_query("UPDATE $table SET comment = '$comment', title = '$title'"
  1583                 . " WHERE cid=$cid AND sid='$sid'");
  1584         
  1585         if (DB_error() ) { //saving to non-existent comment or comment in wrong article
  1586             COM_errorLog("CMT_handleEditSubmit(): {$_USER['uid']} from {$_SERVER['REMOTE_ADDR']} tried "
  1587             . 'to edit to a non-existent comment or the cid/sid did not match');
  1588             return COM_refresh($_CONF['site_url'] . '/index.php');
  1589         }
  1590         //save edit information for published comment
  1591         if ($mode != $LANG03[35]) {
  1592             DB_save($_TABLES['commentedits'],'cid,uid,time',"$cid,$uid,NOW()");
  1593         } else {
  1594             return COM_refresh (COM_buildUrl ($_CONF['site_admin_url'] . "/moderation.php"));
  1595         }
  1596         
  1597     } else {
  1598         COM_errorLog("CMT_handleEditSubmit(): {$_USER['uid']} from {$_SERVER['REMOTE_ADDR']} tried "
  1599                    . 'to submit a comment with invalid $title and/or $comment.');
  1600         return COM_refresh($_CONF['site_url'] . '/index.php');
  1601     }
  1602 
  1603     return COM_refresh(COM_buildUrl($_CONF['site_url']
  1604                                     . "/article.php?story=$sid"));
  1605 }
  1606 
  1607 /**
  1608  * Filters comment text and appends necessary tags (sig and/or edit)
  1609  *
  1610  * @copyright Jared Wenerd 2008
  1611  * @author Jared Wenerd, wenerd87 AT gmail DOT com
  1612  * @param string  $comment  comment text
  1613  * @param string  $postmode ('html', 'plaintext', ...)
  1614  * @param string  $type     Type of item (article, polls, etc.)
  1615  * @param bool    $edit     if true append edit tag
  1616  * @param int     $cid      commentid if editing comment (for proper sig)
  1617  * @return string of comment text
  1618  */
  1619 function CMT_prepareText($comment, $postmode, $type, $edit = false, $cid = null)
  1620 {
  1621     global $_USER, $_TABLES, $LANG03, $_CONF; 
  1622     
  1623     if ($postmode == 'html') {
  1624         $html_perm = ($type == 'article') ? 'story.edit' : "$type.edit";
  1625         $comment = COM_checkWords(COM_checkHTML(COM_stripslashes($comment),
  1626                                                 $html_perm));
  1627     } else {
  1628     	// plaintext
  1629         $comment = htmlspecialchars(COM_checkWords(COM_stripslashes($comment)));
  1630         $newcomment = COM_makeClickableLinks ($comment);
  1631         if (strcmp ($comment, $newcomment) != 0) {
  1632             $comment = nl2br ($newcomment);
  1633         }
  1634     }
  1635     
  1636     if ($edit) {
  1637         $comment .= '<div class="comment-edit">' . $LANG03[30] . ' '
  1638                  . strftime($_CONF['date'], time()) . ' ' .$LANG03[31] .' ' 
  1639                  . $_USER['username'] . '</div><!-- /COMMENTEDIT -->';
  1640         $text = $comment;
  1641         
  1642     }
  1643     
  1644     if (empty ($_USER['uid'])) {
  1645         $uid = 1;
  1646     } elseif ($edit && is_numeric($cid) ){
  1647         //if comment moderator
  1648         $uid = DB_getItem ($_TABLES['comments'], 'uid', "cid = '$cid'");
  1649     } else {
  1650         $uid = $_USER['uid'];
  1651     }
  1652     
  1653     $sig = '';
  1654     if ($uid > 1) {
  1655         $sig = DB_getItem ($_TABLES['users'], 'sig', "uid = '$uid'");
  1656         if (!empty ($sig)) {
  1657             $comment .= '<!-- COMMENTSIG --><div class="comment-sig">';
  1658             if ( $postmode == 'html') {
  1659                 $comment .= '---<br' . XHTML . '>' . nl2br($sig);
  1660             } else {
  1661                 $comment .=  '---' . LB . $sig;
  1662             }
  1663         $comment .= '</div><!-- /COMMENTSIG -->';
  1664         }
  1665     }
  1666     
  1667     return $comment;
  1668 }
  1669 
  1670 /**
  1671  * Disables comments for all stories where current time is past comment expire
  1672  * time and enables comments for certain number of most recent stories.
  1673  *
  1674  * @copyright Jared Wenerd 2008
  1675  * @author Jared Wenerd, wenerd87 AT gmail DOT com
  1676  */
  1677 function CMT_updateCommentcodes()
  1678 {
  1679     global $_CONF, $_TABLES;
  1680 
  1681     if ($_CONF['comment_close_rec_stories'] > 0) {
  1682         $results = DB_query("SELECT sid FROM {$_TABLES['stories']} WHERE (date <= NOW()) AND (draft_flag = 0) ORDER BY date DESC LIMIT {$_CONF['comment_close_rec_stories']}");
  1683         while ($A = DB_fetchArray($results)) {
  1684             $allowedcomments[] = $A['sid'];
  1685         }
  1686         // update comment codes
  1687         $sql = ' AND ';
  1688         if (count($allowedcomments) > 1) {
  1689             $sql .= "sid NOT IN ('" . implode("','", $allowedcomments) . "')";
  1690         } else {
  1691             $sql .= "sid <> '$sid'";
  1692         }
  1693         $sql = "UPDATE {$_TABLES['stories']} SET commentcode = 1 WHERE (commentcode = 0) AND (date < NOW()) AND (draft_flag = 0)" . $sql;
  1694         DB_query($sql);
  1695     }
  1696 
  1697     $sql = "UPDATE {$_TABLES['stories']} SET commentcode = 1 WHERE UNIX_TIMESTAMP(comment_expire) < UNIX_TIMESTAMP() AND UNIX_TIMESTAMP(comment_expire) <> 0";
  1698     DB_query($sql);
  1699 }
  1700 
  1701 /**
  1702  * Rebuilds hierarchical data of comments after moderation using recursion.
  1703  *
  1704  * @copyright Jared Wenerd 2008
  1705  * @author Jared Wenerd, wenerd87 AT gmail DOT com
  1706  * @param  string $sid   id of object comment belongs to
  1707  * @param  int    $pid   id of parent comment
  1708  * @param  int    $left  id of left-hand successor
  1709  * @return int           id of right-hand successor
  1710  * @see    CMT_deleteComment
  1711  *
  1712  */
  1713 function CMT_rebuildTree($sid, $pid = 0, $left = 0)
  1714 {
  1715     global $_TABLES;
  1716     
  1717     $right = $left + 1;
  1718     $result = DB_query ("SELECT cid FROM {$_TABLES['comments']} WHERE sid = '$sid' AND pid = $pid ORDER BY date ASC");
  1719     while (DB_numRows($result) != 0 && $A = DB_fetchArray ($result)) {
  1720         $right = CMT_rebuildTree($sid, $A['cid'], $right);
  1721         
  1722     }
  1723     if ($pid != 0) {
  1724         DB_query ("UPDATE {$_TABLES['comments']} SET lft = $left, rht = $right WHERE cid = $pid");
  1725     }
  1726     
  1727     return $right+1;
  1728 }
  1729 
  1730 /**
  1731  * Moves comment from submission table to comments table
  1732  * 
  1733  * @copyright Jared Wenerd 2008
  1734  * @author Jared Wenerd, wenerd87 AT gmail DOT com
  1735  * @param  string $cid comment id
  1736  * @return string of story id 
  1737  */
  1738 function CMT_approveModeration($cid)
  1739 {
  1740     global $_CONF, $_TABLES;
  1741     
  1742     $result = DB_query("SELECT type, sid, date, title, comment, uid, name, pid, ipaddress FROM {$_TABLES['commentsubmissions']} WHERE cid = '$cid'");
  1743     $A = DB_fetchArray($result);
  1744     
  1745     if ($A['pid'] > 0) {
  1746         // get indent+1 of parent 
  1747         $indent = DB_getItem($_TABLES['comments'], 'indent+1',
  1748                              "cid = '{$A['pid']}'");
  1749     } else {
  1750         $indent = 0;
  1751     }
  1752 
  1753     $A['title'] = addslashes($A['title']);
  1754     $A['comment'] = addslashes($A['comment']);
  1755 
  1756     if (isset($A['name'])) {
  1757         // insert data
  1758         $A['name'] = addslashes($A['name']);
  1759         DB_save($_TABLES['comments'], 'type,sid,date,title,comment,uid,name,pid,ipaddress,indent',
  1760                         "'{$A['type']}','{$A['sid']}','{$A['date']}','{$A['title']}','{$A['comment']}','{$A['uid']}',".
  1761                         "'{$A['name']}','{$A['pid']}','{$A['ipaddress']}',$indent");
  1762     } else {
  1763         // insert data, null automatically goes into name column
  1764         DB_save($_TABLES['comments'], 'type,sid,date,title,comment,uid,pid,ipaddress,indent',
  1765                         "'{$A['type']}','{$A['sid']}','{$A['date']}','{$A['title']}','{$A['comment']}','{$A['uid']}',".
  1766                         "'{$A['pid']}','{$A['ipaddress']}',$indent");
  1767     }
  1768     $newcid = DB_insertId();
  1769 
  1770     DB_delete($_TABLES['commentsubmissions'], 'cid', $cid);
  1771 
  1772     DB_change($_TABLES['commentnotifications'], 'cid', $newcid, 'mid', $cid);
  1773 
  1774     // notify of new published comment
  1775     if ($_CONF['allow_reply_notifications'] == 1 && $A['pid'] > 0) {
  1776         $result = DB_query("SELECT cid, uid, deletehash FROM {$_TABLES['commentnotifications']} WHERE cid = {$A['pid']}");
  1777         $B = DB_fetchArray($result);
  1778         if ($B !== false) {
  1779             CMT_sendReplyNotification($B);
  1780         }
  1781     }
  1782 
  1783     return $A['sid'];
  1784 }
  1785 
  1786 /**
  1787  * Sends a notification of new comment reply
  1788  * 
  1789  * @param  array    $A          contains cid, uid, and deletekey
  1790  * @param  boolean  $send_self  send notification when replying to self?
  1791  * @copyright Jared Wenerd 2008
  1792  * @author Jared Wenerd, wenerd87 AT gmail DOT com
  1793  */
  1794 function CMT_sendReplyNotification($A, $send_self = false)
  1795 {
  1796     global $_CONF, $_TABLES, $_USER, $LANG03;
  1797 
  1798     if (($_USER['uid'] != $A['uid']) || $send_self) {
  1799 
  1800         $name = COM_getDisplayName($A['uid']);
  1801         $title = DB_getItem($_TABLES['comments'], 'title', "cid = {$A['cid']}");
  1802         $commenturl = $_CONF['site_url'] . '/comment.php';
  1803 
  1804         $mailsubject = $_CONF['site_name'] . ': ' . $LANG03[37];
  1805 
  1806         $mailbody  = sprintf($LANG03[41], $name) . LB . LB;
  1807         $mailbody .= sprintf($LANG03[38], $title) . LB . LB;
  1808         $mailbody .= $LANG03[39] . LB . '<' . $commenturl . '?mode=view&cid='
  1809                   . $A['cid'] . '&format=nested' . '>' . LB . LB;
  1810         $mailbody .= $LANG03[40] . LB . '<' . $commenturl
  1811                   . '?mode=unsubscribe&key=' . $A['deletehash'] . '>' . LB;
  1812 
  1813         $email = DB_getItem($_TABLES['users'], 'email', "uid = {$A['uid']}");
  1814         if (!empty($email)) {
  1815             COM_mail($email, $mailsubject, $mailbody);
  1816         }
  1817 
  1818     }
  1819 }
  1820 
  1821 ?>