ExportXml.class.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Set of functions used to build XML dumps of tables
  5. *
  6. * @package PhpMyAdmin-Export
  7. * @subpackage XML
  8. */
  9. if (! defined('PHPMYADMIN')) {
  10. exit;
  11. }
  12. if (! strlen($GLOBALS['db'])) { /* Can't do server export */
  13. $GLOBALS['skip_import'] = true;
  14. return;
  15. }
  16. /* Get the export interface */
  17. require_once 'libraries/plugins/ExportPlugin.class.php';
  18. /**
  19. * Handles the export for the XML class
  20. *
  21. * @package PhpMyAdmin-Export
  22. * @subpackage XML
  23. */
  24. class ExportXml extends ExportPlugin
  25. {
  26. /**
  27. * Table name
  28. *
  29. * @var string
  30. */
  31. private $_table;
  32. /**
  33. * Table names
  34. *
  35. * @var array
  36. */
  37. private $_tables;
  38. /**
  39. * Constructor
  40. */
  41. public function __construct()
  42. {
  43. $this->setProperties();
  44. }
  45. /**
  46. * Initialize the local variables that are used for export PDF
  47. *
  48. * @return void
  49. */
  50. protected function initSpecificVariables()
  51. {
  52. global $table, $tables;
  53. $this->_setTable($table);
  54. $this->_setTables($tables);
  55. }
  56. /**
  57. * Sets the export XML properties
  58. *
  59. * @return void
  60. */
  61. protected function setProperties()
  62. {
  63. $props = 'libraries/properties/';
  64. include_once "$props/plugins/ExportPluginProperties.class.php";
  65. include_once "$props/options/groups/OptionsPropertyRootGroup.class.php";
  66. include_once "$props/options/groups/OptionsPropertyMainGroup.class.php";
  67. include_once "$props/options/items/HiddenPropertyItem.class.php";
  68. include_once "$props/options/items/BoolPropertyItem.class.php";
  69. // create the export plugin property item
  70. $exportPluginProperties = new ExportPluginProperties();
  71. $exportPluginProperties->setText('XML');
  72. $exportPluginProperties->setExtension('xml');
  73. $exportPluginProperties->setMimeType('text/xml');
  74. $exportPluginProperties->setOptionsText(__('Options'));
  75. // create the root group that will be the options field for
  76. // $exportPluginProperties
  77. // this will be shown as "Format specific options"
  78. $exportSpecificOptions = new OptionsPropertyRootGroup();
  79. $exportSpecificOptions->setName("Format Specific Options");
  80. // general options main group
  81. $generalOptions = new OptionsPropertyMainGroup();
  82. $generalOptions->setName("general_opts");
  83. // create primary items and add them to the group
  84. $leaf = new HiddenPropertyItem();
  85. $leaf->setName("structure_or_data");
  86. $generalOptions->addProperty($leaf);
  87. // add the main group to the root group
  88. $exportSpecificOptions->addProperty($generalOptions);
  89. // export structure main group
  90. $structure = new OptionsPropertyMainGroup();
  91. $structure->setName("structure");
  92. $structure->setText(__('Object creation options (all are recommended)'));
  93. // create primary items and add them to the group
  94. if (! PMA_DRIZZLE) {
  95. $leaf = new BoolPropertyItem();
  96. $leaf->setName("export_functions");
  97. $leaf->setText(__('Functions'));
  98. $structure->addProperty($leaf);
  99. $leaf = new BoolPropertyItem();
  100. $leaf->setName("export_procedures");
  101. $leaf->setText(__('Procedures'));
  102. $structure->addProperty($leaf);
  103. }
  104. $leaf = new BoolPropertyItem();
  105. $leaf->setName("export_tables");
  106. $leaf->setText(__('Tables'));
  107. $structure->addProperty($leaf);
  108. if (! PMA_DRIZZLE) {
  109. $leaf = new BoolPropertyItem();
  110. $leaf->setName("export_triggers");
  111. $leaf->setText(__('Triggers'));
  112. $structure->addProperty($leaf);
  113. $leaf = new BoolPropertyItem();
  114. $leaf->setName("export_views");
  115. $leaf->setText(__('Views'));
  116. $structure->addProperty($leaf);
  117. }
  118. $exportSpecificOptions->addProperty($structure);
  119. // data main group
  120. $data = new OptionsPropertyMainGroup();
  121. $data->setName("data");
  122. $data->setText(__('Data dump options'));
  123. // create primary items and add them to the group
  124. $leaf = new BoolPropertyItem();
  125. $leaf->setName("export_contents");
  126. $leaf->setText(__('Export contents'));
  127. $data->addProperty($leaf);
  128. $exportSpecificOptions->addProperty($data);
  129. // set the options for the export plugin property item
  130. $exportPluginProperties->setOptions($exportSpecificOptions);
  131. $this->properties = $exportPluginProperties;
  132. }
  133. /**
  134. * This method is called when any PluginManager to which the observer
  135. * is attached calls PluginManager::notify()
  136. *
  137. * @param SplSubject $subject The PluginManager notifying the observer
  138. * of an update.
  139. *
  140. * @return void
  141. */
  142. public function update (SplSubject $subject)
  143. {
  144. }
  145. /**
  146. * Outputs export header. It is the first method to be called, so all
  147. * the required variables are initialized here.
  148. *
  149. * @return bool Whether it succeeded
  150. */
  151. public function exportHeader ()
  152. {
  153. $this->initSpecificVariables();
  154. global $crlf, $cfg, $db;
  155. $table = $this->_getTable();
  156. $tables = $this->_getTables();
  157. $export_struct = isset($GLOBALS['xml_export_functions'])
  158. || isset($GLOBALS['xml_export_procedures'])
  159. || isset($GLOBALS['xml_export_tables'])
  160. || isset($GLOBALS['xml_export_triggers'])
  161. || isset($GLOBALS['xml_export_views']);
  162. $export_data = isset($GLOBALS['xml_export_contents']) ? true : false;
  163. if ($GLOBALS['output_charset_conversion']) {
  164. $charset = $GLOBALS['charset_of_file'];
  165. } else {
  166. $charset = 'utf-8';
  167. }
  168. $head = '<?xml version="1.0" encoding="' . $charset . '"?>' . $crlf
  169. . '<!--' . $crlf
  170. . '- phpMyAdmin XML Dump' . $crlf
  171. . '- version ' . PMA_VERSION . $crlf
  172. . '- https://www.phpmyadmin.net' . $crlf
  173. . '-' . $crlf
  174. . '- ' . __('Host') . ': ' . htmlspecialchars($cfg['Server']['host']);
  175. if (! empty($cfg['Server']['port'])) {
  176. $head .= ':' . $cfg['Server']['port'];
  177. }
  178. $head .= $crlf
  179. . '- ' . __('Generation Time') . ': '
  180. . PMA_Util::localisedDate() . $crlf
  181. . '- ' . __('Server version') . ': ' . PMA_MYSQL_STR_VERSION . $crlf
  182. . '- ' . __('PHP Version') . ': ' . phpversion() . $crlf
  183. . '-->' . $crlf . $crlf;
  184. $head .= '<pma_xml_export version="1.0"'
  185. . (($export_struct)
  186. ? ' xmlns:pma="https://www.phpmyadmin.net/some_doc_url/"'
  187. : '')
  188. . '>' . $crlf;
  189. if ($export_struct) {
  190. if (PMA_DRIZZLE) {
  191. $result = PMA_DBI_fetch_result(
  192. "SELECT
  193. 'utf8' AS DEFAULT_CHARACTER_SET_NAME,
  194. DEFAULT_COLLATION_NAME
  195. FROM data_dictionary.SCHEMAS
  196. WHERE SCHEMA_NAME = '"
  197. . PMA_Util::sqlAddSlashes($db) . "'"
  198. );
  199. } else {
  200. $result = PMA_DBI_fetch_result(
  201. 'SELECT `DEFAULT_CHARACTER_SET_NAME`, `DEFAULT_COLLATION_NAME`'
  202. . ' FROM `information_schema`.`SCHEMATA` WHERE `SCHEMA_NAME`'
  203. . ' = \''.PMA_Util::sqlAddSlashes($db).'\' LIMIT 1'
  204. );
  205. }
  206. $db_collation = $result[0]['DEFAULT_COLLATION_NAME'];
  207. $db_charset = $result[0]['DEFAULT_CHARACTER_SET_NAME'];
  208. $head .= ' <!--' . $crlf;
  209. $head .= ' - Structure schemas' . $crlf;
  210. $head .= ' -->' . $crlf;
  211. $head .= ' <pma:structure_schemas>' . $crlf;
  212. $head .= ' <pma:database name="' . htmlspecialchars($db)
  213. . '" collation="' . htmlspecialchars($db_collation) . '" charset="' . htmlspecialchars($db_charset)
  214. . '">' . $crlf;
  215. if (count($tables) == 0) {
  216. $tables[] = $table;
  217. }
  218. foreach ($tables as $table) {
  219. // Export tables and views
  220. $result = PMA_DBI_fetch_result(
  221. 'SHOW CREATE TABLE ' . PMA_Util::backquote($db) . '.'
  222. . PMA_Util::backquote($table),
  223. 0
  224. );
  225. $tbl = $result[$table][1];
  226. $is_view = PMA_Table::isView($db, $table);
  227. if ($is_view) {
  228. $type = 'view';
  229. } else {
  230. $type = 'table';
  231. }
  232. if ($is_view && ! isset($GLOBALS['xml_export_views'])) {
  233. continue;
  234. }
  235. if (! $is_view && ! isset($GLOBALS['xml_export_tables'])) {
  236. continue;
  237. }
  238. $head .= ' <pma:' . $type . ' name="' . htmlspecialchars($table) . '">'
  239. . $crlf;
  240. $tbl = " " . htmlspecialchars($tbl);
  241. $tbl = str_replace("\n", "\n ", $tbl);
  242. $head .= $tbl . ';' . $crlf;
  243. $head .= ' </pma:' . $type . '>' . $crlf;
  244. if (isset($GLOBALS['xml_export_triggers'])
  245. && $GLOBALS['xml_export_triggers']
  246. ) {
  247. // Export triggers
  248. $triggers = PMA_DBI_get_triggers($db, $table);
  249. if ($triggers) {
  250. foreach ($triggers as $trigger) {
  251. $code = $trigger['create'];
  252. $head .= ' <pma:trigger name="'
  253. . htmlspecialchars($trigger['name']) . '">' . $crlf;
  254. // Do some formatting
  255. $code = substr(rtrim($code), 0, -3);
  256. $code = " " . htmlspecialchars($code);
  257. $code = str_replace("\n", "\n ", $code);
  258. $head .= $code . $crlf;
  259. $head .= ' </pma:trigger>' . $crlf;
  260. }
  261. unset($trigger);
  262. unset($triggers);
  263. }
  264. }
  265. }
  266. if (isset($GLOBALS['xml_export_functions'])
  267. && $GLOBALS['xml_export_functions']
  268. ) {
  269. // Export functions
  270. $functions = PMA_DBI_get_procedures_or_functions($db, 'FUNCTION');
  271. if ($functions) {
  272. foreach ($functions as $function) {
  273. $head .= ' <pma:function name="'
  274. . htmlspecialchars($function) . '">' . $crlf;
  275. // Do some formatting
  276. $sql = PMA_DBI_get_definition($db, 'FUNCTION', $function);
  277. $sql = rtrim($sql);
  278. $sql = " " . htmlspecialchars($sql);
  279. $sql = str_replace("\n", "\n ", $sql);
  280. $head .= $sql . $crlf;
  281. $head .= ' </pma:function>' . $crlf;
  282. }
  283. unset($function);
  284. unset($functions);
  285. }
  286. }
  287. if (isset($GLOBALS['xml_export_procedures'])
  288. && $GLOBALS['xml_export_procedures']
  289. ) {
  290. // Export procedures
  291. $procedures = PMA_DBI_get_procedures_or_functions($db, 'PROCEDURE');
  292. if ($procedures) {
  293. foreach ($procedures as $procedure) {
  294. $head .= ' <pma:procedure name="'
  295. . htmlspecialchars($procedure) . '">' . $crlf;
  296. // Do some formatting
  297. $sql = PMA_DBI_get_definition($db, 'PROCEDURE', $procedure);
  298. $sql = rtrim($sql);
  299. $sql = " " . htmlspecialchars($sql);
  300. $sql = str_replace("\n", "\n ", $sql);
  301. $head .= $sql . $crlf;
  302. $head .= ' </pma:procedure>' . $crlf;
  303. }
  304. unset($procedure);
  305. unset($procedures);
  306. }
  307. }
  308. unset($result);
  309. $head .= ' </pma:database>' . $crlf;
  310. $head .= ' </pma:structure_schemas>' . $crlf;
  311. if ($export_data) {
  312. $head .= $crlf;
  313. }
  314. }
  315. return PMA_exportOutputHandler($head);
  316. }
  317. /**
  318. * Outputs export footer
  319. *
  320. * @return bool Whether it succeeded
  321. */
  322. public function exportFooter ()
  323. {
  324. $foot = '</pma_xml_export>';
  325. return PMA_exportOutputHandler($foot);
  326. }
  327. /**
  328. * Outputs database header
  329. *
  330. * @param string $db Database name
  331. *
  332. * @return bool Whether it succeeded
  333. */
  334. public function exportDBHeader ($db)
  335. {
  336. global $crlf;
  337. if (isset($GLOBALS['xml_export_contents'])
  338. && $GLOBALS['xml_export_contents']
  339. ) {
  340. $head = ' <!--' . $crlf
  341. . ' - ' . __('Database') . ': ' . '\'' . htmlspecialchars($db) . '\'' . $crlf
  342. . ' -->' . $crlf
  343. . ' <database name="' . htmlspecialchars($db) . '">' . $crlf;
  344. return PMA_exportOutputHandler($head);
  345. } else {
  346. return true;
  347. }
  348. }
  349. /**
  350. * Outputs database footer
  351. *
  352. * @param string $db Database name
  353. *
  354. * @return bool Whether it succeeded
  355. */
  356. public function exportDBFooter ($db)
  357. {
  358. global $crlf;
  359. if (isset($GLOBALS['xml_export_contents'])
  360. && $GLOBALS['xml_export_contents']
  361. ) {
  362. return PMA_exportOutputHandler(' </database>' . $crlf);
  363. } else {
  364. return true;
  365. }
  366. }
  367. /**
  368. * Outputs CREATE DATABASE statement
  369. *
  370. * @param string $db Database name
  371. *
  372. * @return bool Whether it succeeded
  373. */
  374. public function exportDBCreate($db)
  375. {
  376. return true;
  377. }
  378. /**
  379. * Outputs the content of a table in XML format
  380. *
  381. * @param string $db database name
  382. * @param string $table table name
  383. * @param string $crlf the end of line sequence
  384. * @param string $error_url the url to go back in case of error
  385. * @param string $sql_query SQL query for obtaining data
  386. *
  387. * @return bool Whether it succeeded
  388. */
  389. public function exportData ($db, $table, $crlf, $error_url, $sql_query)
  390. {
  391. if (isset($GLOBALS['xml_export_contents'])
  392. && $GLOBALS['xml_export_contents']
  393. ) {
  394. $result = PMA_DBI_query($sql_query, null, PMA_DBI_QUERY_UNBUFFERED);
  395. $columns_cnt = PMA_DBI_num_fields($result);
  396. $columns = array();
  397. for ($i = 0; $i < $columns_cnt; $i++) {
  398. $columns[$i] = stripslashes(PMA_DBI_field_name($result, $i));
  399. }
  400. unset($i);
  401. $buffer = ' <!-- ' . __('Table') . ' ' . htmlspecialchars($table) . ' -->' . $crlf;
  402. if (! PMA_exportOutputHandler($buffer)) {
  403. return false;
  404. }
  405. while ($record = PMA_DBI_fetch_row($result)) {
  406. $buffer = ' <table name="'
  407. . htmlspecialchars($table) . '">' . $crlf;
  408. for ($i = 0; $i < $columns_cnt; $i++) {
  409. // If a cell is NULL, still export it to preserve
  410. // the XML structure
  411. if (! isset($record[$i]) || is_null($record[$i])) {
  412. $record[$i] = 'NULL';
  413. }
  414. $buffer .= ' <column name="'
  415. . htmlspecialchars($columns[$i]) . '">'
  416. . htmlspecialchars((string)$record[$i])
  417. . '</column>' . $crlf;
  418. }
  419. $buffer .= ' </table>' . $crlf;
  420. if (! PMA_exportOutputHandler($buffer)) {
  421. return false;
  422. }
  423. }
  424. PMA_DBI_free_result($result);
  425. }
  426. return true;
  427. }
  428. /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
  429. /**
  430. * Gets the table name
  431. *
  432. * @return void
  433. */
  434. private function _getTable()
  435. {
  436. return $this->_table;
  437. }
  438. /**
  439. * Sets the table name
  440. *
  441. * @param string $table table name
  442. *
  443. * @return void
  444. */
  445. private function _setTable($table)
  446. {
  447. $this->_table = $table;
  448. }
  449. /**
  450. * Gets the table names
  451. *
  452. * @return array
  453. */
  454. private function _getTables()
  455. {
  456. return $this->_tables;
  457. }
  458. /**
  459. * Sets the table names
  460. *
  461. * @param array $tables table names
  462. *
  463. * @return void
  464. */
  465. private function _setTables($tables)
  466. {
  467. $this->_tables = $tables;
  468. }
  469. }
  470. ?>