News:

SMF 2.1.4 has been released! Take it for a spin! Read more.

Main Menu

nneonneo's Shoutbox

Started by nneonneo, December 26, 2006, 06:58:11 PM

Previous topic - Next topic

Sruc

Quote from: nneonneo on November 10, 2007, 03:03:24 PM
What happens when they press del or ban?
The log disappear, and when they update the page, appear already, but it doesn't work.

nneonneo

Hmm, I think it may be due to character encodings -- post, send or attach the file and I'll see what I can do.
Check out the AJAX Shoutbox (my one and only mod to date :P)
Do you like SMF? Are you using ProBoards, InvisionFree, ActiveBoards or some other web-hosted forum? I can help you convert to SMF (without having to purchase a DB conversion)...contact me [nneonneo {at} gmail *dot* com], and see this topic
spammers here!

Sruc

[php]<?php
// Version 1.11
// Editable Options (see yshout/js/yshout.js for more options)
// Set the maximum amount of lines to be displayed at a time
$max_lines = 12;

// Sets the directory to which to log
$logDir = "chats";

// Should we use GZip compression? If you are having trouble with the shoutbox, set this to false.
$gzipCompression=true;

// Guest usage. Set to false if you don't want guests to use the shoutbox: they will not be able to read it or post to it.
$allowGuests=true;

// Guest usage for posting. Set to false if you don't want to let guests post to the shoutbox; if allowGuests is on, they will still see it.
$allowGuestsPost=true;

// Automatic Guest Usernames: should they be able to choose their own usernames?
// Set to some string (a prefix) if you want to disable guest choice of username
// Set to false if you want to allow guests to choose a username
$autoGuestName=false;//'guest-';

// Command options.
// If this is set to false, all typed commands are disabled.
// Admin functions, via admin links, are still available.
$allowCommands=true;

// If this is set to false, guests will be denied access to commands.
$guestCommands=true;

// How long should the script wait for the chats to update? (in seconds)
// If this is set to 0 the script will not wait at all,
// but this will be very detrimental to performance.
// Make sure this is less than the maximum script execution time
// on your server, or the shoutbox will never update.
$updateTimeout=20;

// User-defined array of commands to block.
// Example: $bannedCommands=Array('/impersonate');
// Note that since SMF recognizes /me by default, it can't be blocked.
$bannedCommands=Array();

// How many characters will be permitted in each shout.
$maxShoutChars=125;

// How many characters will be permitted in the username.
// This does not apply to SMF registered usernames.
$maxUsernameChars=25;

/* Documentation
Functions
Command Implementation:
doMsg(string $msg)
Causes the shoutbox to be replaced with $msg until they
use /return (useful for making error messages, etc.)
processCommand(string $text)
Process an admin command. If this function fails to find
a match, it defaults to the user commands.
processUserCommand(string $text)
Process a user command. This function attempts to match
against all known commands. If a valid command match
isn't found, the function will return false and the
shout ("command") will be displayed as a regular shout.
makeShout(string $text)
Produce a shout as if it was from the current user, but
having only a datestamp (and no profile link, etc)
help(string $command - default '')
Allows users to get help on a command. Use <arg> to
denote required arguments and [arg] to denote optional
ones. Note that all <> must be entered as < and >
or they will not work.
Make sure to add an entry in this function for any new
commands.
Shouting:
checkDir(string $logDir)
Check the target directory to make sure it exists.
checkName(string $chatFile)
Check the filename for invalidities.
readChat(string $chatFile,string $logDir)
Dump the contents of the chat file to the client. If the
client is viewing a special message or command, then
readChat simply executes that command or prints the
message back on screen (this command/message is stored
in $_SESSION['readingCmd'])
truncateChat(string $chatFile,string $logDir,integer $max_lines)
Move the first line of a file from the chat file to the
history as long as the chat file exceeds the set
maximum.
writeLine(string $chatFile, string $logDir, string $newText, array $user)
Write a shout to the chat file. $user is an SMF user
session array which determines the username and rank of
the poster.
writeBanList()
Write the current ban list to _banlist.php which is
require'd by this script at the beginning. This allows
for "dynamic" ban lists.
history()
Show the history file in a neat, formatted HTML style.
preg_timeformat(array $matches)
Function used to replace matched <timeval=[UNIX time offset]> with formatted times
as per SMF's timeformat function. Called through preg_replace_callback.
Important Globals
$_SESSION
readingCmd
The command (if it starts with /) or the message to be
read back to the user instead of the normal shoutbox
stuff.
$_GET
n
Used by the history() function to determine the # of
history lines to output.
help
If this is set, the shoutbox will output a full HTML
help message (using help()). Use as a standalone page.
history
If this is set, the shoutbox will output a full HTML
history page (with history()). Use as a standalone page.
banid
For the administrator's ban link: this is passed as the user
ID of the member to be banned.
delete
For deleting shouts; this is a string in the form
datecode | ip (this is the format used in the <em title>
unban
Username/identifier to unban (used by /banlist)
file
File to read for history and delete functions (will be checked)
$_POST
file
Chat file to use. Will be checked for bad characters.
reqtype
What function to carry out (shout, refresh, init)
shout
If reqtype is shout, then this is the shout to be made.
$_SERVER
REMOTE_ADDR
Used for $ip to determine their IP address.
Global Variables
$ban_ips_readpost,$ban_ips_post,$ban_names_readpost,$ban_names_post
Ban variables. _ips or _names is the ban criteria (IP
address or username) while _readpost or _post is the ban
severity (banned from reading+posting or just posting)
$chatFile,$logDir
These determine the location of the chat file.
$chatFile comes from $_POST['file'] while $logDir is hardcoded.
$user
SMF user data array, gleaned from ssi_welcome as a hack.
This determines a lot of things about the user (like the username and status)
$max_lines
Maximum number of lines to have in the shoutbox. Used by truncateChat.
$ip
User's IP address. Gathered from $_SERVER['REMOTE_ADDR'].
$reqType
Request type; see $_POST['reqtype'].
Super-Duper Command Implementation
To add a command, first decide whether this command is *user* or
*admin/mod* level.
The general format of a command is "/command <reqargs>
[optargs]".
Commands are processed in processCommand or processUserCommand.
The former is for admin/mod commands, and the latter is for users.
Processing begins by parsing the args and then running through a
long switch/case block. In this block, you will add your command code.
Your code should begin with a "case '/commandname':"  and end with a
return true; statement.
The two things you will have access to locally are $args and
$cmd. $args is a string containing all the arguments passed, and $cmd is
the exact command used. For example, with the command "/foo bar baz",
$cmd will be "/foo" and $args will be "bar baz". This will be handled by
the "case '/foo':" statement.
Globally, any of the superglobals are available, plus any
globals. All globals are declared already so there is no need to declare
them on your own.
To make a message appear on the client's shoutbox, set the
variable $_SESSION['readingCmd'] to $text (which is the main argument
for the processing function). This causes the exact text of the command
to be reparsed every time the user requests the shoutbox data, and your
information will be returned instead of the regular shouts.
Alternately, the doMsg function allows you to automatically set
a message that will stay up until they use /return.
Remember that whenever your function needs to exit, it must do
so with "return true;" so that the calling function will know not to
"shout" the command.
*/

session_start();
require(
dirname(__FILE__) . "/../SSI.php");
require_once(
$sourcedir . '/Subs-Post.php');
require(
"_banlist.php");
if (!isset(
$maintenance)) $maintenance=false;
$defaultEncoding=(empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set']);
header('Content-type: text/html; charset='.$defaultEncoding);

$ip = $_SERVER['REMOTE_ADDR'];
$max_lines+=1;
$user=ssi_welcome('nothing'); // ssi_welcome only does something IF the parameter is 'echo'; otherwise the user data is returned!
if (loadMemberData(Array($user['id']),false,'minimal')!==false)
{
$group=$user_profile[$user['id']]['ID_GROUP'];
if(in_array($group,array(2)))
{
$user['is_mod']=1;
}
if(in_array($group,array(100,200,300)))
{
die("Sorry, you cannot access the shoutbox.");
}
}
else
{
die("Sorry, you must be logged in to post!");
}
loadUserSettings();
loadTheme();
ssi_logOnline('nothing'); // don't want echo, so just use a nonexistant output method
function preg_timeformat($matches)
{
// format: <timeval=(value)>
return timeformat(intval($matches[1]));
}

if (
in_array($ip, $ban_ips_readpost) || in_array($user['username'], $ban_names_readpost) || in_array($user['name'], $ban_names_readpost))
die($txt['yshout_banned']); // exit;

if (!$user['is_logged'])
{
if(!$allowGuests)
die($txt['yshout_no_guests']);
if($autoGuestName!==false)
$user['username']=$user['name']=$autoGuestName.substr(md5($ip),0,4);
elseif(isset($_POST['username']))
$_COOKIE['username']=$user['username']=$user['name']=$_POST['username'];
elseif(isset($_COOKIE['username']))
$user['username']=$user['name']=$_COOKIE['username'];
}

// Do not edit below this line unless you know what you are doing
if(isset($_GET["history"]))
{
history();
exit;
}

if(isset(
$_GET["help"]))
{
help();
exit;
}

if(isset(
$_GET['banid']))
{
if (!isset($_GET['mode']))
{
global $boardurl;
doMsg(<<<EOF
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<base href="
$boardurl/">
<head>
<meta http-equiv="content-type" content="text/html; charset=
$defaultEncoding" />
<title>
{$txt['yshout_ban_conf']}</title>
</head>
<body>
<h1>
{$txt['yshout_select_mode']}</h1>
<a href="javascript:ajaxGet('banid=
{$_GET['banid']}&amp;mode=rp');">{$txt['yshout_rp']}</a>
<br />
<a href="javascript:ajaxGet('banid=
{$_GET['banid']}&amp;mode=p');">{$txt['yshout_p']}</a>
</body>
</html>
EOF
);
exit;
}
if ($user['is_admin'] || $user['is_mod'])
{
if(!is_numeric($_GET['banid']))
{
// guest banning?
// ban by IP, since that's what will be listed for banning...

$oldread=isset($_SESSION['readingCmd'])?$_SESSION['readingCmd']:NULL;
doBan('ban_ips_',$_GET['mode'],$_GET['banid']);
if($oldread==NULL) unset($_SESSION['readingCmd']);
else $_SESSION['readingCmd']=$oldread;
exit;
}
if(loadMemberData(Array($_GET['banid']),false,'minimal')===false)
{
doMsg($txt['yshout_error'].$txt['yshout_no_user']);
exit;
}
$oldread=isset($_SESSION['readingCmd'])?$_SESSION['readingCmd']:NULL;
doBan('ban_names_',$_GET['mode'],$user_profile[$_GET['banid']]['memberName']);
if($oldread==NULL) unset($_SESSION['readingCmd']);
else $_SESSION['readingCmd']=$oldread;
}
exit;
}

if(isset(
$_GET['delete']))
{
if ($user['is_admin'] || $user['is_Moderador Global'])
{
global $logDir,$chatFile;
$chatFile=isset($_GET['file'])?$_GET['file']:"home.txt";
$chatFile = checkName($chatFile);
$chatPath = "$logDir/$chatFile";
$fileContents = '';

if (file_exists($chatPath))
$fileContents = file_get_contents($chatPath);
$fileContents=preg_replace('/<p[^>]*><em title="'.str_replace('|','\|',$_GET['delete']).'">.+\n/','',$fileContents);
$handle = fopen($chatPath, "w");
fputs($handle, $fileContents);
fclose($handle);
echo $txt['yshout_del_success'];
}
exit;
}

if(isset(
$_GET['unban']))
{
if ($user['is_admin'] || $user['is_mod'])
{
$oldread=isset($_SESSION['readingCmd'])?$_SESSION['readingCmd']:NULL;
doBan('ban_'.$_GET["type"].'s_','u',$_GET['unban']);
if($oldread==NULL) unset($_SESSION['readingCmd']);
else $_SESSION['readingCmd']=$oldread;
}
exit;
}

if(!isset(
$_POST["file"]) || !isset($_POST["reqtype"]))
die($txt['yshout_no_action']);

$chatFile = checkName($_POST["file"]);
$reqType = $_POST["reqtype"];

switch(
$reqType) {
case "init":
if($gzipCompression) ob_start("ob_gzhandler"); // GZip for everything BUT the 404 header
echo '<a href="javascript:goTo(\'file=',checkName($chatFile),'&amp;history\')">',$txt['yshout_history'],'</a>&nbsp;<a href="javascript:goTo(\'help\')">',$txt['yshout_commands'],'</a>';
if($user['is_admin'] || $user['is_mod'])
{
echo '&nbsp;<a href="javascript:history_number=prompt(\'How far back?\',200);if(history_number){goTo(\'file=',checkName($chatFile),'&amp;history&amp;n=\'+history_number)}else{void(0)}">',$txt['yshout_exthistory'],'</a>';
if(!isset($_COOKIE['yShout_hideadmlinks']))
echo '&nbsp;<a href="javascript:set_cookie(\'yShout_hideadmlinks\',\'true\',3600*24*365);delete_cookie(\'yShout_open\');loadChat();">',$txt['yshout_hide'],$txt['yshout_admlinks'],'</a>';
else
echo '&nbsp;<a href="javascript:delete_cookie(\'yShout_hideadmlinks\');delete_cookie(\'yShout_open\');loadChat();">',$txt['yshout_show'],$txt['yshout_admlinks'],'</a>';
echo '&nbsp;<a href="javascript:autoShout(\'/return\');">',$txt['yshout_return'],'</a>';
}
echo '<div id="shouts">';
echo readChat($chatFile, $logDir);
echo '</div>';
if (in_array($ip, $ban_ips_post) || in_array($user['username'], $ban_names_post) || in_array($user['name'], $ban_names_post))
echo '
<form id="shout-form" action="#">
<fieldset>
<input id="forum-name" style="color: #666666;" maxlength="'
,$maxUsernameChars,'" value="',$user['name'], '" type="text" disabled="true" />
<input id="shout-text" style="color: #666666;" maxlength="'
,$maxShoutChars,'" value="',$txt['yshout_p_banned'],'" type="text" disabled="true" />
<input id="shout-button" type="button" value="'
,$txt['yshout_banned'],'" disabled="true" />
</fieldset>
</form>'
;
elseif (!$user['is_admin'] && !$user['is_mod'] && $maintenance!==false)
echo '
<form id="shout-form" action="#">
<fieldset>
<input id="forum-name" style="color: #666666;" maxlength="'
,$maxUsernameChars,'" value="',$user['name'], '" type="text" disabled="true" />
<input id="shout-text" style="color: #666666;" maxlength="'
,$maxShoutChars,'" value="',$maintenance,'" type="text" disabled="true" />
<input id="shout-button" type="button" value="'
,$txt['yshout_maintenance'],'" disabled="true" />
</fieldset>
</form>'
;
elseif (!$user['is_logged'] && !$allowGuestsPost)
echo '
<form id="shout-form" action="#">
<fieldset>
<input id="forum-name" style="color: #666666;" maxlength="'
,$maxUsernameChars,'" value="',$user['name'], '" type="text" disabled="true" />
<input id="shout-text" style="color: #666666;" maxlength="'
,$maxShoutChars,'" value="',$txt['yshout_no_guests'],'" type="text" disabled="true" />
<input id="shout-button" type="button" value="'
,$txt['yshout_maintenance'],'" disabled="true" />
</fieldset>
</form>'
;
else
{
echo '<form id="shout-form" action="#">
<fieldset>'
;
if (!$user['is_logged'] && $autoGuestName===false)
echo '
<input id="forum-name" style="color: #666666;" maxlength="'
,$maxUsernameChars,'" value="',$user['name'], '" type="text" />';
else
echo '
<input id="forum-name" style="color: #666666;" maxlength="'
,$maxUsernameChars,'" value="',$user['name'], '" type="text" disabled="true" />';
echo '
<input id="shout-text" style="color: #666666;" maxlength="'
,$maxShoutChars,'" value="" type="text" />
<input id="shout-button" type="button" value="'
,$txt['yshout_shout_button'],'" />
</fieldset>
</form>'
;
}
if($gzipCompression) ob_end_flush();
break;

case "shout":
if (in_array($ip, $ban_ips_post) || in_array($user['username'], $ban_names_post) || in_array($user['name'], $ban_names_post)) break;
if (!$user['is_logged'] && !$allowGuestsPost) break;
if (!$user['is_admin'] && !$user['is_mod'] && $maintenance!==false) break;
$shoutText = $_POST["shout"];
if($shoutText[0]=='/' && $allowCommands)
{
if($user['is_admin'] || $user['is_mod'])
{
if(processCommand($shoutText)) break;
}
elseif($user['is_logged'] || $guestCommands)
{
$shoutText=substr($shoutText,0,$maxShoutChars);
if(processUserCommand($shoutText)) break;
}
}
$shoutName = $user['name']; //$_POST["name"];

writeLine($chatFile, $logDir, $shoutText, $user);
truncateChat($chatFile, $logDir, $max_lines);
refreshChats(true);
break;

case "refresh":
refreshChats(false);
break;
case "autoshout":
if($user['is_admin'] || $user['is_mod'])
processCommand($_POST["shout"]);
break;
}

function
doMsg($msg)
{
echo $msg; // tell user
$_SESSION['readingCmd']=$msg; // make sure user keeps seeing this message; see readChat
}

function
processCommand($text) {
global $reqType, $chatFile, $logDir, $max_lines, $ip, $user, $bannedCommands, $txt, $maintenance;
global $ban_ips_readpost, $ban_ips_post, $ban_names_readpost, $ban_names_post;
if($text[0]!='/') return false; // no slash, no service
$data=explode(' ',$text,2); // "2" means to make the first "word" separated from the rest
$cmd=$data[0]; // first word is the cmd. No cmds can have spaces, duh!
$args=(isset($data[1])?$data[1]:''); // are there even any arguments?
if(in_array($cmd,$bannedCommands)) return false;
switch($cmd) {
case "/clear":
for($a=0;$a<$max_lines;$a+=1) truncateChat($chatFile,$logDir,0); // truncate $max_lines times, each approaching 0. This assumes that there aren't any shouts past $max_lines.
return true;
case "/return": // I'm done reading
unset($_SESSION['readingCmd']);
echo readChat($chatFile, $logDir);
return true;
case "/lock":
if ($args=='')
{
doMsg($txt['yshout_error'].$txt['yshout_lock_arg_error']);
return true;
}
if($maintenance !== false)
doMsg(sprintf($txt['yshout_lock_changed'],$args));
else
doMsg(sprintf($txt['yshout_lock_success'], $args));
$maintenance = $args;
writeBanList();
return true;
case "/unlock":
if($maintenance === false)
{
doMsg($txt['yshout_error'].$txt['yshout_unlock_already']);
return true;
}
$maintenance = false;
writeBanList();
doMsg($txt['yshout_unlock_success']);
return true;
case "/banlist": // who's banned?
$_SESSION['readingCmd']=$text;
$temp=Array();
echo '<table>
<caption>'
,$txt['yshout_banlist_caption'],'</caption>';
echo '<tr><td>',$txt['yshout_ip_bans'],$txt['yshout_rp'],'</td><td>';
$temp=Array();
foreach($ban_ips_readpost as $i)
$temp[]="<a href=\"javascript:ajaxGet('unban=$i&type=ip');\">$i</a>";
echo implode($temp,','),'</tr>';
echo '<tr><td>',$txt['yshout_ip_bans'],$txt['yshout_p'],'</td><td>';
$temp=Array();
foreach($ban_ips_post as $i)
$temp[]="<a href=\"javascript:ajaxGet('unban=$i&type=ip');\">$i</a>";
echo implode($temp,','),'</tr>';
echo '<tr><td>',$txt['yshout_username_bans'],$txt['yshout_rp'],'</td><td>';
$temp=Array();
foreach($ban_names_readpost as $i)
$temp[]="<a href=\"javascript:ajaxGet('unban=$i&type=name');\">$i</a>";
echo implode($temp,','),'</tr>';
echo '<tr><td>',$txt['yshout_username_bans'],$txt['yshout_p'],'</td><td>';
$temp=Array();
foreach($ban_names_post as $i)
$temp[]="<a href=\"javascript:ajaxGet('unban=$i&type=name');\">$i</a>";
echo implode($temp,','),'</tr>';
echo '</table>';
return true;
case "/ban": // need to be more specific!
doMsg($txt['yshout_error'].$txt['yshout_ban_type_error']);
return true;
case "/banuser": // go away, we don't like you!
case "/banip":
$type=($cmd=='/banip')?'ban_ips_':'ban_names_'; // prefixes for vars
$ar=explode(' ',$args,2); // true argument array. the "2" ensures that we cut only once: mode can't have spaces but user can.
if(count($ar)!=2) // whoops: only one argument?
{
doMsg($txt['yshout_error'].$txt['yshout_ban_mode_error']);
return true;
}
$mode=$ar[0]; // set up vars
$id=$ar[1];
doBan($type,$mode,$id);
return true;
case "/impersonate": // lets pwn some n00bs!
// <user> [userlevel] [ip] [userid] /[shout text]
$slashpos=strpos($args,' /'); // use ' /' as a separator, so we can see how many args came before
if($slashpos===false) // no shout? invalid formatting?
{
doMsg($txt['yshout_error'].$txt['yshout_imp_slash_error']);
return true;
}
$shout=substr($args,$slashpos+2);
$ar=explode(' ',substr($args,0,$slashpos));
$name='';
$userlevel=0;
$userid=0;

switch(count($ar)) // how many args did we get?
{
case 0: // no args--what are you doing?
doMsg($txt['yshout_error'].$txt['yshout_imp_uname_error']);
return true;
case 4: // reverse order to save space: we just set them from the back!
$userid=intval($ar[3]);
case 3:
$ip=$ar[2]; // corrupt the global >:D
case 2:
$userlevel=intval($ar[1]);
case 1:
$name=html_entity_decode($ar[0]);
break;
default:
doMsg($txt['yshout_error'].$txt['yshout_imp_max4_error']); // just so they know that we only have 4 params
return true;
}
$ip.='.'; // to set off the impersonated msgs
$fakeuser=array('id'=>$userid,'name'=>$name,'is_admin'=>($userlevel==2)?1:0,'is_mod'=>($userlevel==1)?1:0,'is_logged'=>($userlevel==-1)?0:1); // fake SMF $user array
writeLine($chatFile,$logDir,$shout,$fakeuser); // do it, write the line
truncateChat($chatFile, $logDir, $max_lines); // make sure to scroll it, or bad things will happen
echo readChat($chatFile, $logDir); // update admin's display
return true;
default: // it wasn't a command, n00b!
return processUserCommand($text);
}
return false;
}

function
processUserCommand($text) {
global $reqType, $chatFile, $logDir,$max_lines, $ip,$ban_ips_readpost,$ban_ips_post,$ban_names_readpost,$ban_names_post,$user,$bannedCommands,$func;
if($text[0]!='/') return false; // no slash, no service
$data=explode(' ',$text,2); // "2" means to make the first "word" separated from the rest
$cmd=$data[0]; // first word is the cmd. No cmds can have spaces, duh!
$args=(isset($data[1])?$data[1]:''); // are there even any arguments?
if(in_array($cmd,$bannedCommands)) return false;
switch($cmd) {
case "/help":
if(empty($args)) help();
elseif($args[0]!='/') help('/'.$args);
else help($args);
$_SESSION['readingCmd']=$text;
return true;
case "/return": // I'm done reading
unset($_SESSION['readingCmd']);
echo readChat($chatFile, $logDir);
return true;
case "/pi":
$s_pi='141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609';
$n=5;
if($args!='') $n=intval($args);
$res=($n==0)?"PI IS EXACTLY 3!":'3.'.substr($s_pi,0,$n-1).(substr($s_pi,$n-1,1)+(substr($s_pi,$n,1)>=5?1:0));
// all that nasty little bit does is add the first n-2 chars, then add the last digit and increment if rounding is necessary.
makeShout($res);
return true;
case "/me":
checkDir($logDir);

$chatFile = checkName($chatFile);

$chatPath = "$logDir/$chatFile";

$newText = $args.' ';
$newText = $func['htmlspecialchars'](stripslashes($newText), ENT_QUOTES);
$newText = str_replace(array("[list]","[center]","[left]","[right]"),"",$newText); // kill some BBCode--these tags are useless and can be abused
preparsecode($newText); // gah, sanitize input!!
$newText = parse_bbc($newText); // w00t!
censorText($newText);
$shoutName=$user['name'];
$userID=$user['id'];
$writeText = "<p><em title=\"".time()." | $ip\"><span class=\"shout-timestamp\">[<timeval=".time().">]</span><font color=\"red\"> * $shoutName</em> $newText</p></font>\n";
$handle = fopen($chatPath, "a");
if($handle===false) die("File error (processing /me); aborted");
$failcount=0;
while( !flock($handle, LOCK_EX) ) // just IN CASE two ppl write to it at once
{
usleep(50000);
$failcount++;
if($failcount > 20) die('Write error (processing /me); aborted'); // one second
}
fwrite($handle, $writeText);
flock($handle, LOCK_UN);
fclose($handle);
truncateChat($chatFile, $logDir, $max_lines);
refreshChats(true);
return true;
default:
return false;
}
return false;
}

function
doBan($type,$mode,$id)
{
global $ban_ips_readpost,$ban_ips_post,$ban_names_readpost,$ban_names_post,$txt;
switch($mode)
{
case 'u': // nice guy
$r=$type.'readpost'; // need to search both ban arrays. Search this one first...
$index=array_search($id,$$r); // where is my little banned user?
if($index===false)
{
$r=$type.'post'; // ...and this one second on failure.
$index=array_search($id,$$r);
if($index===false) // whoops, both searches failed!
{
doMsg($txt['yshout_error'].'Couldn\'t find user to unban!');
return false;
}
}
array_splice($$r,$index,1); // cut the 1 element loose with splice. $$r is used because $r is the string variable denoting the target array.
doMsg("Success: unbanned $id.");
break;
case 'rp':
array_push(${$type.'readpost'},$id); // easy, huh!
doMsg("Success: banned $id from reading and posting.");
break;
case 'p':
array_push(${$type.'post'},$id);
doMsg("Success: banned $id from posting.");
break;
default:
doMsg($txt['yshout_error']."Invalid mode $mode! Use only 'u', 'rp' or 'p'!");
return false;
}
writeBanList(); // write the final report
return true;
}

function
makeShout($text) {
global $chatFile,$logDir,$user,$max_lines;

writeLine($chatFile, $logDir, $text, $user);
truncateChat($chatFile, $logDir, $max_lines);
refreshChats(true);
}

function
refreshChats($force=false) {
global $chatFile,$logDir,$user,$max_lines,$gzipCompression,$updateTimeout;
$time=file_exists("$logDir/$chatFile")?filemtime("$logDir/$chatFile"):0;
$start_time=time();
session_write_close(); // so that future session requests succeed
while(!$force && (time() - $start_time < $updateTimeout) && $time && ($time==filemtime("$logDir/$chatFile")))
{
sleep(1);
clearstatcache();
}
if($gzipCompression) ob_start("ob_gzhandler");
echo readChat($chatFile, $logDir);
if($gzipCompression) ob_end_flush();
}

function
checkDir($logDir) {
if (!is_dir($logDir))
mkdir($logDir);
}

function
checkName($chatFile) {
$ret = $chatFile;
$ret = str_replace('/', '', $chatFile);
return $ret;
}

function
readChat($chatFile, $logDir) {
global $user;
if(isset($_SESSION['readingCmd']))
{
$c=$_SESSION['readingCmd'];
if($c[0]!='/') echo $c; // doMsg was used. Don't use doMsg with a slash unless you know what you're doing ;)
else
{
if($user['is_admin'] || $user['is_mod']) processCommand($_SESSION['readingCmd']); // execute the same command so the user gets to keep reading the message w/o interruption.
else processUserCommand($_SESSION['readingCmd']);
}
return ' ';
}
$chatFile = checkName($chatFile);
$chatPath = "$logDir/$chatFile";

$chatText = "";

if (file_exists($chatPath))
$chatText = file_get_contents($chatPath);
if ($user['is_admin'] || $user['is_mod'])
{
if (!isset($_COOKIE['yShout_hideadmlinks']))
{
$chatText = preg_replace('/<em title="(\\d+) \| ([^"]+)"><span class="shout-timestamp">\[<timeval=(\d+)>\]<\/span> ([^<])/','<em title="\\1 | \\2"><span class="shout-timestamp">[<timeval=\\3>]</span>&nbsp;<a href="javascript:ajaxGet(\'banid=\\2\')"><span class="adminlink">ban</span></a>&nbsp;\\4',$chatText);
$chatText = preg_replace('/<em title="(\\d+ \| [^"]+)"><span class="shout-timestamp">\[<timeval=(\d+)>\]<\/span>/','<em title="\\1"><span class="shout-timestamp">[<timeval=\\2>]</span>&nbsp;<a href="javascript:ajaxGet(\'file='.$chatFile.'&amp;delete=\\1\')"><span class="adminlink">del</span></a>&nbsp;',$chatText);
$chatText = preg_replace('/<a href="index\.php\\?action=profile;u=(\\d+)">/','<a href="javascript:ajaxGet(\'banid=\\1\')"><span class="adminlink">ban</span></a>&nbsp;<a href="index.php?action=profile;u=\\1">',$chatText);
}
}
else
{
$chatText = preg_replace('/<em title="(\d+) \| [0-9.]+"><span class="shout-timestamp">/','<em title="\\1 | logged"><span class="shout-timestamp">',$chatText);
}
$chatText=preg_replace_callback("/<timeval=(\d+)>/","preg_timeformat",$chatText);
return $chatText.' '; // hack: totally empty responses can break some browsers
}

// truncateChat function based on one written by Travis Roman (http://mapleglobal.mine.nu/)

function truncateChat($chatFile, $logDir, $max_lines) {
$chatFile = checkName($chatFile);
$chatPath = "$logDir/$chatFile";
$fileContents = '';

if (file_exists($chatPath))
$fileContents = file_get_contents($chatPath);

$lines = explode("\n", $fileContents);

if(count($lines) > $max_lines) {
$newText = substr($fileContents, strpos($fileContents, "\n") + 1);
$handle = fopen($chatPath, "w");
fputs($handle, $newText);
fclose($handle);

 // History
$oldText = substr($fileContents, 0, strpos($fileContents, "\n") + 1);
$handle = fopen("$logDir/history.$chatFile", "a");
fputs($handle, $oldText);
fclose($handle);
}
}

function
writeLine($chatFile, $logDir, $newText, $user) {
global $ip,$func;
checkDir($logDir);

$chatFile = checkName($chatFile);

$chatPath = "$logDir/$chatFile";

// $ip = $_SERVER['REMOTE_ADDR']; // impersonate >:D
$newText .= " ";
$newText = $func['htmlspecialchars'](stripslashes($newText), ENT_QUOTES);
$newText = str_replace(array("[list]","[center]","[left]","[right]"),"",$newText); // kill some BBCode--these tags are useless and can be abused
preparsecode($newText); // gah, sanitize input!!
$newText = parse_bbc($newText); // w00t!
censorText($newText);
// $newText = preg_replace("(http:\/\/(.+?) )is", "<a href=\"http://$1\" target=\"_blank\">http://$1</a> ", $newText);

$p_class = "";

if($user['is_admin']) $p_class = ' class="owner"';
if($user['is_mod']) $p_class = ' class="moderator"';
if(!$user['is_logged']) $p_class = ' class="guest"';
$shoutName=$user['name'];
$userID=$user['id'];
$writeText="<p$p_class><em title=\"".time()." | $ip\"><span class=\"shout-timestamp\">[<timeval=".time().">]</span> ";
if($user['is_logged'])
$writeText.="<a href=\"index.php?action=profile;u=$userID\">$shoutName</a>";
else
$writeText.="$shoutName";
$writeText.=":</em> $newText</p>\n";
$handle = fopen($chatPath, "a");
$failcount=0;
if($handle===false) die('File error (writeLine); aborted');
while( !flock($handle, LOCK_EX) ) // just IN CASE two ppl write to it at once
{
usleep(50000);
$failcount++;
if($failcount > 20) die('Write error (writeLine); aborted'); // one second
}
fwrite($handle, $writeText);
flock($handle, LOCK_UN);
fclose($handle);
}

function
help($command='')
{
global $user,$defaultEncoding,$txt;
$cmdlist=$txt['yshout_cmdlist'];

$cmdlistadmin=$txt['yshout_cmdlistadmin'];
if($user['is_admin'] || $user['is_mod'])
$cmdlist=array_merge($cmdlist,$cmdlistadmin);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<base href="/advforums/">
<head>
<meta http-equiv="content-type" content="text/html; charset=<?php echo $defaultEncoding ?>" />
<title><?php echo $txt['yshout_cmd_reference']; ?></title>
</head>
<body>
<?php
if($command=='')
{
echo '<h1>',$txt['yshout_shoutbox'],' ',$txt['yshout_commands'],'</h1>';
foreach($cmdlist as $cmd=>$desc)
{
echo "$cmd$desc<br />\n";
}
}
else
{
if(isset($cmdlist[$command])) echo "$command{$cmdlist[$command]}<br />\n";
else echo "$command not found";
}
?>
</body>
</html>
<?php
}

function
writeBanList() // generate our dynamic ban list, which is 'require'd at the start of this script
{
global $ban_ips_readpost,$ban_ips_post,$ban_names_readpost,$ban_names_post,$maintenance;
$writeText = "<?php\n"; // php header
$writeText .= '$ban_ips_readpost = '.var_export($ban_ips_readpost,true).";\n"; // bans
$writeText .= '$ban_ips_post = '.var_export($ban_ips_post,true).";\n";
$writeText .= '$ban_names_readpost = '.var_export($ban_names_readpost,true).";\n";
$writeText .= '$ban_names_post = '.var_export($ban_names_post,true).";\n";
$writeText .= '$maintenance = '.var_export($maintenance,true).";\n";
$writeText .= '?>'; // end tag
$handle = fopen("_banlist.php", "w");
if($handle===false) die('File error (writeBanList); aborted');
$failcount=0;
while( !flock($handle, LOCK_EX) ) // just IN CASE two ppl write to it at once
{
usleep(50000);
$failcount++;
if($failcount > 20) die('Write error (writeBanList); aborted'); // one second
}
fwrite($handle, $writeText);
flock($handle, LOCK_UN);
fclose($handle);
}

function history()
{
global $logDir,$boardurl,$gzipCompression,$defaultEncoding,$txt;
checkDir($logDir);

$chatFile=isset($_GET['file'])?$_GET['file']:"home.txt";
$chatFile = checkName($chatFile);

$chatPath = "$logDir/$chatFile";
$n=250;
if(isset($_GET['n'])) $n=intval($_GET['n']); // integers only!
if($gzipCompression) ob_start("ob_gzhandler");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<base href="<?php echo $boardurl,'/'; ?>">
<head>
<meta http-equiv="content-type" content="text/html; charset=<?php echo $defaultEncoding ?>" />
<title><?php echo $txt['yshout_shoutbox'],' ',$txt['yshout_history']; ?></title>
<style type="text/css">
#yshout {
font-size: 10px;
}
#yshout p {
margin: 0 0 0; /* Top Bottom Linespacing */
}
.shout-invalid {
background: #FFFDD1;
}
#yshout fieldset {
border: none;
}
#yshout em {
font-style: normal;
}
#yshout p {
line-height: 1;
margin-top: 0;
}
#yshout {
overflow: hidden;
}
#yshout .shout-timestamp {
font-weight: normal;
color: #000;
}
a:link {
color: #476C8E;
}
#shouts .owner a {
color: #F00;
}
#shouts .moderator a {
color: #00F;
}
</style>
</head>
<body>
<h1><?php echo $txt['yshout_shoutbox'],' ',$txt['yshout_history']; ?></h1>
<div id="yshout">
<div id="shouts">
<?php
global $user;
require_once("class.tail.php");
$mytail = new tail("$logDir/history.$chatFile");
$mytail->setGrep(".*");
$mytail->setNumberOfLines($n);
$text=$mytail->output(PLAIN).file_get_contents("$logDir/$chatFile");
if(!($user['is_admin'] || $user['is_mod']))
$text = preg_replace('/<em title="(\d+) \| [0-9.]+"><span class="shout-timestamp">/','<em title="\\1 | logged"><span class="shout-timestamp">',$text);
echo preg_replace_callback("/<timeval=(\d+)>/","preg_timeformat",$text);
?>
</div>
</div>
</body>
</html>
<?php
if(
$gzipCompression) ob_end_flush();
exit;
}
?>
[/php]


Thank you

nneonneo

Hmm? I meant the Modifications.portuguese.php file, sorry about the confusion.
Check out the AJAX Shoutbox (my one and only mod to date :P)
Do you like SMF? Are you using ProBoards, InvisionFree, ActiveBoards or some other web-hosted forum? I can help you convert to SMF (without having to purchase a DB conversion)...contact me [nneonneo {at} gmail *dot* com], and see this topic
spammers here!

adventurer

Quote from: nneonneo on November 07, 2007, 06:19:40 PM
@adventurer: Hmm, odd. Have you checked the server error log?

nothing wrong ....
????

nneonneo

Hum? Nothing in the server error log, yet moderators can't ban or delete?

Anything in the forum error logs?
Check out the AJAX Shoutbox (my one and only mod to date :P)
Do you like SMF? Are you using ProBoards, InvisionFree, ActiveBoards or some other web-hosted forum? I can help you convert to SMF (without having to purchase a DB conversion)...contact me [nneonneo {at} gmail *dot* com], and see this topic
spammers here!

Sruc

#1306
I find this error in forum error logs:

8: Undefined index: yshout_loading
Archivo: /homepages/11/d219923774/htdocs/Foro/Themes/Black22/BoardIndex.template.php (main_above sub template - eval?)
Línea: 288


I have searched the line 288:
               return;

Only this.

nneonneo

Oh dear, my apologies (to everyone!). I missed a post, and now I've posted wrong advice >.<


Here:

@Sruc: Banning should work, but deletion doesn't work because you've modified this line:
if ($user['is_admin'] || $user['is_Moderador Global'])
This should read
if ($user['is_admin'] || $user['is_mod'])

As for the yshout_loading error, copy Themes/default/languages/Modifications.english.php to Themes/default/languages/Modifications.<yourlanguage>.php to fix that.

@adventurer: Yet, history will not show? Give me a URL to your forum and I will check it out.

@okidokiss: It's probably due to character encodings (the failure of the special characters to show). Post, PM or attach your Modifications.language.php file, and I'll see what I can do.
Check out the AJAX Shoutbox (my one and only mod to date :P)
Do you like SMF? Are you using ProBoards, InvisionFree, ActiveBoards or some other web-hosted forum? I can help you convert to SMF (without having to purchase a DB conversion)...contact me [nneonneo {at} gmail *dot* com], and see this topic
spammers here!

Sruc

OMFG I'm a newbie >.<'

Excuse me already for the inconveniences and thank you very much.

trekkie2444

How do I place the shoutbox directly below my boards and right before the info center?

exxocet

Very effective shotbox, Unfortunately yshout.php is restricted by many shared server hosts, they say it uses too much resources on refresh.

nneonneo

@trekkie2444: For the default theme, everything you need to do is in Themes/default.
Edit index.template.php and do these three steps:
1) Change
',empty($options['collapse_header']) ? 'loadChat();':'','
to
loadChat();
2) Remove
// YSHOUT HERE
document.getElementById("yshout").style.display = mode ? "none" : "";
if(!mode)
{
loadChat();
}
// YSHOUT END

3) Remove
// YSHOUT HERE
echo '
<br /><b>Shout Box</b><br /><br />
<div id="yshout"', empty($options['collapse_header']) ? '>' : ' style="display: none;">',$txt['yshout_loading'],'<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div>';
// YSHOUT END

This may appear twice.

The rest depends on where you want it exactly and how it should appear. You have many options:
1) as the first block in the info center
2) as a separate block styled like the info center
3) as a separate block styled like the blocks in the info center (e.g. Users Online block)
Also, it will only appear on the board index, and nowhere else, if this is what you want.

@exxocet: Hmm, I would suppose this is primarily due to my earlier versions being poor at efficiency. The new versions check for new shouts every 20 seconds, which is on par with most autorefresh shoutboxes, but more live because new shouts are near-instantly shown and the 20-second timer reset, instead of waiting for the shoutbox to refresh.
Check out the AJAX Shoutbox (my one and only mod to date :P)
Do you like SMF? Are you using ProBoards, InvisionFree, ActiveBoards or some other web-hosted forum? I can help you convert to SMF (without having to purchase a DB conversion)...contact me [nneonneo {at} gmail *dot* com], and see this topic
spammers here!

jossanaijr

Quote from: nneonneo on November 12, 2007, 03:32:29 PM
The rest depends on where you want it exactly and how it should appear.
Is it difficult to change to a separete block style before my boards?

nneonneo

Nope. Follow the three steps outlined from before (these prevent the box from getting hit by strange collapse bugs).

Now, you have two options, because of where you want it.

a) On every page (this requires an edit to index.template.php)
b) On only the board index (this requires an edit to BoardIndex.template.php).

These two options produce vastly different locations in the code, but should result in approximately the same appearance. Let me know which one you want.
Check out the AJAX Shoutbox (my one and only mod to date :P)
Do you like SMF? Are you using ProBoards, InvisionFree, ActiveBoards or some other web-hosted forum? I can help you convert to SMF (without having to purchase a DB conversion)...contact me [nneonneo {at} gmail *dot* com], and see this topic
spammers here!

jossanaijr


nneonneo

By the way, the code which should be inserted looks like the following:

// YSHOUT HERE
echo '
<div class="tborder" style="margin-top: 0;' , $context['browser']['needs_size_fix'] && !$context['browser']['is_ie6'] ? 'width: 100%;' : '', '">
<div class="catbg" style="padding: 5px 5px 5px 10px;">',$txt['yshout_shoutbox'],'
</div>
<table border="0" width="100%" cellspacing="1" cellpadding="5" class="bordercolor" style="margin-top: 1px;">
<tr><td class="windowbg2"><div id="yshout">',$txt['yshout_loading'],'<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div></td></tr></table>
</div><br />';
// YSHOUT END


This gets placed wherever you wish the shoutbox to appear. It will wrap the shoutbox with a category-like box, with the words Shout Box over the top.

For "only on the board index, before the first board", place this before
/* Each category in categories is made up of:
id, href, link, name, is_collapsed (is it collapsed?), can_collapse (is it okay if it is?),
new (is it new?), collapse_href (href to collapse/expand), collapse_image (up/down image),
and boards. (see below.) */

in BoardIndex.template.php.

For "on every page, after the tabs", put it after
// The end of tab section.
echo '
<td class="maintab_' , $last , '">&nbsp;</td>
</tr>
</table>';


For "before the info center", put it before
// Here's where the "Info Center" starts... in BoardIndex.template.php.

EDIT: Yeah, I think I've answered your recent post there jossanaijr, let me know if there is a problem.
Check out the AJAX Shoutbox (my one and only mod to date :P)
Do you like SMF? Are you using ProBoards, InvisionFree, ActiveBoards or some other web-hosted forum? I can help you convert to SMF (without having to purchase a DB conversion)...contact me [nneonneo {at} gmail *dot* com], and see this topic
spammers here!

jossanaijr

Worked.  Thanks AGAIN!!!!

iyeru42

I tried doing the ...loading shoutbox fix, but it still shows that problem.

nneonneo

@jossanaijr: Good to hear.

@iyeru42: Odd. If you give me a URL to your forum, I'll check it out.
Check out the AJAX Shoutbox (my one and only mod to date :P)
Do you like SMF? Are you using ProBoards, InvisionFree, ActiveBoards or some other web-hosted forum? I can help you convert to SMF (without having to purchase a DB conversion)...contact me [nneonneo {at} gmail *dot* com], and see this topic
spammers here!

iyeru42

Quote from: nneonneo on November 16, 2007, 12:02:31 AM
@jossanaijr: Good to hear.

@iyeru42: Odd. If you give me a URL to your forum, I'll check it out.

I can't seem to find your fix anymore, but here it is for the newest version:
var board_url = "'; $boardurlparsed = parse_url($boardurl); echo $boardurlparsed['path'], '";

change to

var board_url = "/home2/iyeru42/public_html/board";

Link to the Board

I use the Scribbles theme, and PHP4... because my host's hoster won't upgrade to PHP5.

Advertisement: