Файл: crons/dbbackup.php
Строк: 423
<?php
include("../config.php");
include("../autoconfig.php");
include("yandexdisk.php");
include("database.php");
if (!ini_get('zlib.output_compression') && function_exists('ob_gzhandler')) ob_start('ob_gzhandler');
if(STATUS_BUD)
{
    $SDBU = new Santi_Dumper();
    set_error_handler('sxd_error_handler');
    chdir(dirname(__FILE__));
    autopilots_add_time(7);
    $archivename = $SDBU->init();
    if(YADISK_BUD)
    {
        if(file_exists(SANTI_SERVERPATH."/".SANTI_PATH."/datas/backups/".$archivename))            
            send_to_yadisk($archivename);
        unlink(SANTI_SERVERPATH."/".SANTI_PATH."/datas/backups/".$archivename);
    }
}
else
{
    die();
}
 
class Santi_Dumper {
    function Santi_Dumper() {
        define('TIMER', array_sum(explode(' ', microtime()))); 
        define('V_SXD', 20010);
        define('V_PHP', sxd_ver2int(phpversion()));
    }
    function init($args = false){
        $CFG = array (
          'charsets' => 'cp1251 utf8 latin1',
          'lang' => 'ru',
          'time_web' => '600',
          'time_cron' => '600',
          'backup_path' => '../datas/backups/',
          'backup_url' => '../datas/backups/',
          'only_create' => 'MRG_MyISAM MERGE HEAP MEMORY',
          'globstat' => 0,
          'my_host' => SANTI_DB_HOST,
          'my_port' => 3306,
          'my_user' => SANTI_DB_USER,
          'my_pass' => SANTI_DB_PASSWORD,
          'my_comp' => 0,
          'my_db' => '',
          'auth' => 'mysql cfg',
          'user' => '',
          'pass' => '',
          'confirm' => '6',
          'exitURL' => './',
        );
        $this->CFG = &$CFG;
        $this->try = false;
        $this->cron_mode = true;
        
        set_time_limit(0);
        $auth = $this->connect();
        $this->ajax($this->loadJob());
        if(file_exists($this->JOB['file_log'])) unlink($this->JOB['file_log']);
        if(file_exists($this->JOB['file_rtl'])) unlink($this->JOB['file_rtl']);
        return $this->JOB['file'];
    }
    function saveToFile($name, $content){
        $fp = fopen($name, "w");
        fwrite($fp, $content);
        fclose($fp);
    }
    function connect($host = null, $port = null, $user = null, $pass = null){
        $this->error = '';
        $this->try = true;
        if(!empty($user) && isset($pass)) {
            $this->CFG['my_host'] = $host;
            $this->CFG['my_port'] = $port;
            $this->CFG['my_user'] = $user;
            $this->CFG['my_pass'] = $pass;
        }
        if(mysql_connect($this->CFG['my_host'] . ($this->CFG['my_host']{0} != ':' ? ":{$this->CFG['my_port']}" : ''),  $this->CFG['my_user'], $this->CFG['my_pass'])) {
            if(V_PHP > 50202) mysql_set_charset('utf8') or sxd_my_error();
            else mysql_query('SET NAMES utf8') or sxd_my_error();
            define('V_MYSQL', sxd_ver2int(mysql_get_server_info()));
        }
        else {
            define('V_MYSQL', 0); 
            $this->error = "sxd.actions.tab_connects();alert(" . sxd_esc(mysql_error()) . ");";
        }    
        $this->try = false;
        return V_MYSQL ? true: false;
    }
    function main(){
          $this->db = 'temp';
        $zip = array();
        if (function_exists("gzopen")) {
            for($i = 1; $i <10; $i++){
                $zip[] = "GZip: {$i}";
            }
        }
        if (function_exists("bzopen")) {
            $zip[10] = "BZip";
        }
        end($zip);
        
        //echo sxd_tpl_page();
    }
    function ajax($req){
        $res = '';
        $act = $req['act'];
        if($req['act'] == 'run_savedjob'){
            $req = $this->loadJob($req);
        }
        switch($req['act']){            
            case 'save_connect': 
                //$res = $this->saveConnect($req);
                break;
            case 'save_job': 
                unset($req['act']);
                $this->saveJob('sj_' . $req['job'] , $req);
                $res = $this->getSavedJobs();
                break;
            case 'backup': 
                $this->addBackupJob($req);
                break;
            case 'restore': 
                //$this->addRestoreJob($req);
                break;
            case 'exit': 
                setcookie('sxd', '', 0);
                $res = "top.location.href = " . sxd_esc($this->CFG['exitURL']) . ";";
                break;
        }    
        echo $res;
    }
    function loadJob(){
        $charset = '0';
        if(SANTI_DB_CHARSET == '0')
            $charset = '0';
        elseif(SANTI_DB_CHARSET == '1')
            $charset = 'utf8';
        elseif(SANTI_DB_CHARSET == '2')
            $charset = 'cp1251';
        elseif(SANTI_DB_CHARSET == '3')
            $charset = 'koi8';
        $JOB = array (
          'type' => 'backup',
          'db' => SANTI_DB_NAME,
          'charset' => $charset,
          'zip' => '7',
          'comment' => '',
          'del_time' => '',
          'del_count' => '',
          'obj' => 
          array (
            'TA' => 
            array (
              0 => '*',
            ),
          ),
          'job' => 'dbbackup',
          'title' => '',
        );
        $JOB['act'] = $JOB['type'];
        $JOB['type'] = 'run';
        return $JOB;
    }
    function cfg2js($cfg){
        foreach($cfg AS $k => $v){
            $cfg[$k] = sxd_esc($v, false);
        }
        return $cfg;
    }
    function addDb($req){
        $r = mysql_query('CREATE DATABASE `' . sxd_esc($req['name'], false) . '`' . (V_MYSQL > 40100 ? "CHARACTER SET {$req['charset']} COLLATE {$req['collate']}" : ''));
        if($r)
            echo "sxd.addOpt(" . sxd_php2json(array('db' => array($req['name'] => "{$req['name']} (0)"))) . ");";
        else
             sxd_my_error();
    }    
    function createFilters(&$obj, &$filter, &$object){
        $types = array('TA', 'TC', 'VI', 'PR', 'FU', 'TR', 'EV');
        foreach($types AS $type){
            $filter[$type] = array();
            $object[$type] = array();
            if(!empty($obj[$type])){
                foreach($obj[$type] AS $v){
                    if(strpos($v, '*') !== false) {
                        $filter[$type][] = str_replace('*', '.*?', $v); 
                    }
                    else {
                        $object[$type][$v] = true;
                    }
                }
                $filter[$type] = count($filter[$type]) > 0 ? '/^(' . implode('|', $filter[$type]) . ')$/i' : '';
            }
        }
    }
    function closeConnect(){
        @ignore_user_abort(1); 
        header("Connection: close"); 
        header("Content-Length: 0"); 
        @ob_end_flush(); 
        @flush();
    }            
    function addBackupJob($job) {
        $this->closeConnect();
        // Создаем новое задание
        $this->JOB = $job;
        mysql_select_db($this->JOB['db']);
        // Создаем список объектов и фильтр
        $filter = $object = array();
        $this->createFilters($this->JOB['obj'], $filter, $object);
        $queries = array(
            array('TABLE STATUS', 'Name', 'TA')
        );
        if (V_MYSQL > 50014) {
            $queries[] = array("PROCEDURE STATUS WHERE db='{$this->JOB['db']}'", 'Name', 'PR');
            $queries[] = array("FUNCTION STATUS WHERE db='{$this->JOB['db']}'", 'Name', 'FU');
            $queries[] = array('TRIGGERS', 'Trigger', 'TR');
            if(V_MYSQL > 50100) $queries[] = array('EVENTS', 'Name', 'EV');
        }
        $todo = $header = array();
        $tabs = $rows = 0;
        $only_create = explode(' ', $this->CFG['only_create']);
        foreach($queries AS $query){
            $t = $query[2];
            if($t == 'TA' && (!empty($object['TC']) || !empty($filter['TC']))) {}
            elseif(empty($object[$t]) && empty($filter[$t])) continue;
            $r = mysql_query('SHOW ' . $query[0]) or sxd_my_error();
            if (!$r) continue;
            $todo[$t] = array();
            $header[$t] = array();
            
            while($item = mysql_fetch_assoc($r)){
                $n = $item[$query[1]];
                switch($t){
                    case 'TA':
                    case 'TC':
                        if(V_MYSQL > 40101 && is_null($item['Engine']) && preg_match('/^VIEW/i', $item['Comment'])) {
                            if(sxd_check($n, $object['VI'], $filter['VI'])){
                                $todo['VI'] = array();
                                $header['VI']= array();
                            }
                            continue;
                        }
                        elseif(sxd_check($n, $object['TA'], $filter['TA'])){
                            $engine = V_MYSQL > 40101 ? $item['Engine'] : $item['Type'];
                            $t = in_array($engine, $only_create) ? 'TC' : 'TA';
                        }
                        elseif(sxd_check($n, $object['TC'], $filter['TC'])) {
                            $t = 'TC';
                            $item['Rows'] = $item['Data_length'] = '';
                        }
                        else continue;
                        $todo['TA'][]   = array($t, $n, !empty($item['Collation']) ? $item['Collation'] : '', $item['Auto_increment'], $item['Rows'], $item['Data_length']);
                        $header['TA'][] = "{$n}`{$item['Rows']}`{$item['Data_length']}";
                        $tabs++;
                        $rows += $item['Rows'];
                    break;
                    default:
                        if(sxd_check($n, $object[$t], $filter[$t])) {
                            $todo[$t][] = array($t, $n, !empty($item['collation_connection']) ? $item['collation_connection'] : '');
                            $header[$t][] = $n;
                        }
                }
            }
            
        }
        if (V_MYSQL > 50014 && (!empty($object['VI']) || !empty($filter['VI']))) {
            // Бэкап обзоров, нужно отсортировать зависимые
            $r = mysql_query("SELECT table_name, view_definition /*!50121 , collation_connection */ FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '{$this->JOB['db']}'") or sxd_my_error();
            $views = $dumped = $views_collation = array();
            $re = "/`{$this->JOB['db']}`.`(.+?)`/";
            while($item = mysql_fetch_assoc($r)){
                preg_match_all($re, preg_replace("/^select.+? from/i", '', $item['view_definition']), $m);
                $used = $m[1];    
                $views_collation[$item['table_name']] = !empty($item['collation_connection']) ? $item['collation_connection'] : '';
                $views[$item['table_name']] = $used;
            }
            
            while (count($views) > 0) {
                foreach($views AS $n => $view) {
                    $can_dumped = true;
                    foreach($view AS $k) {
                        if (isset($views[$k]) && !isset($dumped[$k])) $can_dumped = false;    
                    }
                    if ($can_dumped) {
                        if(sxd_check($n, $object['VI'], $filter['VI'])){
                            $todo['VI'][] = array('VI', $n, $views_collation[$n]);
                            $header['VI'][] = $n;
                        }
                        $dumped[$n] = 1;
                        unset($views[$n]);
                    }
                }
            }
            unset($dumped);
            unset($views);
            unset($views_collation);
        }
        $this->JOB['file_tmp'] = $this->CFG['backup_path'] . $this->JOB['job'] . '.tmp';
        $this->JOB['file_rtl'] = $this->CFG['backup_path'] . $this->JOB['job'] . '.rtl';
        $this->JOB['file_log'] = $this->CFG['backup_path'] . $this->JOB['job'] . '.log';
        $this->JOB['file_stp'] = $this->CFG['backup_path'] . $this->JOB['job'] . '.stp';
        if(file_exists($this->JOB['file_stp'])) unlink($this->JOB['file_stp']);
        $this->fh_tmp = $this->openFile($this->JOB['file_tmp'], 'w');
        $this->JOB['file'] = sprintf('%s_%s.%s', (isset($this->JOB['title']) ? $this->JOB['job'] : $this->JOB['db']), date('Y-m-d_H-i-s'), $this->JOB['file_ext']);
        $this->JOB['file_name'] = $this->CFG['backup_path'] . $this->JOB['file'];
        $this->JOB['todo'] = $todo;
        $this->saveJob($this->JOB['job'], $this->JOB);
        $fcache = implode('|', array('#SXD20', V_SXD, V_MYSQL, V_PHP, date('Y.m.d H:i:s'), $this->JOB['db'], $this->JOB['charset'], $tabs, $rows, sxd_esc($this->JOB['comment'], false))) . "n";
        foreach($header AS $t => $o){
            if (!empty($o)) $fcache .= "#{$t} " . implode('|', $o) . "n";    
        }
        $this->fh_rtl = fopen($this->JOB['file_rtl'], 'wb');
        $this->fh_log = fopen($this->JOB['file_log'], 'wb');
        $this->rtl = array(time(), time(), $rows, 0, '', '', '', 0, 0, 0, 0, TIMER, "n");
        $fcache .= "#EOHnn";
        $this->write($fcache);        
        $this->runBackupJob();
    }
    function runBackupJob($continue = false){
        if($continue){
            $this->fh_tmp = $this->openFile($this->JOB['file_tmp'], 'a');
            mysql_select_db($this->JOB['db']);
        }
        mysql_query("SET SQL_QUOTE_SHOW_CREATE = 1");
        $types = array('VI' => 'View', 'PR' => 'Procedure', 'FU' => 'Function', 'TR' => 'Trigger', 'EV' => 'Event');
        $fcache = '';
        $writes = 0;
        
        if(V_MYSQL > 40101) mysql_query("SET SESSION character_set_results = '" . ($this->JOB['charset'] ? $this->JOB['charset'] : 'binary') ."'") or sxd_my_error();
        $time_old = time();
        $exit_time = $time_old + $this->CFG['time_web'] - 1;
        $no_cache = V_MYSQL < 40101 ? 'SQL_NO_CACHE ' : '';
        foreach($this->JOB['todo'] AS $t => $o){
            if (empty($this->rtl[4])) $this->rtl[4] = $t;
            elseif ($this->rtl[4] != $t) continue;
            foreach($o AS $n){ 
                if (empty($this->rtl[5])) {
                    $this->rtl[5] = $n[1];
                    $this->rtl[7] = 0;
                    $this->rtl[8] = !empty($n[4]) ? $n[4] : 0;
                }
                elseif ($this->rtl[5] != $n[1]) continue;
                // Делаем бэкап
                switch($n[0]){
                    case 'TC':
                    case 'TD':                 
                    case 'TA':
                        $from = '';
                        if ($n[0] == 'TC' || $this->rtl[7] == 0){
                            // Бэкап структуры таблицы
                            $r = mysql_query("SHOW CREATE TABLE `{$n[1]}`") or sxd_my_error();
                            $item = mysql_fetch_assoc($r);
                            $fcache .= "#tTC`{$n[1]}`{$n[2]}t;n{$item['Create Table']}t;n";
                            $this->rtl[7] = 0; 
                            if($n[0] == 'TC' || !$n[4]) break;
                            // Бэкапим данные таблицы
                            $fcache .= "#tTD`{$n[1]}`{$n[2]}t;nINSERT INTO `{$n[1]}` VALUES n";
                        }
                        else {
                            $from = " LIMIT {$this->rtl[7]}, {$this->rtl[8]}";
                        }
                        // Определяем типы полей
                        $notNum = array();
                        $r = mysql_query("SHOW COLUMNS FROM `{$n[1]}`") or sxd_my_error();
                        $fields = 0;
                        while($col = mysql_fetch_array($r)) {
                            // TODO: проверить типы SET, ENUM и BIT
                            $notNum[$fields] = preg_match("/^(tinyint|smallint|mediumint|bigint|int|float|double|real|decimal|numeric|year)/", $col['Type']) ? 0 : 1; 
                            $fields++;
                        }
                        $time_old = time();
                        $z = 0;
                        // Достаем данные
                        $r = mysql_unbuffered_query("SELECT {$no_cache}* FROM `{$n[1]}`{$from}");
                        while($row = mysql_fetch_row($r)) {
                             if (strlen($fcache) >= 61440) {
                                 $z = 0;
                                if($time_old < time()) {
                                    if(file_exists($this->JOB['file_stp'])){
                                        $type = file_get_contents($this->JOB['file_stp']);
                                        $this->rtl[9] = !empty($type) ? $type : 2;
                                        $this->write($fcache);
                                        if($type == 1) {
                                            
                                        }
                                        unset($this->rtl);
                                        exit;
                                    }
                                    $time_old = time();
                                    if($time_old >= $exit_time){
                                        $this->rtl[9] = 3;
                                        $this->write($fcache);
                                        unset($this->rtl);
                                        exit;
                                    }
                                    clearstatcache(); 
                                }
                                $this->write($fcache); 
                            }
                            for($k = 0; $k < $fields; $k++){
                                if(!isset($row[$k])) {$row[$k] = 'N';}
                                elseif($notNum[$k]) {$row[$k] =  ''' . mysql_real_escape_string($row[$k]) . ''';} // TODO: Потестить скорость эскэйпинга строк
                            }
                            $fcache .= '(' . implode(',', $row) . "),n";
                            $this->rtl[7]++;  
                            $this->rtl[10]++;
                        }
                        unset($row);
                        mysql_free_result($r);
                        $fcache = substr_replace($fcache, "t;n",  -2, 2);
                    break;
                    default:
                        if(V_MYSQL < 50121 && $n[0] == 'TR'){
                            // SHOW CREATE TRIGGER отсутствует до MySQL 5.1.21
                            $r = mysql_query("SELECT * FROM `INFORMATION_SCHEMA`.`TRIGGERS` WHERE `TRIGGER_SCHEMA` = '{$this->JOB['db']}' AND `TRIGGER_NAME` = '{$n[1]}'") or sxd_my_error();
                            $item = mysql_fetch_assoc($r);
                            $fcache .= "#tTR`{$n[1]}`{$n[2]}t;nCREATE TRIGGER `{$item['TRIGGER_NAME']}` {$item['ACTION_TIMING']} {$item['EVENT_MANIPULATION']} ON `{$item['EVENT_OBJECT_TABLE']}` FOR EACH ROW {$item['ACTION_STATEMENT']}t;n";
                        }
                        else {
                            $r = mysql_query("SHOW CREATE {$types[$n[0]]} `{$n[1]}`") or sxd_my_error();
                            $item = mysql_fetch_assoc($r);
                            $fcache .= "#t{$n[0]}`{$n[1]}`{$n[2]}t;n" . preg_replace("/DEFINER=`.+?`@`.+?` /", '', ($n[0] == 'TR' ? $item['SQL Original Statement'] : $item['Create ' . $types[$n[0]]])) . "t;n";
                        }
                }
                
                $this->rtl[5] = '';
            }
            $this->rtl[4] = '';
        }
        $this->rtl[4] = 'EOJ';
        $this->rtl[5] = round(array_sum(explode(' ', microtime())) - $this->rtl[11], 4);
        $this->rtl[6] = '';
        $this->rtl[7] = 0;
        $this->rtl[8] = 0;
        $this->write($fcache);
        fclose($this->fh_tmp);
        rename($this->JOB['file_tmp'], $this->JOB['file_name']);
        
        if ($this->JOB['del_time'] || $this->JOB['del_count']) {
            $deldate = '';
            if (!empty($this->JOB['del_time'])){ // Удаление по дням
                $deldate = date("Y-m-d_H-i-s", time() - intval($this->JOB['del_time']) * 86400);
            }
            $deleted = false;
            if ($dh = opendir($this->CFG['backup_path'])) {
                $files = array();
                $name = isset($this->JOB['title']) ? $this->JOB['job'] : $this->JOB['db'];
                while (false !== ($file = readdir($dh))) { 
                    if (preg_match("/^{$name}_(d{4}-d{2}-d{2}_d{2}-d{2}-d{2}).sql/", $file, $m)) { 
                        if ($deldate && $m[1] < $deldate) {
                            $deleted = true;
                        }
                        else {$files[$m[1]] = $file;}
                    }
                }
                closedir($dh);
                // Сортируем файлы по дате и удаляем самые старые
                if (!empty($this->JOB['del_count'])){
                    ksort($files);
                    $file_to_delete = count($files) - $this->JOB['del_count'];
                    foreach ($files AS $file){
                        if ($file_to_delete-- > 0){ 
                            $deleted = true;
                        }
                    }
                }
            }
        }
        fclose($this->fh_log);
        fclose($this->fh_rtl);
    }
    function write(&$str){
        fseek($this->fh_rtl, 0);
        $this->rtl[1] = time();
        $this->rtl[3] += fwrite($this->fh_tmp, $str);
        fwrite($this->fh_rtl, implode("t", $this->rtl));
        $str = '';
    }
    
    function getSavedJobs(){
        $sj = array('sj_backup' => array(), 'sj_restore' => array(),);
        if (is_dir($this->CFG['backup_path']) && false !== ($handle = opendir($this->CFG['backup_path']))) {
            while (false !== ($file = readdir($handle))) {
                if (preg_match("/^sj_(.+?).job.php$/", $file)) {
                    include($this->CFG['backup_path'] . $file);
                    $sj['sj_' . $JOB['type']][$JOB['job']] = "<b>{$JOB['job']}</b><br><i>{$JOB['title']} </i>";
                }
            }
            closedir($handle);
        }
        if(count($sj['sj_backup']) > 0){
            ksort($sj['sj_backup']);    
        }
        else {
            $sj['sj_backup'] = array();    
        }
        if(count($sj['sj_restore']) > 0){
            ksort($sj['sj_restore']);    
        }
        else {
            $sj['sj_restore'] = array();    
        }
        return "sxd.clearOpt('sj_backup');sxd.clearOpt('sj_restore');sxd.addOpt(" . sxd_php2json($sj) . ");";
    }    
    function saveJob($job, $config){
        $this->saveToFile($this->CFG['backup_path'] . $job . '.job.php', "<?phpn$JOB = " . var_export($config, true) . ";n" . "?>");
    }
    function openFile($name, $mode){
        if($mode == 'r') {
            if(preg_match('/.(sql|sql.bz2|sql.gz)$/i', $name, $m)) $this->JOB['file_ext'] = strtolower($m[1]);
        }
        else{
            switch($this->JOB['zip']) {
                case 0 : $this->JOB['file_ext'] = 'sql'; break;
                case 10: $this->JOB['file_ext'] = 'sql.bz2'; break;
                default: $this->JOB['file_ext'] = 'sql.gz'; break; 
            }
        }
        switch ($this->JOB['file_ext']){
            case 'sql':
                return fopen($name, "{$mode}b");
                break;
            case 'sql.bz2':
                return bzopen($name, $mode);
                break;
            case 'sql.gz':
                return gzopen($name, $mode . ($mode == 'w' ? $this->JOB['zip'] : ''));
                break;
            default: return false;
        }
    }
}
function sxd_read_sql($f, &$seek, $ei, $delimiter = "t;", $eol = "n"){
    static $l = '';
    static $r = 0;
    $fs = ftell($f);
    $delim_len = strlen($delimiter . $eol);
    while($r || $s = fread($f, 61440)){
        if(!$r) $l .= $s;
        $pos = strpos($l, $delimiter . $eol);
        if ($pos !== false) {
            // Есть окончание запроса
            $q = substr($l, 0, $pos);
            $l = substr($l, $pos+$delim_len);
            $r = 1;
            $seek = strlen($l);
            return $q;
        }
        if($ei) {
            $pos = strrpos($l, $eol);
            if($pos > 0 && $l{$pos-1} === ',') {
                // Окончание не найдено
                $q = substr($l, 0, $pos-1);
                $l = substr($l, $pos+ strlen($eol));
                $seek = strlen($l);
                $r = 0;
                return $q;
            }
        }
        $r = 0;    
    }
    if (!empty($l)) {
        return $l;
    }
    return false;
}
function sxd_error_handler($errno, $errmsg, $filename, $linenum, $vars){
    global $SXD;
    if($SXD->try) return;
    if($errno == 8192) return;
    if(strpos($errmsg, 'timezone settings')) return;
    $errortype = array(1 => 'Error', 2 => 'Warning', 4 => 'Parsing Error', 8 => 'Notice', 16 => 'Core Error', 32 => 'Core Warning', 64 => 'Compile Error',
                       128 => 'Compile Warning', 256 => 'MySQL Error', 512 => 'Warning', 1024 => 'Notice',
                        2048 => 'Strict', 8192 => 'Deprecated', 16384 => 'Deprecated');
    $str = sxd_esc("{$errortype[$errno]}: {$errmsg} ({$filename}:{$linenum})", false);
    if(SXD_DEBUG) error_log("[index.php]n{$str}n", 3, "backup/error.log");
    
    if($errno == 8 || $errno == 1024) {
        if (!$SXD->fh_log && !$SXD->fh_rtl) echo isset($_POST['ajax']) ? "alert('" . ($str) . "');" : $str;
        else {
            fwrite($SXD->fh_log, date('Y.m.d H:i:s') . "t3t{$str}n");
        }
    }
    elseif($errno < 1024) {
        $SXD->error = true;
        if (!$SXD->fh_log && !$SXD->fh_rtl) echo isset($_POST['ajax']) ? "alert('" . ($str) . "');" : $str;
        else {
            $SXD->rtl[1] = time();
            $SXD->rtl[9] = 5;
            fseek($SXD->fh_rtl, 0);
            fwrite($SXD->fh_rtl, implode("t", $SXD->rtl));
            fwrite($SXD->fh_log, date('Y.m.d H:i:s') . "t4t{$str}n");
            unset($SXD->rtl);
        }
        
        die;
    }
}
function sxd_check($n, $obj, $filt){
    return isset($obj[$n]) || ($filt && preg_match($filt, $n));
}
function sxd_ver2int($ver){
    return preg_match("/^(d+).(d+).(d+)/", $ver, $m) ? sprintf("%d%02d%02d", $m[1], $m[2], $m[3]) : 0;
}
function sxd_esc($str, $quoted = true){
    return $quoted ? "'" . addcslashes($str, "\ nrt'") . "'" : addcslashes($str, "\ nrt'");
}
function sxd_my_error(){
    trigger_error(mysql_error(), E_USER_ERROR);    
}
function sxd_antimagic($arr){
    return is_array($arr) ? array_map('sxd_antimagic', $arr) : stripslashes($arr);
}
?>