commit
0e3b24a641
After Width: | Height: | Size: 172 KiB |
After Width: | Height: | Size: 172 KiB |
@ -0,0 +1,103 @@
|
||||
<?PHP
|
||||
|
||||
#error_reporting(E_ALL);
|
||||
|
||||
// Examples:
|
||||
// $str = base85::encode("Hello world!");
|
||||
// $str = base85::decode(":e4D*;K$&\Er");
|
||||
|
||||
class base85
|
||||
{
|
||||
|
||||
public static function decode($str) {
|
||||
$str = preg_replace("/ \t\r\n\f/","",$str);
|
||||
$str = preg_replace("/z/","!!!!!",$str);
|
||||
$str = preg_replace("/y/","+<VdL/",$str);
|
||||
|
||||
// Pad the end of the string so it's a multiple of 5
|
||||
$padding = 5 - (strlen($str) % 5);
|
||||
if (strlen($str) % 5 === 0) {
|
||||
$padding = 0;
|
||||
}
|
||||
$str .= str_repeat('u',$padding);
|
||||
|
||||
$num = 0;
|
||||
$ret = '';
|
||||
|
||||
// Foreach 5 chars, convert it to an integer
|
||||
while ($chunk = substr($str, $num * 5, 5)) {
|
||||
$tmp = 0;
|
||||
|
||||
foreach (unpack('C*',$chunk) as $item) {
|
||||
$tmp *= 85;
|
||||
$tmp += $item - 33;
|
||||
}
|
||||
|
||||
// Convert the integer in to a string
|
||||
$ret .= pack('N', $tmp);
|
||||
|
||||
$num++;
|
||||
}
|
||||
|
||||
// Remove any padding we had to add
|
||||
$ret = substr($ret,0,strlen($ret) - $padding);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public static function encode($str) {
|
||||
$ret = '';
|
||||
$debug = 0;
|
||||
|
||||
$padding = 4 - (strlen($str) % 4);
|
||||
if (strlen($str) % 4 === 0) {
|
||||
$padding = 0;
|
||||
}
|
||||
|
||||
if ($debug) {
|
||||
printf("Length: %d = Padding: %s<br /><br />\n",strlen($str),$padding);
|
||||
}
|
||||
|
||||
// If we don't have a four byte chunk, append \0s
|
||||
$str .= str_repeat("\0", $padding);
|
||||
|
||||
foreach (unpack('N*',$str) as $chunk) {
|
||||
// If there is an all zero chunk, it has a shortcut of 'z'
|
||||
if ($chunk == "\0") {
|
||||
$ret .= "z";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Four spaces has a shortcut of 'y'
|
||||
if ($chunk == 538976288) {
|
||||
$ret .= "y";
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($debug) {
|
||||
var_dump($chunk); print "<br />\n";
|
||||
}
|
||||
|
||||
// Convert the integer into 5 "quintet" chunks
|
||||
for ($a = 0; $a < 5; $a++) {
|
||||
$b = intval($chunk / (pow(85,4 - $a)));
|
||||
$ret .= chr($b + 33);
|
||||
|
||||
if ($debug) {
|
||||
printf("%03d = %s <br />\n",$b,chr($b+33));
|
||||
}
|
||||
|
||||
$chunk -= $b * pow(85,4 - $a);
|
||||
}
|
||||
}
|
||||
|
||||
// If we added some null bytes, we remove them from the final string
|
||||
if ($padding) {
|
||||
$ret = preg_replace("/z$/",'!!!!!',$ret);
|
||||
$ret = substr($ret,0,strlen($ret) - $padding);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
} // End of base85 class
|
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
require_once "/main.inc";
|
||||
|
||||
class Encryption
|
||||
{
|
||||
public $publicKey=null;
|
||||
public $privateKey=null;
|
||||
private $res=null;
|
||||
private $dt=null;
|
||||
|
||||
private $psk=null;
|
||||
private $upsk=false;
|
||||
|
||||
private static $sklen = 4096;
|
||||
|
||||
private static $config = array(
|
||||
"digest_alg" => "sha512",
|
||||
"private_key_bits" => 4096,
|
||||
"private_key_type"=> OPENSSL_KEYTYPE_RSA,
|
||||
);
|
||||
private function generateNewSymmetricKey()
|
||||
{
|
||||
return openssl_random_pseudo_bytes(self::$sklen);
|
||||
}
|
||||
private function _begin($prec)
|
||||
{
|
||||
$this->res = openssl_pkey_new(self::$config);
|
||||
openssl_pkey_export($this->res, $this->publicKey);
|
||||
$this->dt=openssl_pkey_get_details($this->res);
|
||||
$this->publicKey=$this->dt["key"];
|
||||
|
||||
if($prec)
|
||||
{
|
||||
$this->upsk = true;
|
||||
$this->psk = generateNewSymmetricKey();
|
||||
}
|
||||
}
|
||||
public function __construct()
|
||||
{
|
||||
$this->_begin(false);
|
||||
}
|
||||
public function __construct1($p)
|
||||
{
|
||||
$this->_begin($p);
|
||||
}
|
||||
private function s_decrypt($data, $key)
|
||||
{
|
||||
return s_encrypt($data, $key); //same;
|
||||
}
|
||||
private function s_encrypt($data, $key)
|
||||
{
|
||||
$j=0;
|
||||
$out = "";
|
||||
for($i=0;$i<strlen($data);$i++)
|
||||
{
|
||||
if($j>=strlen($key)) $j=0;
|
||||
$out .= ($data[$i] ^ $key[$j]);
|
||||
$j+=1;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function encrypt($data)
|
||||
{
|
||||
$skey = ($this->upsk?$this->psk:$this->generateNewSymmetricKey());
|
||||
$e_skey = null;
|
||||
openssl_public_encrypt($skey, $e_skey, $this->publicKey);
|
||||
|
||||
$e_data = $this->s_encrypt($data, $skey);
|
||||
|
||||
return CreateFromEncryption(array("ekey"=>$e_skey, "edata"=>$e_data));
|
||||
}
|
||||
public function decrypt(EncryptedData $ed)
|
||||
{
|
||||
$ekey = $ed->e_symmetricKey();
|
||||
$edata = $ed->e_data();
|
||||
|
||||
$skey = null;
|
||||
openssl_private_decrypt($ekey, $skey, $this->privateKey);
|
||||
return $this->s_decrypt($edata, $skey);
|
||||
}
|
||||
public function encdata_create($data)
|
||||
{
|
||||
return EncryptedData::CreateFromData($data);
|
||||
}
|
||||
}
|
||||
class EncryptedData
|
||||
{
|
||||
private $ekey=null;
|
||||
private $edata=null;
|
||||
private function __construct(Array $data)
|
||||
{
|
||||
$this->ekey = $data["ekey"];
|
||||
$this->edata = $data["edata"];
|
||||
}
|
||||
public function __construct1($ek, $ed)
|
||||
{
|
||||
$this->ekey = $ek;
|
||||
$this->edata = $ed;
|
||||
}
|
||||
private function __construct2()
|
||||
{
|
||||
|
||||
}
|
||||
public function binaryData($set=null)
|
||||
{
|
||||
if($set==null) {
|
||||
return "{".strlen($this->ekey).", ".strlen($this->edata)."}".$this->ekey.$this->edata;
|
||||
}
|
||||
else
|
||||
{
|
||||
$kvals = explode(", ", substr(substr($set, 0, strpos($set, "}")), 1));
|
||||
$klen = intval($kvals[0]);
|
||||
$dlen = intval($kvals[1]);
|
||||
|
||||
$this->ekey = substr($set, strpos($set, "}")+1, $klen);
|
||||
$this->edata = substr($set, strpos($set, "}")+1+$klen, $dlen);
|
||||
}
|
||||
}
|
||||
public function e_symmetricKey($val=null)
|
||||
{
|
||||
if($val==null) {
|
||||
return $this->ekey;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->ekey = $val;
|
||||
}
|
||||
}
|
||||
public function e_data($val=null)
|
||||
{
|
||||
if($val==null) {
|
||||
return $this->edata;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->edata = $val;
|
||||
}
|
||||
}
|
||||
public static function CreateFromData($data)
|
||||
{
|
||||
$val = new EncryptedData();
|
||||
$val->binaryData($data);
|
||||
return $val;
|
||||
}
|
||||
public static function CreateFromEncryption(Array $data)
|
||||
{
|
||||
return new EncryptedData($data);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,651 @@
|
||||
<?php
|
||||
define('TIMEALLOWED', (60*15));
|
||||
define('TIME_MINUTE', (60));
|
||||
define('TIME_HOUR', (60*60));
|
||||
define('TIME_DAY', (60*60*24));
|
||||
define('TIME_WEEK', (60*60*24*7));
|
||||
define('TIME_MONTH', (60*60*24*7*5));
|
||||
define('TIME_YEAR', (60*60*24*365));
|
||||
|
||||
define("SQL_DEFAULT_HOST_NAME", "localhost");
|
||||
define("SQL_DEFAULT_USER", "root");
|
||||
define("SQL_DEFAULT_PASSWORD", "root");
|
||||
|
||||
if(isLogForce()) doLoggerOnce();
|
||||
|
||||
|
||||
if(isForced())
|
||||
{
|
||||
if(isBanned(getip())) die();
|
||||
if(!isActive())
|
||||
{
|
||||
if(getAdminLevel(getip())===false) die();
|
||||
}
|
||||
}
|
||||
function setForceLog($fl)
|
||||
{
|
||||
file_put_contents("/forcelog", $fl?"true":"false");
|
||||
}
|
||||
function isLogForce()
|
||||
{
|
||||
$ar = file_get_contents("/forcelog");
|
||||
return streq($ar,"true");
|
||||
|
||||
}
|
||||
|
||||
function bcrypt_verify($name, $hash)
|
||||
{
|
||||
return bcrypt($name) == $hash;
|
||||
}
|
||||
|
||||
function bcrypt($str)
|
||||
{
|
||||
return crypt($str, '_J9..rasm');
|
||||
}
|
||||
|
||||
function pa($str)
|
||||
{
|
||||
$out="";
|
||||
$col="";
|
||||
$level==0;
|
||||
$fonttags=0;
|
||||
$vr=0;
|
||||
for($i=0;$i<strlen($str);$i++)
|
||||
{
|
||||
if($str[$i] == "\n")
|
||||
{
|
||||
if($level==1) {
|
||||
$out .="<font color=#$col>";
|
||||
$vr+=1;
|
||||
$col="";
|
||||
$level-=1;
|
||||
}
|
||||
else
|
||||
$level+=1;
|
||||
}
|
||||
elseif($level==1)
|
||||
{
|
||||
$col.=$str[$i];
|
||||
}
|
||||
else {
|
||||
$out.=$str[$i];
|
||||
}
|
||||
}
|
||||
return $out.str_repeat("</font>", $vr);
|
||||
}
|
||||
function phplib($nm)
|
||||
{
|
||||
require_once "/phplib/$nm";
|
||||
}
|
||||
function jtostring($val)
|
||||
{
|
||||
$out = "{";
|
||||
$keys = array_keys($val);
|
||||
for($i=0;$i<count($keys);$i++)
|
||||
{
|
||||
$key = is_array($keys[$i])?jtostring($keys[$i]):$keys[$i];
|
||||
$value = is_array($val[$keys[$i]])?jtostring($val[$keys[$i]]):$val[$keys[$i]];
|
||||
|
||||
$out .= "[$key] = [$value]".(($i==(count($keys)-1))?"":", ");
|
||||
}
|
||||
return $out . "}";
|
||||
}
|
||||
function setupNotifications()
|
||||
{
|
||||
jslib("notify.js");
|
||||
|
||||
}
|
||||
function isActive()
|
||||
{
|
||||
return streq(file_get_contents("/active"), "true");
|
||||
}
|
||||
function getLastMember($array)
|
||||
{
|
||||
$el = end($array);
|
||||
reset($array);
|
||||
return $el;
|
||||
}
|
||||
function arraydup($ar)
|
||||
{
|
||||
return unserialize(serialize($ar));
|
||||
}
|
||||
function getSessionInfo($ip=null)
|
||||
{
|
||||
$sql = beginSQL("server");
|
||||
$res = mysql_query_return_assoc("SELECT * FROM sessionInfo ".($ip!=null?"WHERE `ip` = '$ip' ":"")."LIMIT 0, 1");
|
||||
$ret=null;
|
||||
if($res!==false)
|
||||
{
|
||||
$ret = $res;
|
||||
}
|
||||
@mysql_free_result_array($res);
|
||||
endSQL($sql);
|
||||
return $ret;
|
||||
}
|
||||
function defaultNotify()
|
||||
{
|
||||
notifyBar("__user_message");
|
||||
notifyBar("__temp_message");
|
||||
notifyBar("__get_message");
|
||||
notifyBar("__server_message");
|
||||
|
||||
if(isset($_REQUEST["msg"]))
|
||||
js("setNotifyBar('#__get_message', '".$_REQUEST["msg"]."', 2000);");
|
||||
js("defnot_set_load_user_message(\"".getip()."\");
|
||||
defnot_set_load_server_message();");
|
||||
}
|
||||
function startsWith($haystack, $needle) {
|
||||
// search backwards starting from haystack length characters from the end
|
||||
return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE;
|
||||
}
|
||||
function endsWith($haystack, $needle) {
|
||||
// search forward starting from end minus needle length characters
|
||||
return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle, $temp) !== FALSE);
|
||||
}
|
||||
function checkTempNotify()
|
||||
{
|
||||
if(tempNotifyExists())
|
||||
{
|
||||
$vl = readTempNotify();
|
||||
js("setNotifyBar('#__temp_message', '".addslashes($vl)."', 3000);");
|
||||
}
|
||||
|
||||
}
|
||||
function notifyBar($id)
|
||||
{
|
||||
echo("<div class='none' style='font-family: Consolas; font-size: 20px; text-align: center' id='$id'></div>");
|
||||
}
|
||||
function getifexists($ar, $vl)
|
||||
{
|
||||
if(isset($ar[$vl])) return $ar[$vl];
|
||||
else return null;
|
||||
}
|
||||
function jserialise($ar) {return jsserialise($ar);}
|
||||
function jsserialise($ar)
|
||||
{
|
||||
$keys = array_keys($ar);
|
||||
$values = array_values($ar);
|
||||
$out = "";
|
||||
for($i=0;$i<count($values);$i++)
|
||||
{
|
||||
|
||||
$key = (is_array($keys[$i])?"array_".base64_encode(jsserialise($keys[$i])):base64_encode($keys[$i]));
|
||||
$value = (is_array($values[$i])?"array_".base64_encode(jsserialise($values[$i])):base64_encode($values[$i]));
|
||||
|
||||
$out .= "$key-$value\r\n";
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
function setForced($vl)
|
||||
{
|
||||
file_put_contents("/force", $vl?"true":"false");
|
||||
}
|
||||
function isForced()
|
||||
{
|
||||
return streq(file_get_contents("/force"), "true");
|
||||
}
|
||||
function readUntil($str, $c)
|
||||
{
|
||||
|
||||
$pos = strpos($str, $c);
|
||||
if($pos!==false&&$pos>0)
|
||||
{
|
||||
return substr($str, 0, $pos-1);
|
||||
}
|
||||
else return $str;
|
||||
}
|
||||
function junserialise($ar) {return jsunserialise($ar);}
|
||||
function jsunserialise($ar)
|
||||
{
|
||||
$ars= array();
|
||||
foreach(explode("\r\n", $ar) as $line)
|
||||
{
|
||||
if($line!="") {
|
||||
$ur = explode("-", $line);
|
||||
|
||||
$key = startsWith($ur[0], "array_")?junserialise(base64_decode(substr($ur[0], 6))):base64_decode($ur[0]);
|
||||
$value = startsWith($ur[1], "array_")?junserialise(base64_decode(substr($ur[1], 6))):base64_decode($ur[1]);
|
||||
|
||||
$ars[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $ars;
|
||||
}
|
||||
function formatDateTime($dt)
|
||||
{
|
||||
if($dt<TIME_MINUTE)
|
||||
return $dt." seconds ago";
|
||||
elseif($dt<TIME_HOUR)
|
||||
return round($dt/TIME_MINUTE)." minutes ago";
|
||||
elseif($dt<TIME_DAY)
|
||||
return round($dt/TIME_HOUR)." hours ago";
|
||||
elseif($dt<TIME_WEEK)
|
||||
return round($dt/TIME_DAY)." days ago";
|
||||
elseif($dt<TIME_MONTH)
|
||||
return round($dt/TIME_WEEK)." weeks ago";
|
||||
elseif($dt<TIME_YEAR)
|
||||
return round($dt/TIME_MONTH)." months ago";
|
||||
else
|
||||
return (round(($dt/TIME_YEAR)*100.00)/100.00)." years ago";
|
||||
}
|
||||
function jss($script)
|
||||
{
|
||||
echo ("<script src='$script'></script>");
|
||||
}
|
||||
function jslib($name)
|
||||
{
|
||||
jss("/jslib/$name");
|
||||
}
|
||||
function isBanned($ip)
|
||||
{
|
||||
$sql = beginSQL("server");
|
||||
$res = mysql_query_return_assoc("SELECT banned FROM sessionInfo WHERE `ip`='$ip'");
|
||||
$ret = $res[0]["banned"];
|
||||
@mysql_free_result_array($res);
|
||||
endSQL($sql);
|
||||
return $ret;
|
||||
}
|
||||
function redirect($page,$wtime=0)
|
||||
{
|
||||
echo '<meta http-equiv="REFRESH" content="'.$wtime.';url='.$page.'"></HEAD>';
|
||||
}
|
||||
function getAdminLevel($ip)
|
||||
{
|
||||
$sql = beginSQL("server");
|
||||
$res = mysql_query_return_assoc("SELECT `level` FROM admins WHERE `ip`='$ip'");
|
||||
$ret=false;
|
||||
if($res != array())
|
||||
{
|
||||
$ret = $res[0]["level"];
|
||||
}
|
||||
@mysql_free_result_array($res);
|
||||
endSQL($sql);
|
||||
return $ret;
|
||||
}
|
||||
function banUser($ip)
|
||||
{
|
||||
$sql = beginSQL("server");
|
||||
mysql_query("UPDATE sessionInfo SET
|
||||
`banned`=1
|
||||
WHERE `ip`='$ip'");
|
||||
endSQL($sql);
|
||||
}
|
||||
function unbanUser($ip)
|
||||
{
|
||||
$sql = beginSQL("server");
|
||||
mysql_query("UPDATE sessionInfo SET
|
||||
`banned`=0
|
||||
WHERE `ip`='$ip'");
|
||||
endSQL($sql);
|
||||
}
|
||||
function jquery()
|
||||
{
|
||||
jslib("jquery-1.8.2.js");
|
||||
jslib("jquery.base64.js");
|
||||
}
|
||||
function js($str)
|
||||
{
|
||||
echo("<script>$str</script>");
|
||||
}
|
||||
function issetmultiple($ar, $vls)
|
||||
{
|
||||
$val = true;
|
||||
foreach($vls as $r) $val = $val && isset($ar[$r]);
|
||||
return $val;
|
||||
}
|
||||
function pageinit_n($sql=null)
|
||||
{
|
||||
pageinit($sql);
|
||||
jquery();
|
||||
jslib("notify.js");
|
||||
enableBanCheck();
|
||||
doActiveCheck();
|
||||
}
|
||||
function pathfix($str)
|
||||
{
|
||||
return str_replace("\\", "/", $str);
|
||||
}
|
||||
function sqldate($stamp=null)
|
||||
{
|
||||
return date("y.m.d H.i.s", $stamp==null?time():$stamp);
|
||||
}
|
||||
function enableBanCheck()
|
||||
{
|
||||
jslib("check.js");
|
||||
js("banCheck();");
|
||||
if(isBanned(getip())) doBan();
|
||||
}
|
||||
function activeNotifyBar($id, $val)
|
||||
{
|
||||
echo("<div class='notify' style='font-family: Consolas; font-size: 20px; text-align: center' id='$id'>$val</div>");
|
||||
}
|
||||
function doActiveCheck()
|
||||
{
|
||||
if(!isActive()) {
|
||||
if(getAdminLevel(getip())!==false)
|
||||
{
|
||||
echo("<div class='notify' style='font-family: Consolas; font-size: 20px; text-align: center' id='__active_n'>WEBSITE OFFLINE</div>");
|
||||
}
|
||||
else
|
||||
die("website offline");
|
||||
}
|
||||
}
|
||||
function doBan()
|
||||
{
|
||||
redirect("/banned.php");
|
||||
die();
|
||||
}
|
||||
function pageinit($vsql=null)
|
||||
{
|
||||
$sql = $vsql==null?beginSQL("server"):$vsql;
|
||||
if($vsql!=null)
|
||||
{
|
||||
mysql_select_db("server",$sql);
|
||||
}
|
||||
$res = mysql_query_return_assoc("SELECT * FROM `sessionInfo` WHERE `ip`='".getip()."'");
|
||||
echo(mysql_error());
|
||||
if($res==array())
|
||||
{
|
||||
mysql_query("INSERT INTO sessionInfo (
|
||||
ip, url, sessionid, last
|
||||
) VALUES (
|
||||
'".getip()."',
|
||||
'".geturl()."',
|
||||
".(sessionid()==null||streq(sessionid(),"")?"NULL":"'".$_REQUEST["PHPSESSID"]."'").",
|
||||
'".date("y.m.d H:i:s")."'
|
||||
)");
|
||||
echo(mysql_error());
|
||||
}
|
||||
else
|
||||
{
|
||||
mysql_query("UPDATE sessionInfo SET
|
||||
url='".geturl()."',
|
||||
sessionid=".(sessionid()==null||streq(sessionid(),"")?"NULL":"'".$_REQUEST["PHPSESSID"]."'").",
|
||||
|
||||
last='".date("y.m.d H:i:s")."',
|
||||
views=views+1
|
||||
WHERE
|
||||
`ip`='".getip()."'
|
||||
");
|
||||
|
||||
echo(mysql_error());
|
||||
}
|
||||
@mysql_free_result_array($res);
|
||||
doLogger();
|
||||
|
||||
if($vsql==null) endSQL($sql);
|
||||
}
|
||||
function doLoggerOnce()
|
||||
{
|
||||
$sql = beginSQL("server");
|
||||
doLogger();
|
||||
endSQL($sql);
|
||||
}
|
||||
function setLogAll($l)
|
||||
{
|
||||
file_put_contents("/logall", $l?"true":"false");
|
||||
}
|
||||
function isLogAll()
|
||||
{
|
||||
return streq(file_get_contents("/logall"), "true")?true:false;
|
||||
}
|
||||
function js_onKeyPress($id, $func, $key)
|
||||
{
|
||||
js('$(document).ready(function()
|
||||
{
|
||||
$("'.$id.'").keypress(function (e){
|
||||
if(e.keyCode=='.$key.')
|
||||
'.$func.';
|
||||
});
|
||||
});');
|
||||
}
|
||||
function js_onEnterPress($id, $func)
|
||||
{
|
||||
js_onKeyPress($id, $func, 13);
|
||||
}
|
||||
function doLogger()
|
||||
{
|
||||
$r = mysql_query_return_assoc("SELECT * FROM logInfo WHERE `ip`='".getip()."'");
|
||||
if(($r!=array())||isLogAll())
|
||||
{
|
||||
mysql_query("INSERT INTO logs (
|
||||
ip, url, session, time
|
||||
) VALUES (
|
||||
'".getip()."',
|
||||
'".geturl()."',
|
||||
".(sessionid()==null||streq(sessionid(),"")?"NULL":"'".$_REQUEST["PHPSESSID"]."'").",
|
||||
'".sqldate()."'
|
||||
)");
|
||||
}
|
||||
else @mysql_free_result_array($r);
|
||||
}
|
||||
function writeAllText($fn, $txt)
|
||||
{
|
||||
$p = fopen($fn, "w");
|
||||
fwrite($p, $txt);
|
||||
fclose($p);
|
||||
}
|
||||
function sessionid()
|
||||
{
|
||||
return $_REQUEST["PHPSESSID"];
|
||||
}
|
||||
function geturl() {
|
||||
$actual_link = "http://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"];
|
||||
return $actual_link;
|
||||
}
|
||||
function getmsg()
|
||||
{
|
||||
$txt = @readalltext("\message");
|
||||
if(streq($txt,"")) return NULL;
|
||||
return $txt;
|
||||
}
|
||||
function button($value, $onclick=null,$other="")
|
||||
{
|
||||
echo("<input type='button' value='$value' ".($onclick==null?"":"onclick='$onclick' ")." $other />");
|
||||
}
|
||||
function sessionActive()
|
||||
{
|
||||
return sessionid() !== '';
|
||||
}
|
||||
function setTempNotify($msg)
|
||||
{
|
||||
$_SESSION["msg"]=$msg;
|
||||
}
|
||||
function tempNotifyExists()
|
||||
{
|
||||
return isset($_SESSION["msg"]);
|
||||
}
|
||||
function readTempNotify()
|
||||
{
|
||||
$msg=null;
|
||||
if(isset($_SESSION["msg"])) {
|
||||
$msg = $_SESSION["msg"];
|
||||
unset($_SESSION["msg"]);
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
function index($ar, $i)
|
||||
{
|
||||
return $ar[$i];
|
||||
}
|
||||
function mysql_query_return_assoc($q)
|
||||
{
|
||||
$res = (mysql_query($q));
|
||||
$ret=array();
|
||||
$i=0;
|
||||
|
||||
if(!$res) echo(mysql_error());
|
||||
else
|
||||
while($cur = mysql_fetch_assoc($res))
|
||||
{
|
||||
$ret[$i++] = $cur;
|
||||
}
|
||||
//mysql_free_result($q);
|
||||
return $ret;
|
||||
|
||||
}
|
||||
function readAllText($fn)
|
||||
{
|
||||
$fp = fopen($fn,"r");
|
||||
$data = fread($fp, filesize($fn));
|
||||
fclose($fp);
|
||||
return $data;
|
||||
}
|
||||
function beginSQL($db)
|
||||
{
|
||||
$con = mysql_connect(SQL_DEFAULT_HOST_NAME, SQL_DEFAULT_USER, SQL_DEFAULT_PASSWORD);
|
||||
mysql_select_db($db, $con);
|
||||
return $con;
|
||||
}
|
||||
function endSQL($con)
|
||||
{
|
||||
mysql_close($con);
|
||||
}
|
||||
function css($css)
|
||||
{
|
||||
echo '<LINK href="'.$css.'" rel="stylesheet" type="text/css">';
|
||||
}
|
||||
function css_main($dir="/")
|
||||
{
|
||||
echo '<LINK href="'.$dir.'css/main.css" rel="stylesheet" type="text/css">';
|
||||
}
|
||||
function title($title, $others="",$id=null)
|
||||
{
|
||||
echo "<p id='center' $others class='title' ".($id==null?"":"id='".$id."'").">$title</p>\n";
|
||||
echo "<title>$title</title>";
|
||||
}
|
||||
function mysql_free_result_array($res)
|
||||
{
|
||||
foreach($res as $re)
|
||||
mysql_free_result($re);
|
||||
}
|
||||
function lb()
|
||||
{
|
||||
echo("<br />");
|
||||
}
|
||||
function para()
|
||||
{
|
||||
echo("<p />");
|
||||
}
|
||||
function validip($ip)
|
||||
{
|
||||
return preg_match("~([0-9]{1,3}[.]){3,3}[0-9]{1,3}~",$ip);
|
||||
}
|
||||
function getip()
|
||||
{
|
||||
if (validip($_SERVER["HTTP_CLIENT_IP"])) {
|
||||
return $_SERVER["HTTP_CLIENT_IP"];
|
||||
}
|
||||
foreach (explode(",",$_SERVER["HTTP_X_FORWARDED_FOR"]) as $ip) {
|
||||
if (validip(trim($ip))) {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
if (validip($_SERVER["HTTP_X_FORWARDED"])) {
|
||||
return $_SERVER["HTTP_X_FORWARDED"];
|
||||
} elseif (validip($_SERVER["HTTP_FORWARDED_FOR"])) {
|
||||
return $_SERVER["HTTP_FORWARDED_FOR"];
|
||||
} elseif (validip($_SERVER["HTTP_FORWARDED"])) {
|
||||
return $_SERVER["HTTP_FORWARDED"];
|
||||
} elseif (validip($_SERVER["HTTP_X_FORWARDED"])) {
|
||||
return $_SERVER["HTTP_X_FORWARDED"];
|
||||
} else {
|
||||
return $_SERVER["REMOTE_ADDR"];
|
||||
}
|
||||
}
|
||||
function link_tab($res, $txt, $other="")
|
||||
{
|
||||
link($res, $txt, "target='_black' ".$other);
|
||||
}
|
||||
function link($res, $txt, $other="")
|
||||
{
|
||||
echo("<a $other href='$res'>$txt</a>");
|
||||
}
|
||||
function streq($str,$str2)
|
||||
{
|
||||
return strcmp($str,$str2)==0;
|
||||
}
|
||||
function echoline($ln)
|
||||
{
|
||||
echo($ln); lb();
|
||||
}
|
||||
function echopara($pa)
|
||||
{
|
||||
echo($pa); para();
|
||||
}
|
||||
class Session {
|
||||
public static function unserialize($session_data) {
|
||||
$method = ini_get("session.serialize_handler");
|
||||
switch ($method) {
|
||||
case "php":
|
||||
return self::unserialize_php($session_data);
|
||||
break;
|
||||
case "php_binary":
|
||||
return self::unserialize_phpbinary($session_data);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unsupported session.serialize_handler: " . $method . ". Supported: php, php_binary");
|
||||
}
|
||||
}
|
||||
|
||||
private static function unserialize_php($session_data) {
|
||||
$return_data = array();
|
||||
$offset = 0;
|
||||
while ($offset < strlen($session_data)) {
|
||||
if (!strstr(substr($session_data, $offset), "|")) {
|
||||
throw new Exception("invalid data, remaining: " . substr($session_data, $offset));
|
||||
}
|
||||
$pos = strpos($session_data, "|", $offset);
|
||||
$num = $pos - $offset;
|
||||
$varname = substr($session_data, $offset, $num);
|
||||
$offset += $num + 1;
|
||||
$data = unserialize(substr($session_data, $offset));
|
||||
$return_data[$varname] = $data;
|
||||
$offset += strlen(serialize($data));
|
||||
}
|
||||
return $return_data;
|
||||
}
|
||||
|
||||
private static function unserialize_phpbinary($session_data) {
|
||||
$return_data = array();
|
||||
$offset = 0;
|
||||
while ($offset < strlen($session_data)) {
|
||||
$num = ord($session_data[$offset]);
|
||||
$offset += 1;
|
||||
$varname = substr($session_data, $offset, $num);
|
||||
$offset += $num;
|
||||
$data = unserialize(substr($session_data, $offset));
|
||||
$return_data[$varname] = $data;
|
||||
$offset += strlen(serialize($data));
|
||||
}
|
||||
return $return_data;
|
||||
}
|
||||
public static function serialize( $array, $safe = true ) {
|
||||
|
||||
// the session is passed as refernece, even if you dont want it to
|
||||
if( $safe )
|
||||
$array = unserialize(serialize( $array )) ;
|
||||
|
||||
//var_dump($array);
|
||||
$raw = '' ;
|
||||
$line = 0 ;
|
||||
$keys = array_keys( $array ) ;
|
||||
foreach( $keys as $key ) {
|
||||
$value = $array[ $key ] ;
|
||||
$line ++ ;
|
||||
|
||||
$raw .= $key .'|' ;
|
||||
|
||||
if( is_array( $value ) && isset( $value['huge_recursion_blocker_we_hope'] )) {
|
||||
$raw .= 'R:'. $value['huge_recursion_blocker_we_hope'] . ';' ;
|
||||
} else {
|
||||
$raw .= serialize( $value ) ;
|
||||
}
|
||||
$array[$key] = Array( 'huge_recursion_blocker_we_hope' => $line ) ;
|
||||
}
|
||||
|
||||
return $raw ;
|
||||
|
||||
}
|
||||
}
|
||||
?>
|
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
require_once "/main.inc";
|
||||
define("CHUNKSIZE", 512);
|
||||
|
||||
function imagexy($im)
|
||||
{
|
||||
return array(imagesx($im), imagesy($im));
|
||||
}
|
||||
|
||||
class ImageScrambler
|
||||
{
|
||||
public $source=null;
|
||||
public $seed=null;
|
||||
|
||||
public function __construct($image, $rndr)
|
||||
{
|
||||
$this->source=$image;
|
||||
$this->seed = $rndr;
|
||||
|
||||
srand($rndr);
|
||||
}
|
||||
private function getAreas()
|
||||
{
|
||||
$v = imagexy($this->source);
|
||||
$xv = $v[0] % CHUNKSIZE;
|
||||
$yv = $v[1] % CHUNKSIZE;
|
||||
$ret = array();
|
||||
$i=0;
|
||||
for($y=0;$i<$yv;$y++)
|
||||
{
|
||||
for($x=0;$x<$xv;$x++)
|
||||
{
|
||||
$ret[$i++] = array($x*CHUNKSIZE, $y*CHUNKSIZE,CHUNKSIZE,CHUNKSIZE);
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
private function _swap($ar,$i,$j)
|
||||
{
|
||||
$cp = $ar[$i];
|
||||
$ar[$i] = $ar[$j];
|
||||
$ar[$j] = $cp;
|
||||
}
|
||||
private function scrambleArea($ar)
|
||||
{
|
||||
for($i=count($ar)-1;$i>=0;$i--)
|
||||
{
|
||||
$this->_swap($ar, $i, rand(0, $i));
|
||||
}
|
||||
return $ar;
|
||||
}
|
||||
|
||||
public function scramble()
|
||||
{
|
||||
$area = $this->getAreas();
|
||||
$sarea = $this->scrambleArea($area);
|
||||
$nw = imagecreate(imagesx($this->source), imagesy($this->source));
|
||||
for($i=0;count($area);$i+=2)
|
||||
{
|
||||
imagecopy($nw, $this->source, $sarea[$i+1][0], $sarea[$i+1][1], $sarea[$i][0], $sarea[$i][1],CHUNKSIZE,CHUNKSIZE);
|
||||
}
|
||||
imagedestroy($this->source);
|
||||
$this->source=$nw;
|
||||
return $sarea;
|
||||
}
|
||||
public function destroy()
|
||||
{
|
||||
imagedestroy($this->$source);
|
||||
}
|
||||
}
|
||||
?>
|
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
require_once "/main.inc";
|
||||
|
||||
function _plist_isName($name, $val)
|
||||
{
|
||||
return password_verify($name, $val);
|
||||
}
|
||||
|
||||
function _plist_name($nm) {
|
||||
return bcrypt($nm);
|
||||
}
|
||||
|
||||
function plist_add($name, $value)
|
||||
{
|
||||
$val = _plist_name($name);
|
||||
|
||||
}
|
||||
?>
|
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
require_once "/main.inc";
|
||||
function mp4video($file) {
|
||||
$fp = @fopen($file, 'rb');
|
||||
|
||||
$size = filesize($file); // File size
|
||||
$length = $size; // Content length
|
||||
$start = 0; // Start byte
|
||||
$end = $size - 1; // End byte
|
||||
|
||||
header('Content-type: video/mp4');
|
||||
//header("Accept-Ranges: 0-$length");
|
||||
header("Accept-Ranges: bytes");
|
||||
if (isset($_SERVER['HTTP_RANGE'])) {
|
||||
|
||||
$c_start = $start;
|
||||
$c_end = $end;
|
||||
|
||||
list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
|
||||
if (strpos($range, ',') !== false) {
|
||||
header('HTTP/1.1 416 Requested Range Not Satisfiable');
|
||||
header("Content-Range: bytes $start-$end/$size");
|
||||
exit;
|
||||
}
|
||||
if ($range == '-') {
|
||||
$c_start = $size - substr($range, 1);
|
||||
}else{
|
||||
$range = explode('-', $range);
|
||||
$c_start = $range[0];
|
||||
$c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size;
|
||||
}
|
||||
$c_end = ($c_end > $end) ? $end : $c_end;
|
||||
if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) {
|
||||
header('HTTP/1.1 416 Requested Range Not Satisfiable');
|
||||
header("Content-Range: bytes $start-$end/$size");
|
||||
exit;
|
||||
}
|
||||
$start = $c_start;
|
||||
$end = $c_end;
|
||||
$length = $end - $start + 1;
|
||||
fseek($fp, $start);
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
}
|
||||
header("Content-Range: bytes $start-$end/$size");
|
||||
header("Content-Length: ".$length);
|
||||
|
||||
$buffer = 1024 * 8;
|
||||
while(!feof($fp) && ($p = ftell($fp)) <= $end) {
|
||||
|
||||
if ($p + $buffer > $end) {
|
||||
$buffer = $end - $p + 1;
|
||||
}
|
||||
set_time_limit(0);
|
||||
echo fread($fp, $buffer);
|
||||
flush();
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
exit();
|
||||
}
|
||||
function webmvideo($file) {
|
||||
$fp = @fopen($file, 'rb');
|
||||
|
||||
$size = filesize($file); // File size
|
||||
$length = $size; // Content length
|
||||
$start = 0; // Start byte
|
||||
$end = $size - 1; // End byte
|
||||
|
||||
header('Content-type: video/webm');
|
||||
//header("Accept-Ranges: 0-$length");
|
||||
header("Accept-Ranges: bytes");
|
||||
if (isset($_SERVER['HTTP_RANGE'])) {
|
||||
|
||||
$c_start = $start;
|
||||
$c_end = $end;
|
||||
|
||||
list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
|
||||
if (strpos($range, ',') !== false) {
|
||||
header('HTTP/1.1 416 Requested Range Not Satisfiable');
|
||||
header("Content-Range: bytes $start-$end/$size");
|
||||
exit;
|
||||
}
|
||||
if ($range == '-') {
|
||||
$c_start = $size - substr($range, 1);
|
||||
}else{
|
||||
$range = explode('-', $range);
|
||||
$c_start = $range[0];
|
||||
$c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size;
|
||||
}
|
||||
$c_end = ($c_end > $end) ? $end : $c_end;
|
||||
if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) {
|
||||
header('HTTP/1.1 416 Requested Range Not Satisfiable');
|
||||
header("Content-Range: bytes $start-$end/$size");
|
||||
exit;
|
||||
}
|
||||
$start = $c_start;
|
||||
$end = $c_end;
|
||||
$length = $end - $start + 1;
|
||||
fseek($fp, $start);
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
}
|
||||
header("Content-Range: bytes $start-$end/$size");
|
||||
header("Content-Length: ".$length);
|
||||
|
||||
$buffer = 1024 * 8;
|
||||
while(!feof($fp) && ($p = ftell($fp)) <= $end) {
|
||||
|
||||
if ($p + $buffer > $end) {
|
||||
$buffer = $end - $p + 1;
|
||||
}
|
||||
set_time_limit(0);
|
||||
echo fread($fp, $buffer);
|
||||
flush();
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
exit();
|
||||
}
|
||||
?>
|
@ -0,0 +1,3 @@
|
||||
[Trash Info]
|
||||
Path=static/www/.file
|
||||
DeletionDate=2018-07-07T16:06:51
|
@ -0,0 +1,3 @@
|
||||
[Trash Info]
|
||||
Path=rtbw/Untitled%20Folder
|
||||
DeletionDate=2018-08-29T14:14:52
|
@ -0,0 +1,3 @@
|
||||
[Trash Info]
|
||||
Path=rtbw/Untitled%20Folder
|
||||
DeletionDate=2018-08-13T18:01:21
|
@ -0,0 +1,3 @@
|
||||
[Trash Info]
|
||||
Path=static/www/i/bg%20%28copy%29.png
|
||||
DeletionDate=2018-05-11T11:36:18
|
@ -0,0 +1,3 @@
|
||||
[Trash Info]
|
||||
Path=static/www/i/bg.png
|
||||
DeletionDate=2018-05-11T11:36:13
|
@ -0,0 +1,3 @@
|
||||
[Trash Info]
|
||||
Path=rtbw/maintain/ctl.js
|
||||
DeletionDate=2018-08-29T14:15:18
|
@ -0,0 +1,3 @@
|
||||
[Trash Info]
|
||||
Path=static/old
|
||||
DeletionDate=2018-05-11T10:07:58
|
@ -0,0 +1,37 @@
|
||||
static/
|
||||
git/
|
||||
rtbw/
|
||||
www.old/
|
||||
www/.*/
|
||||
api/
|
||||
www/favicon.ico
|
||||
|
||||
*.node
|
||||
*.pid
|
||||
*.swp
|
||||
.build
|
||||
.lock*
|
||||
.DS_Store
|
||||
authdump
|
||||
config.js
|
||||
graveyard
|
||||
error.log
|
||||
findapng
|
||||
hot.js
|
||||
jsmin
|
||||
node_modules/
|
||||
package-lock.json
|
||||
perceptual
|
||||
imager/tmp
|
||||
state
|
||||
tripcode/.build
|
||||
tripcode/build
|
||||
upkeep/credentials.json
|
||||
voice/*.mp3
|
||||
www/archive
|
||||
www/js/client*.js
|
||||
www/js/vendor*.js
|
||||
www/src
|
||||
www/thumb
|
||||
www/mid
|
||||
www/vint
|
@ -0,0 +1,19 @@
|
||||
Copyright (C) 2010-2017 Lal'C Mellk Mal
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,14 @@
|
||||
all:
|
||||
$(MAKE) -C imager
|
||||
$(MAKE) -C tripcode
|
||||
|
||||
client:
|
||||
@echo 'make client' is no longer necessary
|
||||
@false
|
||||
|
||||
.PHONY: all clean client
|
||||
|
||||
clean:
|
||||
rm -rf -- .build state www/js/{client,vendor}{.,-}*.js
|
||||
$(MAKE) -C imager -w clean
|
||||
$(MAKE) -C tripcode -w clean
|
@ -0,0 +1,50 @@
|
||||
Real-time imageboard.
|
||||
MIT licensed.
|
||||
|
||||
Setup:
|
||||
|
||||
* Install dependencies listed below
|
||||
* Sign up for reCAPTCHA
|
||||
* Create a GitHub Application (callback URL = site URL + /login)
|
||||
* Copy config.js.example to config.js and configure
|
||||
* Copy hot.js.example to hot.js and configure
|
||||
* Copy imager/config.js.example to imager/config.js and configure
|
||||
* Copy report/config.js.example to report/config.js and configure
|
||||
* You might need to run `npm install -g node-gyp`
|
||||
* Run `npm install` to install npm deps and compile a few helpers
|
||||
* Run `node builder.js` to run an auto-reloading development server
|
||||
|
||||
Production:
|
||||
|
||||
* Have your webserver serve www/ (or wherever you've moved src, thumb, etc.)
|
||||
- Configure `imager.config.MEDIA_URL` appropriately
|
||||
- Then turn off `SERVE_STATIC_FILES` and `SERVE_IMAGES`
|
||||
* If you're behind Cloudflare turn on `CLOUDFLARE`
|
||||
- Or if you're behind any reverse proxy (nginx etc) turn on `TRUST_X_FORWARDED_FOR`
|
||||
* Run `node server/server.js` for just the server
|
||||
* You can update client code & hot.js on-the-fly with `node server/kill.js`
|
||||
* For nginx hosting/reverse proxying, refer to docs/nginx.conf.example
|
||||
* For a sample init script, refer to docs/doushio.initscript.example
|
||||
* config.DAEMON support is old and broken, PRs welcome
|
||||
|
||||
Dependencies:
|
||||
|
||||
* ImageMagick
|
||||
* libpng
|
||||
* node.js + npm
|
||||
* redis
|
||||
* ffmpeg 2.2+ if supporting WebM
|
||||
* jhead and jpegtran optionally, for EXIF autorotation
|
||||
|
||||
Optional npm deps for various features:
|
||||
|
||||
* ~~daemon~~ (broken currently)
|
||||
* icecast now-playing banners: node-expat
|
||||
* [send](https://github.com/visionmedia/send) (if you want to serve static files directly from the node.js process; useful in debug mode also)
|
||||
|
||||
Standalone upkeep scripts:
|
||||
|
||||
* archive/daemon.js - moves old threads to the archive
|
||||
* upkeep/backup.js - uploads rdb to S3
|
||||
* upkeep/clean.js - deletes archived images
|
||||
* upkeep/radio.js - icecast2 server integration
|
@ -0,0 +1,5 @@
|
||||
* Update `syncs` in client when on /live
|
||||
* Actually tell user when a particular thread failed to sync
|
||||
* Tokenize text instead of multiple levels of regexps
|
||||
* Should retrieve live body and hctr in one transaction
|
||||
* Consolidate or disambiguate the (three!) different hook/trigger mechanisms
|
@ -0,0 +1,473 @@
|
||||
/* NOTE: This file is processed by server/state.js
|
||||
and served by server/server.js (to auth'd users only) */
|
||||
|
||||
$('<link>', {rel: 'stylesheet', type: 'text/css', href: mediaURL+'css/mod.css'}).appendTo('head');
|
||||
|
||||
var $selectButton, $controls;
|
||||
window.loggedInUser = IDENT.user;
|
||||
window.x_csrf = IDENT.csrf;
|
||||
|
||||
function show_toolbox() {
|
||||
var specs = [
|
||||
{name: 'Lewd', kind: 7},
|
||||
{name: 'Porn', kind: 8},
|
||||
{name: 'Delete', kind: 9},
|
||||
{name: 'Lock', kind: 11},
|
||||
];
|
||||
if (IDENT.auth == 'Admin')
|
||||
specs.push({name: 'Panel', kind: 'panel'});
|
||||
var $toolbox = $('<div/>', {id: 'toolbox', "class": 'mod'});
|
||||
|
||||
$selectButton = $('<input />', {
|
||||
type: 'button', val: 'Select',
|
||||
click: function (e) { toggle_multi_selecting(); },
|
||||
});
|
||||
$toolbox.append($selectButton, ' ');
|
||||
|
||||
$controls = $('<span></span>').hide();
|
||||
_.each(specs, function (spec) {
|
||||
$controls.append($('<input />', {
|
||||
type: 'button',
|
||||
val: spec.name,
|
||||
data: {kind: spec.kind},
|
||||
}), ' ');
|
||||
});
|
||||
$controls.on('click', 'input[type=button]', tool_action);
|
||||
|
||||
_.each(delayNames, function (when, i) {
|
||||
var id = 'delay-' + when;
|
||||
var $label = $('<label/>', {text: when, 'for': id});
|
||||
var $radio = $('<input/>', {
|
||||
id: id, type: 'radio', val: when, name: 'delay',
|
||||
});
|
||||
if (i == 0)
|
||||
$radio.prop('checked', true);
|
||||
$controls.append($radio, $label, ' ');
|
||||
});
|
||||
|
||||
$toolbox.append($controls).insertBefore(THREAD ? 'hr:last' : $ceiling);
|
||||
}
|
||||
|
||||
function tool_action(event) {
|
||||
var ids = [];
|
||||
var $sel = $('.selected');
|
||||
$sel.each(function () {
|
||||
var id = extract_num(parent_post($(this)));
|
||||
if (id)
|
||||
ids.push(id);
|
||||
});
|
||||
var $button = $(this);
|
||||
var kind = $button.data('kind');
|
||||
if (kind == 'panel')
|
||||
return toggle_panel();
|
||||
|
||||
/* On a thread page there's only one thread to lock, so... */
|
||||
if (kind == 11 && THREAD && !ids.length)
|
||||
ids = [THREAD];
|
||||
|
||||
if (ids.length) {
|
||||
var when = $('input:radio[name=delay]:checked').val();
|
||||
ids.unshift(parseInt(kind, 10), {when: when});
|
||||
send(ids);
|
||||
$sel.removeClass('selected');
|
||||
}
|
||||
else {
|
||||
var orig = $button.val();
|
||||
var caption = _.bind($button.val, $button);
|
||||
caption('Nope.');
|
||||
if (orig != 'Nope.')
|
||||
_.delay(caption, 2000, orig);
|
||||
}
|
||||
}
|
||||
|
||||
readOnly.push('graveyard');
|
||||
menuOptions.unshift('Select');
|
||||
menuHandlers.Hide = function () { alert('nope.avi'); };
|
||||
|
||||
var multiSelecting = false;
|
||||
|
||||
function toggle_multi_selecting(model, $post) {
|
||||
var oldTarget;
|
||||
if ($post && model) {
|
||||
oldTarget = lockTarget;
|
||||
set_lock_target(model.id);
|
||||
}
|
||||
with_dom(function () {
|
||||
multiSelecting = !multiSelecting;
|
||||
if (multiSelecting) {
|
||||
$('body').addClass('multi-select');
|
||||
make_selection_handle().prependTo('article');
|
||||
make_selection_handle().prependTo('section > header');
|
||||
if ($post)
|
||||
select_post($post);
|
||||
$controls.show();
|
||||
$selectButton.val('X');
|
||||
}
|
||||
else {
|
||||
$('body').removeClass('multi-select');
|
||||
$('.select-handle').remove();
|
||||
$controls.hide();
|
||||
$selectButton.val('Select');
|
||||
}
|
||||
});
|
||||
if ($post)
|
||||
set_lock_target(oldTarget);
|
||||
}
|
||||
|
||||
menuHandlers.Select = toggle_multi_selecting;
|
||||
|
||||
function enable_multi_selecting() {
|
||||
if (!multiSelecting)
|
||||
toggle_multi_selecting();
|
||||
}
|
||||
|
||||
function select_post($post) {
|
||||
$post.find('.select-handle:first').addClass('selected');
|
||||
}
|
||||
|
||||
function make_selection_handle() {
|
||||
return $('<a class="select-handle" href="#"/>');
|
||||
}
|
||||
|
||||
window.fun = function () {
|
||||
send([33, THREAD]);
|
||||
};
|
||||
|
||||
override(ComposerView.prototype, 'make_alloc_request',
|
||||
function (orig, text, img) {
|
||||
var msg = orig.call(this, text, img);
|
||||
if ($('#authname').is(':checked'))
|
||||
msg.auth = IDENT.auth;
|
||||
return msg;
|
||||
});
|
||||
|
||||
$DOC.on('click', '.select-handle', function (event) {
|
||||
event.preventDefault();
|
||||
$(event.target).toggleClass('selected');
|
||||
});
|
||||
|
||||
with_dom(function () {
|
||||
$('h1').text('Moderation - ' + $('h1').text());
|
||||
var $authname = $('<input>', {type: 'checkbox', id: 'authname'});
|
||||
var $label = $('<label/>', {text: ' '+IDENT.auth}).prepend($authname);
|
||||
$name.after(' ', $label);
|
||||
|
||||
/* really ought to be done with model observation! */
|
||||
$authname.change(function () {
|
||||
if (postForm)
|
||||
postForm.propagate_ident();
|
||||
});
|
||||
oneeSama.hook('fillMyName', function ($el) {
|
||||
var auth = $('#authname').is(':checked');
|
||||
$el.toggleClass(IDENT.auth.toLowerCase(), auth);
|
||||
if (auth)
|
||||
$el.append(' ## ' + IDENT.auth)
|
||||
});
|
||||
|
||||
Backbone.on('afterInsert', function (model, $el) {
|
||||
if (multiSelecting)
|
||||
make_selection_handle().prependTo($el);
|
||||
});
|
||||
show_toolbox();
|
||||
});
|
||||
|
||||
var Address = Backbone.Model.extend({
|
||||
idAttribute: 'key',
|
||||
defaults: {
|
||||
count: 0,
|
||||
},
|
||||
});
|
||||
|
||||
var AddressView = Backbone.View.extend({
|
||||
className: 'mod address',
|
||||
events: {
|
||||
'keydown .name': 'entered_name',
|
||||
'click .sel-all': 'select_all',
|
||||
'click .ban': 'ban',
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
var $el = this.$el;
|
||||
$('<span/>', {"class": 'ip'}).appendTo($el);
|
||||
$el.append(' ', $('<input/>', {
|
||||
"class": 'sel-all',
|
||||
type: 'button',
|
||||
val: 'Sel All'
|
||||
}));
|
||||
if (IDENT.auth == 'Admin')
|
||||
$el.append($('<input/>', {
|
||||
"class": 'ban',
|
||||
type: 'button',
|
||||
val: 'Ban'
|
||||
}));
|
||||
|
||||
$el.append(
|
||||
'<br>',
|
||||
$('<input>', {"class": 'name', placeholder: 'Name'})
|
||||
);
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var attrs = this.model.attributes;
|
||||
if (attrs.shallow) {
|
||||
this.$('.ip').text(attrs.ip ? attrs.ip + ' "\u2026"' : 'Loading...');
|
||||
return this;
|
||||
}
|
||||
this.$('.ip').text(attrs.ip);
|
||||
var $name = this.$('.name');
|
||||
if (!this.focusedName) {
|
||||
_.defer(function () {
|
||||
$name.focus().prop({
|
||||
selectionStart: 0,
|
||||
selectionEnd: $name.val().length,
|
||||
});
|
||||
});
|
||||
this.focusedName = true;
|
||||
}
|
||||
if (attrs.name != $name.val()) {
|
||||
$name.val(attrs.name);
|
||||
}
|
||||
this.$('.ban')
|
||||
.val(attrs.ban ? 'Unban' : 'Ban');
|
||||
return this;
|
||||
},
|
||||
|
||||
entered_name: function (event) {
|
||||
if (event.which != 13)
|
||||
return;
|
||||
event.preventDefault();
|
||||
var name = this.$('.name').val().trim();
|
||||
var ip = this.model.get('ip');
|
||||
send([SET_ADDRESS_NAME, ip, name]);
|
||||
this.remove();
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
this.trigger('preremove');
|
||||
Backbone.View.prototype.remove.call(this);
|
||||
},
|
||||
|
||||
select_all: function () {
|
||||
if (!THREAD)
|
||||
return alert('TODO');
|
||||
// TODO: do where query by ip_key lookup
|
||||
var models = Threads.get(THREAD).get('replies').where({
|
||||
ip: this.model.get('ip'),
|
||||
});
|
||||
if (!models.length)
|
||||
return;
|
||||
enable_multi_selecting();
|
||||
with_dom(function () {
|
||||
$.each(models, function () {
|
||||
select_post($('#' + this.id));
|
||||
});
|
||||
});
|
||||
this.remove();
|
||||
},
|
||||
|
||||
ban: function () {
|
||||
var ip = this.model.get('ip');
|
||||
var attrs = this.model.attributes;
|
||||
var act, type;
|
||||
if (!attrs.ban) {
|
||||
act = 'Ban';
|
||||
type = 'timeout';
|
||||
} else {
|
||||
act = 'Unban';
|
||||
type = 'unban';
|
||||
}
|
||||
if (!confirm(act + ' ' + ip + '?'))
|
||||
return;
|
||||
|
||||
send([BAN, ip, type]);
|
||||
// show ... while processing
|
||||
this.$('.ban').val('...');
|
||||
},
|
||||
});
|
||||
|
||||
// basically just a link
|
||||
var AddrView = Backbone.View.extend({
|
||||
tagName: 'a',
|
||||
className: 'mod addr',
|
||||
|
||||
events: {
|
||||
click: 'toggle_expansion',
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.$el.attr('href', '#');
|
||||
this.listenTo(this.model, 'change:name', this.render);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var attrs = this.model.attributes;
|
||||
var text = ip_mnemonic(attrs.ip);
|
||||
if (attrs.name)
|
||||
text += ' "' + attrs.name + '"';
|
||||
if (attrs.country)
|
||||
text += ' ' + attrs.country;
|
||||
this.$el.attr('title', attrs.ip).text(text);
|
||||
return this;
|
||||
},
|
||||
|
||||
toggle_expansion: function (event) {
|
||||
if (event.target !== this.el)
|
||||
return;
|
||||
event.preventDefault();
|
||||
|
||||
if (this.expansion)
|
||||
return this.expansion.remove();
|
||||
var ip = this.model.get('ip');
|
||||
if (!ip)
|
||||
return;
|
||||
|
||||
this.expansion = new AddressView({model: this.model});
|
||||
this.$el.after(this.expansion.render().el);
|
||||
this.listenTo(this.expansion, 'preremove',
|
||||
this.expansion_removed);
|
||||
|
||||
if (this.model.get('shallow'))
|
||||
send([FETCH_ADDRESS, ip]);
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
if (this.expansion)
|
||||
this.expansion.remove();
|
||||
Backbone.View.prototype.remove.call(this);
|
||||
},
|
||||
|
||||
expansion_removed: function () {
|
||||
this.expansion = null;
|
||||
},
|
||||
});
|
||||
|
||||
var Addresses = Backbone.Collection.extend({
|
||||
model: Address,
|
||||
comparator: function (a) { return ip_mnemonic(a.ip); },
|
||||
});
|
||||
|
||||
window.addrs = new Addresses;
|
||||
|
||||
function hook_up_address(model, $post) {
|
||||
var $a = $post.find('a.mod.addr:first');
|
||||
if (!$a.length)
|
||||
return;
|
||||
var ip = $a.prop('title') || $a.text();
|
||||
var givenName;
|
||||
var m = $a.text().match(/^([\w'.:]+(?: [\w'.:]*)?) "(.+)"$/);
|
||||
if (m) {
|
||||
if (is_IPv4_ip(m[1]))
|
||||
ip = m[1];
|
||||
givenName = m[2];
|
||||
}
|
||||
if (!is_valid_ip(ip))
|
||||
return;
|
||||
|
||||
/* Activate this address link */
|
||||
var key = ip_key(ip);
|
||||
var address = window.addrs.get(key);
|
||||
if (!address) {< |