db.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <?php
  2. /*
  3. [UCenter] (C)2001-2099 Comsenz Inc.
  4. This is NOT a freeware, use is subject to license terms
  5. $Id: db.php 35059 2014-11-03 08:54:20Z hypowang $
  6. */
  7. !defined('IN_UC') && exit('Access Denied');
  8. class control extends adminbase {
  9. var $startrow = 0;
  10. var $sizelimit = 0;
  11. var $complete = TRUE;
  12. function __construct() {
  13. $this->control();
  14. }
  15. function control() {
  16. parent::__construct();
  17. $this->check_priv();
  18. if(!$this->user['isfounder'] && !$this->user['allowadmindb']) {
  19. $this->message('no_permission_for_this_module');
  20. }
  21. $this->check_priv();
  22. $this->load('misc');
  23. }
  24. function onls() {
  25. $status = 0;
  26. $operate = getgpc('o');
  27. if($operate == 'list') {
  28. if($delete = $_POST['delete']) {
  29. if(is_array($delete)) {
  30. foreach($delete AS $filename) {
  31. @unlink('./data/backup/'.str_replace(array('/', '\\'), '', $filename));
  32. }
  33. }
  34. $status = 2;
  35. $this->writelog('db_delete', "delete=".implode(',', $_POST['delete']));
  36. }
  37. $baklist = array();
  38. if(is_dir(UC_ROOT.'./data/backup/')) {
  39. $dir = dir(UC_ROOT.'./data/backup/');
  40. while($entry = $dir->read()) {
  41. $file = './data/backup/'.$entry;
  42. if(is_dir($file) && preg_match("/backup_(\d+)_\w+/i", $file, $match)) {
  43. $baklist[] = array('name' => $match[0], 'date' => $match[1]);
  44. }
  45. }
  46. $dir->close();
  47. } else {
  48. cpmsg('db_export_dest_invalid');
  49. }
  50. $this->view->assign('baklist', $baklist);
  51. } elseif($operate == 'view') {
  52. $dir = getgpc('dir');
  53. $this->load('app');
  54. $applist = $_ENV['app']->get_apps();
  55. $this->view->assign('applist', $applist);
  56. $this->view->assign('dir', $dir);
  57. } elseif($operate == 'ping') {
  58. $appid = intval(getgpc('appid'));
  59. $app = $this->cache['apps'][$appid];
  60. $dir = trim(getgpc('dir'));
  61. if($app['type'] == 'DISCUZX') {
  62. $url = $app['url'].'/api/db/dbbak.php?apptype='.$app['type'];
  63. } else {
  64. $url = $app['url'].'/api/dbbak.php?apptype='.$app['type'];
  65. }
  66. $code = $this->authcode('&method=ping&dir='.$dir.'&time='.time(), 'ENCODE', $app['authkey']);
  67. $url .= '&code='.urlencode($code);
  68. $res = $_ENV['misc']->dfopen2($url, 0, '', '', 1, $app['ip'], 20, TRUE);
  69. if($res == '1') {
  70. $this->message($this->_parent_js($appid, '<img src="images/correct.gif" border="0" class="statimg" /><span class="green">'.$this->lang['dumpfile_exists'].'</span>').'<script>parent.import_status['.$appid.']=true;</script>');
  71. } else {
  72. $this->message($this->_parent_js($appid, '<img src="images/error.gif" border="0" class="statimg" /><span class="red">'.$this->lang['dumpfile_not_exists'].'</span>').'<script>parent.import_status['.$appid.']=false;</script>');
  73. }
  74. exit;
  75. } else {
  76. $this->load('app');
  77. $applist = $_ENV['app']->get_apps();
  78. $this->view->assign('applist', $applist);
  79. $this->view->assign('dir', 'backup_'.date('ymd', time()).'_'.$this->random(6));
  80. }
  81. $this->view->assign('operate', $operate);
  82. $this->view->display('admin_db');
  83. }
  84. function onoperate() {
  85. require_once UC_ROOT.'lib/xml.class.php';
  86. $nexturl = getgpc('nexturl');
  87. $appid = intval(getgpc('appid'));
  88. $type = getgpc('t') == 'import' ? 'import' : 'export';
  89. $backupdir = getgpc('backupdir');
  90. $app = $this->cache['apps'][$appid];
  91. if($nexturl) {
  92. $url = $nexturl;
  93. } else {
  94. if($appid) {
  95. if(!isset($this->cache['apps'][$appid])) {
  96. $this->message($this->_parent_js($appid, 'appid_invalid'));
  97. }
  98. if($app['type'] == 'DISCUZX') {
  99. $url = $app['url'].'/api/db/dbbak.php?apptype='.$app['type'];
  100. } else {
  101. $url = $app['url'].'/api/dbbak.php?apptype='.$app['type'];
  102. }
  103. $code = $this->authcode('&method='.$type.'&sqlpath='.$backupdir.'&time='.time(), 'ENCODE', $app['authkey']);
  104. } else {
  105. $url = 'http://'.$_SERVER['HTTP_HOST'].str_replace('admin.php', 'api/dbbak.php', $_SERVER['PHP_SELF']).'?apptype=UCENTER';
  106. $code = $this->authcode('&method='.$type.'&sqlpath='.$backupdir.'&time='.time(), 'ENCODE', UC_KEY);
  107. }
  108. $url .= '&code='.urlencode($code);
  109. }
  110. if(empty($appid)) {
  111. $app['ip'] = defined('UC_IP') ? UC_IP : '';
  112. }
  113. $res = $_ENV['misc']->dfopen2($url, 0, '', '', 1, $app['ip'], 20, TRUE);
  114. if(empty($res)) {
  115. $this->message($this->_parent_js($appid, 'db_back_api_url_invalid'));
  116. }
  117. $arr = $this->_xml2array($res);
  118. if(empty($arr['fileinfo'])) {
  119. $this->message($this->_parent_js($appid, 'undefine_error'));
  120. } elseif($arr['error']['errorcode']) {
  121. $this->message($this->_parent_js($appid, 'dbback_error_code_'.$arr['error']['errorcode']));
  122. } elseif($arr['nexturl']) {
  123. $this->message($this->_parent_js($appid, 'db_'.$type.'_multivol_redirect', array('$volume' => $arr['fileinfo']['file_num'])), 'admin.php?m=db&a=operate&t='.$type.'&appid='.$appid.'&nexturl='.urlencode($arr['nexturl']));
  124. } elseif(empty($arr['nexturl'])) {
  125. $this->message($this->_parent_js($appid, 'db_'.$type.'_multivol_succeed'));
  126. } else {
  127. $this->message($this->_parent_js($appid, 'undefine_error'));
  128. }
  129. exit;
  130. }
  131. function ondelete() {
  132. require_once UC_ROOT.'lib/xml.class.php';
  133. $appid = intval(getgpc('appid'));
  134. $backupdir = getgpc('backupdir');
  135. $app = $this->cache['apps'][$appid];
  136. if(empty($appid)) {
  137. $app['ip'] = defined('UC_IP') ? UC_IP : '';
  138. $url = 'http://'.$_SERVER['HTTP_HOST'].str_replace('admin.php', 'api/dbbak.php', $_SERVER['PHP_SELF']).'?apptype=UCENTER';
  139. $code = $this->authcode('&method=delete&sqlpath='.$backupdir.'&time='.time(), 'ENCODE', UC_KEY);
  140. $appname = 'UCenter';
  141. } else {
  142. if(!isset($this->cache['apps'][$appid])) {
  143. $this->message($this->_parent_js($appid, 'appid_invalid'));
  144. }
  145. $url = $app['url'].'/api/dbbak.php?apptype='.$app['type'];
  146. $code = $this->authcode('&method=delete&sqlpath='.$backupdir.'&time='.time(), 'ENCODE', $app['authkey']);
  147. $appname = $app['name'];
  148. }
  149. $url .= '&code='.urlencode($code);
  150. $res = $_ENV['misc']->dfopen2($url, 0, '', '', 1, $app['ip'], 20, TRUE);
  151. $next_appid = $this->_next_appid($appid);
  152. if($next_appid != $appid) {
  153. $this->message($this->_parent_js($backupdir, 'delete_dumpfile_redirect', array('$appname' => $appname)), 'admin.php?m=db&a=delete&appid='.$next_appid.'&backupdir='.$backupdir.'&sid='.$this->sid);
  154. } else {
  155. $this->message($this->_parent_js($backupdir, 'delete_dumpfile_success'));
  156. }
  157. }
  158. function _next_appid($appid) {
  159. $last_appid = 0;
  160. foreach($this->cache['apps'] as $key => $val) {
  161. if($appid == $last_appid) {
  162. return $key;
  163. }
  164. $last_appid = $key;
  165. }
  166. return $last_appid;
  167. }
  168. function _parent_js($extid, $message, $vars = array()) {
  169. include UC_ROOT.'view/default/messages.lang.php';
  170. if(isset($lang[$message])) {
  171. $message = $lang[$message] ? str_replace(array_keys($vars), array_values($vars), $lang[$message]) : $message;
  172. }
  173. return '<script type="text/javascript">parent.show_status(\''.$extid.'\', \''.$message.'\');</script>';
  174. }
  175. function _xml2array($xml) {
  176. $arr = xml_unserialize($xml, 1);
  177. preg_match('/<error errorCode="(\d+)" errorMessage="([^\/]+)" \/>/', $xml, $match);
  178. $arr['error'] = array('errorcode' => $match[1], 'errormessage' => $match[2]);
  179. return $arr;
  180. }
  181. function random($length, $numeric = 0) {
  182. PHP_VERSION < '4.2.0' && mt_srand((double)microtime() * 1000000);
  183. if($numeric) {
  184. $hash = sprintf('%0'.$length.'d', mt_rand(0, pow(10, $length) - 1));
  185. } else {
  186. $hash = '';
  187. $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
  188. $max = strlen($chars) - 1;
  189. for($i = 0; $i < $length; $i++) {
  190. $hash .= $chars[mt_rand(0, $max)];
  191. }
  192. }
  193. return $hash;
  194. }
  195. function sqldumptable($table, $startfrom = 0, $currsize = 0) {
  196. $offset = 300;
  197. $tabledump = '';
  198. $usehex = TRUE;
  199. $tablefields = array();
  200. $query = $this->db->query("SHOW FULL COLUMNS FROM $table", 'SILENT');
  201. if(!$query && $this->db->errno() == 1146) {
  202. return;
  203. } elseif(!$query) {
  204. $usehex = FALSE;
  205. } else {
  206. while($fieldrow = $this->db->fetch_array($query)) {
  207. $tablefields[] = $fieldrow;
  208. }
  209. }
  210. if(!$startfrom) {
  211. $createtable = $this->db->query("SHOW CREATE TABLE $table", 'SILENT');
  212. if(!$this->db->error()) {
  213. $tabledump = "DROP TABLE IF EXISTS $table;\n";
  214. } else {
  215. return '';
  216. }
  217. $create = $this->db->fetch_row($createtable);
  218. $tabledump .= $create[1];
  219. $tablestatus = $this->db->fetch_first("SHOW TABLE STATUS LIKE '$table'");
  220. $tabledump .= ($tablestatus['Auto_increment'] && strpos($create[1], 'AUTO_INCREMENT') === FALSE ? " AUTO_INCREMENT=$tablestatus[Auto_increment]" : '').";\n\n";
  221. }
  222. $tabledumped = 0;
  223. $numrows = $offset;
  224. $firstfield = $tablefields[0];
  225. while($currsize + strlen($tabledump) + 500 < $this->sizelimit * 1000 && $numrows == $offset) {
  226. if($firstfield['Extra'] == 'auto_increment') {
  227. $selectsql = "SELECT * FROM $table WHERE $firstfield[Field] > $startfrom LIMIT $offset";
  228. } else {
  229. $selectsql = "SELECT * FROM $table LIMIT $startfrom, $offset";
  230. }
  231. $tabledumped = 1;
  232. $rows = $this->db->query($selectsql);
  233. $numfields = $this->db->num_fields($rows);
  234. $numrows = $this->db->num_rows($rows);
  235. while($row = $this->db->fetch_row($rows)) {
  236. $comma = $t = '';
  237. for($i = 0; $i < $numfields; $i++) {
  238. $t .= $comma.($usehex && !empty($row[$i]) && (strpos($tablefields[$i]['Type'], 'char') !== FALSE || strpos($tablefields[$i]['Type'], 'text') !== FALSE) ? '0x'.bin2hex($row[$i]) : '\''.$this->db->escape_string($row[$i]).'\'');
  239. $comma = ',';
  240. }
  241. if(strlen($t) + $currsize + strlen($tabledump) + 500 < $this->sizelimit * 1000) {
  242. if($firstfield['Extra'] == 'auto_increment') {
  243. $startfrom = $row[0];
  244. } else {
  245. $startfrom++;
  246. }
  247. $tabledump .= "INSERT INTO $table VALUES ($t);\n";
  248. } else {
  249. $this->complete = FALSE;
  250. break 2;
  251. }
  252. }
  253. }
  254. $this->startrow = $startfrom;
  255. $tabledump .= "\n";
  256. return $tabledump;
  257. }
  258. function splitsql($sql) {
  259. $sql = str_replace("\r", "\n", $sql);
  260. $ret = array();
  261. $num = 0;
  262. $queriesarray = explode(";\n", trim($sql));
  263. unset($sql);
  264. foreach($queriesarray as $query) {
  265. $queries = explode("\n", trim($query));
  266. foreach($queries as $query) {
  267. $ret[$num] .= $query[0] == "#" ? NULL : $query;
  268. }
  269. $num++;
  270. }
  271. return($ret);
  272. }
  273. function syntablestruct($sql, $version, $dbcharset) {
  274. if(strpos(trim(substr($sql, 0, 18)), 'CREATE TABLE') === FALSE) {
  275. return $sql;
  276. }
  277. $sqlversion = strpos($sql, 'ENGINE=') === FALSE ? FALSE : TRUE;
  278. if($sqlversion === $version) {
  279. return $sqlversion && $dbcharset ? preg_replace(array('/ character set \w+/i', '/ collate \w+/i', "/DEFAULT CHARSET=\w+/is"), array('', '', "DEFAULT CHARSET=$dbcharset"), $sql) : $sql;
  280. }
  281. if($version) {
  282. return preg_replace(array('/TYPE=HEAP/i', '/TYPE=(\w+)/is'), array("ENGINE=MEMORY DEFAULT CHARSET=$dbcharset", "ENGINE=\\1 DEFAULT CHARSET=$dbcharset"), $sql);
  283. } else {
  284. 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);
  285. }
  286. }
  287. function sizecount($filesize) {
  288. if($filesize >= 1073741824) {
  289. $filesize = round($filesize / 1073741824 * 100) / 100 . ' GB';
  290. } elseif($filesize >= 1048576) {
  291. $filesize = round($filesize / 1048576 * 100) / 100 . ' MB';
  292. } elseif($filesize >= 1024) {
  293. $filesize = round($filesize / 1024 * 100) / 100 . ' KB';
  294. } else {
  295. $filesize = $filesize . ' Bytes';
  296. }
  297. return $filesize;
  298. }
  299. }
  300. ?>