ExportXml.class.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  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. . '- http://www.phpmyadmin.net' . $crlf
  173. . '-' . $crlf
  174. . '- ' . __('Host:') . ' ' . $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="http://www.phpmyadmin.net/some_doc_url/"'
  187. : '')
  188. . '>' . $crlf;
  189. if ($export_struct) {
  190. if (PMA_DRIZZLE) {
  191. $result = $GLOBALS['dbi']->fetchResult(
  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 = $GLOBALS['dbi']->fetchResult(
  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="' . $db_collation . '" charset="' . $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 = $GLOBALS['dbi']->fetchResult(
  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="' . $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 = $GLOBALS['dbi']->getTriggers($db, $table);
  249. if ($triggers) {
  250. foreach ($triggers as $trigger) {
  251. $code = $trigger['create'];
  252. $head .= ' <pma:trigger name="'
  253. . $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 = $GLOBALS['dbi']->getProceduresOrFunctions(
  271. $db, 'FUNCTION'
  272. );
  273. if ($functions) {
  274. foreach ($functions as $function) {
  275. $head .= ' <pma:function name="'
  276. . $function . '">' . $crlf;
  277. // Do some formatting
  278. $sql = $GLOBALS['dbi']->getDefinition(
  279. $db, 'FUNCTION', $function
  280. );
  281. $sql = rtrim($sql);
  282. $sql = " " . htmlspecialchars($sql);
  283. $sql = str_replace("\n", "\n ", $sql);
  284. $head .= $sql . $crlf;
  285. $head .= ' </pma:function>' . $crlf;
  286. }
  287. unset($function);
  288. unset($functions);
  289. }
  290. }
  291. if (isset($GLOBALS['xml_export_procedures'])
  292. && $GLOBALS['xml_export_procedures']
  293. ) {
  294. // Export procedures
  295. $procedures = $GLOBALS['dbi']->getProceduresOrFunctions(
  296. $db, 'PROCEDURE'
  297. );
  298. if ($procedures) {
  299. foreach ($procedures as $procedure) {
  300. $head .= ' <pma:procedure name="'
  301. . $procedure . '">' . $crlf;
  302. // Do some formatting
  303. $sql = $GLOBALS['dbi']->getDefinition(
  304. $db, 'PROCEDURE', $procedure
  305. );
  306. $sql = rtrim($sql);
  307. $sql = " " . htmlspecialchars($sql);
  308. $sql = str_replace("\n", "\n ", $sql);
  309. $head .= $sql . $crlf;
  310. $head .= ' </pma:procedure>' . $crlf;
  311. }
  312. unset($procedure);
  313. unset($procedures);
  314. }
  315. }
  316. unset($result);
  317. $head .= ' </pma:database>' . $crlf;
  318. $head .= ' </pma:structure_schemas>' . $crlf;
  319. if ($export_data) {
  320. $head .= $crlf;
  321. }
  322. }
  323. return PMA_exportOutputHandler($head);
  324. }
  325. /**
  326. * Outputs export footer
  327. *
  328. * @return bool Whether it succeeded
  329. */
  330. public function exportFooter ()
  331. {
  332. $foot = '</pma_xml_export>';
  333. return PMA_exportOutputHandler($foot);
  334. }
  335. /**
  336. * Outputs database header
  337. *
  338. * @param string $db Database name
  339. *
  340. * @return bool Whether it succeeded
  341. */
  342. public function exportDBHeader ($db)
  343. {
  344. global $crlf;
  345. if (isset($GLOBALS['xml_export_contents'])
  346. && $GLOBALS['xml_export_contents']
  347. ) {
  348. $head = ' <!--' . $crlf
  349. . ' - ' . __('Database:') . ' ' . '\'' . $db . '\'' . $crlf
  350. . ' -->' . $crlf
  351. . ' <database name="' . htmlspecialchars($db) . '">' . $crlf;
  352. return PMA_exportOutputHandler($head);
  353. } else {
  354. return true;
  355. }
  356. }
  357. /**
  358. * Outputs database footer
  359. *
  360. * @param string $db Database name
  361. *
  362. * @return bool Whether it succeeded
  363. */
  364. public function exportDBFooter ($db)
  365. {
  366. global $crlf;
  367. if (isset($GLOBALS['xml_export_contents'])
  368. && $GLOBALS['xml_export_contents']
  369. ) {
  370. return PMA_exportOutputHandler(' </database>' . $crlf);
  371. } else {
  372. return true;
  373. }
  374. }
  375. /**
  376. * Outputs CREATE DATABASE statement
  377. *
  378. * @param string $db Database name
  379. *
  380. * @return bool Whether it succeeded
  381. */
  382. public function exportDBCreate($db)
  383. {
  384. return true;
  385. }
  386. /**
  387. * Outputs the content of a table in XML format
  388. *
  389. * @param string $db database name
  390. * @param string $table table name
  391. * @param string $crlf the end of line sequence
  392. * @param string $error_url the url to go back in case of error
  393. * @param string $sql_query SQL query for obtaining data
  394. *
  395. * @return bool Whether it succeeded
  396. */
  397. public function exportData ($db, $table, $crlf, $error_url, $sql_query)
  398. {
  399. if (isset($GLOBALS['xml_export_contents'])
  400. && $GLOBALS['xml_export_contents']
  401. ) {
  402. $result = $GLOBALS['dbi']->query(
  403. $sql_query, null, PMA_DatabaseInterface::QUERY_UNBUFFERED
  404. );
  405. $columns_cnt = $GLOBALS['dbi']->numFields($result);
  406. $columns = array();
  407. for ($i = 0; $i < $columns_cnt; $i++) {
  408. $columns[$i] = stripslashes($GLOBALS['dbi']->fieldName($result, $i));
  409. }
  410. unset($i);
  411. $buffer = ' <!-- ' . __('Table') . ' ' . $table . ' -->' . $crlf;
  412. if (! PMA_exportOutputHandler($buffer)) {
  413. return false;
  414. }
  415. while ($record = $GLOBALS['dbi']->fetchRow($result)) {
  416. $buffer = ' <table name="'
  417. . htmlspecialchars($table) . '">' . $crlf;
  418. for ($i = 0; $i < $columns_cnt; $i++) {
  419. // If a cell is NULL, still export it to preserve
  420. // the XML structure
  421. if (! isset($record[$i]) || is_null($record[$i])) {
  422. $record[$i] = 'NULL';
  423. }
  424. $buffer .= ' <column name="'
  425. . htmlspecialchars($columns[$i]) . '">'
  426. . htmlspecialchars((string)$record[$i])
  427. . '</column>' . $crlf;
  428. }
  429. $buffer .= ' </table>' . $crlf;
  430. if (! PMA_exportOutputHandler($buffer)) {
  431. return false;
  432. }
  433. }
  434. $GLOBALS['dbi']->freeResult($result);
  435. }
  436. return true;
  437. }
  438. /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */
  439. /**
  440. * Gets the table name
  441. *
  442. * @return string
  443. */
  444. private function _getTable()
  445. {
  446. return $this->_table;
  447. }
  448. /**
  449. * Sets the table name
  450. *
  451. * @param string $table table name
  452. *
  453. * @return void
  454. */
  455. private function _setTable($table)
  456. {
  457. $this->_table = $table;
  458. }
  459. /**
  460. * Gets the table names
  461. *
  462. * @return array
  463. */
  464. private function _getTables()
  465. {
  466. return $this->_tables;
  467. }
  468. /**
  469. * Sets the table names
  470. *
  471. * @param array $tables table names
  472. *
  473. * @return void
  474. */
  475. private function _setTables($tables)
  476. {
  477. $this->_tables = $tables;
  478. }
  479. }
  480. ?>