replication_gui.lib.php 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Functions for the replication GUI
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. /**
  12. * returns HTML for error message
  13. *
  14. * @return String HTML code
  15. */
  16. function PMA_getHtmlForErrorMessage()
  17. {
  18. $html = '';
  19. if (isset($_SESSION['replication']['sr_action_status'])
  20. && isset($_SESSION['replication']['sr_action_info'])
  21. ) {
  22. if ($_SESSION['replication']['sr_action_status'] == 'error') {
  23. $error_message = $_SESSION['replication']['sr_action_info'];
  24. $html .= PMA_Message::error($error_message)->getDisplay();
  25. $_SESSION['replication']['sr_action_status'] = 'unknown';
  26. } elseif ($_SESSION['replication']['sr_action_status'] == 'success') {
  27. $success_message = $_SESSION['replication']['sr_action_info'];
  28. $html .= PMA_Message::success($success_message)->getDisplay();
  29. $_SESSION['replication']['sr_action_status'] = 'unknown';
  30. }
  31. }
  32. return $html;
  33. }
  34. /**
  35. * returns HTML for master replication
  36. *
  37. * @return String HTML code
  38. */
  39. function PMA_getHtmlForMasterReplication()
  40. {
  41. $html = '';
  42. if (! isset($_REQUEST['repl_clear_scr'])) {
  43. $html .= '<fieldset>';
  44. $html .= '<legend>' . __('Master replication') . '</legend>';
  45. $html .= __('This server is configured as master in a replication process.');
  46. $html .= '<ul>';
  47. $html .= ' <li><a href="#" id="master_status_href">';
  48. $html .= __('Show master status') . '</a>';
  49. $html .= PMA_getHtmlForReplicationStatusTable('master', true, false);
  50. $html .= ' </li>';
  51. $html .= ' <li><a href="#" id="master_slaves_href">';
  52. $html .= __('Show connected slaves') . '</a>';
  53. $html .= PMA_getHtmlForReplicationSlavesTable(true);
  54. $html .= ' </li>';
  55. $_url_params = $GLOBALS['url_params'];
  56. $_url_params['mr_adduser'] = true;
  57. $_url_params['repl_clear_scr'] = true;
  58. $html .= ' <li><a href="server_replication.php';
  59. $html .= PMA_URL_getCommon($_url_params)
  60. . '" id="master_addslaveuser_href">';
  61. $html .= __('Add slave replication user') . '</a></li>';
  62. }
  63. // Display 'Add replication slave user' form
  64. if (isset($_REQUEST['mr_adduser'])) {
  65. $html .= PMA_getHtmlForReplicationMasterAddSlaveuser();
  66. } elseif (! isset($_REQUEST['repl_clear_scr'])) {
  67. $html .= "</ul>";
  68. $html .= "</fieldset>";
  69. }
  70. return $html;
  71. }
  72. /**
  73. * returns HTML for master replication configuration
  74. *
  75. * @return String HTML code
  76. */
  77. function PMA_getHtmlForMasterConfiguration()
  78. {
  79. $html = '<fieldset>';
  80. $html .= '<legend>' . __('Master configuration') . '</legend>';
  81. $html .= __(
  82. 'This server is not configured as master server in a '
  83. . 'replication process. You can choose from either replicating '
  84. . 'all databases and ignoring certain (useful if you want to replicate '
  85. . 'majority of databases) or you can choose to ignore all databases by '
  86. . 'default and allow only certain databases to be replicated. '
  87. . 'Please select the mode:'
  88. ) . '<br /><br />';
  89. $html .= '<select name="db_type" id="db_type">';
  90. $html .= '<option value="all">' . __('Replicate all databases; Ignore:');
  91. $html .= '</option>';
  92. $html .= '<option value="ign">' . __('Ignore all databases; Replicate:');
  93. $html .= '</option>';
  94. $html .= '</select>';
  95. $html .= '<br /><br />';
  96. $html .= __('Please select databases:') . '<br />';
  97. $html .= PMA_getHtmlForReplicationDbMultibox();
  98. $html .= '<br /><br />';
  99. $html .= __(
  100. 'Now, add the following lines at the end of [mysqld] section'
  101. . ' in your my.cnf and please restart the MySQL server afterwards.'
  102. ) . '<br />';
  103. $html .= '<pre id="rep"></pre>';
  104. $html .= __(
  105. 'Once you restarted MySQL server, please click on Go button. '
  106. . 'Afterwards, you should see a message informing you, that this server'
  107. . ' <b>is</b> configured as master.'
  108. );
  109. $html .= '</fieldset>';
  110. $html .= '<fieldset class="tblFooters">';
  111. $html .= ' <form method="post" action="server_replication.php" >';
  112. $html .= PMA_URL_getHiddenInputs('', '');
  113. $html .= ' <input type="submit" value="' . __('Go') . '" id="goButton" />';
  114. $html .= ' </form>';
  115. $html .= '</fieldset>';
  116. return $html;
  117. }
  118. /**
  119. * returns HTML for slave replication configuration
  120. *
  121. * @param bool $server_slave_status Whether it is Master or Slave
  122. * @param Array $server_slave_replication Slave replication
  123. *
  124. * @return String HTML code
  125. */
  126. function PMA_getHtmlForSlaveConfiguration(
  127. $server_slave_status, $server_slave_replication
  128. ) {
  129. $html = '<fieldset>';
  130. $html .= '<legend>' . __('Slave replication') . '</legend>';
  131. if ($server_slave_status) {
  132. $html .= '<div id="slave_configuration_gui">';
  133. $_url_params = $GLOBALS['url_params'];
  134. $_url_params['sr_take_action'] = true;
  135. $_url_params['sr_slave_server_control'] = true;
  136. if ($server_slave_replication[0]['Slave_IO_Running'] == 'No') {
  137. $_url_params['sr_slave_action'] = 'start';
  138. } else {
  139. $_url_params['sr_slave_action'] = 'stop';
  140. }
  141. $_url_params['sr_slave_control_parm'] = 'IO_THREAD';
  142. $slave_control_io_link = 'server_replication.php'
  143. . PMA_URL_getCommon($_url_params);
  144. if ($server_slave_replication[0]['Slave_SQL_Running'] == 'No') {
  145. $_url_params['sr_slave_action'] = 'start';
  146. } else {
  147. $_url_params['sr_slave_action'] = 'stop';
  148. }
  149. $_url_params['sr_slave_control_parm'] = 'SQL_THREAD';
  150. $slave_control_sql_link = 'server_replication.php'
  151. . PMA_URL_getCommon($_url_params);
  152. if ($server_slave_replication[0]['Slave_IO_Running'] == 'No'
  153. || $server_slave_replication[0]['Slave_SQL_Running'] == 'No'
  154. ) {
  155. $_url_params['sr_slave_action'] = 'start';
  156. } else {
  157. $_url_params['sr_slave_action'] = 'stop';
  158. }
  159. $_url_params['sr_slave_control_parm'] = null;
  160. $slave_control_full_link = 'server_replication.php'
  161. . PMA_URL_getCommon($_url_params);
  162. $_url_params['sr_slave_action'] = 'reset';
  163. $slave_control_reset_link = 'server_replication.php'
  164. . PMA_URL_getCommon($_url_params);
  165. $_url_params = $GLOBALS['url_params'];
  166. $_url_params['sr_slave_skip_error'] = true;
  167. $slave_skip_error_link = 'server_replication.php'
  168. . PMA_URL_getCommon($_url_params);
  169. if ($server_slave_replication[0]['Slave_SQL_Running'] == 'No') {
  170. $html .= PMA_Message::error(
  171. __('Slave SQL Thread not running!')
  172. )->getDisplay();
  173. }
  174. if ($server_slave_replication[0]['Slave_IO_Running'] == 'No') {
  175. $html .= PMA_Message::error(
  176. __('Slave IO Thread not running!')
  177. )->getDisplay();
  178. }
  179. $_url_params = $GLOBALS['url_params'];
  180. $_url_params['sl_configure'] = true;
  181. $_url_params['repl_clear_scr'] = true;
  182. $reconfiguremaster_link = 'server_replication.php'
  183. . PMA_URL_getCommon($_url_params);
  184. $html .= __('Server is configured as slave in a replication process. Would you like to:');
  185. $html .= '<br />';
  186. $html .= '<ul>';
  187. $html .= ' <li><a href="#" id="slave_status_href">';
  188. $html .= __('See slave status table') . '</a>';
  189. $html .= PMA_getHtmlForReplicationStatusTable('slave', true, false);
  190. $html .= ' </li>';
  191. $html .= ' <li><a href="#" id="slave_control_href">';
  192. $html .= __('Control slave:') . '</a>';
  193. $html .= ' <div id="slave_control_gui" style="display: none">';
  194. $html .= ' <ul>';
  195. $html .= ' <li><a href="' . $slave_control_full_link . '">';
  196. $html .= (($server_slave_replication[0]['Slave_IO_Running'] == 'No' ||
  197. $server_slave_replication[0]['Slave_SQL_Running'] == 'No')
  198. ? __('Full start')
  199. : __('Full stop')) . ' </a></li>';
  200. $html .= ' <li><a href="' . $slave_control_reset_link . '">';
  201. $html .= __('Reset slave') . '</a></li>';
  202. if ($server_slave_replication[0]['Slave_SQL_Running'] == 'No') {
  203. $html .= ' <li><a href="' . $slave_control_sql_link . '">';
  204. $html .= __('Start SQL Thread only') . '</a></li>';
  205. } else {
  206. $html .= ' <li><a href="' . $slave_control_sql_link . '">';
  207. $html .= __('Stop SQL Thread only') . '</a></li>';
  208. }
  209. if ($server_slave_replication[0]['Slave_IO_Running'] == 'No') {
  210. $html .= ' <li><a href="' . $slave_control_io_link . '">';
  211. $html .= __('Start IO Thread only') . '</a></li>';
  212. } else {
  213. $html .= ' <li><a href="' . $slave_control_io_link . '">';
  214. $html .= __('Stop IO Thread only') . '</a></li>';
  215. }
  216. $html .= ' </ul>';
  217. $html .= ' </div>';
  218. $html .= ' </li>';
  219. $html .= ' <li>';
  220. $html .= PMA_getHtmlForSlaveErrorManagement($slave_skip_error_link);
  221. $html .= ' </li>';
  222. $html .= ' <li><a href="' . $reconfiguremaster_link . '">';
  223. $html .= __('Change or reconfigure master server') . '</a></li>';
  224. $html .= '</ul>';
  225. $html .= '</div>';
  226. } elseif (! isset($_REQUEST['sl_configure'])) {
  227. $_url_params = $GLOBALS['url_params'];
  228. $_url_params['sl_configure'] = true;
  229. $_url_params['repl_clear_scr'] = true;
  230. $html .= sprintf(
  231. __(
  232. 'This server is not configured as slave in a replication process. '
  233. . 'Would you like to <a href="%s">configure</a> it?'
  234. ),
  235. 'server_replication.php' . PMA_URL_getCommon($_url_params)
  236. );
  237. }
  238. $html .= '</fieldset>';
  239. return $html;
  240. }
  241. /**
  242. * returns HTML for Slave Error Management
  243. *
  244. * @param String $slave_skip_error_link error link
  245. *
  246. * @return String HTML code
  247. */
  248. function PMA_getHtmlForSlaveErrorManagement($slave_skip_error_link)
  249. {
  250. $html = '<a href="#" id="slave_errormanagement_href">';
  251. $html .= __('Error management:') . '</a>';
  252. $html .= ' <div id="slave_errormanagement_gui" style="display: none">';
  253. $html .= PMA_Message::error(
  254. __('Skipping errors might lead into unsynchronized master and slave!')
  255. )->getDisplay();
  256. $html .= ' <ul>';
  257. $html .= ' <li><a href="' . $slave_skip_error_link . '">';
  258. $html .= __('Skip current error') . '</a></li>';
  259. $html .= ' <li>';
  260. $html .= ' <form method="post" action="server_replication.php">';
  261. $html .= PMA_URL_getHiddenInputs('', '');
  262. $html .= sprintf(
  263. __('Skip next %s errors.'),
  264. '<input type="text" name="sr_skip_errors_count" value="1" '
  265. . 'style="width: 30px" />'
  266. );
  267. $html .= ' <input type="submit" name="sr_slave_skip_error" ';
  268. $html .= 'value="' . __('Go') . '" />';
  269. $html .= ' <input type="hidden" name="sr_take_action" value="1" />';
  270. $html .= ' </form></li>';
  271. $html .= ' </ul>';
  272. $html .= ' </div>';
  273. return $html;
  274. }
  275. /**
  276. * returns HTML for not configure for a server replication
  277. *
  278. * @return String HTML code
  279. */
  280. function PMA_getHtmlForNotServerReplication()
  281. {
  282. $_url_params = $GLOBALS['url_params'];
  283. $_url_params['mr_configure'] = true;
  284. $html = '<fieldset>';
  285. $html .= '<legend>' . __('Master replication') . '</legend>';
  286. $html .= sprintf(
  287. __(
  288. 'This server is not configured as master in a replication process. '
  289. . 'Would you like to <a href="%s">configure</a> it?'
  290. ),
  291. 'server_replication.php' . PMA_URL_getCommon($_url_params)
  292. );
  293. $html .= '</fieldset>';
  294. return $html;
  295. }
  296. /**
  297. * returns HTML code for selecting databases
  298. *
  299. * @return String HTML code
  300. */
  301. function PMA_getHtmlForReplicationDbMultibox()
  302. {
  303. $multi_values = '';
  304. $multi_values .= '<select name="db_select[]" '
  305. . 'size="6" multiple="multiple" id="db_select">';
  306. foreach ($GLOBALS['pma']->databases as $current_db) {
  307. if ($GLOBALS['dbi']->isSystemSchema($current_db)) {
  308. continue;
  309. }
  310. $current_db = htmlspecialchars($current_db);
  311. $multi_values .= ' <option value="' . $current_db . '" ';
  312. $multi_values .= '>';
  313. $multi_values .= $current_db . '</option>';
  314. } // end while
  315. $multi_values .= '</select>';
  316. $multi_values .= '<br /><a href="#" id="db_reset_href">';
  317. $multi_values .= __('Uncheck All') . '</a>';
  318. return $multi_values;
  319. }
  320. /**
  321. * returns HTML for changing master
  322. *
  323. * @param String $submitname - submit button name
  324. *
  325. * @return String HTML code
  326. */
  327. function PMA_getHtmlForReplicationChangeMaster($submitname)
  328. {
  329. $html = '';
  330. list($username_length, $hostname_length)
  331. = PMA_replicationGetUsernameHostnameLength();
  332. $html .= '<form method="post" action="server_replication.php">';
  333. $html .= PMA_URL_getHiddenInputs('', '');
  334. $html .= ' <fieldset id="fieldset_add_user_login">';
  335. $html .= ' <legend>' . __('Slave configuration');
  336. $html .= ' - ' . __('Change or reconfigure master server') . '</legend>';
  337. $html .= __(
  338. 'Make sure, you have unique server-id in your configuration file (my.cnf). '
  339. . 'If not, please add the following line into [mysqld] section:'
  340. );
  341. $html .= '<br />';
  342. $html .= '<pre>server-id=' . time() . '</pre>';
  343. $html .= PMA_getHtmlForAddUserInputDiv(
  344. array('text'=>__('User name:'), 'for'=>"text_username"),
  345. array(
  346. 'type'=>'text',
  347. 'name'=>'username',
  348. 'id'=>'text_username',
  349. 'maxlength'=>$username_length,
  350. 'title'=>__('User name'),
  351. 'required'=>'required'
  352. )
  353. );
  354. $html .= PMA_getHtmlForAddUserInputDiv(
  355. array('text'=>__('Password:'), 'for'=>"text_pma_pw"),
  356. array(
  357. 'type'=>'password',
  358. 'name'=>'pma_pw',
  359. 'id'=>'text_pma_pw',
  360. 'title'=>__('Password'),
  361. 'required'=>'required'
  362. )
  363. );
  364. $html .= PMA_getHtmlForAddUserInputDiv(
  365. array('text'=>__('Host:'), 'for'=>"text_hostname"),
  366. array(
  367. 'type'=>'text',
  368. 'name'=>'hostname',
  369. 'id'=>'text_hostname',
  370. 'maxlength'=>$hostname_length,
  371. 'value'=>'',
  372. 'required'=>'required'
  373. )
  374. );
  375. $html .= PMA_getHtmlForAddUserInputDiv(
  376. array('text'=>__('Port:'), 'for'=>"text_port"),
  377. array(
  378. 'type'=>'number',
  379. 'name'=>'text_port',
  380. 'id'=>'text_port',
  381. 'maxlength'=>6,
  382. 'value'=>'3306',
  383. 'required'=>'required'
  384. )
  385. );
  386. $html .= ' </fieldset>';
  387. $html .= ' <fieldset id="fieldset_user_privtable_footer" class="tblFooters">';
  388. $html .= ' <input type="hidden" name="sr_take_action" value="true" />';
  389. $html .= ' <input type="hidden" name="' . $submitname . '" value="1" />';
  390. $html .= ' <input type="submit" id="confslave_submit" value="';
  391. $html .= __('Go') . '" />';
  392. $html .= ' </fieldset>';
  393. $html .= '</form>';
  394. return $html;
  395. }
  396. /**
  397. * returns HTML code for Add user input div
  398. *
  399. * @param Array $label_array label tag elements
  400. * @param Array $input_array input tag elements
  401. *
  402. * @return String HTML code
  403. */
  404. function PMA_getHtmlForAddUserInputDiv($label_array, $input_array)
  405. {
  406. $html = ' <div class="item">';
  407. $html .= ' <label for="' . $label_array['for'] . '">';
  408. $html .= $label_array['text'] . '</label>';
  409. $html .= ' <input ';
  410. foreach ($input_array as $key=>$value) {
  411. $html .= ' ' . $key . '="' . $value . '" ';
  412. }
  413. $html .= ' />';
  414. $html .= ' </div>';
  415. return $html;
  416. }
  417. /**
  418. * This function returns html code for table with replication status.
  419. *
  420. * @param string $type either master or slave
  421. * @param boolean $hidden if true, then default style is set to hidden,
  422. * default value false
  423. * @param boolean $title if true, then title is displayed, default true
  424. *
  425. * @return String HTML code
  426. */
  427. function PMA_getHtmlForReplicationStatusTable($type, $hidden = false, $title = true)
  428. {
  429. global ${"{$type}_variables"};
  430. global ${"{$type}_variables_alerts"};
  431. global ${"{$type}_variables_oks"};
  432. global ${"server_{$type}_replication"};
  433. global ${"strReplicationStatus_{$type}"};
  434. $html = '';
  435. // TODO check the Masters server id?
  436. // seems to default to '1' when queried via SHOW VARIABLES ,
  437. // but resulted in error on the master when slave connects
  438. // [ERROR] Error reading packet from server: Misconfigured master
  439. // - server id was not set ( server_errno=1236)
  440. // [ERROR] Got fatal error 1236: 'Misconfigured master
  441. // - server id was not set' from master when reading data from binary log
  442. //
  443. //$server_id = $GLOBALS['dbi']->fetchValue(
  444. // "SHOW VARIABLES LIKE 'server_id'", 0, 1
  445. //);
  446. $html .= '<div id="replication_' . $type . '_section" style="';
  447. $html .= ($hidden ? 'display: none;' : '') . '"> ';
  448. if ($title) {
  449. if ($type == 'master') {
  450. $html .= '<h4><a name="replication_' . $type . '"></a>';
  451. $html .= __('Master status') . '</h4>';
  452. } else {
  453. $html .= '<h4><a name="replication_' . $type . '"></a>';
  454. $html .= __('Slave status') . '</h4>';
  455. }
  456. } else {
  457. $html .= '<br />';
  458. }
  459. $html .= ' <table id="server' . $type . 'replicationsummary" class="data"> ';
  460. $html .= ' <thead>';
  461. $html .= ' <tr>';
  462. $html .= ' <th>' . __('Variable') . '</th>';
  463. $html .= ' <th>' . __('Value') . '</th>';
  464. $html .= ' </tr>';
  465. $html .= ' </thead>';
  466. $html .= ' <tbody>';
  467. $odd_row = true;
  468. foreach (${"{$type}_variables"} as $variable) {
  469. $html .= ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">';
  470. $html .= ' <td class="name">';
  471. $html .= $variable;
  472. $html .= ' </td>';
  473. $html .= ' <td class="value">';
  474. // TODO change to regexp or something, to allow for negative match
  475. if (isset(${"{$type}_variables_alerts"}[$variable])
  476. && ${"{$type}_variables_alerts"}[$variable] == ${"server_{$type}_replication"}[0][$variable]
  477. ) {
  478. $html .= '<span class="attention">';
  479. } elseif (isset(${"{$type}_variables_oks"}[$variable])
  480. && ${"{$type}_variables_oks"}[$variable]
  481. == ${"server_{$type}_replication"}[0][$variable]
  482. ) {
  483. $html .= '<span class="allfine">';
  484. } else {
  485. $html .= '<span>';
  486. }
  487. // allow wrapping long table lists into multiple lines
  488. static $variables_wrap = array(
  489. 'Replicate_Do_DB', 'Replicate_Ignore_DB',
  490. 'Replicate_Do_Table', 'Replicate_Ignore_Table',
  491. 'Replicate_Wild_Do_Table', 'Replicate_Wild_Ignore_Table');
  492. if (in_array($variable, $variables_wrap)) {
  493. $html .= str_replace(
  494. ',',
  495. ', ',
  496. ${"server_{$type}_replication"}[0][$variable]
  497. );
  498. } else {
  499. $html .= ${"server_{$type}_replication"}[0][$variable];
  500. }
  501. $html .= '</span>';
  502. $html .= ' </td>';
  503. $html .= ' </tr>';
  504. $odd_row = ! $odd_row;
  505. }
  506. $html .= ' </tbody>';
  507. $html .= ' </table>';
  508. $html .= ' <br />';
  509. $html .= '</div>';
  510. return $html;
  511. }
  512. /**
  513. * returns html code for table with slave users connected to this master
  514. *
  515. * @param boolean $hidden - if true, then default style is set to hidden,
  516. * - default value false
  517. *
  518. * @return string
  519. */
  520. function PMA_getHtmlForReplicationSlavesTable($hidden = false)
  521. {
  522. $html = '';
  523. // Fetch data
  524. $data = $GLOBALS['dbi']->fetchResult('SHOW SLAVE HOSTS', null, null);
  525. $html .= ' <br />';
  526. $html .= ' <div id="replication_slaves_section" style="';
  527. $html .= ($hidden ? 'display: none;' : '') . '"> ';
  528. $html .= ' <table class="data">';
  529. $html .= ' <thead>';
  530. $html .= ' <tr>';
  531. $html .= ' <th>' . __('Server ID') . '</th>';
  532. $html .= ' <th>' . __('Host') . '</th>';
  533. $html .= ' </tr>';
  534. $html .= ' </thead>';
  535. $html .= ' <tbody>';
  536. $odd_row = true;
  537. foreach ($data as $slave) {
  538. $html .= ' <tr class="' . ($odd_row ? 'odd' : 'even') . '">';
  539. $html .= ' <td class="value">' . $slave['Server_id'] . '</td>';
  540. $html .= ' <td class="value">' . $slave['Host'] . '</td>';
  541. $html .= ' </tr>';
  542. $odd_row = ! $odd_row;
  543. }
  544. $html .= ' </tbody>';
  545. $html .= ' </table>';
  546. $html .= ' <br />';
  547. $html .= PMA_Message::notice(
  548. __(
  549. 'Only slaves started with the '
  550. . '--report-host=host_name option are visible in this list.'
  551. )
  552. )->getDisplay();
  553. $html .= ' <br />';
  554. $html .= ' </div>';
  555. return $html;
  556. }
  557. /**
  558. * get the correct username and hostname lengths for this MySQL server
  559. *
  560. * @return array username length, hostname length
  561. */
  562. function PMA_replicationGetUsernameHostnameLength()
  563. {
  564. $fields_info = $GLOBALS['dbi']->getColumns('mysql', 'user');
  565. $username_length = 16;
  566. $hostname_length = 41;
  567. foreach ($fields_info as $val) {
  568. if ($val['Field'] == 'User') {
  569. strtok($val['Type'], '()');
  570. $v = strtok('()');
  571. if (is_int($v)) {
  572. $username_length = $v;
  573. }
  574. } elseif ($val['Field'] == 'Host') {
  575. strtok($val['Type'], '()');
  576. $v = strtok('()');
  577. if (is_int($v)) {
  578. $hostname_length = $v;
  579. }
  580. }
  581. }
  582. return array($username_length, $hostname_length);
  583. }
  584. /**
  585. * returns html code to add a replication slave user to the master
  586. *
  587. * @return String HTML code
  588. */
  589. function PMA_getHtmlForReplicationMasterAddSlaveuser()
  590. {
  591. $html = '';
  592. list($username_length, $hostname_length)
  593. = PMA_replicationGetUsernameHostnameLength();
  594. if (isset($_REQUEST['username']) && strlen($_REQUEST['username']) === 0) {
  595. $GLOBALS['pred_username'] = 'any';
  596. }
  597. $html .= '<div id="master_addslaveuser_gui">';
  598. $html .= '<form autocomplete="off" method="post" ';
  599. $html .= 'action="server_privileges.php"';
  600. $html .= ' onsubmit="return checkAddUser(this);">';
  601. $html .= PMA_URL_getHiddenInputs('', '');
  602. $html .= '<fieldset id="fieldset_add_user_login">'
  603. . '<legend>' . __('Add slave replication user') . '</legend>'
  604. . PMA_getHtmlForAddUserLoginForm($username_length)
  605. . '<div class="item">'
  606. . '<label for="select_pred_hostname">'
  607. . ' ' . __('Host:')
  608. . '</label>'
  609. . '<span class="options">'
  610. . ' <select name="pred_hostname" id="select_pred_hostname" title="'
  611. . __('Host') . '"';
  612. $_current_user = $GLOBALS['dbi']->fetchValue('SELECT USER();');
  613. if (! empty($_current_user)) {
  614. $thishost = str_replace(
  615. "'",
  616. '',
  617. substr($_current_user, (strrpos($_current_user, '@') + 1))
  618. );
  619. if ($thishost == 'localhost' || $thishost == '127.0.0.1') {
  620. unset($thishost);
  621. }
  622. }
  623. $html .= ' onchange="if (this.value == \'any\') { hostname.value = \'%\'; } '
  624. . 'else if (this.value == \'localhost\') '
  625. . '{ hostname.value = \'localhost\'; } '
  626. . (empty($thishost)
  627. ? ''
  628. : 'else if (this.value == \'thishost\') { hostname.value = \''
  629. . addslashes(htmlspecialchars($thishost)) . '\'; } ')
  630. . 'else if (this.value == \'hosttable\') { hostname.value = \'\'; } '
  631. . 'else if (this.value == \'userdefined\') '
  632. . '{ hostname.focus(); hostname.select(); }">'
  633. . "\n";
  634. unset($_current_user);
  635. // when we start editing a user, $GLOBALS['pred_hostname'] is not defined
  636. if (! isset($GLOBALS['pred_hostname']) && isset($_REQUEST['hostname'])) {
  637. switch (strtolower($_REQUEST['hostname'])) {
  638. case 'localhost':
  639. case '127.0.0.1':
  640. $GLOBALS['pred_hostname'] = 'localhost';
  641. break;
  642. case '%':
  643. $GLOBALS['pred_hostname'] = 'any';
  644. break;
  645. default:
  646. $GLOBALS['pred_hostname'] = 'userdefined';
  647. break;
  648. }
  649. }
  650. $html .= ' <option value="any"'
  651. . ((isset($GLOBALS['pred_hostname']) && $GLOBALS['pred_hostname'] == 'any')
  652. ? ' selected="selected"' : '') . '>' . __('Any host')
  653. . '</option>'
  654. . ' <option value="localhost"'
  655. . ((isset($GLOBALS['pred_hostname'])
  656. && $GLOBALS['pred_hostname'] == 'localhost')
  657. ? ' selected="selected"' : '') . '>' . __('Local')
  658. . '</option>';
  659. if (!empty($thishost)) {
  660. $html .= ' <option value="thishost"'
  661. . ((isset($GLOBALS['pred_hostname'])
  662. && $GLOBALS['pred_hostname'] == 'thishost')
  663. ? ' selected="selected"' : '') . '>' . __('This Host')
  664. . '</option>';
  665. }
  666. unset($thishost);
  667. $html .= PMA_getHtmlForTableInfoForm($hostname_length);
  668. $html .= '</form>';
  669. $html .= '</div>';
  670. return $html;
  671. }
  672. /**
  673. * returns html code to add a replication slave user to the master
  674. *
  675. * @param int $username_length Username length
  676. *
  677. * @return String HTML code
  678. */
  679. function PMA_getHtmlForAddUserLoginForm($username_length)
  680. {
  681. $html = '<input type="hidden" name="grant_count" value="25" />'
  682. . '<input type="hidden" name="createdb" id="createdb_0" value="0" />'
  683. . '<input id="checkbox_Repl_slave_priv" type="hidden"'
  684. . ' title="Needed for the replication slaves." '
  685. . 'value="Y" name="Repl_slave_priv"/>'
  686. . '<input id="checkbox_Repl_client_priv" type="hidden" '
  687. . 'title="Needed for the replication slaves."'
  688. . ' value="Y" name="Repl_client_priv"/> '
  689. . '<input type="hidden" name="sr_take_action" value="true" />'
  690. . '<div class="item">'
  691. . '<label for="select_pred_username">'
  692. . ' ' . __('User name:')
  693. . '</label>'
  694. . '<span class="options">'
  695. . ' <select name="pred_username" id="select_pred_username" '
  696. . 'title="' . __('User name') . '"'
  697. . ' onchange="if (this.value == \'any\') { username.value = \'\'; } '
  698. . 'else if (this.value == \'userdefined\') { '
  699. . ' username.focus(); username.select(); }">'
  700. . ' <option value="any"'
  701. . ((isset($GLOBALS['pred_username'])
  702. && $GLOBALS['pred_username'] == 'any') ? ' selected="selected"' : '')
  703. . '>' . __('Any user') . '</option>'
  704. . ' <option value="userdefined"'
  705. . ((! isset($GLOBALS['pred_username'])
  706. || $GLOBALS['pred_username'] == 'userdefined')
  707. ? ' selected="selected"' : '')
  708. . '>' . __('Use text field:') . '</option>'
  709. . ' </select>'
  710. . '</span>'
  711. . '<input type="text" name="username" maxlength="'
  712. . $username_length . '" title="' . __('User name') . '"'
  713. . (empty($_REQUEST['username']) ? '' : ' value="'
  714. . (isset($GLOBALS['new_username'])
  715. ? $GLOBALS['new_username']
  716. : $_REQUEST['username']) . '"')
  717. . ' onchange="pred_username.value = \'userdefined\';" />'
  718. . '</div>';
  719. return $html;
  720. }
  721. /**
  722. * returns HTML for TableInfoForm
  723. *
  724. * @param int $hostname_length Selected hostname length
  725. *
  726. * @return String HTML code
  727. */
  728. function PMA_getHtmlForTableInfoForm($hostname_length)
  729. {
  730. $html = ' <option value="hosttable"'
  731. . ((isset($GLOBALS['pred_hostname'])
  732. && $GLOBALS['pred_hostname'] == 'hosttable')
  733. ? ' selected="selected"' : '') . '>' . __('Use Host Table')
  734. . '</option>'
  735. . ' <option value="userdefined"'
  736. . ((isset($GLOBALS['pred_hostname'])
  737. && $GLOBALS['pred_hostname'] == 'userdefined')
  738. ? ' selected="selected"' : '')
  739. . '>' . __('Use text field:') . '</option>'
  740. . ' </select>'
  741. . '</span>'
  742. . '<input type="text" name="hostname" maxlength="'
  743. . $hostname_length . '" value="'
  744. . (isset($_REQUEST['hostname']) ? $_REQUEST['hostname'] : '')
  745. . '" title="' . __('Host')
  746. . '" onchange="pred_hostname.value = \'userdefined\';" />'
  747. . PMA_Util::showHint(
  748. __(
  749. 'When Host table is used, this field is ignored '
  750. . 'and values stored in Host table are used instead.'
  751. )
  752. )
  753. . '</div>'
  754. . '<div class="item">'
  755. . '<label for="select_pred_password">'
  756. . ' ' . __('Password:')
  757. . '</label>'
  758. . '<span class="options">'
  759. . ' <select name="pred_password" id="select_pred_password" title="'
  760. . __('Password') . '"'
  761. . ' onchange="if (this.value == \'none\') '
  762. . '{ pma_pw.value = \'\'; pma_pw2.value = \'\'; } '
  763. . 'else if (this.value == \'userdefined\') '
  764. . '{ pma_pw.focus(); pma_pw.select(); }">'
  765. . ' <option value="none"';
  766. if (isset($_REQUEST['username'])) {
  767. $html .= ' selected="selected"';
  768. }
  769. $html .= '>' . __('No Password') . '</option>'
  770. . ' <option value="userdefined"'
  771. . (isset($_REQUEST['username']) ? '' : ' selected="selected"')
  772. . '>' . __('Use text field:') . '</option>'
  773. . ' </select>'
  774. . '</span>'
  775. . '<input type="password" id="text_pma_pw" name="pma_pw" title="'
  776. . __('Password') . '" onchange="pred_password.value = \'userdefined\';" />'
  777. . '</div>'
  778. . '<div class="item">'
  779. . '<label for="text_pma_pw2">'
  780. . ' ' . __('Re-type:')
  781. . '</label>'
  782. . '<span class="options">&nbsp;</span>'
  783. . '<input type="password" name="pma_pw2" id="text_pma_pw2" title="'
  784. . __('Re-type') . '" onchange="pred_password.value = \'userdefined\';" />'
  785. . '</div>'
  786. . '<div class="item">'
  787. . '<label for="button_generate_password">'
  788. . ' ' . __('Generate Password:')
  789. . '</label>'
  790. . '<span class="options">'
  791. . ' <input type="button" class="button" '
  792. . 'id="button_generate_password" value="' . __('Generate')
  793. . '" onclick="suggestPassword(this.form)" />'
  794. . '</span>'
  795. . '<input type="text" name="generated_pw" id="generated_pw" />'
  796. . '</div>'
  797. . '</fieldset>';
  798. $html .= '<fieldset id="fieldset_user_privtable_footer" class="tblFooters">'
  799. . ' <input type="hidden" name="adduser_submit" value="1" />'
  800. . ' <input type="submit" id="adduser_submit" value="' . __('Go') . '" />'
  801. . '</fieldset>';
  802. return $html;
  803. }
  804. /**
  805. * handle control requests
  806. *
  807. * @return NULL
  808. */
  809. function PMA_handleControlRequest()
  810. {
  811. if (isset($_REQUEST['sr_take_action'])) {
  812. $refresh = false;
  813. $result = null;
  814. $messageSuccess = null;
  815. $messageError = null;
  816. if (isset($_REQUEST['slave_changemaster'])) {
  817. $result = PMA_handleRequestForSlaveChangeMaster();
  818. } elseif (isset($_REQUEST['sr_slave_server_control'])) {
  819. $result = PMA_handleRequestForSlaveServerControl();
  820. $refresh = true;
  821. switch ($_REQUEST['sr_slave_action']) {
  822. case 'start':
  823. $messageSuccess = __('Replication started successfully.');
  824. $messageError = __('Error starting replication.');
  825. break;
  826. case 'stop':
  827. $messageSuccess = __('Replication stopped successfully.');
  828. $messageError = __('Error stopping replication.');
  829. break;
  830. case 'reset':
  831. $messageSuccess = __('Replication resetting successfully.');
  832. $messageError = __('Error resetting replication.');
  833. break;
  834. default:
  835. $messageSuccess = __('Success.');
  836. $messageError = __('Error.');
  837. break;
  838. }
  839. } elseif (isset($_REQUEST['sr_slave_skip_error'])) {
  840. $result = PMA_handleRequestForSlaveSkipError();
  841. }
  842. if ($refresh) {
  843. $response = PMA_Response::getInstance();
  844. if ($response->isAjax()) {
  845. $response->isSuccess($result);
  846. $response->addJSON(
  847. 'message',
  848. $result ? PMA_Message::success($messageSuccess) : PMA_Message::error($messageError)
  849. );
  850. } else {
  851. PMA_sendHeaderLocation(
  852. $GLOBALS['cfg']['PmaAbsoluteUri'] . 'server_replication.php'
  853. . PMA_URL_getCommon($GLOBALS['url_params'], '&')
  854. );
  855. }
  856. }
  857. unset($refresh);
  858. }
  859. }
  860. /**
  861. * handle control requests for Slave Change Master
  862. *
  863. * @return boolean
  864. */
  865. function PMA_handleRequestForSlaveChangeMaster()
  866. {
  867. $sr = array();
  868. $_SESSION['replication']['m_username'] = $sr['username']
  869. = PMA_Util::sqlAddSlashes($_REQUEST['username']);
  870. $_SESSION['replication']['m_password'] = $sr['pma_pw']
  871. = PMA_Util::sqlAddSlashes($_REQUEST['pma_pw']);
  872. $_SESSION['replication']['m_hostname'] = $sr['hostname']
  873. = PMA_Util::sqlAddSlashes($_REQUEST['hostname']);
  874. $_SESSION['replication']['m_port'] = $sr['port']
  875. = PMA_Util::sqlAddSlashes($_REQUEST['port']);
  876. $_SESSION['replication']['m_correct'] = '';
  877. $_SESSION['replication']['sr_action_status'] = 'error';
  878. $_SESSION['replication']['sr_action_info'] = __('Unknown error');
  879. // Attempt to connect to the new master server
  880. $link_to_master = PMA_Replication_connectToMaster(
  881. $sr['username'], $sr['pma_pw'], $sr['hostname'], $sr['port']
  882. );
  883. if (! $link_to_master) {
  884. $_SESSION['replication']['sr_action_status'] = 'error';
  885. $_SESSION['replication']['sr_action_info'] = sprintf(
  886. __('Unable to connect to master %s.'),
  887. htmlspecialchars($sr['hostname'])
  888. );
  889. } else {
  890. // Read the current master position
  891. $position = PMA_Replication_Slave_binLogMaster($link_to_master);
  892. if (empty($position)) {
  893. $_SESSION['replication']['sr_action_status'] = 'error';
  894. $_SESSION['replication']['sr_action_info']
  895. = __(
  896. 'Unable to read master log position. '
  897. . 'Possible privilege problem on master.'
  898. );
  899. } else {
  900. $_SESSION['replication']['m_correct'] = true;
  901. if (! PMA_Replication_Slave_changeMaster(
  902. $sr['username'],
  903. $sr['pma_pw'],
  904. $sr['hostname'],
  905. $sr['port'],
  906. $position,
  907. true,
  908. false
  909. )
  910. ) {
  911. $_SESSION['replication']['sr_action_status'] = 'error';
  912. $_SESSION['replication']['sr_action_info']
  913. = __('Unable to change master!');
  914. } else {
  915. $_SESSION['replication']['sr_action_status'] = 'success';
  916. $_SESSION['replication']['sr_action_info'] = sprintf(
  917. __('Master server changed successfully to %s.'),
  918. htmlspecialchars($sr['hostname'])
  919. );
  920. }
  921. }
  922. }
  923. return $_SESSION['replication']['sr_action_status'] === 'success';
  924. }
  925. /**
  926. * handle control requests for Slave Server Control
  927. *
  928. * @return boolean
  929. */
  930. function PMA_handleRequestForSlaveServerControl()
  931. {
  932. if (empty($_REQUEST['sr_slave_control_parm'])) {
  933. $_REQUEST['sr_slave_control_parm'] = null;
  934. }
  935. if ($_REQUEST['sr_slave_action'] == 'reset') {
  936. $qStop = PMA_Replication_Slave_control("STOP");
  937. $qReset = $GLOBALS['dbi']->tryQuery("RESET SLAVE;");
  938. $qStart = PMA_Replication_Slave_control("START");
  939. $result = ($qStop !== false && $qStop !== -1 &&
  940. $qReset !== false && $qReset !== -1 &&
  941. $qStart !== false && $qStart !== -1);
  942. } else {
  943. $qControl = PMA_Replication_Slave_control(
  944. $_REQUEST['sr_slave_action'],
  945. $_REQUEST['sr_slave_control_parm']
  946. );
  947. $result = ($qControl !== false && $qControl !== -1);
  948. }
  949. return $result;
  950. }
  951. /**
  952. * handle control requests for Slave Skip Error
  953. *
  954. * @return boolean
  955. */
  956. function PMA_handleRequestForSlaveSkipError()
  957. {
  958. $count = 1;
  959. if (isset($_REQUEST['sr_skip_errors_count'])) {
  960. $count = $_REQUEST['sr_skip_errors_count'] * 1;
  961. }
  962. $qStop = PMA_Replication_Slave_control("STOP");
  963. $qSkip = $GLOBALS['dbi']->tryQuery(
  964. "SET GLOBAL SQL_SLAVE_SKIP_COUNTER = " . $count . ";"
  965. );
  966. $qStart = PMA_Replication_Slave_control("START");
  967. $result = ($qStop !== false && $qStop !== -1 &&
  968. $qSkip !== false && $qSkip !== -1 &&
  969. $qStart !== false && $qStart !== -1);
  970. return $result;
  971. }
  972. ?>