Discuz!官方免费开源建站系统

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索

[求助] ${discuz-admincp_db.php-vul}漏洞修复方法

[复制链接]
amo123 发表于 2018-9-3 09:37:22 | 显示全部楼层 |阅读模式
本帖最后由 amo123 于 2018-9-3 09:46 编辑

阿里云发现的 ${discuz-admincp_db.php-vul}
使用阿里云的自动修复之后的文件现在发出来,搭建对比下看看
  1. <?php

  2. /**
  3. *      [Discuz!] (C)2001-2099 Comsenz Inc.
  4. *      This is NOT a freeware, use is subject to license terms
  5. *
  6. *      $Id: admincp_db.php 33605 2013-07-16 03:36:20Z hypowang $
  7. */

  8. if(!defined('IN_DISCUZ') || !defined('IN_ADMINCP')) {
  9.         exit('Access Denied');
  10. }

  11. $db = & DB::object();

  12. $tabletype = $db->version() > '4.1' ? 'Engine' : 'Type';
  13. $tablepre = $_G['config']['db'][1]['tablepre'];
  14. $dbcharset = $_G['config']['db'][1]['dbcharset'];

  15. require_once libfile('function/attachment');
  16. cpheader();

  17. if(!isfounder()) cpmsg('noaccess_isfounder', '', 'error');


  18. $excepttables = array($tablepre.'common_admincp_session', $tablepre.'common_syscache', $tablepre.'common_failedlogin', $tablepre.'forum_rsscache', $tablepre.'common_searchindex', $tablepre.'forum_spacecache', $tablepre.'common_session');

  19. $backupdir = C::t('common_setting')->fetch('backupdir');

  20. if(!$backupdir) {
  21.         $backupdir = random(6);
  22.         @mkdir('./data/backup_'.$backupdir, 0777);
  23.         C::t('common_setting')->update('backupdir',$backupdir);
  24. }
  25. $backupdir = 'backup_'.$backupdir;
  26. if(!is_dir('./data/'.$backupdir)) {
  27.         mkdir('./data/'.$backupdir, 0777);
  28. }

  29. if($operation == 'export') {

  30.         if(!submitcheck('exportsubmit', 1)) {

  31.                 $shelldisabled = function_exists('shell_exec') ? '' : 'disabled';

  32.                 $tables = '';
  33.                 $dztables = array();
  34.                 $tables = C::t('common_setting')->fetch('custombackup', true);

  35.                 $discuz_tables = fetchtablelist($tablepre);

  36.                 foreach($discuz_tables as $table) {
  37.                         $dztables[$table['Name']] = $table['Name'];
  38.                 }

  39.                 $defaultfilename = date('ymd').'_'.random(8);

  40.                 include DISCUZ_ROOT.'./config/config_ucenter.php';
  41.                 $uc_tablepre = explode('.', UC_DBTABLEPRE);
  42.                 $uc_tablepre = $uc_tablepre[1] ? $uc_tablepre[1] : $uc_tablepre[0];
  43.                 $uc_tablepre = substr($uc_tablepre, '0', '-8');
  44.                 if(UC_CONNECT == 'mysql' && UC_DBHOST == $_G['config']['db'][1]['dbhost'] && UC_DBNAME == $_G['config']['db'][1]['dbname'] && $uc_tablepre == $tablepre) {
  45.                         $db_export = 'db_export_discuz_uc';
  46.                         $db_export_key = 'discuz_uc';
  47.                         $db_export_tips = cplang('db_export_tips_uc', array('uc_backup_url' => $uc_backup_url)).cplang('db_export_tips');
  48.                         $db_export_discuz_table = cplang('db_export_discuz_table_uc');
  49.                 } else {
  50.                         $db_export = 'db_export_discuz';
  51.                         $db_export_key = 'discuz';
  52.                         $uc_backup_url = UC_API.'/admin.php?m=db&a=ls&iframe=1';
  53.                         $db_export_tips = cplang('db_export_tips_nouc', array('uc_backup_url' => $uc_backup_url)).cplang('db_export_tips');
  54.                         $db_export_discuz_table = cplang('db_export_discuz_table');
  55.                 }

  56.                 shownav('founder', 'nav_db', 'nav_db_export');
  57.                 showsubmenu('nav_db', array(
  58.                         array('nav_db_export', 'db&operation=export', 1),
  59.                         array('nav_db_import', 'db&operation=import', 0),
  60.                         array('nav_db_runquery', 'db&operation=runquery', 0),
  61.                         array('nav_db_optimize', 'db&operation=optimize', 0),
  62.                         array('nav_db_dbcheck', 'db&operation=dbcheck', 0)
  63.                 ));
  64.                 showtips($db_export_tips);
  65.                 showformheader('db&operation=export&setup=1');
  66.                 showtableheader();
  67.                 showsetting('db_export_type', array('type', array(
  68.                         array($db_export_key, $lang[$db_export], array('showtables' => 'none')),
  69.                         array('custom', $lang['db_export_custom'], array('showtables' => ''))
  70.                 )), $db_export_key, 'mradio');

  71.                 showtagheader('tbody', 'showtables');
  72.                 showtablerow('', '', '<input class="checkbox" name="chkall" onclick="checkAll(\'prefix\', this.form, \'customtables\', \'chkall\', true)" checked="checked" type="checkbox" id="chkalltables" /><label for="chkalltables"> '.cplang('db_export_custom_select_all').' - '.$db_export_discuz_table ).'</label>';
  73.                 showtablerow('', 'colspan="2"', mcheckbox('customtables', $dztables));
  74.                 showtagfooter('tbody');

  75.                 showtagheader('tbody', 'advanceoption');
  76.                 showsetting('db_export_method', '', '', '<ul class="nofloat"><li><input class="radio" type="radio" name="method" value="shell" '.$shelldisabled.' onclick="if(\''.intval($db->version() < '4.1').'\') {if(this.form.sqlcompat[2].checked==true) this.form.sqlcompat[0].checked=true; this.form.sqlcompat[2].disabled=true; this.form.sizelimit.disabled=true;} else {this.form.sqlcharset[0].checked=true; for(var i=1; i<=5; i++) {if(this.form.sqlcharset[i]) this.form.sqlcharset[i].disabled=true;}}" id="method_shell" /><label="method_shell"> '.$lang['db_export_shell'].'</label></li><li><input class="radio" type="radio" name="method" value="multivol" checked="checked" onclick="this.form.sqlcompat[2].disabled=false; this.form.sizelimit.disabled=false; for(var i=1; i<=5; i++) {if(this.form.sqlcharset[i]) this.form.sqlcharset[i].disabled=false;}" id="method_multivol" /><label for="method_multivol"> '.$lang['db_export_multivol'].'</label> <input type="text" class="txt" size="40" name="sizelimit" value="2048" /></li></ul>');
  77.                 showtitle('db_export_options');
  78.                 showsetting('db_export_options_extended_insert', 'extendins', 0, 'radio');
  79.                 showsetting('db_export_options_sql_compatible', array('sqlcompat', array(
  80.                         array('', $lang['default']),
  81.                         array('MYSQL40', 'MySQL 3.23/4.0.x'),
  82.                         array('MYSQL41', 'MySQL 4.1.x/5.x')
  83.                 )), '', 'mradio');
  84.                 showsetting('db_export_options_charset', array('sqlcharset', array(
  85.                         array('', cplang('default')),
  86.                         $dbcharset ? array($dbcharset, strtoupper($dbcharset)) : array(),
  87.                         $db->version() > '4.1' && $dbcharset != 'utf8' ? array('utf8', 'UTF-8') : array()
  88.                 ), TRUE), 0, 'mradio');
  89.                 showsetting('db_export_usehex', 'usehex', 1, 'radio');
  90.                 if(function_exists('gzcompress')) {
  91.                         showsetting('db_export_usezip', array('usezip', array(
  92.                                 array('1', $lang['db_export_zip_1']),
  93.                                 array('2', $lang['db_export_zip_2']),
  94.                                 array('0', $lang['db_export_zip_3'])
  95.                         )), 0, 'mradio');
  96.                 }
  97.                 showsetting('db_export_filename', '', '', '<input type="text" class="txt" name="filename" value="'.$defaultfilename.'" />.sql');
  98.                 showtagfooter('tbody');

  99.                 showsubmit('exportsubmit', 'submit', '', 'more_options');
  100.                 showtablefooter();
  101.                 showformfooter();

  102.         } else {

  103.                 DB::query('SET SQL_QUOTE_SHOW_CREATE=0', 'SILENT');

  104.                 if(!$_GET['filename'] || !preg_match('/^[\w\_]+$/', $_GET['filename'])) {
  105.                         cpmsg('database_export_filename_invalid', '', 'error');
  106.                 }

  107.                 $time = dgmdate(TIMESTAMP);
  108.                 if($_GET['type'] == 'discuz' || $_GET['type'] == 'discuz_uc') {
  109.                         $tables = arraykeys2(fetchtablelist($tablepre), 'Name');
  110.                 } elseif($_GET['type'] == 'custom') {
  111.                         $tables = array();
  112.                         if(empty($_GET['setup'])) {
  113.                                 $tables = C::t('common_setting')->fetch('custombackup', true);
  114.                         } else {
  115.                                 C::t('common_setting')->update('custombackup', empty($_GET['customtables'])? '' : $_GET['customtables']);
  116.                                 $tables = & $_GET['customtables'];
  117.                         }
  118.                         if( !is_array($tables) || empty($tables)) {
  119.                                 cpmsg('database_export_custom_invalid', '', 'error');
  120.                         }
  121.                 }

  122.                 $memberexist = array_search(DB::table('common_member'), $tables);
  123.                 if($memberexist !== FALSE) {
  124.                         unset($tables[$memberexist]);
  125.                         array_unshift($tables, DB::table('common_member'));
  126.                 }

  127.                 $volume = intval($_GET['volume']) + 1;
  128.                 $idstring = '# Identify: '.base64_encode("$_G[timestamp],".$_G['setting']['version'].",{$_GET['type']},{$_GET['method']},{$volume},{$tablepre},{$dbcharset}")."\n";


  129.                 $dumpcharset = $_GET['sqlcharset'] ? $_GET['sqlcharset'] : str_replace('-', '', $_G['charset']);
  130.                 $setnames = ($_GET['sqlcharset'] && $db->version() > '4.1' && (!$_GET['sqlcompat'] || $_GET['sqlcompat'] == 'MYSQL41')) ? "SET NAMES '$dumpcharset';\n\n" : '';
  131.                 if($db->version() > '4.1') {
  132.                         if($_GET['sqlcharset']) {
  133.                                 DB::query('SET NAMES %s', array($_GET['sqlcharset']));
  134.                         }
  135.                         if($_GET['sqlcompat'] == 'MYSQL40') {
  136.                                 DB::query("SET SQL_MODE='MYSQL40'");
  137.                         } elseif($_GET['sqlcompat'] == 'MYSQL41') {
  138.                                 DB::query("SET SQL_MODE=''");
  139.                         }
  140.                 }

  141.                 $backupfilename = './data/'.$backupdir.'/'.str_replace(array('/', '\\', '.', "'"), '', $_GET['filename']);

  142.                 if($_GET['usezip']) {
  143.                         require_once './source/class/class_zip.php';
  144.                 }

  145.                 if($_GET['method'] == 'multivol') {

  146.                         $sqldump = '';
  147.                         $tableid = intval($_GET['tableid']);
  148.                         $startfrom = intval($_GET['startfrom']);

  149.                         if(!$tableid && $volume == 1) {
  150.                                 foreach($tables as $table) {
  151.                                         $sqldump .= sqldumptablestruct($table);
  152.                                 }
  153.                         }

  154.                         $complete = TRUE;
  155.                         for(; $complete && $tableid < count($tables) && strlen($sqldump) + 500 < $_GET['sizelimit'] * 1000; $tableid++) {
  156.                                 $sqldump .= sqldumptable($tables[$tableid], $startfrom, strlen($sqldump));
  157.                                 if($complete) {
  158.                                         $startfrom = 0;
  159.                                 }
  160.                         }

  161.                         $dumpfile = $backupfilename."-%s".'.sql';
  162.                         !$complete && $tableid--;
  163.                         if(trim($sqldump)) {
  164.                                 $sqldump = "$idstring".
  165.                                         "# <?php exit();?>\n".
  166.                                         "# Discuz! Multi-Volume Data Dump Vol.$volume\n".
  167.                                         "# Version: Discuz! {$_G[setting][version]}\n".
  168.                                         "# Time: $time\n".
  169.                                         "# Type: {$_GET['type']}\n".
  170.                                         "# Table Prefix: $tablepre\n".
  171.                                         "#\n".
  172.                                         "# Discuz! Home: http://www.discuz.com\n".
  173.                                         "# Please visit our website for newest infomation about Discuz!\n".
  174.                                         "# --------------------------------------------------------\n\n\n".
  175.                                         "$setnames".
  176.                                         $sqldump;
  177.                                 $dumpfilename = sprintf($dumpfile, $volume);
  178.                                 @$fp = fopen($dumpfilename, 'wb');
  179.                                 @flock($fp, 2);
  180.                                 if(@!fwrite($fp, $sqldump)) {
  181.                                         @fclose($fp);
  182.                                         cpmsg('database_export_file_invalid', '', 'error');
  183.                                 } else {
  184.                                         fclose($fp);
  185.                                         if($_GET['usezip'] == 2) {
  186.                                                 $fp = fopen($dumpfilename, "r");
  187.                                                 $content = @fread($fp, filesize($dumpfilename));
  188.                                                 fclose($fp);
  189.                                                 $zip = new zipfile();
  190.                                                 $zip->addFile($content, basename($dumpfilename));
  191.                                                 $fp = fopen(sprintf($backupfilename."-%s".'.zip', $volume), 'w');
  192.                                                 if(@fwrite($fp, $zip->file()) !== FALSE) {
  193.                                                         @unlink($dumpfilename);
  194.                                                 }
  195.                                                 fclose($fp);
  196.                                         }
  197.                                         unset($sqldump, $zip, $content);
  198.                                         cpmsg('database_export_multivol_redirect', "action=db&operation=export&type=".rawurlencode($_GET['type'])."&saveto=server&filename=".rawurlencode($_GET['filename'])."&method=multivol&sizelimit=".rawurlencode($_GET['sizelimit'])."&volume=".rawurlencode($volume)."&tableid=".rawurlencode($tableid)."&startfrom=".rawurlencode($startrow)."&extendins=".rawurlencode($_GET['extendins'])."&sqlcharset=".rawurlencode($_GET['sqlcharset'])."&sqlcompat=".rawurlencode($_GET['sqlcompat'])."&exportsubmit=yes&usehex={$_GET['usehex']}&usezip={$_GET['usezip']}", 'loading', array('volume' => $volume));
  199.                                 }
  200.                         } else {
  201.                                 $volume--;
  202.                                 $filelist = '<ul>';
  203.                                 cpheader();

  204.                                 if($_GET['usezip'] == 1) {
  205.                                         $zip = new zipfile();
  206.                                         $zipfilename = $backupfilename.'.zip';
  207.                                         $unlinks = array();
  208.                                         for($i = 1; $i <= $volume; $i++) {
  209.                                                 $filename = sprintf($dumpfile, $i);
  210.                                                 $fp = fopen($filename, "r");
  211.                                                 $content = @fread($fp, filesize($filename));
  212.                                                 fclose($fp);
  213.                                                 $zip->addFile($content, basename($filename));
  214.                                                 $unlinks[] = $filename;
  215.                                                 $filelist .= "<li><a href="$filename">$filename</a></li>\n";
  216.                                         }
  217.                                         $fp = fopen($zipfilename, 'w');
  218.                                         if(@fwrite($fp, $zip->file()) !== FALSE) {
  219.                                                 foreach($unlinks as $link) {
  220.                                                         @unlink($link);
  221.                                                 }
  222.                                         } else {
  223.                                                 C::t('common_cache')->insert(array(
  224.                                                         'cachekey' => 'db_export',
  225.                                                         'cachevalue' => serialize(array('dateline' => $_G['timestamp'])),
  226.                                                         'dateline' => $_G['timestamp'],
  227.                                                 ), false, true);
  228.                                                 cpmsg('database_export_multivol_succeed', '', 'succeed', array('volume' => $volume, 'filelist' => $filelist));
  229.                                         }
  230.                                         unset($sqldump, $zip, $content);
  231.                                         fclose($fp);
  232.                                         @touch('./data/'.$backupdir.'/index.htm');
  233.                                         $filename = $zipfilename;
  234.                                         C::t('common_cache')->insert(array(
  235.                                                 'cachekey' => 'db_export',
  236.                                                 'cachevalue' => serialize(array('dateline' => $_G['timestamp'])),
  237.                                                 'dateline' => $_G['timestamp'],
  238.                                         ), false, true);
  239.                                         cpmsg('database_export_zip_succeed', '', 'succeed', array('filename' => $filename));
  240.                                 } else {
  241.                                         @touch('./data/'.$backupdir.'/index.htm');
  242.                                         for($i = 1; $i <= $volume; $i++) {
  243.                                                 $filename = sprintf($_GET['usezip'] == 2 ? $backupfilename."-%s".'.zip' : $dumpfile, $i);
  244.                                                 $filelist .= "<li><a href="$filename">$filename</a></li>\n";
  245.                                         }
  246.                                         C::t('common_cache')->insert(array(
  247.                                                 'cachekey' => 'db_export',
  248.                                                 'cachevalue' => serialize(array('dateline' => $_G['timestamp'])),
  249.                                                 'dateline' => $_G['timestamp'],
  250.                                         ), false, true);
  251.                                         cpmsg('database_export_multivol_succeed', '', 'succeed', array('volume' => $volume, 'filelist' => $filelist));
  252.                                 }
  253.                         }

  254.                 } else {

  255.                         $tablesstr = '';
  256.                         foreach($tables as $table) {
  257.                                 $tablesstr .= '"'.$table.'" ';
  258.                         }

  259.                         require DISCUZ_ROOT . './config/config_global.php';
  260.                         list($dbhost, $dbport) = explode(':', $dbhost);

  261.                         $query = DB::query("SHOW VARIABLES LIKE 'basedir'");
  262.                         list(, $mysql_base) = DB::fetch($query, DB::$drivertype == 'mysqli' ? MYSQLI_NUM : MYSQL_NUM);

  263.                         $dumpfile = addslashes(dirname(dirname(__FILE__))).'/'.$backupfilename.'.sql';
  264.                         @unlink($dumpfile); $tablesstr=escapeshellarg($tablesstr)

  265.                         $mysqlbin = $mysql_base == '/' ? '' : addslashes($mysql_base).'bin/';
  266.                         @shell_exec($mysqlbin.'mysqldump --force --quick '.($db->version() > '4.1' ? '--skip-opt --create-options' : '-all').' --add-drop-table'.($_GET['extendins'] == 1 ? ' --extended-insert' : '').''.($db->version() > '4.1' && $_GET['sqlcompat'] == 'MYSQL40' ? ' --compatible=mysql40' : '').' --host="'.$dbhost.($dbport ? (is_numeric($dbport) ? ' --port='.$dbport : ' --socket="'.$dbport.'"') : '').'" --user="'.$dbuser.'" --password="'.$dbpw.'" "'.$dbname.'" '.$tablesstr.' > '.$dumpfile);

  267.                         if(@file_exists($dumpfile)) {

  268.                                 if($_GET['usezip']) {
  269.                                         require_once libfile('class/zip');
  270.                                         $zip = new zipfile();
  271.                                         $zipfilename = $backupfilename.'.zip';
  272.                                         $fp = fopen($dumpfile, "r");
  273.                                         $content = @fread($fp, filesize($dumpfile));
  274.                                         fclose($fp);
  275.                                         $zip->addFile($idstring."# <?php exit();?>\n ".$setnames."\n #".$content, basename($dumpfile));
  276.                                         $fp = fopen($zipfilename, 'w');
  277.                                         @fwrite($fp, $zip->file());
  278.                                         fclose($fp);
  279.                                         @unlink($dumpfile); $tablesstr=escapeshellarg($tablesstr)
  280.                                         @touch('./data/'.$backupdir.'/index.htm');
  281.                                         $filename = $backupfilename.'.zip';
  282.                                         unset($sqldump, $zip, $content);
  283.                                         C::t('common_cache')->insert(array(
  284.                                                 'cachekey' => 'db_export',
  285.                                                 'cachevalue' => serialize(array('dateline' => $_G['timestamp'])),
  286.                                                 'dateline' => $_G['timestamp'],
  287.                                         ), false, true);
  288.                                         cpmsg('database_export_zip_succeed', '', 'succeed', array('filename' => $filename));
  289.                                 } else {
  290.                                         if(@is_writeable($dumpfile)) {
  291.                                                 $fp = fopen($dumpfile, 'rb+');
  292.                                                 @fwrite($fp, $idstring."# <?php exit();?>\n ".$setnames."\n #");
  293.                                                 fclose($fp);
  294.                                         }
  295.                                         @touch('./data/'.$backupdir.'/index.htm');
  296.                                         $filename = $backupfilename.'.sql';
  297.                                         C::t('common_cache')->insert(array(
  298.                                                 'cachekey' => 'db_export',
  299.                                                 'cachevalue' => serialize(array('dateline' => $_G['timestamp'])),
  300.                                                 'dateline' => $_G['timestamp'],
  301.                                         ), false, true);
  302.                                         cpmsg('database_export_succeed', '', 'succeed', array('filename' => $filename));
  303.                                 }

  304.                         } else {

  305.                                 cpmsg('database_shell_fail', '', 'error');

  306.                         }

  307.                 }
  308.         }

  309. } elseif($operation == 'import') {

  310.         checkpermission('dbimport');

  311.         if(!submitcheck('deletesubmit')) {

  312.                 $exportlog = $exportsize = $exportziplog = array();
  313.                 if(is_dir(DISCUZ_ROOT.'./data/'.$backupdir)) {
  314.                         $dir = dir(DISCUZ_ROOT.'./data/'.$backupdir);
  315.                         while($entry = $dir->read()) {
  316.                                 $entry = './data/'.$backupdir.'/'.$entry;
  317.                                 if(is_file($entry)) {
  318.                                         if(preg_match("/\.sql$/i", $entry)) {
  319.                                                 $filesize = filesize($entry);
  320.                                                 $fp = fopen($entry, 'rb');
  321.                                                 $identify = explode(',', base64_decode(preg_replace("/^# Identify:\s*(\w+).*/s", "\\1", fgets($fp, 256))));
  322.                                                 fclose($fp);
  323.                                                 $key = preg_replace('/^(.+?)(\-\d+)\.sql$/i', '\\1', basename($entry));
  324.                                                 $exportlog[$key][$identify[4]] = array(
  325.                                                         'version' => $identify[1],
  326.                                                         'type' => $identify[2],
  327.                                                         'method' => $identify[3],
  328.                                                         'volume' => $identify[4],
  329.                                                         'filename' => $entry,
  330.                                                         'dateline' => filemtime($entry),
  331.                                                         'size' => $filesize
  332.                                                 );
  333.                                                 $exportsize[$key] += $filesize;
  334.                                         } elseif(preg_match("/\.zip$/i", $entry)) {
  335.                                                 $filesize = filesize($entry);
  336.                                                 $exportziplog[] = array(
  337.                                                         'type' => 'zip',
  338.                                                         'filename' => $entry,
  339.                                                         'size' => filesize($entry),
  340.                                                         'dateline' => filemtime($entry)
  341.                                                 );
  342.                                         }
  343.                                 }
  344.                         }
  345.                         $dir->close();
  346.                 } else {
  347.                         cpmsg('database_export_dest_invalid', '', 'error');
  348.                 }

  349.                 $restore_url = $_G['siteurl'].'data/restore.php';

  350.                 shownav('founder', 'nav_db', 'nav_db_import');
  351.                 showsubmenu('nav_db', array(
  352.                         array('nav_db_export', 'db&operation=export', 0),
  353.                         array('nav_db_import', 'db&operation=import', 1),
  354.                         array('nav_db_runquery', 'db&operation=runquery', 0),
  355.                         array('nav_db_optimize', 'db&operation=optimize', 0),
  356.                         array('nav_db_dbcheck', 'db&operation=dbcheck', 0)
  357.                 ));
  358.                 showtips('db_import_tips');
  359.                 showtableheader('db_import');
  360.                 showtablerow('', array('colspan="9" class="tipsblock"'), array(cplang('do_import_option', array('restore_url' => $restore_url))));

  361.                 showformheader('db&operation=import');
  362.                 showtitle('db_export_file');
  363.                 showsubtitle(array('', 'filename', 'version', 'time', 'type', 'size', 'db_method', 'db_volume', ''));

  364.                 $datasiteurl = $_G['siteurl'].'data/';

  365.                 foreach($exportlog as $key => $val) {
  366.                         $info = $val[1];
  367.                         $info['dateline'] = is_int($info['dateline']) ? dgmdate($info['dateline']) : $lang['unknown'];
  368.                         $info['size'] = sizecount($exportsize[$key]);
  369.                         $info['volume'] = count($val);
  370.                         $info['method'] = $info['type'] != 'zip' ? ($info['method'] == 'multivol' ? $lang['db_multivol'] : $lang['db_shell']) : '';
  371.                         $datafile_server = '.'.$info['filename'];
  372.                         showtablerow('', '', array(
  373.                                 "<input class="checkbox" type="checkbox" name="delete[]" value="".$key."">",
  374.                                 "<a href="javascript:;" onclick="display('exportlog_$key')">".$key."</a>",
  375.                                 $info['version'],
  376.                                 $info['dateline'],
  377.                                 $lang['db_export_'.$info['type']],
  378.                                 $info['size'],
  379.                                 $info['method'],
  380.                                 $info['volume'],
  381.                                 $info['type'] == 'zip' ? "<a href="".$datasiteurl."restore.php?operation=importzip&datafile_server=$datafile_server&importsubmit=yes"  onclick="return confirm('$lang[db_import_confirm_zip]');" class="act" target="_blank">$lang[db_import_unzip]</a>" : "<a class="act" href="".$datasiteurl."restore.php?operation=import&from=server&datafile_server=$datafile_server&importsubmit=yes"".($info['version'] != $_G['setting']['version'] ? " onclick="return confirm('$lang[db_import_confirm]');"" : " onclick="return confirm('$lang[db_import_confirm_sql]');"")." class="act" target="_blank">$lang[import]</a>"
  382.                         ));
  383.                         echo '<tbody id="exportlog_'.$key.'" style="display:none">';
  384.                         foreach($val as $info) {
  385.                                 $info['dateline'] = is_int($info['dateline']) ? dgmdate($info['dateline']) : $lang['unknown'];
  386.                                 $info['size'] = sizecount($info['size']);
  387.                                 showtablerow('', '', array(
  388.                                         '',
  389.                                         "<a href="$info[filename]">".substr(strrchr($info['filename'], "/"), 1)."</a>",
  390.                                         $info['version'],
  391.                                         $info['dateline'],
  392.                                         '',
  393.                                         $info['size'],
  394.                                         '',
  395.                                         $info['volume'],
  396.                                         ''
  397.                                 ));
  398.                         }
  399.                         echo '</tbody>';
  400.                 }

  401.                 foreach($exportziplog as $info) {
  402.                         $info['dateline'] = is_int($info['dateline']) ? dgmdate($info['dateline']) : $lang['unknown'];
  403.                         $info['size'] = sizecount($info['size']);
  404.                         $info['method'] = $info['method'] == 'multivol' ? $lang['db_multivol'] : $lang['db_zip'];
  405.                         $datafile_server = '.'.$info['filename'];
  406.                         showtablerow('', '', array(
  407.                                 "<input class="checkbox" type="checkbox" name="delete[]" value="".basename($info['filename'])."">",
  408.                                 "<a href="$info[filename]">".substr(strrchr($info['filename'], "/"), 1)."</a>",
  409.                                 '',
  410.                                 $info['dateline'],
  411.                                 $lang['db_export_'.$info['type']],
  412.                                 $info['size'],
  413.                                 $info['method'],
  414.                                 '',
  415.                                 "<a href="".$datasiteurl."restore.php?operation=importzip&datafile_server=$datafile_server&importsubmit=yes"  onclick="return confirm('$lang[db_import_confirm_zip]');" class="act" target="_blank">$lang[db_import_unzip]</a>"
  416.                         ));
  417.                 }

  418.                 showsubmit('deletesubmit', 'submit', 'del');
  419.                 showformfooter();

  420.                 showtablefooter();

  421.         } else {
  422.                 if(is_array($_GET['delete'])) {
  423.                         foreach($_GET['delete'] as $filename) {
  424.                                 $file_path = './data/'.$backupdir.'/'.str_replace(array('/', '\\'), '', $filename);
  425.                                 if(is_file($file_path)) {
  426.                                         @unlink($file_path);
  427.                                 } else {
  428.                                         $i = 1;
  429.                                         while(1) {
  430.                                                 $file_path = './data/'.$backupdir.'/'.str_replace(array('/', '\\'), '', $filename.'-'.$i.'.sql');
  431.                                                 if(is_file($file_path)) {
  432.                                                         @unlink($file_path);
  433.                                                         $i++;
  434.                                                 } else {
  435.                                                         break;
  436.                                                 }
  437.                                         }
  438.                                 }
  439.                         }
  440.                         cpmsg('database_file_delete_succeed', '', 'succeed');
  441.                 } else {
  442.                         cpmsg('database_file_delete_invalid', '', 'error');
  443.                 }
  444.         }




  445. } elseif($operation == 'runquery') {

  446.         $checkperm = checkpermission('runquery', 0);

  447.         $runquerys = array();
  448.         include_once(DISCUZ_ROOT.'source/admincp/admincp_quickquery.php');

  449.         if(!submitcheck('sqlsubmit')) {

  450.                 $runqueryselect = '';
  451.                 foreach($simplequeries as $key => $query) {
  452.                         if(empty($query['sql'])) {
  453.                                 $runqueryselect .= "<optgroup label="$query[comment]">";
  454.                         } else {
  455.                                 $runqueryselect .= '<option value="'.$key.'">'.$query['comment'].'</option>';
  456.                         }
  457.                 }
  458.                 if($runqueryselect) {
  459.                         $runqueryselect = '<select name="queryselect" style="width:500px">'.$runqueryselect.'</select>';
  460.                 }
  461.                 $queryselect = intval($_GET['queryselect']);
  462.                 $queries = $queryselect ? $runquerys[$queryselect] : '';

  463.                 shownav('founder', 'nav_db', 'nav_db_runquery');
  464.                 showsubmenu('nav_db', array(
  465.                         array('nav_db_export', 'db&operation=export', 0),
  466.                         array('nav_db_import', 'db&operation=import', 0),
  467.                         array('nav_db_runquery', 'db&operation=runquery', 1),
  468.                         array('nav_db_optimize', 'db&operation=optimize', 0),
  469.                         array('nav_db_dbcheck', 'db&operation=dbcheck', 0)
  470.                 ));
  471.                 showtips('db_runquery_tips');
  472.                 showtableheader();
  473.                 showformheader('db&operation=runquery&option=simple');
  474.                 showsetting('db_runquery_simply', '', '', $runqueryselect);
  475.                 showsetting('', '', '', '<input type="checkbox" class="checkbox" name="createcompatible" value="1" checked="checked" />'.cplang('db_runquery_createcompatible'));
  476.                 showsubmit('sqlsubmit');
  477.                 showformfooter();

  478.                 if($checkperm) {
  479.                         showformheader('db&operation=runquery&option=');
  480.                         showsetting('db_runquery_sql', '', '', '<textarea cols="85" rows="10" name="queries" style="width:500px;" onkeyup="textareasize(this)" onkeydown="textareakey(this, event)">'.$queries.'</textarea>');
  481.                         showsetting('', '', '', '<input type="checkbox" class="checkbox" name="createcompatible" value="1" checked="checked" />'.cplang('db_runquery_createcompatible'));
  482.                         showsubmit('sqlsubmit', 'submit', '', cplang('db_runquery_comment'));
  483.                         showformfooter();
  484.                 }

  485.                 showtablefooter();

  486.         } else {
  487.                 $queries = $_GET['queries'];
  488.                 if($_GET['option'] == 'simple') {
  489.                         $queryselect = intval($_GET['queryselect']);
  490.                         $queries = isset($simplequeries[$queryselect]) && $simplequeries[$queryselect]['sql'] ? $simplequeries[$queryselect]['sql'] : '';
  491.                 } elseif(!$checkperm) {
  492.                         cpmsg('database_run_query_denied', '', 'error');
  493.                 }
  494.                 $sqlquery = splitsql(str_replace(array(' {tablepre}', ' cdb_', ' `cdb_', ' pre_', ' `pre_'), array(' '.$tablepre, ' '.$tablepre, ' `'.$tablepre, ' '.$tablepre, ' `'.$tablepre), $queries));
  495.                 $affected_rows = 0;
  496.                 foreach($sqlquery as $sql) {
  497.                         if(trim($sql) != '') {
  498.                                 $sql = !empty($_GET['createcompatible']) ? syntablestruct(trim($sql), $db->version() > '4.1', $dbcharset) : $sql;

  499.                                 DB::query($sql, 'SILENT');
  500.                                 if($sqlerror = DB::error()) {
  501.                                         break;
  502.                                 } else {
  503.                                         $affected_rows += intval(DB::affected_rows());
  504.                                 }
  505.                         }
  506.                 }

  507.                 $sqlerror ? cpmsg('database_run_query_invalid', '', 'error', array('sqlerror' => $sqlerror)) : cpmsg('database_run_query_succeed', '', 'succeed', array('affected_rows' => $affected_rows));

  508.         }

  509. } elseif($operation == 'optimize') {

  510.         $optimizetable = '';
  511.         $totalsize = 0;
  512.         $tablearray = array( 0 => $tablepre);

  513.         shownav('founder', 'nav_db', 'nav_db_optimize');
  514.         showsubmenu('nav_db', array(
  515.                 array('nav_db_export', 'db&operation=export', 0),
  516.                 array('nav_db_import', 'db&operation=import', 0),
  517.                 array('nav_db_runquery', 'db&operation=runquery', 0),
  518.                 array('nav_db_optimize', 'db&operation=optimize', 1),
  519.                 array('nav_db_dbcheck', 'db&operation=dbcheck', 0)
  520.         ));
  521.         showtips('db_optimize_tips');
  522.         showformheader('db&operation=optimize');
  523.         showtableheader('db_optimize_tables');
  524.         showsubtitle(array('', 'db_optimize_table_name', 'type', 'db_optimize_rows', 'db_optimize_data', 'db_optimize_index', 'db_optimize_frag'));

  525.         if(!submitcheck('optimizesubmit')) {

  526.                 foreach($tablearray as $tp) {
  527.                         $query = DB::query("SHOW TABLE STATUS LIKE '$tp%'", 'SILENT');
  528.                         while($table = DB::fetch($query)) {
  529.                                 if($table['Data_free'] && $table[$tabletype] == 'MyISAM') {
  530.                                         $checked = $table[$tabletype] == 'MyISAM' ? 'checked' : 'disabled';
  531.                                         showtablerow('', '', array(
  532.                                                 "<input class="checkbox" type="checkbox" name="optimizetables[]" value="$table[Name]" $checked>",
  533.                                                 $table[Name],
  534.                                                 $table[$tabletype],
  535.                                                 $table[Rows],
  536.                                                 $table[Data_length],
  537.                                                 $table[Index_length],
  538.                                                 $table[Data_free],
  539.                                         ));
  540.                                         $totalsize += $table['Data_length'] + $table['Index_length'];
  541.                                 }
  542.                         }
  543.                 }
  544.                 if(empty($totalsize)) {
  545.                         showtablerow('', 'colspan="6"', $lang['db_optimize_done']);
  546.                 } else {
  547.                         showtablerow('', 'colspan="6"', $lang['db_optimize_used'].' '.sizecount($totalsize));
  548.                         showsubmit('optimizesubmit', 'submit', '<input name="chkall" id="chkall" class="checkbox" onclick="checkAll(\'prefix\', this.form)" checked="checked" type="checkbox" /><label for="chkall">'.$lang[db_optimize_opt].'</label>');
  549.                 }

  550.         } else {


  551.                 foreach($tablearray as $tp) {
  552.                         $query = DB::query("SHOW TABLE STATUS LIKE '$tp%'", 'SILENT');
  553.                         while($table = DB::fetch($query)) {
  554.                                 if($table['Data_free'] && $table[$tabletype] == 'MyISAM') {
  555.                                         $optimizeinput = "<input class="checkbox" type="checkbox" name="optimizetables[]" value="$table[Name]" $checked>";
  556.                                         if(is_array($_GET['optimizetables']) && in_array($table['Name'], $_GET['optimizetables'])) {
  557.                                                 DB::query("OPTIMIZE TABLE $table[Name]");
  558.                                                 $table[Data_free] = 0;
  559.                                                 $optimizeinput = '';
  560.                                         }
  561.                                         showtablerow('', '', array(
  562.                                                 $optimizeinput,
  563.                                                 $table[Name],
  564.                                                 $db->version() > '4.1' ?  $table['Engine'] : $table['Type'],
  565.                                                 $table[Rows],
  566.                                                 $table[Data_length],
  567.                                                 $table[Index_length],
  568.                                                 $table[Data_free]
  569.                                         ));
  570.                                         $totalsize += $table['Data_length'] + $table['Index_length'];
  571.                                 }
  572.                         }
  573.                 }
  574.                 showtablerow('', 'colspan="6"', $lang['db_optimize_used'].' '.sizecount($totalsize));
  575.         }

  576.         showtablefooter();
  577.         showformfooter();

  578. } elseif($operation == 'dbcheck') {

  579.         if(!C::t('common_setting')->fetch_all_field()) {
  580.                 cpmsg('dbcheck_permissions_invalid', '', 'error');
  581.         }

  582.         $step = max(1, intval($_GET['step']));
  583.         if($step == 3) {

  584.                 if(!file_exists('source/admincp/discuzdb.md5')) {
  585.                         cpmsg('dbcheck_nofound_md5file', '', 'error');
  586.                 }

  587.                 $dbcharset = $discuz->config['db'][1]['dbcharset'];
  588.                 unset($dbuser, $dbpw, $dbname);

  589.                 $fp = fopen(DISCUZ_ROOT.'./source/admincp/discuzdb.md5', "rb");
  590.                 $discuzdb = fread($fp, filesize(DISCUZ_ROOT.'./source/admincp/discuzdb.md5'));
  591.                 fclose($fp);
  592.                 $dbmd5 = substr($discuzdb, 0, 32);
  593.                 $discuzdb = dunserialize(substr($discuzdb, 34));
  594.                 $settingsdata = $discuzdb[1];
  595.                 $discuzdb = $discuzdb[0][0];
  596.                 $repair = !empty($_GET['repair']) ? $_GET['repair'] : array();
  597.                 $setting = !empty($_GET['setting']) ? $_GET['setting'] : array();
  598.                 $missingtable = !empty($_GET['missingtable']) ? $_GET['missingtable'] : array();
  599.                 $repairtable = is_array($_GET['repairtable']) && !empty($_GET['repairtable']) ? $_GET['repairtable'] : array();

  600.                 $except = array('threads' => array('sgid'));
  601.                 foreach(C::t('common_member_profile_setting')->range() as $profilefields) {
  602.                         $except['memberfields'][] = 'field_'.$profilefields[$fieldid];
  603.                 }

  604.                 if(submitcheck('repairsubmit') && (!empty($repair) || !empty($setting) || !empty($repairtable) || !empty($missingtable))) {
  605.                         $error = '';
  606.                         $errorcount = 0;
  607.                         $alter = $fielddefault = array();

  608.                         foreach($missingtable as $value) {
  609.                                 if(!isset($installdata)) {
  610.                                         $fp = fopen(DISCUZ_ROOT.'./install/install.sql', "rb");
  611.                                         $installdata = fread($fp, filesize(DISCUZ_ROOT.'./install/install.sql'));
  612.                                         fclose($fp);
  613.                                 }
  614.                                 preg_match("/CREATE TABLE ".DB::table($value)."\s+\(.+?;/is", $installdata, $a);
  615.                                 DB::query(createtable($a[0], $dbcharset));
  616.                         }

  617.                         foreach($repair as $value) {
  618.                                 if(!in_array($r_table, $repairtable)) {
  619.                                         list($r_table, $r_field, $option) = explode('|', $value);
  620.                                         if(!isset($repairrtable[$r_table]) && $fieldsquery = DB::query("SHOW FIELDS FROM ".DB::table($r_table), 'SILENT')) {
  621.                                                 while($fields = DB::fetch($fieldsquery)) {
  622.                                                         $fielddefault[$r_table][$fields['Field']] = $fields['Default'];
  623.                                                 }
  624.                                         }

  625.                                         $field = $discuzdb[$r_table][$r_field];
  626.                                         $altersql = '`'.$field['Field'].'` '.$field['Type'];
  627.                                         $altersql .= $field['Null'] == 'NO' ? ' NOT NULL' : '';
  628.                                         $altersql .= in_array($fielddefault[$r_table][$field['Field']], array('', '0')) && in_array($field['Default'], array('', '0')) ||
  629.                                                 $field['Null'] == 'NO' && $field['Default'] == '' ||
  630.                                                 preg_match('/text/i', $field['Type']) || preg_match('/auto_increment/i', $field['Extra']) ?
  631.                                                 '' : ' default \''.$field['Default'].'\'';
  632.                                         $altersql .= $field['Extra'] != '' ? ' '.$field['Extra'] : '';
  633.                                         $altersql = $option == 'modify' ? "MODIFY COLUMN ".$altersql : "ADD COLUMN ".$altersql;
  634.                                         $alter[$r_table][] = $altersql;
  635.                                 }
  636.                         }

  637.                         foreach($alter as $r_table => $sqls) {
  638.                                 DB::query("ALTER TABLE `$tablepre$r_table` ".implode(',', $sqls), 'SILENT');
  639.                                 if($sqlerror = DB::error()) {
  640.                                         $errorcount += count($sqls);
  641.                                         $error .= $sqlerror.'<br /><br />';
  642.                                 }
  643.                         }
  644.                         $alter = array();

  645.                         foreach($repairtable as $value) {
  646.                                 foreach($discuzdb[$value] as $field) {
  647.                                         if(!isset($fielddefault[$value]) && $fieldsquery = DB::query("SHOW FIELDS FROM ".DB::table($value), 'SILENT')) {
  648.                                                 while($fields = DB::fetch($fieldsquery)) {
  649.                                                         $fielddefault[$value][$fields['Field']] = $fields['Default'];
  650.                                                 }
  651.                                         }
  652.                                         $altersql = '`'.$field['Field'].'` '.$field['Type'];
  653.                                         $altersql .= $field['Null'] == 'NO' ? ' NOT NULL' : '';
  654.                                         $altersql .= in_array($fielddefault[$value][$field['Field']], array('', '0')) && in_array($field['Default'], array('', '0')) ||
  655.                                                 $field['Null'] == 'NO' && $field['Default'] == '' ||
  656.                                                 preg_match('/text/i', $field['Type']) || preg_match('/auto_increment/i', $field['Extra']) ?
  657.                                                 '' : ' default \''.$field['Default'].'\'';
  658.                                         $altersql .= $field['Extra'] != '' ? ' '.$field['Extra'] : '';
  659.                                         $altersql = "MODIFY COLUMN ".$altersql;
  660.                                         $alter[$value][] = $altersql;
  661.                                 }
  662.                         }

  663.                         foreach($alter as $r_table => $sqls) {
  664.                                 DB::query("ALTER TABLE `".DB::table($r_table)."` ".implode(',', $sqls), 'SILENT');
  665.                                 if($sqlerror = DB::error()) {
  666.                                         $errorcount += count($sqls);
  667.                                         $error .= $sqlerror.'<br /><br />';
  668.                                 }
  669.                         }

  670.                         if(!empty($setting)) {
  671.                                 $settingsdatanow = $newsettings = array();
  672.                                 $allsetting = C::t('common_setting')->fetch_all();
  673.                                 $settingsdatanew = array_keys($allsetting);
  674.                                 unset($allsetting);
  675.                                 $settingsdellist = @array_diff($settingsdata, $settingsdatanew);
  676.                                 if($setting['del'] && is_array($settingsdellist)) {
  677.                                         foreach($settingsdellist as $variable) {
  678.                                                 $newsettings[$variable] = '';
  679.                                         }
  680.                                 }
  681.                                 if($newsettings) {
  682.                                         C::t('common_setting')->update_batch($newsettings);
  683.                                         updatecache('setting');
  684.                                 }
  685.                         }

  686.                         if($errorcount) {
  687.                                 cpmsg('dbcheck_repair_error', '', 'error', array('errorcount' => $errorcount, 'error' => $error));
  688.                         } else {
  689.                                 cpmsg('dbcheck_repair_completed', 'action=db&operation=dbcheck&step=3', 'succeed');
  690.                         }
  691.                 }

  692.                 $installexists = file_exists(DISCUZ_ROOT.'./install/install.sql');
  693.                 $discuzdbnew = $deltables = $excepttables = $missingtables = $charseterror = array();
  694.                 foreach($discuzdb as $dbtable => $fields) {
  695.                         if($fieldsquery = DB::query("SHOW FIELDS FROM ".DB::table($dbtable), 'SILENT')) {
  696.                                 while($fields = DB::fetch($fieldsquery)) {
  697.                                         $r = '/^'.$tablepre.'/';
  698.                                         $cuttable = preg_replace($r, '', $dbtable);
  699.                                         if($db->version() < '4.1' && $cuttable == 'sessions' && $fields['Field'] == 'sid') {
  700.                                                 $fields['Type'] = str_replace(' binary', '', $fields['Type']);
  701.                                         }
  702.                                         if($cuttable == 'memberfields' && preg_match('/^field\_\d+$/', $fields['Field'])) {
  703.                                                 unset($discuzdbnew[$cuttable][$fields['Field']]);
  704.                                                 continue;
  705.                                         }
  706.                                         $discuzdbnew[$cuttable][$fields['Field']]['Field'] = $fields['Field'];
  707.                                         $discuzdbnew[$cuttable][$fields['Field']]['Type'] = $fields['Type'];
  708.                                         $discuzdbnew[$cuttable][$fields['Field']]['Null'] = $fields['Null'] == '' ? 'NO' : $fields['Null'];
  709.                                         $discuzdbnew[$cuttable][$fields['Field']]['Extra'] = $fields['Extra'];
  710.                                         $discuzdbnew[$cuttable][$fields['Field']]['Default'] = $fields['Default'] == '' || $fields['Default'] == '0' ? '' : $fields['Default'];
  711.                                 }
  712.                                 ksort($discuzdbnew[$cuttable]);
  713.                         } else {
  714.                                 $missingtables[] = '<span style="float:left;width:33%">'.(($installexists ? '<input name="missingtable[]" type="checkbox" class="checkbox" value="'.$dbtable.'">' : '').$tablepre.$dbtable).'</span>';
  715.                                 $excepttables[] = $dbtable;
  716.                         }
  717.                 }

  718.                 if($db->version() > '4.1') {
  719.                         $dbcharset = strtoupper($dbcharset) == 'UTF-8' ? 'UTF8' : strtoupper($dbcharset);
  720.                         $query = DB::query("SHOW TABLE STATUS LIKE '$tablepre%'");
  721.                         while($tables = DB::fetch($query)) {
  722.                                 $r = '/^'.$tablepre.'/';
  723.                                 $cuttable = preg_replace($r, '', $tables['Name']);
  724.                                 $tabledbcharset = substr($tables['Collation'], 0, strpos($tables['Collation'], '_'));
  725.                                 if($dbcharset != strtoupper($tabledbcharset)) {
  726.                                         $charseterror[] = '<span style="float:left;width:33%">'.$tablepre.$cuttable.'('.$tabledbcharset.')</span>';
  727.                                 }
  728.                         }
  729.                 }

  730.                 $dbmd5new = md5(serialize($discuzdbnew));

  731.                 $settingsdatanow = array();
  732.                 $allsetting = C::t('common_setting')->fetch_all();
  733.                 $settingsdatanew = array_keys($allsetting);
  734.                 unset($allsetting);
  735.                 $settingsdellist = @array_diff($settingsdata, $settingsdatanew);

  736.                 if($dbmd5 == $dbmd5new && empty($charseterror) && empty($settingsdellist)) {
  737.                         cpmsg('dbcheck_ok', '', 'succeed');
  738.                 }

  739.                 $showlist = $addlists = '';
  740.                 foreach($discuzdb as $dbtable => $fields) {
  741.                         $addlist = $modifylist = $dellist = array();
  742.                         if($fields != $discuzdbnew[$dbtable]) {
  743.                                 foreach($discuzdb[$dbtable] as $key => $value) {
  744.                                         $tempvalue = str_replace('mediumtext', 'text', $value);
  745.                                         $discuzdbnew[$dbtable][$key] = str_replace('mediumtext', 'text', $discuzdbnew[$dbtable][$key]);
  746.                                         if(is_array($missingtables) && in_array($tablepre.$dbtable, $missingtables)) {
  747.                                         } elseif(!isset($discuzdbnew[$dbtable][$key])) {
  748.                                                 $dellist[] = $value;
  749.                                         } elseif($tempvalue != $discuzdbnew[$dbtable][$key]) {
  750.                                                 $modifylist[] = $value;
  751.                                         }
  752.                                 }
  753.                                 if(is_array($discuzdbnew[$dbtable])) {
  754.                                         foreach($discuzdbnew[$dbtable] as $key => $value) {
  755.                                                 if(!isset($discuzdb[$dbtable][$key]) && !@in_array($value['Field'], $except[$dbtable])) {
  756.                                                         $addlist[] = $value;
  757.                                                 }
  758.                                         }
  759.                                 }
  760.                         }

  761.                         if(($modifylist || $dellist) && !in_array($dbtable, $excepttables)) {

  762.                                 $showlist .= showtablerow('', '', array("<span class="diffcolor3">$tablepre$dbtable</span> $lang[dbcheck_field]", $lang[dbcheck_org_field], $lang[dbcheck_status]), TRUE);

  763.                                 foreach($modifylist as $value) {
  764.                                         $slowstatus = slowcheck($discuzdbnew[$dbtable][$value['Field']]['Type'], $value['Type']);

  765.                                         $showlist .= "<tr><td><input name="repair[]" class="checkbox" type="checkbox" value="$dbtable|$value[Field]|modify"> <b>".$value['Field']."</b> ".
  766.                                                 $discuzdbnew[$dbtable][$value['Field']]['Type'].
  767.                                                 ($discuzdbnew[$dbtable][$value['Field']]['Null'] == 'NO' ? ' NOT NULL' : '').
  768.                                                 (!preg_match('/auto_increment/i', $discuzdbnew[$dbtable][$value['Field']]['Extra']) && !preg_match('/text/i', $discuzdbnew[$dbtable][$value['Field']]['Type']) ? ' default \''.$discuzdbnew[$dbtable][$value['Field']]['Default'].'\'' : '').
  769.                                                 ' '.$discuzdbnew[$dbtable][$value['Field']]['Extra'].
  770.                                                 "</td><td><b>".$value['Field']."</b> ".$value['Type'].
  771.                                                 ($value['Null'] == 'NO' ? ' NOT NULL' : '').
  772.                                                 (!preg_match('/auto_increment/i', $value['Extra']) && !preg_match('/text/i', $value['Type']) ? ' default \''.$value['Default'].'\'' : '').
  773.                                                 ' '.$value['Extra']."</td><td>".
  774.                                                 (!$slowstatus ? "<em class="edited">$lang[dbcheck_modify]</em></td></tr>" : "<em class="unknown">$lang[dbcheck_slow]</em>")."</td></tr>";
  775.                                 }

  776.                                 if($modifylist) {
  777.                                         $showlist .= showtablerow('', 'colspan="3"', "<input onclick="setrepaircheck(this, this.form, '$dbtable')" name="repairtable[]" class="checkbox" type="checkbox" value="$dbtable"> <b>$lang[dbcheck_repairtable]</b>", TRUE);
  778.                                 }

  779.                                 foreach($dellist as $value) {
  780.                                         $showlist .= "<tr><td><input name="repair[]" class="checkbox" type="checkbox" value="$dbtable|$value[Field]|add"> <strike><b>".$value['Field']."</b></strike></td><td> <b>".$value['Field']."</b> ".$value['Type'].($value['Null'] == 'NO' ? ' NOT NULL' : '')."</td><td>".
  781.                                                 "<em class="del">$lang[dbcheck_delete]</em></td></tr>";
  782.                                 }
  783.                         }

  784.                         if($addlist) {
  785.                                 $addlists .= "<tr><td colspan="3"><b>$tablepre$dbtable</b> $lang[dbcheck_new_field]</td></tr>";

  786.                                 foreach($addlist as $value) {
  787.                                         $addlists .= "<tr><td colspan="3">    <b>".$value['Field']."</b> ".$discuzdbnew[$dbtable][$value['Field']]['Type'].($discuzdbnew[$dbtable][$value['Field']]['Null'] == 'NO' ? ' NOT NULL' : '')."</td></tr>";
  788.                                 }
  789.                         }

  790.                 }

  791.                 if($showlist) {
  792.                         $showlist = showtablerow('', 'colspan="3" class="partition"', $lang['dbcheck_errorfields_tables'], TRUE).$showlist;
  793.                 }

  794.                 if($missingtables) {
  795.                         $showlist .= showtablerow('', 'colspan="3" class="partition"', $lang['dbcheck_missing_tables'], TRUE);
  796.                         $showlist .= showtablerow('', 'colspan="3" class="partition"', implode('', $missingtables), TRUE);
  797.                 }

  798.                 if($settingsdellist) {
  799.                         $showlist .= "<tr class="partition"><td colspan="3">$lang[dbcheck_setting]</td></tr>";
  800.                         $showlist .= '<tr><td colspan="3">';
  801.                         $showlist .= "<input name="setting[del]" class="checkbox" type="checkbox" value="1"> ".implode(', ', $settingsdellist).'<br />';
  802.                         $showlist .= '</td></tr>';
  803.                 }

  804.                 if($showlist) {
  805.                         $showlist .= '<tr><td colspan="3"><input class="btn" type="submit" value="'.$lang['dbcheck_repair'].'" name="repairsubmit"></td></tr>';
  806.                 }

  807.                 if($charseterror) {
  808.                         $showlist .= "<tr><td class="partition" colspan="3">$lang[dbcheck_charseterror_tables] ($lang[dbcheck_charseterror_notice] $dbcharset)</td></tr>";
  809.                         $showlist .= '<tr><td colspan="3">'.implode('', $charseterror).'</td></tr>';
  810.                 }

  811.                 if($addlists) {
  812.                         $showlist .= '<tr><td class="partition" colspan="3">'.$lang['dbcheck_userfields'].'</td></tr>'.$addlists;
  813.                 }

  814.         }

  815.         shownav('founder', 'nav_db', 'nav_db_dbcheck');
  816.         showsubmenu('nav_db', array(
  817.                 array('nav_db_export', 'db&operation=export', 0),
  818.                 array('nav_db_import', 'db&operation=import', 0),
  819.                 array('nav_db_runquery', 'db&operation=runquery', 0),
  820.                 array('nav_db_optimize', 'db&operation=optimize', 0),
  821.                 array('nav_db_dbcheck', 'db&operation=dbcheck', 1)
  822.         ));
  823.         showsubmenusteps('', array(
  824.                 array('nav_filecheck_confirm', $step == 1),
  825.                 array('nav_filecheck_verify', $step == 2),
  826.                 array('nav_filecheck_completed', $step == 3)
  827.         ));

  828.         if($step == 1) {
  829.                 cpmsg(cplang('dbcheck_tips_step1'), 'action=db&operation=dbcheck&step=2', 'button', '', FALSE);
  830.         } elseif($step == 2) {
  831.                 cpmsg(cplang('dbcheck_verifying'), "action=db&operation=dbcheck&step=3", 'loading', '', FALSE);
  832.         } elseif($step == 3) {
  833.                 showtips('dbcheck_tips');
  834.                 echo <<<EOT
  835. <script type="text/JavaScript">
  836.         function setrepaircheck(obj, form, table) {
  837.                 eval('var rem = /^' + table + '\\\\|.+?\\\\|modify$/;');
  838.                 eval('var rea = /^' + table + '\\\\|.+?\\\\|add$/;');
  839.                 for(var i = 0; i < form.elements.length; i++) {
  840.                         var e = form.elements[i];
  841.                         if(e.type == 'checkbox' && e.name == 'repair[]') {
  842.                                 if(rem.exec(e.value) != null) {
  843.                                         if(obj.checked) {
  844.                                                 e.checked = false;
  845.                                                 e.disabled = true;
  846.                                         } else {
  847.                                                 e.checked = false;
  848.                                                 e.disabled = false;

  849.                                         }
  850.                                 }
  851.                                 if(rea.exec(e.value) != null) {
  852.                                         if(obj.checked) {
  853.                                                 e.checked = true;
  854.                                                 e.disabled = false;
  855.                                         } else {
  856.                                                 e.checked = false;
  857.                                                 e.disabled = false;
  858.                                         }
  859.                                 }
  860.                         }
  861.                 }
  862.         }
  863. </script>
  864. EOT;
  865.                 showformheader('db&operation=dbcheck&step=3', 'fixpadding');
  866.                 showtableheader();
  867.                 echo $showlist;
  868.                 showtablefooter();
  869.                 showformfooter();

  870.         }

  871. }

  872. function createtable($sql, $dbcharset) {
  873.         $type = strtoupper(preg_replace("/^\s*CREATE TABLE\s+.+\s+\(.+?\).*(ENGINE|TYPE)\s*=\s*([a-z]+?).*$/isU", "\\2", $sql));
  874.         $type = in_array($type, array('MYISAM', 'HEAP')) ? $type : 'MYISAM';
  875.         return preg_replace("/^\s*(CREATE TABLE\s+.+\s+\(.+?\)).*$/isU", "\\1", $sql).
  876.                 (mysql_get_server_info() > '4.1' ? " ENGINE=$type DEFAULT CHARSET=$dbcharset" : " TYPE=$type");
  877. }

  878. function fetchtablelist($tablepre = '') {
  879.         global $db;
  880.         $arr = explode('.', $tablepre);
  881.         $dbname = $arr[1] ? $arr[0] : '';
  882.         $tablepre = str_replace('_', '\_', $tablepre);
  883.         $sqladd = $dbname ? " FROM $dbname LIKE '$arr[1]%'" : "LIKE '$tablepre%'";
  884.         $tables = $table = array();
  885.         $query = DB::query("SHOW TABLE STATUS $sqladd");
  886.         while($table = DB::fetch($query)) {
  887.                 $table['Name'] = ($dbname ? "$dbname." : '').$table['Name'];
  888.                 $tables[] = $table;
  889.         }
  890.         return $tables;
  891. }

  892. function arraykeys2($array, $key2) {
  893.         $return = array();
  894.         foreach($array as $val) {
  895.                 $return[] = $val[$key2];
  896.         }
  897.         return $return;
  898. }


  899. function syntablestruct($sql, $version, $dbcharset) {

  900.         if(strpos(trim(substr($sql, 0, 18)), 'CREATE TABLE') === FALSE) {
  901.                 return $sql;
  902.         }

  903.         $sqlversion = strpos($sql, 'ENGINE=') === FALSE ? FALSE : TRUE;

  904.         if($sqlversion === $version) {

  905.                 return $sqlversion && $dbcharset ? preg_replace(array('/ character set \w+/i', '/ collate \w+/i', "/DEFAULT CHARSET=\w+/is"), array('', '', "DEFAULT CHARSET=$dbcharset"), $sql) : $sql;
  906.         }

  907.         if($version) {
  908.                 return preg_replace(array('/TYPE=HEAP/i', '/TYPE=(\w+)/is'), array("ENGINE=MEMORY DEFAULT CHARSET=$dbcharset", "ENGINE=\\1 DEFAULT CHARSET=$dbcharset"), $sql);

  909.         } else {
  910.                 return preg_replace(array('/character set \w+/i', '/collate \w+/i', '/ENGINE=MEMORY/i', '/\s*DEFAULT CHARSET=\w+/is', '/\s*COLLATE=\w+/is', '/ENGINE=(\w+)(.*)/is'), array('', '', 'ENGINE=HEAP', '', '', 'TYPE=\\1\\2'), $sql);
  911.         }
  912. }

  913. function sqldumptablestruct($table) {
  914.         global $_G, $db, $excepttables;

  915.         if(in_array($table, $excepttables)) {
  916.                 return;
  917.         }

  918.         $createtable = DB::query("SHOW CREATE TABLE $table", 'SILENT');

  919.         if(!DB::error()) {
  920.                 $tabledump = "DROP TABLE IF EXISTS $table;\n";
  921.         } else {
  922.                 return '';
  923.         }

  924.         $create = $db->fetch_row($createtable);

  925.         if(strpos($table, '.') !== FALSE) {
  926.                 $tablename = substr($table, strpos($table, '.') + 1);
  927.                 $create[1] = str_replace("CREATE TABLE $tablename", 'CREATE TABLE '.$table, $create[1]);
  928.         }
  929.         $tabledump .= $create[1];

  930.         if($_GET['sqlcompat'] == 'MYSQL41' && $db->version() < '4.1') {
  931.                 $tabledump = preg_replace("/TYPE\=(.+)/", "ENGINE=\\1 DEFAULT CHARSET=".$dumpcharset, $tabledump);
  932.         }
  933.         if($db->version() > '4.1' && $_GET['sqlcharset']) {
  934.                 $tabledump = preg_replace("/(DEFAULT)*\s*CHARSET=.+/", "DEFAULT CHARSET=".$_GET['sqlcharset'], $tabledump);
  935.         }

  936.         $tablestatus = DB::fetch_first("SHOW TABLE STATUS LIKE '$table'");
  937.         $tabledump .= ($tablestatus['Auto_increment'] ? " AUTO_INCREMENT=$tablestatus[Auto_increment]" : '').";\n\n";
  938.         if($_GET['sqlcompat'] == 'MYSQL40' && $db->version() >= '4.1' && $db->version() < '5.1') {
  939.                 if($tablestatus['Auto_increment'] <> '') {
  940.                         $temppos = strpos($tabledump, ',');
  941.                         $tabledump = substr($tabledump, 0, $temppos).' auto_increment'.substr($tabledump, $temppos);
  942.                 }
  943.                 if($tablestatus['Engine'] == 'MEMORY') {
  944.                         $tabledump = str_replace('TYPE=MEMORY', 'TYPE=HEAP', $tabledump);
  945.                 }
  946.         }
  947.         return $tabledump;
  948. }

  949. function sqldumptable($table, $startfrom = 0, $currsize = 0) {
  950.         global $_G, $db, $startrow, $dumpcharset, $complete, $excepttables;

  951.         $offset = 300;
  952.         $tabledump = '';
  953.         $tablefields = array();

  954.         $query = DB::query("SHOW FULL COLUMNS FROM $table", 'SILENT');
  955.         if(strexists($table, 'adminsessions')) {
  956.                 return ;
  957.         } elseif(!$query && DB::errno() == 1146) {
  958.                 return;
  959.         } elseif(!$query) {
  960.                 $_GET['usehex'] = FALSE;
  961.         } else {
  962.                 while($fieldrow = DB::fetch($query)) {
  963.                         $tablefields[] = $fieldrow;
  964.                 }
  965.         }

  966.         if(!in_array($table, $excepttables)) {
  967.                 $tabledumped = 0;
  968.                 $numrows = $offset;
  969.                 $firstfield = $tablefields[0];

  970.                 if($_GET['extendins'] == '0') {
  971.                         while($currsize + strlen($tabledump) + 500 < $_GET['sizelimit'] * 1000 && $numrows == $offset) {
  972.                                 if($firstfield['Extra'] == 'auto_increment') {
  973.                                         $selectsql = "SELECT * FROM $table WHERE $firstfield[Field] > $startfrom ORDER BY $firstfield[Field] LIMIT $offset";
  974.                                 } else {
  975.                                         $selectsql = "SELECT * FROM $table LIMIT $startfrom, $offset";
  976.                                 }
  977.                                 $tabledumped = 1;
  978.                                 $rows = DB::query($selectsql);
  979.                                 $numfields = $db->num_fields($rows);

  980.                                 $numrows = DB::num_rows($rows);
  981.                                 while($row = $db->fetch_row($rows)) {
  982.                                         $comma = $t = '';
  983.                                         for($i = 0; $i < $numfields; $i++) {
  984.                                                 $t .= $comma.($_GET['usehex'] && !empty($row[$i]) && (strexists($tablefields[$i]['Type'], 'char') || strexists($tablefields[$i]['Type'], 'text')) ? '0x'.bin2hex($row[$i]) : '\''.mysql_escape_string($row[$i]).'\'');
  985.                                                 $comma = ',';
  986.                                         }
  987.                                         if(strlen($t) + $currsize + strlen($tabledump) + 500 < $_GET['sizelimit'] * 1000) {
  988.                                                 if($firstfield['Extra'] == 'auto_increment') {
  989.                                                         $startfrom = $row[0];
  990.                                                 } else {
  991.                                                         $startfrom++;
  992.                                                 }
  993.                                                 $tabledump .= "INSERT INTO $table VALUES ($t);\n";
  994.                                         } else {
  995.                                                 $complete = FALSE;
  996.                                                 break 2;
  997.                                         }
  998.                                 }
  999.                         }
  1000.                 } else {
  1001.                         while($currsize + strlen($tabledump) + 500 < $_GET['sizelimit'] * 1000 && $numrows == $offset) {
  1002.                                 if($firstfield['Extra'] == 'auto_increment') {
  1003.                                         $selectsql = "SELECT * FROM $table WHERE $firstfield[Field] > $startfrom LIMIT $offset";
  1004.                                 } else {
  1005.                                         $selectsql = "SELECT * FROM $table LIMIT $startfrom, $offset";
  1006.                                 }
  1007.                                 $tabledumped = 1;
  1008.                                 $rows = DB::query($selectsql);
  1009.                                 $numfields = $db->num_fields($rows);

  1010.                                 if($numrows = DB::num_rows($rows)) {
  1011.                                         $t1 = $comma1 = '';
  1012.                                         while($row = $db->fetch_row($rows)) {
  1013.                                                 $t2 = $comma2 = '';
  1014.                                                 for($i = 0; $i < $numfields; $i++) {
  1015.                                                         $t2 .= $comma2.($_GET['usehex'] && !empty($row[$i]) && (strexists($tablefields[$i]['Type'], 'char') || strexists($tablefields[$i]['Type'], 'text'))? '0x'.bin2hex($row[$i]) : '\''.mysql_escape_string($row[$i]).'\'');
  1016.                                                         $comma2 = ',';
  1017.                                                 }
  1018.                                                 if(strlen($t1) + $currsize + strlen($tabledump) + 500 < $_GET['sizelimit'] * 1000) {
  1019.                                                         if($firstfield['Extra'] == 'auto_increment') {
  1020.                                                                 $startfrom = $row[0];
  1021.                                                         } else {
  1022.                                                                 $startfrom++;
  1023.                                                         }
  1024.                                                         $t1 .= "$comma1 ($t2)";
  1025.                                                         $comma1 = ',';
  1026.                                                 } else {
  1027.                                                         $tabledump .= "INSERT INTO $table VALUES $t1;\n";
  1028.                                                         $complete = FALSE;
  1029.                                                         break 2;
  1030.                                                 }
  1031.                                         }
  1032.                                         $tabledump .= "INSERT INTO $table VALUES $t1;\n";
  1033.                                 }
  1034.                         }
  1035.                 }

  1036.                 $startrow = $startfrom;
  1037.                 $tabledump .= "\n";
  1038.         }

  1039.         return $tabledump;
  1040. }

  1041. function splitsql($sql) {
  1042.         $sql = str_replace("\r", "\n", $sql);
  1043.         $ret = array();
  1044.         $num = 0;
  1045.         $queriesarray = explode(";\n", trim($sql));
  1046.         unset($sql);
  1047.         foreach($queriesarray as $query) {
  1048.                 $queries = explode("\n", trim($query));
  1049.                 foreach($queries as $query) {
  1050.                         $ret[$num] .= $query[0] == "#" ? NULL : $query;
  1051.                 }
  1052.                 $num++;
  1053.         }
  1054.         return($ret);
  1055. }

  1056. function slowcheck($type1, $type2) {
  1057.         $t1 = explode(' ', $type1);$t1 = $t1[0];
  1058.         $t2 = explode(' ', $type2);$t2 = $t2[0];
  1059.         $arr = array($t1, $t2);
  1060.         sort($arr);
  1061.         if($arr == array('mediumtext', 'text')) {
  1062.                 return TRUE;
  1063.         } elseif(substr($arr[0], 0, 4) == 'char' && substr($arr[1], 0, 7) == 'varchar') {
  1064.                 return TRUE;
  1065.         }
  1066.         return FALSE;
  1067. }

  1068. ?>
复制代码


民审大大 发表于 2018-9-3 10:06:20 | 显示全部楼层
这个代码将
  1. $_SERVER['REQUEST_METHOD'] = 'POST';
  2. if(!submitcheck('exportsubmit')) {
复制代码
改为了
  1. if(!submitcheck('exportsubmit', 1)) {
复制代码
导致formhash验证被越过,并没有起到什么修复作用,反而造成了隐患
回复

使用道具 举报

蓝色经典 发表于 2018-9-3 10:15:37 | 显示全部楼层
你的DZ 不是最新版本的,新版本早已经解决了这个问题。建议去git 上,下载最新的代码。
阿里云的判断比较简单。修复的方法也很粗糙


/**
*      [Discuz!] (C)2001-2099 Comsenz Inc.
*      This is NOT a freeware, use is subject to license terms
*
*      $Id: admincp_db.php 34644 2014-06-16 09:07:08Z hypowang $
*/

最新的是 2014 年6月的版本
回复

使用道具 举报

ytzjm 发表于 2018-9-3 11:13:04 | 显示全部楼层
蓝色经典 发表于 2018-9-3 10:15
你的DZ 不是最新版本的,新版本早已经解决了这个问题。建议去git 上,下载最新的代码。
阿里云的判断比较 ...

我的:
<?php

/**
*      [Discuz!] (C)2001-2099 Comsenz Inc.
*      This is NOT a freeware, use is subject to license terms
*
*      $Id: admincp_db.php 34644 2014-06-16 09:07:08Z hypowang $
*/
是2014年的也被阿里云检测出了漏洞?!
回复

使用道具 举报

crx349 发表于 2018-9-3 12:16:04 | 显示全部楼层
本帖最后由 crx349 于 2018-9-3 12:56 编辑

同民审观点 改那个更容易绕过
  1. public static function submitcheck($var, $allowget = 0, $seccodecheck = 0, $secqaacheck = 0) {
  2.                 if(!getgpc($var)) {
  3.                         return FALSE;
  4.                 } else {
  5.                         global $_G;
  6.                         if($allowget || ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_GET['formhash']) && $_GET['formhash'] == formhash() && empty($_SERVER['HTTP_X_FLASH_VERSION']) && (empty($_SERVER['HTTP_REFERER']) ||
  7.                                 strncmp($_SERVER['HTTP_REFERER'], 'http://wsq.discuz.com/', 22) === 0 || preg_replace("/https?:\/\/([^\:\/]+).*/i", "\\1", $_SERVER['HTTP_REFERER']) == preg_replace("/([^\:]+).*/", "\\1", $_SERVER['HTTP_HOST'])))) {
  8.                                 if(checkperm('seccode')) {
  9.                                         if($secqaacheck && !check_secqaa($_GET['secanswer'], $_GET['secqaahash'])) {
  10.                                                 showmessage('submit_secqaa_invalid');
  11.                                         }
  12.                                         if($seccodecheck && !check_seccode($_GET['seccodeverify'], $_GET['seccodehash'], 0, $_GET['seccodemodid'])) {
  13.                                                 showmessage('submit_seccode_invalid');
  14.                                         }
  15.                                 }
  16.                                 return TRUE;
  17.                         } else {
  18.                                 showmessage('submit_invalid');
  19.                         }
  20.                 }
  21.         }
复制代码
如果是 submitcheck('exportsubmit', 1)
$_GET['formhash']  直接被绕过了

回复

使用道具 举报

 楼主| amo123 发表于 2018-9-3 13:58:10 | 显示全部楼层
民审大大 发表于 2018-9-3 10:06
这个代码将
改为了导致formhash验证被越过,并没有起到什么修复作用,反而造成了隐患

那你倒是给个官方的修复方法啊
回复

使用道具 举报

xiaoyuwxz 发表于 2018-9-3 14:18:44 | 显示全部楼层
本帖最后由 xiaoyuwxz 于 2018-9-3 14:27 编辑

一楼的是什么版本的,很老的文件,阿里上,3.4不是这样改的
https://www.anquanke.com/post/id/158270
回复

使用道具 举报

wanw 发表于 2018-9-4 14:02:10 | 显示全部楼层
这个bug 官方怎么没有做回应呢????
回复

使用道具 举报

巴中网 发表于 2018-9-4 14:17:56 | 显示全部楼层
菜鸟站长还是寄往官方更新修复安全bug
回复

使用道具 举报

wanw 发表于 2018-9-5 08:57:56 | 显示全部楼层
官方有回应了吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|Discuz! 官方站 ( 皖ICP备16010102号 )star

GMT+8, 2024-11-23 18:25 , Processed in 0.034039 second(s), 5 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表