Cyber Anakins Lightsaber - A Minishell-based backdoor
<?php
require("design.php");
session_start();
if (!adminAuth(RIGHT_EDIT_EVENTS)) die("ERROR: Доступ закрыт!");
if (isset($_POST['action']) && $_POST['action']=="set")
{
$table = _POST_('table');
$mysql = mysqlopen();
$table = preg_split("/\n/",$table);
$idCol = 0;
$nameCol = 1;
$filialCol = 2;
$dateCol = 3;
$catCol = 4;
$descCol = 5;
$admin = intval($_SESSION['admin']);
$sql = "";
for($i=0; $i < count($table); $i++)
{
$cols = preg_split("/\t/",$table[$i]);
$id = intval($cols[$idCol]);
$name = $cols[$nameCol];
$filial = -1;
if (preg_match("/(библиотека|филиал|библиотека\-филиал) №\s+(\d+)/iu",$cols[$filialCol], $g)) $filial = intval($g[2]);
else
if (preg_match("/Юношеская[\s\S]+библиотека/iu", $cols[$filialCol])) $filial = 1;
else
if (preg_match("/Центральная[\s\S]+городская/iu",$cols[$filialCol])) $filial = 11;
else
if (preg_match("/Центральная[\s\S]+детская/iu", $cols[$filialCol])) $filial = 4;
if (!preg_match("/(\d{1,2})\.(\d\d)\.(\d\d\d\d)\s+(\d{1,2})[\.\:](\d\d)/", $cols[$dateCol], $g)) continue;
$date = sprintf("%04d-%02d-%02d %02d:%02d:00", $g[3],$g[2],$g[1],$g[4],$g[5]);
$cat = intval($cols[$catCol]);
$desc = str_replace("<br>","\n",$cols[$descCol]);
$name = mysqli_escape_string($mysql, $name);
$desc = mysqli_escape_string($mysql, $desc);
if ($sql!="") $sql.=";\n";
if ($id==0)
{
$sql.="INSERT INTO libOnlineEvents (`title`,`date`,`desc`,`filial`,`category`,`author`,`publicDate`) VALUES
('$name','$date','$desc',$filial,$cat, $admin, NOW())";
}
else
{
$sql.="UPDATE libOnlineEvents SET `title`='$name',`date`='$date',`desc`='$desc',`filial`=$filial,`category`=$cat,`author`=$admin,`publicDate`=NOW() WHERE `id`=$id";
}
}
if ($sql=='') die("ERROR: Нечего импортировать!");
mysqli_multi_query($mysql, $sql);
if (mysqli_errno($mysql)) die("ERROR: ".mysqli_error($mysql)." at line ".__LINE__." of file ".__FILE__."\n");
die("OK");
}
TOP(-1);
?>
<style>
.mainCell { background-color:#f5f5f5; }
</style>
<h1>Мастер разбора таблицы онлайн-мероприятий</h1>
<div>Выделите в Word всю таблицу онлайн-мероприятий, скопируйте ее в буфер обмена и вставьте сюда:</div>
<textarea style='width:100%' rows=3 id=rawText></textarea>
<br><br>
<form name=resultForm style='display:none'>
<hr>
<div>В таблице ниже отобразились все мероприятия из вставленной таблицы. Часть из этих мероприятий уже существовало на сайте, поэтому с них снята галочка. Необходимо отметить галочкой те мероприятия, которые должны быть вставлены в базу данных или обновлены. Следует отметить, что в случае переноса даты или времени мероприятия система не сможет правильно связать мероприятия. В этом случае нужно вручную удалить старое мероприятие с сайта ил просто вручную его отредактировать.</div>
<center style='margin-top:10; margin-bottom:10'>
<input type=button style='width:150;height:32' value="Снять все галочки" onclick='uncheckAll()'>
<input id=importBtn type=button style='width:150;height:32' value="Импорт" onclick='doImport()'>
</center>
<br>
<div id='resultDiv'></div>
<center style='margin-top:10; margin-bottom:10'><input type=button value="Импорт" onclick='doImport()'></center>
</form>
<?php
$mysql = mysqlopen();
$result = mysqli_query($mysql, "SELECT `id`,`filial`,`date` FROM libOnlineEvents");
if (mysqli_errno($mysql)) die("ERROR: ".mysqli_error($mysql)." at line ".__LINE__." of file ".__FILE__."\n");
$json = array();
while($row = mysqli_fetch_assoc($result))
{
$row['id'] = intval($row['id']);
$row['filial'] = intval($row['filial']);
array_push($json, $row);
}
mysqli_free_result($result);
print "<script>\nexistEvents = ".json_encode($json).";\n</script>";
?>
<script>
rawText = document.getElementById('rawText');
resultDiv = document.getElementById('resultDiv');
importBtn = document.getElementById('importBtn');
function IsEventExists(date, filial)
{
for(var i=0; i < existEvents.length; i++)
{
if (existEvents[i].filial == filial &&
existEvents[i].date == date) return existEvents[i].id;
}
return 0;
}
rows = [];
dateCol=-1;
filialCol=-1;
catCol=-1;
descCol=-1;
function parseTable(text)
{
text = text.replaceAll(//,'—');
while(true)
{
var text2 = text.replace(/[\r\n]+(\d+)[\s^\t]*\+/m,'\t$1+');
if (text2==text) break;
text = text2;
}
while(true)
{
var text2 = text.replace(/\t{2,}(\d+\+)/m,'\t$1');
if (text2==text) break;
text = text2;
}
while(true)
{
var text2 = text.replace(/\n(\d+)\.\t\t/m,'\n$1.\t');
if (text2==text) break;
text = text2;
}
text = text.replace(/[\w\W]*(№\s+п\/п)/,'$1');
text = text.replace(/[\w\W]*(№\\№)/,'$1');
text = text.replace(/[\r\n\s]+\d{1,2}\s+(января|февраля|марта|апреля|мая|июня|июля|августа|сентября|октября|ноября|декабря)\s+20\d\d[\r\n\s]+Директор[\w\W]*/,'');
text = text.replace(/[\r\n\s]+\d{1,2}\.\d\d\.20\d\d\s*[\r\n\s]+Директор[\w\W]*/,'');
rows = text.split(/[\r\n]+\d+\.\t/);
if (rows.length < 2)
{
errorBox("Не найден \"1.\"!");
return false;
}
var cols = rows[0].split("\t");
var result = '';
result ='<table cellspacing=0 cellpadding=4 border=1 bordercolor=black bgcolor=white>';
result+='<tr>';
dateCol = -1;
filialCol = -1;
catCol = -1;
descCol = -1;
var colCount = cols.length;
for(var i=0; i < colCount; i++)
{
if (cols[i].match(/^Дата/i)) dateCol = i;
else
if (cols[i].match(/филиал/i)) filialCol = i;
else
if (cols[i].match(/Возраст/i)) catCol = i;
else
if (cols[i].match(/содержание[\w\W]+мероприятия/i)) descCol = i;
result+="<th>"+cols[i]+"</th>";
}
result+='</tr>\n';
if (dateCol < 1)
{
errorBox("Не найдена колонка \"Дата...\"!");
return false;
}
if (filialCol < 1)
{
errorBox("Не найдена колонка \"Филиал...\"!");
return false;
}
if (descCol < 1)
{
errorBox("Не найдена колонка \"Краткое содержание мероприятия\"!");
return false;
}
dateCol--;
filialCol--;
catCol--;
descCol--;
colCount--;
for(var j=1; j < rows.length; j++)
{
rows[j] = rows[j].split("\t");
}
for(var j=1; j < rows.length; j++)
{
cols = rows[j];
var g;
var ok = true;
for(var i=0; i <= cols.length-2; i++)
{
if (cols[i]=='' && cols[i+1]=='')
{
ok = false;
break;
}
}
if (!ok) continue;
if (!cols[dateCol]) continue;
if ((g = cols[dateCol].match(/(\d{1,2})\.(\d\d)\.(\d\d\d\d)\s+(\d{1,2})[:\.](\d\d)/)))
{
if (g[1].length < 2) g[1] = '0'+g[1];
if (g[4].length < 2) g[4] = '0'+g[4];
var date = g[3]+'-'+g[2]+'-'+g[1]+' '+g[4]+':'+g[5]+':00';
var filial = -1;
g = cols[filialCol].match(/(библиотека|филиал|библиотека\-филиал)\s+№\s*(\d+)/i);
if (g) filial = parseInt(g[2]);
else
if (cols[filialCol].match(/Юношеская[\s\S]+библиотека/i)) filial = 1;
else
if (cols[filialCol].match(/Центральная[\s\S]+городская/i)) filial = 11;
else
if (cols[filialCol].match(/Центральная[\s\S]+детская/i)) filial = 4;
var exists = IsEventExists(date, filial);
result+='<tr';
if (exists==0) result+=' style="background-color:#ddffdd"';
result+='><td nowrap';
if (exists!=0) result+=' style="background-color:#ffff99"';
result+='><label>'+j+'. <input type=checkbox '+(exists!=0?'':'checked')+' value='+j+' data-id='+exists+' onclick="toggleRow(this)"></label></td>';
for(var i=0; i < cols.length; i++)
{
result+='<td>'+cols[i]+'</td>';
}
result+='</tr>\n';
}
}
result+='</table>';
return result;
}
function toggleRow(checkbox)
{
var tr = checkbox.parentNode.parentNode.parentNode;
tr.style.backgroundColor=checkbox.checked ? "#ddffdd" : "";
}
function uncheckAll()
{
var form = document.forms['resultForm'];
for(var i=0; i < form.elements.length; i++)
{
if (form.elements[i].type.match(/checkbox/i))
{
form.elements[i].checked = false;
form.elements[i].parentNode.parentNode.parentNode.style.backgroundColor="";
}
}
}
rawText.addEventListener('paste', function()
{
document.forms['resultForm'].style.display="";
resultDiv.innerHTML = '<center>Идёт преобразование...</center>';
setTimeout(function()
{
var html = parseTable(rawText.value);
if (html===false)
{
resultDiv.innerHTML = '<center>Ошибка!</center>';
return;
}
rawText.value = '';
resultDiv.innerHTML = html;
},100);
});
function doImport()
{
var post = '';
var form = document.forms['resultForm'];
for(var i=0; i < form.elements.length; i++)
{
var checkBox = form.elements[i];
if (checkBox.type.match(/checkbox/i) && checkBox.checked)
{
var rowInx = parseInt(checkBox.value);
var id = parseInt(checkBox.dataset.id);
if (post.length != 0) post+='\n';
post+=id;
var cols = rows[rowInx];
post+='\t'+cols[0].replaceAll('\t',' ').replaceAll(/[\r\n]+/,'<br>');
post+='\t'+cols[filialCol].replaceAll('\t',' ').replaceAll(/[\r\n]+/,'<br>');
post+='\t'+cols[dateCol].replaceAll('\t',' ').replaceAll(/[\r\n]+/,' ');
if (catCol>0)
post+='\t'+parseInt(cols[catCol]);
else
post+='\t0';
post+='\t'+cols[descCol].replaceAll('\t',' ').replaceAll(/[\r\n]+/,'<br>');
}
}
post = 'action=set&table='+encodeURIComponent(post);
resultDiv.innerHTML = '<center><br><img src="formular/waiting.gif" width=128 height=128></center>';
importBtn.disabled=true;
sendXHR('onlineeventparser.php',post,
function(response)
{
location = "online.php?rnd="+Math.random();
},
function(error)
{
resultDiv.innerHTML = '';
importBtn.disabled=false;
errorBox(error);
});
}
</script>
<?php
BOTTOM();
?>
May the force be with you, always.