go back see line numbers get (semi)raw file download file
you are viewing pages/irc/stats.php
Back to Directory


<?php
/*`
#########################################
###            moo Stat Page          ###
###    this stat page is made for:    ###          (__)
###            /\/\( )( )             ###          (oo)
### Machine Optimized for Observation ###    /------\/
###-----------------------------------###   / |    ||
###        written by weekend         ###  *  /\---/\
###                                   ###     ~~   ~~
#########################################
edit log:                [dd/mm/yy]
origninal by weekend: 14/04/07
edit by weekend: 17/04/2007        added an admin feature that can edit the numbers of any user
edit by weekend: 25/04/2007        added a link to the source
edit by weekend: 02/05/2007        linked nicknames to hts accounts
edit by weekend: 03/07/2007        fixed a Full Path disclosure exploit (see notes)
edit by weekend: 16/07/2007        used the script HTS uses to prevent Full Path disclosure (see notes)
                                   by using $_POST and $_GET instead of $HTTP_POST_VARS and $HTTP_GET_VARS
                                   also only weekend gets to use admin stuff now instead of all mods
edit by weekend: 09/08/2007        small fix for xwww (the hts beta thing)
edit by comperr: 11/5/08 bug fixing and bad code fixed
edit by xelix:   25/12/2008 Fixed bugs, edit works, source link (bottom) fixed.
edit by jokerrrr: 15/05/2009 Fixed SQL injection.
edit by weekend: 2/04/2013 Fixed full path disclosure exploit (again!), script hts uses to prevent it has been removed

todo:
add admin features to delete users

notes:
looked at /pages/user/rankings/index.php for inspiration   altough this is way better ;)

POST and GET work here or only get (for start)
if both get send POST should take priority

forms and links have the GET data in them so it doesn't lose any thing the user has set when going to another page or whatever
(unlike the ranking page.. again this is just way cooler)

Full Path disclosure exploit: using an array in a get or post var like nick could result in an error that will display the full path of the file.
                              http://www.hackthissite.org/irc/stats.php?nickname=&mode=words&order=DESC&start=0&admin=edit&nick[]=nietzche
                              would result in:
                              Warning: htmlspecialchars() expects parameter 1 to be string, array given in /bla/bla/bla/bla/irc/stats.php on line 60
                              this was discovered by xenoix who also sugested a fix (see commented part)

                              HTS already did a check on $_POST and $_GET but I was using $HTTP_POST_VARS and $HTTP_GET_VARS
                              
                              UPDATE: The above check has been removed somewhere in the last x years, check it again on the page.

everything is extremly commented so anyone no mather how stupid can eddit the code

Comperr's first edit: SQL injection
    the NICK input was wholly unvalidated as was the entire $order_by.
    I just added an extra mysql_real_escape string to those parts to fix it.
    -- ty StenoPlasma
*/


require $_SERVER['DOCUMENT_ROOT'] . "/global.inc.php";

require 
HEADER;

checkReferer();

/* Create "cleaning" arrays */
$dirty = array();
$clean = array();
$mysql = array();


//HTS already does this <-- nope it doesn't, added it back (weekend on 2/04/2013)
//-----------------------------------------------------------------------------------
//--------------------------full-path-disclosure exploit-fix-------------------------
//-----------------------------------------------------------------------------------
//fix that xenoix sugested.
foreach($_POST as $checkFPD)
{
        if(
is_array($checkFPD))
        {
                die(
'$_POST vars are not alowed to be an array!');
        }
}
foreach(
$_GET as $checkFPD)
{
        if(
is_array($checkFPD))
        {
                die(
'$_GET vars are not alowed to be an array!');
        }
}

//-----------------------------------------------------------------------------------
//-------------------------------vars-related-to-admin-stuff-------------------------
//-----------------------------------------------------------------------------------

//ALWAYS check access before using these vars
$isadmin=FALSE;
if (
$_SESSION['member_group']==5||$_SESSION['member_id']==70)
{
    
$isadmin TRUE;
}

//--------------------------------setting---$admin------------------------------------
if ((isset($_GET['admin']) || isset($_POST['admin'])) && $isadmin)
//only for mods or weekend
        
$admin = ( isset($_POST['admin']) ) ? $_POST['admin'] : $_GET['admin'];
}else{

        
$admin ''//nothing set in this var
}

//--------------------------------setting---$clean['editNick']-------------------------------
if ((isset($_GET['nick']) || isset($_POST['nick'])) && $isadmin)
//only for mods or weekend
        
$dirty['editNick'] = isset($_POST['nick']) ? $_POST['nick'] : $_GET['nick'];
        
$clean['editNick'] = htmlentities($dirty['editNick'], ENT_QUOTES);
        
$mysql['editNick'] = mysql_real_escape_string($dirty['editNick']);
}else{
        
$clean['editNick'] = ''//nothing set in this var
        
$mysql['editNick'] = '';
}

//--------------------------------setting---$edit_sentences--------------------------
//note that i do not make the number positive, users can be punished with negative numbers!
if (isset($_POST['sentences']) && is_numeric($_POST['sentences']))
{
        
$edit_sentences intval($_POST['sentences']);

}elseif (isset(
$_GET['sentences']) && is_numeric($_GET['sentences']))
{
        
$edit_sentences intval($_GET['sentences']);
}else{
        
$edit_sentences 0;        //no sentences at all
}

//--------------------------------setting---$edit_words------------------------------
//note that i do not make the number positive, users can be punished with negative numbers!
if (isset($_POST['words']) && is_numeric($_POST['words']))
{
        
$edit_words intval($_POST['words']);

}elseif (isset(
$_GET['words']) && is_numeric($_GET['words']))
{
        
$edit_words intval($_GET['words']);
}else{
        
$edit_words 0;        //no words at all
}

//--------------------------------setting---$edit_actions----------------------------
//note that i do not make the number positive, users can be punished with negative numbers!
if (isset($_POST['actions']) && is_numeric($_POST['actions']))
{
        
$edit_actions intval($_POST['actions']);

}elseif (isset(
$_GET['actions']) && is_numeric($_GET['actions']))
{
        
$edit_actions intval($_GET['actions']);
}else{
        
$edit_actions 0;        //no actions at all
}

//-----------------------------------------------------------------------------------
//-------------------------------vars-related-to-showing-stuff-----------------------
//-----------------------------------------------------------------------------------

//--------------------------------setting---$start-----------------------------------
if (isset($_GET['start']) && is_numeric($_GET['start']))        //if it's set and a real number (no evil haxors here ;)
{
        
$start intval($_GET['start']);        //this sets the value in the var (as an int)
        
$start max(0$start);                        //this thing makes it 0 if its a negative number
        
$start round($start/10)*10;                        //this rounds the value

}else{
        
$start 0;        //standard place to start
}

//-------------------------------setting---$clean['nickname']----------------------------------
if ( isset($_GET['nickname']) || isset($_POST['nickname']) )
{
        
$dirty['nickname'] = isset($_POST['nickname']) ? urldecode($_POST['nickname']) : urldecode($_GET['nickname']);
        
$clean['nickname'] = htmlentities($dirty['nickname'], ENT_QUOTES);
        
$mysql['nickname'] = mysql_real_escape_string($dirty['nickname']);
        
$mysql['nickname'] = str_replace('*''%'trim($mysql['nickname'])); //allows people to use * as a wildcard

}else{

        
$clean['nickname'] = ''//no nickname set
        
$mysql['nickname'] = '';
}

//--------------------------------setting---$mode-----------------------------------
//this thing desides by what things get sorted
if ( isset($_GET['mode']) || isset($_POST['mode']) )
{
        
$mode = ( isset($_POST['mode']) ) ? $_POST['mode'] : $_GET['mode'];
        
//there is no security set here because it will go in a switch statement
        //if you make it go in an sql statement or directly to the page please CHANGE IT!
}else{

        
$mode 'words';        //standard mode is words because sentences with a lot of words are better then strange one worded sentences
}

//--------------------------------setting---$order-----------------------------------
if(isset($_POST['order']))
{
        
$order = ($_POST['order'] == 'ASC') ? 'ASC' 'DESC';

}else if(isset(
$_GET['order']))
{
        
$order = ($_GET['order'] == 'ASC') ? 'ASC' 'DESC';

}else{

        
$order 'DESC';
}

//-----------------------------setting-$select_sort_mode-----------------------------
//in this var we set some HTML code that alows users to select what sorting mode they want to use
$mode_types_text = array('Nickname''Sentences''Words''Actions');
$mode_types = array('nickname''sentences''words''actions');

//I take 2 arrays so we can rename it without having to change the sql table (or change the sql table without renaming)
//(and because thats how its done in the file I used as an example)

$select_sort_mode '<select name="mode">';
for(
$i 0$i count($mode_types_text); $i++)
{
        
$selected = ( $mode == $mode_types[$i] ) ? ' selected="selected"' '';
        
$select_sort_mode .= '<option value="' $mode_types[$i] . '"' $selected '>' $mode_types_text[$i] . '</option>';
}
$select_sort_mode .= '</select>';

//-----------------------------setting-$select_sort_order----------------------------
//in this var we set some HTML code that alows users to select if they want it ascending or descending
$select_sort_order '<select name="order">';
if(
$sort_order == 'ASC')
{
        
$select_sort_order .= '<option value="ASC" selected="selected">Ascending</option><option value="DESC">Descending</option>';

}else{

        
$select_sort_order .= '<option value="ASC">Ascending</option><option value="DESC" selected="selected">Descending</option>';
}
$select_sort_order .= '</select>';

//--------------------------------setting---$where-----------------------------------
//this thing goes in an sql statement
if (!$mysql['nickname']) { //if its not specified

        
$where "";

}elseif (
$mysql['nickname'] == '%') { //if someone tries to select everyone.. wich is just lame and still limited to 10 people

        
$where "";

}else{
        
$where "WHERE nickname LIKE '"$mysql['nickname'] ."'";
}

//--------------------------------setting---$order_by--------------------------------
switch( $mode )
{
        case 
'nickname':
                
$order_by "$where ORDER BY nickname $order";
                break;
        case 
'sentences':
                
$order_by "$where ORDER BY sentences $order";
                break;
        case 
'words':
                
$order_by "$where ORDER BY words $order";
                break;
        case 
'actions':
                
$order_by "$where ORDER BY actions $order";
                break;
        default:
                
$order_by "$where ORDER BY words $order";
                
$mode "words";         //so it gets put in the GET thing with the page thing
                                        //this also prevents any xss since it will be one of the cases or turn into "words"
}
//----------------------------sending-some-html-to-the-user--------------------------
?>

<table width="95%"  border="0" align="center" cellpadding="5" cellspacing="0" class="dark-td">
        <tr class="blight-td">
              <td width="30%" align="left" style="font-size: 12px;"><b>IRC Statistic Page</b> <a href="http://www.hackthissite.org/pages/showsource/viewhts.php?g=pages/irc/&f=stats.php" class="nav">(source)</a></td>
          <td width="70%" align="right"><form method="POST" action="<?php echo htmlentities ($_SERVER['PHP_SELF'], ENT_QUOTES) .'?nickname='.$clean['nickname'].'&start='.$start;?>">Sort &nbsp; <?php echo "$select_sort_mode"?> &nbsp; &nbsp; Order &nbsp; <?php echo "$select_sort_order"?> &nbsp; <input type="submit" name="submit" value="Sort" class="submit-button" /></form></td>
        </tr>
        <tr>
          <td colspan="2">

<table width="100%"  border="0" cellspacing="2" cellpadding="5" class="dark-td" align="center">
        <tr>
          <td align="center" class="bdark-td" style="font-size: 12px; font-weight:bold;">Note</td>
        </tr>
        <tr>
          <td style="font-size: 12px; font-weight:bold; background: #888888;"><?php include('note.php');?></td>
        </tr>
</table>

<br />

<table width="100%"  border="0" cellspacing="2" cellpadding="0">
        <tr>
          <td width="50%" style="font-size: 12px; font-weight:bold;"><form name="username" method="POST" action="<?php echo htmlentities ($_SERVER['PHP_SELF']) .'?mode='.$mode.'&order='.$order;?>">Nickname: <input name="nickname" type="text" value="<?php echo $clean['nickname']; ?>" size="15" /> <input type="submit" name="Submit" value="Search" class="submit-button" /> </form></td>
          <td width="50%" style="font-size: 12px; font-weight:bold;" align="right">Pages:

<?php

//------------------------------SQL-part-of-the-code--------------------------------

mysql_select_db('weekend');         //change the db from the hts one to the one moo is using
                                    //(which happends to be named after moo's creator weekend)

//admin changing the stuff

//the access checking is not really needed because it gets checked before setting $admin
//but lets do it anyway in case someone who doesn't know what they are doing edits the code
if (($admin == "change") && $isadmin)
{
        
$sql = ("UPDATE v3_weekend.nick_stats SET words = '%d', sentences = '%d', actions = '%d' WHERE nickname = '%s'");
        
$result mysql_query(sprintf($sql$edit_words$edit_sentences$edit_actions$mysql['editNick'])) or die(mysql_error());
        
//changing to the new value
}

//the sql part that selects the stuff to display
//first we want to know howmany posibilities the query has then we will select it again but limited
//this is actualy a STUPID way of doing it but lets do it anyway
$sql = ("SELECT * FROM v3_weekend.nick_stats ".$order_by);
$result mysql_query($sql) or die(mysql_error());
$count mysql_num_rows($result);

$order_by .= " LIMIT $start, 10"//limiting the query
$sql = ("SELECT * FROM v3_weekend.nick_stats $order_by");
$result mysql_query($sql) or die(mysql_error());



//--------------------------the-code-that-handles-the-page-buttons-------------------
$page = ( $start 10 );
echo 
'<a href="'htmlentities ($_SERVER['PHP_SELF'], ENT_QUOTES) .'?nickname='.$clean['nickname'].'&mode='.$mode.'&order='.$order.'&start=0"><img src="pages/user/img/left.gif" border="0" alt="Left" /></a> &nbsp;';

for(
$i = ($page 1) ; $i < ($page+ceil($count/10) ? ceil($count/10) : $page+3) ; $i++)
{
        if (
$i >= 0)
        {
                if (
$i == $page)
                        echo 
$page."&nbsp; &nbsp;" ;
                else
                        echo 
'<a href="'htmlentities ($_SERVER['PHP_SELF'], ENT_QUOTES) .'?nickname='.$clean['nickname'].'&mode='.$mode.'&order='.$order.'&start='.$i.'0" class="nav">'.$i.'</a> &nbsp; ';
        }
}
echo 
'<a href="'htmlentities ($_SERVER['PHP_SELF'], ENT_QUOTES) .'?nickname='.$clean['nickname'].'&mode='.$mode.'&order='.$order.'&start='.floor($count/10).'0"><img src="pages/user/img/right.gif" border="0" alt="Right" /></a> &nbsp; &nbsp;';


//some more html stuff
if ($isadmin)
{
//admin people get to see this (or weekend)
        
echo '
                </td>
        </tr>
</table>

<table width="100%"  border="0" cellspacing="2" cellpadding="5" class="dark-td" align="center">
        <tr>

          <td width="150" align="center"         class="bdark-td" style="font-size: 12px; font-weight:bold;">Nickname</td>
          <td width="125" align="center"         class="bdark-td" style="font-size: 12px; font-weight:bold;">Sentences</td>
          <td width="125" align="center"         class="bdark-td" style="font-size: 12px; font-weight:bold;">Words</td>
          <td width="125" align="center"         class="bdark-td" style="font-size: 12px; font-weight:bold;">Actions</td>
          <td width="125" align="center"         class="bdark-td" style="font-size: 12px; font-weight:bold;">Edit</td>
        </tr>
        '
;
        if (
$admin == 'edit')
        {
                echo 
'<form method="post" action="'
                
htmlentities ($_SERVER['PHP_SELF'], ENT_QUOTES) .'?nickname='.$clean['nickname'].'&mode='.$mode.'&order='.$order.'&start='.$start.'&nick='.$clean['editNick'].'&admin=change">';
        }

}else{
//non admin people get to see this
echo '
                </td>
        </tr>
</table>

<table width="100%"  border="0" cellspacing="2" cellpadding="5" class="dark-td" align="center">
        <tr>

          <td width="200" align="center"         class="bdark-td" style="font-size: 12px; font-weight:bold;">Nickname</td>
          <td width="150" align="center"         class="bdark-td" style="font-size: 12px; font-weight:bold;">Sentences</td>
          <td width="150" align="center"         class="bdark-td" style="font-size: 12px; font-weight:bold;">Words</td>
          <td width="150" align="center"         class="bdark-td" style="font-size: 12px; font-weight:bold;">Actions</td>
        </tr>
'
;
}

//--------------------------the-code-that-displays-all-the-info----------------------
//this is where things get messy.. someone should fix that *hint* *hint* YOU
$i=1;
while (
$r mysql_fetch_array($result))
{
        
$nick $r['nickname'];
        
$sentences $r['sentences'];
        
$words $r['words'];
        
$actions $r['actions'];
        
$tdColor = ($i %2) ? "white-td" "blight-td"//takes care of the pritty colors ;)
        
$sql = ("SELECT * FROM v3_weekend.link WHERE nickname = '".mysql_real_escape_string($nick)."' LIMIT 1");
        
$query mysql_query($sql) or die(mysql_error());
        
$row mysql_fetch_array($query);
        if ((
$admin == edit) && ($clean['editNick'] == $nick))
        {
        echo 
"
        <tr>
    <td style=\"font-size: 12px; font-weight:bold;\" class=\"
$tdColor\" align=\"center\">" .(($row['lvl'] > 0) ? "<a class=\"nav\" href=\"/user/view/".rawurlencode($row['htsnick'])."/\">$nick</a>" $nick)."</td>
    <td style=\"font-size: 12px; font-weight:bold;\" class=\"
$tdColor\" align=\"center\"><input name=\"sentences\" type=\"text\" value=\"$sentences\" size=\"10\" /></td>
    <td style=\"font-size: 12px; font-weight:bold;\" class=\"
$tdColor\" align=\"center\"><input name=\"words\" type=\"text\" value=\"$words\" size=\"10\" /></td>
    <td style=\"font-size: 12px; font-weight:bold;\" class=\"
$tdColor\" align=\"center\"><input name=\"actions\" type=\"text\" value=\"$actions\" size=\"10\" /></td>
    <td style=\"font-size: 12px; font-weight:bold;\" class=\"
$tdColor\" align=\"center\"><input type=\"submit\" name=\"Submit\" value=\"Edit\" class=\"submit-button\" /></form></td>";
        }
        else {
                echo 
"
        <tr>
    <td style=\"font-size: 12px; font-weight:bold;\" class=\"
$tdColor\" align=\"center\">" .(($row['lvl'] > 0) ? "<a class=\"nav\" href=\"/user/view/".rawurlencode($row['htsnick'])."/\">$nick</a>" $nick)."</td>
    <td style=\"font-size: 12px; font-weight:bold;\" class=\"
$tdColor\" align=\"center\">$sentences</td>
    <td style=\"font-size: 12px; font-weight:bold;\" class=\"
$tdColor\" align=\"center\">$words</td>
    <td style=\"font-size: 12px; font-weight:bold;\" class=\"
$tdColor\" align=\"center\">$actions</td>        ";
                if (
$isadmin)
                {
                        echo 
"
    <td style=\"font-size: 12px; font-weight:bold;\" class=\"
$tdColor\" align=\"center\"><a class=\"nav\" href=\""
                
htmlentities ($_SERVER['PHP_SELF'], ENT_QUOTES) .'?nickname='.$clean['nickname'].'&mode='.$mode.'&order='.$order.'&start='.$start.'&admin=edit&nick='.$nick.'">edit</a></td>';
                }
        }
        echo 
"
        </tr>"
;
        
$i++;
}
mysql_select_db('v3_hts');       //changing it back to the hts db in case some fancy sql stuff happends in the footer or whereever

//this code changes the colour to whatever it wasn't was before
if ($tdColor == "white-td")
{
        
$tdColor "blight-td";
}
else
{
        
$tdColor "white-td";
}

//--------------------------------the-search-stuff-again-----------------------------
?>
</table>

<table width="100%"  border="0" cellspacing="2" cellpadding="0">
        <tr>
          <td width="50%" style="font-size: 12px; font-weight:bold;"><form name="username" method="POST" action="<?php echo htmlentities ($_SERVER['PHP_SELF']) .'?mode='.$mode.'&order='.$order;?>">Nickname: <input name="nickname" type="text" value="<?php echo $clean['nickname']; ?>" size="15" /> <input type="submit" name="Submit" value="Search" class="submit-button" /> </form></td>
          <td width="50%" style="font-size: 12px; font-weight:bold;" align="right">Pages:

<?php
//--------------------------the-code-that-handles-the-page-buttons-(again)-----------
$page = ( $start 10 );
echo 
'<a href="' htmlentities ($_SERVER['PHP_SELF'], ENT_QUOTES) . '?nickname='.$clean['nickname'].'&mode='.$mode.'&order='.$order.'&start=0"><img src="pages/user/img/left.gif" border="0" alt="Left" /></a> &nbsp;';

for(
$i $page-1$i < ($page+ceil($count/10) ? ceil($count/10) : $page+3) ; $i++)
{
        if (
$i >= 0)
        {
                if (
$i == $page)
                        echo 
$page."&nbsp; &nbsp;";
                else
                        echo 
'<a href="'.htmlentities ($_SERVER['PHP_SELF'], ENT_QUOTES).'?nickname='.$clean['nickname'].'&mode='.$mode.'&order='.$order.'&start='.$i.'0" class="nav">'.$i.'</a> &nbsp; ';
        }
}
echo 
'<a href="'htmlentities ($_SERVER['PHP_SELF'], ENT_QUOTES) . '?nickname='.$clean['nickname'].'&mode='.$mode.'&order='.$order.'&start='.floor($count/10).'0"><img src="pages/user/img/right.gif" border="0" alt="Right" /></a> &nbsp; &nbsp;';

?>

          </td>
        </tr>
</table>
</td>
        </tr>

        <tr class="blight-td">
          <td width="30%" align="left" style="font-size: 12px;"><b>IRC Statistic Page</b> <a href="http://www.hackthissite.org/pages/showsource/viewhts.php?g=pages/irc/&f=stats.php" class="nav">(source)</a></td>
          <td width="70%" align="right"><form method="POST" action="<?php echo htmlentities ($_SERVER['PHP_SELF'], ENT_QUOTES) .'?nickname='.$clean['nickname'].'&start='.$start;?>">Sort &nbsp; <?php echo "$select_sort_mode"?> &nbsp; &nbsp; Order &nbsp; <?php echo "$select_sort_order"?> &nbsp; <input type="submit" name="submit" value="Sort" class="submit-button" /></form></td>
        </tr>
</table>

<?php
require FOOTER;
?>

You are currently viewing the HTS source code. Copyright held by HTS developers. No permission to reproduce is given.