SECURITY: fix stupid XSS vulnerability on initial post submit; add in support for the new search API
--- a/decir/functions.php Wed Nov 14 19:26:21 2007 -0500
+++ b/decir/functions.php Thu Nov 29 21:48:02 2007 -0500
@@ -35,6 +35,16 @@
$post_text = $db->escape($post_text);
$post_subject = $db->escape($post_subject);
+ if ( empty($post_subject) )
+ {
+ $q = $db->sql_query('SELECT topic_title FROM '.table_prefix.'decir_topics WHERE topic_id = ' . $topic_id . ';');
+ if ( !$q )
+ $db->_die('Decir functions.php in decir_submit_post()');
+ if ( $db->numrows() < 1 )
+ return false;
+ list($post_subject) = $db->fetchrow_num();
+ $post_subject = 'Re: ' . $db->escape($post_subject);
+ }
$q = $db->sql_query('INSERT INTO '.table_prefix."decir_posts(topic_id,poster_id,poster_name,post_subject,timestamp) VALUES($topic_id, $poster_id, '$poster_name', '$post_subject', $timestamp);");
if ( !$q )
@@ -114,7 +124,7 @@
if ( !$q )
$db->_die('Decir functions.php in decir_edit_post()');
- $q = $db->sql_query('UPDATE '.table_prefix."decir_posts_text SET post_text='$post_text' WHERE post_id=$post_id;");
+ $q = $db->sql_query('UPDATE '.table_prefix."decir_posts_text SET post_text='$post_text',bbcode_uid='$bbcode_uid' WHERE post_id=$post_id;");
if ( !$q )
$db->_die('Decir functions.php in decir_edit_post()');
--- a/decir/posting.php Wed Nov 14 19:26:21 2007 -0500
+++ b/decir/posting.php Thu Nov 29 21:48:02 2007 -0500
@@ -90,11 +90,13 @@
if ( sizeof($errors) < 1 )
{
// Collect other options
+ $post_text = trim(htmlspecialchars($_POST['post_text']));
+ $post_subject = trim(htmlspecialchars($_POST['subject']));
// Submit post
if ( $parms['mode'] == 'reply' || $parms['mode'] == 'quote' )
{
- $result = decir_submit_post($parms['topic_in'], $_POST['subject'], $_POST['post_text'], $post_id);
+ $result = decir_submit_post($parms['topic_in'], $post_subject, $post_text, $post_id);
if ( $result )
{
// update forum stats
@@ -110,7 +112,7 @@
}
else if ( $parms['mode'] == 'topic' )
{
- $result = decir_submit_topic($parms['forum_id'], $_POST['subject'], $_POST['post_text'], $topic_id, $post_id);
+ $result = decir_submit_topic($parms['forum_id'], $post_subject, $post_text, $topic_id, $post_id);
if ( $result )
{
// update forum stats
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/decir/search.php Thu Nov 29 21:48:02 2007 -0500
@@ -0,0 +1,135 @@
+<?php
+/*
+ * Decir
+ * Version 0.1
+ * Copyright (C) 2007 Dan Fuhry
+ * search.php - Integration with Enano's search system
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ */
+
+$plugins->attachHook('search_global_inner', 'decir_search($query, $query_phrase, $scores, $page_data, $case_sensitive, $word_list);');
+
+/**
+ * Searches the forums for the specified search terms. Called from a hook.
+ * @access private
+ */
+
+function decir_search(&$query, &$query_phrase, &$scores, &$page_data, &$case_sensitive, &$word_list)
+{
+ global $db, $session, $paths, $template, $plugins; // Common objects
+
+ require_once( DECIR_ROOT . '/bbcode.php' );
+ require_once( DECIR_ROOT . '/functions_viewtopic.php' );
+
+ // Based on the search function from Snapr
+
+ // Let's do this all in one query
+ $terms = array(
+ 'any' => array_merge($query['any'], $query_phrase['any']),
+ 'req' => array_merge($query['req'], $query_phrase['req']),
+ 'not' => $query['not']
+ );
+ $where = array('any' => array(), 'req' => array(), 'not' => array());
+ $where_any =& $where['any'];
+ $where_req =& $where['req'];
+ $where_not =& $where['not'];
+ $title_col = ( $case_sensitive ) ? 'p.post_subject' : 'lcase(p.post_subject)';
+ $desc_col = ( $case_sensitive ) ? 't.post_text' : 'lcase(t.post_text)';
+ foreach ( $terms['any'] as $term )
+ {
+ $term = escape_string_like($term);
+ if ( !$case_sensitive )
+ $term = strtolower($term);
+ $where_any[] = "( $title_col LIKE '%{$term}%' OR $desc_col LIKE '%{$term}%' )";
+ }
+ foreach ( $terms['req'] as $term )
+ {
+ $term = escape_string_like($term);
+ if ( !$case_sensitive )
+ $term = strtolower($term);
+ $where_req[] = "( $title_col LIKE '%{$term}%' OR $desc_col LIKE '%{$term}%' )";
+ }
+ foreach ( $terms['not'] as $term )
+ {
+ $term = escape_string_like($term);
+ if ( !$case_sensitive )
+ $term = strtolower($term);
+ $where_not[] = "$title_col NOT LIKE '%{$term}%' AND $desc_col NOT LIKE '%{$term}%'";
+ }
+ if ( empty($where_any) )
+ unset($where_any, $where['any']);
+ if ( empty($where_req) )
+ unset($where_req, $where['req']);
+ if ( empty($where_not) )
+ unset($where_not, $where['not']);
+
+ $where_any = '(' . implode(' OR ', $where_any) . '' . ( isset($where['req']) || isset($where['not']) ? ' OR 1 = 1' : '' ) . ')';
+
+ if ( isset($where_req) )
+ $where_req = implode(' AND ', $where_req);
+ if ( isset($where_not) )
+ $where_not = implode( 'AND ', $where_not);
+
+ $where = implode(' AND ', $where);
+ $sql = "SELECT p.post_id, p.post_subject, t.post_text, p.poster_name, p.poster_id, u.username, p.edit_count, p.last_edited_by, p.timestamp,\n"
+ . " p.post_deleted, u2.username AS editor, p.edit_reason, u.user_level, u.reg_time, t.post_text, t.bbcode_uid\n"
+ . " FROM " . table_prefix . "decir_posts AS p\n"
+ . " LEFT JOIN " . table_prefix . "decir_posts_text AS t\n"
+ . " ON ( t.post_id = p.post_id )\n"
+ . " LEFT JOIN " . table_prefix . "users AS u2\n"
+ . " ON (u2.user_id=p.last_edited_by OR p.last_edited_by IS NULL)\n"
+ . " LEFT JOIN " . table_prefix . "users AS u\n"
+ . " ON ( u.user_id = p.poster_id )\n"
+ . " WHERE ( $where ) AND post_deleted != 1\n"
+ . " GROUP BY p.post_id;";
+
+ if ( !($q = $db->sql_unbuffered_query($sql)) )
+ {
+ $db->_die('Error is in auto-generated SQL query in the Decir plugin search module');
+ }
+
+ $postbit = new DecirPostbit();
+
+ if ( $row = $db->fetchrow() )
+ {
+ do
+ {
+ $idstring = 'ns=DecirPost;pid=' . $row['post_id'];
+ foreach ( $word_list as $term )
+ {
+ $func = ( $case_sensitive ) ? 'strstr' : 'stristr';
+ $inc = ( $func($row['post_subject'], $term) ? 1.5 : ( $func($row['text'], $term) ? 1 : 0 ) );
+ ( isset($scores[$idstring]) ) ? $scores[$idstring] = $scores[$idstring] + $inc : $scores[$idstring] = $inc;
+ }
+ // Generate text...
+ $text = render_bbcode($row['post_text'], $row['bbcode_uid']);
+ $text = highlight_and_clip_search_result($text, $word_list);
+ $post_length = strlen($row['post_text']);
+
+ $row['post_text'] = $text;
+ $rendered_postbit = $postbit->_render('', $row);
+
+ // Inject result
+
+ if ( isset($scores[$idstring]) )
+ {
+ // echo('adding image "' . $row['img_title'] . '" to results<br />');
+ $page_data[$idstring] = array(
+ 'page_name' => highlight_search_result(htmlspecialchars($row['post_subject']), $word_list),
+ 'page_text' => $rendered_postbit,
+ 'score' => $scores[$idstring],
+ 'page_note' => '[Forum post]',
+ 'page_id' => strval($row['post_id']),
+ 'namespace' => 'DecirPost',
+ 'page_length' => $post_length,
+ );
+ }
+ }
+ while ( $row = $db->fetchrow() );
+ }
+}
--- a/decir/viewforum.php Wed Nov 14 19:26:21 2007 -0500
+++ b/decir/viewforum.php Thu Nov 29 21:48:02 2007 -0500
@@ -78,6 +78,8 @@
{
if ( $num_replies < 0 )
$num_replies = 0;
+ if ( $i == $db->numrows() && $i == 1 )
+ $num_replies++;
if ( $last_row['topic_deleted'] == 1 )
{
$thread_link = '<Deleted>';
--- a/plugins/Decir.php Wed Nov 14 19:26:21 2007 -0500
+++ b/plugins/Decir.php Thu Nov 29 21:48:02 2007 -0500
@@ -34,6 +34,7 @@
');
require( DECIR_ROOT . '/admincp/admin_base.php' );
+require( DECIR_ROOT . '/search.php' );
function decir_early_init(&$paths, &$session)
{