/** * Handles requests for executing a routine * * @return void */ function PMA_RTN_handleExecute() { global $_GET, $_POST, $_REQUEST, $GLOBALS, $db; /** * Handle all user requests other than the default of listing routines */ if (!empty($_REQUEST['execute_routine']) && !empty($_REQUEST['item_name'])) { // Build the queries $routine = PMA_RTN_getDataFromName($_REQUEST['item_name'], $_REQUEST['item_type'], false, true); if ($routine === false) { $message = __('Error in processing request:') . ' '; $message .= sprintf(PMA_RTE_getWord('not_found'), htmlspecialchars(PMA\libraries\Util::backquote($_REQUEST['item_name'])), htmlspecialchars(PMA\libraries\Util::backquote($db))); $message = Message::error($message); if ($GLOBALS['is_ajax_request']) { $response = PMA\libraries\Response::getInstance(); $response->setRequestStatus(false); $response->addJSON('message', $message); exit; } else { echo $message->getDisplay(); unset($_POST); } } $queries = array(); $end_query = array(); $args = array(); $all_functions = $GLOBALS['PMA_Types']->getAllFunctions(); for ($i = 0; $i < $routine['item_num_params']; $i++) { if (isset($_REQUEST['params'][$routine['item_param_name'][$i]])) { $value = $_REQUEST['params'][$routine['item_param_name'][$i]]; if (is_array($value)) { // is SET type $value = implode(',', $value); } $value = $GLOBALS['dbi']->escapeString($value); if (!empty($_REQUEST['funcs'][$routine['item_param_name'][$i]]) && in_array($_REQUEST['funcs'][$routine['item_param_name'][$i]], $all_functions)) { $queries[] = "SET @p{$i}=" . $_REQUEST['funcs'][$routine['item_param_name'][$i]] . "('{$value}');\n"; } else { $queries[] = "SET @p{$i}='{$value}';\n"; } $args[] = "@p{$i}"; } else { $args[] = "@p{$i}"; } if ($routine['item_type'] == 'PROCEDURE') { if ($routine['item_param_dir'][$i] == 'OUT' || $routine['item_param_dir'][$i] == 'INOUT') { $end_query[] = "@p{$i} AS " . PMA\libraries\Util::backquote($routine['item_param_name'][$i]); } } } if ($routine['item_type'] == 'PROCEDURE') { $queries[] = "CALL " . PMA\libraries\Util::backquote($routine['item_name']) . "(" . implode(', ', $args) . ");\n"; if (count($end_query)) { $queries[] = "SELECT " . implode(', ', $end_query) . ";\n"; } } else { $queries[] = "SELECT " . PMA\libraries\Util::backquote($routine['item_name']) . "(" . implode(', ', $args) . ") " . "AS " . PMA\libraries\Util::backquote($routine['item_name']) . ";\n"; } // Get all the queries as one SQL statement $multiple_query = implode("", $queries); $outcome = true; $affected = 0; // Execute query if (!$GLOBALS['dbi']->tryMultiQuery($multiple_query)) { $outcome = false; } // Generate output if ($outcome) { // Pass the SQL queries through the "pretty printer" $output = PMA\libraries\Util::formatSql(implode($queries, "\n")); // Display results $output .= "<fieldset><legend>"; $output .= sprintf(__('Execution results of routine %s'), PMA\libraries\Util::backquote(htmlspecialchars($routine['item_name']))); $output .= "</legend>"; $nbResultsetToDisplay = 0; do { $result = $GLOBALS['dbi']->storeResult(); $num_rows = $GLOBALS['dbi']->numRows($result); if ($result !== false && $num_rows > 0) { $output .= "<table><tr>"; foreach ($GLOBALS['dbi']->getFieldsMeta($result) as $field) { $output .= "<th>"; $output .= htmlspecialchars($field->name); $output .= "</th>"; } $output .= "</tr>"; $color_class = 'odd'; while ($row = $GLOBALS['dbi']->fetchAssoc($result)) { $output .= "<tr>" . browseRow($row, $color_class) . "</tr>"; $color_class = $color_class == 'odd' ? 'even' : 'odd'; } $output .= "</table>"; $nbResultsetToDisplay++; $affected = $num_rows; } if (!$GLOBALS['dbi']->moreResults()) { break; } $output .= "<br/>"; $GLOBALS['dbi']->freeResult($result); } while ($GLOBALS['dbi']->nextResult()); $output .= "</fieldset>"; $message = __('Your SQL query has been executed successfully.'); if ($routine['item_type'] == 'PROCEDURE') { $message .= '<br />'; // TODO : message need to be modified according to the // output from the routine $message .= sprintf(_ngettext('%d row affected by the last statement inside the ' . 'procedure.', '%d rows affected by the last statement inside the ' . 'procedure.', $affected), $affected); } $message = Message::success($message); if ($nbResultsetToDisplay == 0) { $notice = __('MySQL returned an empty result set (i.e. zero rows).'); $output .= Message::notice($notice)->getDisplay(); } } else { $output = ''; $message = Message::error(sprintf(__('The following query has failed: "%s"'), htmlspecialchars($multiple_query)) . '<br /><br />' . __('MySQL said: ') . $GLOBALS['dbi']->getError(null)); } // Print/send output if ($GLOBALS['is_ajax_request']) { $response = PMA\libraries\Response::getInstance(); $response->setRequestStatus($message->isSuccess()); $response->addJSON('message', $message->getDisplay() . $output); $response->addJSON('dialog', false); exit; } else { echo $message->getDisplay(), $output; if ($message->isError()) { // At least one query has failed, so shouldn't // execute any more queries, so we quit. exit; } unset($_POST); // Now deliberately fall through to displaying the routines list } return; } else { if (!empty($_GET['execute_dialog']) && !empty($_GET['item_name'])) { /** * Display the execute form for a routine. */ $routine = PMA_RTN_getDataFromName($_GET['item_name'], $_GET['item_type'], true, true); if ($routine !== false) { $form = PMA_RTN_getExecuteForm($routine); if ($GLOBALS['is_ajax_request'] == true) { $title = __("Execute routine") . " " . PMA\libraries\Util::backquote(htmlentities($_GET['item_name'], ENT_QUOTES)); $response = PMA\libraries\Response::getInstance(); $response->addJSON('message', $form); $response->addJSON('title', $title); $response->addJSON('dialog', true); } else { echo "\n\n<h2>" . __("Execute routine") . "</h2>\n\n"; echo $form; } exit; } else { if ($GLOBALS['is_ajax_request'] == true) { $message = __('Error in processing request:') . ' '; $message .= sprintf(PMA_RTE_getWord('not_found'), htmlspecialchars(PMA\libraries\Util::backquote($_REQUEST['item_name'])), htmlspecialchars(PMA\libraries\Util::backquote($db))); $message = Message::error($message); $response = PMA\libraries\Response::getInstance(); $response->setRequestStatus(false); $response->addJSON('message', $message); exit; } } } } }
/** * Handles requests for executing a routine */ function PMA_RTN_handleExecute() { global $_GET, $_POST, $_REQUEST, $GLOBALS, $db, $cfg; /** * Handle all user requests other than the default of listing routines */ if (!empty($_REQUEST['execute_routine']) && !empty($_REQUEST['item_name'])) { // Build the queries $routine = PMA_RTN_getDataFromName($_REQUEST['item_name'], $_REQUEST['item_type'], false); if ($routine !== false) { $queries = array(); $end_query = array(); $args = array(); for ($i = 0; $i < $routine['item_num_params']; $i++) { if (isset($_REQUEST['params'][$routine['item_param_name'][$i]])) { $value = $_REQUEST['params'][$routine['item_param_name'][$i]]; if (is_array($value)) { // is SET type $value = implode(',', $value); } $value = PMA_sqlAddSlashes($value); if (!empty($_REQUEST['funcs'][$routine['item_param_name'][$i]]) && in_array($_REQUEST['funcs'][$routine['item_param_name'][$i]], $cfg['Functions'])) { $queries[] = "SET @p{$i}={$_REQUEST['funcs'][$routine['item_param_name'][$i]]}('{$value}');\n"; } else { $queries[] = "SET @p{$i}='{$value}';\n"; } $args[] = "@p{$i}"; } else { $args[] = "@p{$i}"; } if ($routine['item_type'] == 'PROCEDURE') { if ($routine['item_param_dir'][$i] == 'OUT' || $routine['item_param_dir'][$i] == 'INOUT') { $end_query[] = "@p{$i} AS " . PMA_backquote($routine['item_param_name'][$i]); } } } if ($routine['item_type'] == 'PROCEDURE') { $queries[] = "CALL " . PMA_backquote($routine['item_name']) . "(" . implode(', ', $args) . ");\n"; if (count($end_query)) { $queries[] = "SELECT " . implode(', ', $end_query) . ";\n"; } } else { $queries[] = "SELECT " . PMA_backquote($routine['item_name']) . "(" . implode(', ', $args) . ") " . "AS " . PMA_backquote($routine['item_name']) . ";\n"; } // Execute the queries $affected = 0; $result = null; $outcome = true; foreach ($queries as $query) { $resource = PMA_DBI_try_query($query); if ($resource === false) { $outcome = false; break; } while (true) { if (!PMA_DBI_more_results()) { break; } PMA_DBI_next_result(); } if (substr($query, 0, 6) == 'SELECT') { $result = $resource; } else { if (substr($query, 0, 4) == 'CALL') { $result = $resource ? $resource : $result; $affected = PMA_DBI_affected_rows() - PMA_DBI_num_rows($resource); } } } // Generate output if ($outcome) { $message = __('Your SQL query has been executed successfully'); if ($routine['item_type'] == 'PROCEDURE') { $message .= '<br />'; $message .= sprintf(_ngettext('%d row affected by the last statement inside the procedure', '%d rows affected by the last statement inside the procedure', $affected), $affected); } $message = PMA_message::success($message); // Pass the SQL queries through the "pretty printer" $output = '<code class="sql" style="margin-bottom: 1em;">'; $output .= PMA_SQP_formatHtml(PMA_SQP_parse(implode($queries))); $output .= '</code>'; // Display results if ($result) { $output .= "<fieldset><legend>"; $output .= sprintf(__('Execution results of routine %s'), PMA_backquote(htmlspecialchars($routine['item_name']))); $output .= "</legend>"; $output .= "<table><tr>"; foreach (PMA_DBI_get_fields_meta($result) as $key => $field) { $output .= "<th>"; $output .= htmlspecialchars($field->name); $output .= "</th>"; } $output .= "</tr>"; // Stored routines can only ever return ONE ROW. $data = PMA_DBI_fetch_single_row($result); foreach ($data as $key => $value) { if ($value === null) { $value = '<i>NULL</i>'; } else { $value = htmlspecialchars($value); } $output .= "<td class='odd'>" . $value . "</td>"; } $output .= "</table></fieldset>"; } else { $notice = __('MySQL returned an empty result set (i.e. zero rows).'); $output .= PMA_message::notice($notice)->getDisplay(); } } else { $output = ''; $message = PMA_message::error(sprintf(__('The following query has failed: "%s"'), $query) . '<br /><br />' . __('MySQL said: ') . PMA_DBI_getError(null)); } // Print/send output if ($GLOBALS['is_ajax_request']) { $extra_data = array('dialog' => false); PMA_ajaxResponse($message->getDisplay() . $output, $message->isSuccess(), $extra_data); } else { echo $message->getDisplay() . $output; if ($message->isError()) { // At least one query has failed, so shouldn't // execute any more queries, so we quit. exit; } unset($_POST); // Now deliberately fall through to displaying the routines list } } else { $message = __('Error in processing request') . ' : '; $message .= sprintf(PMA_RTE_getWord('not_found'), htmlspecialchars(PMA_backquote($_REQUEST['item_name'])), htmlspecialchars(PMA_backquote($db))); $message = PMA_message::error($message); if ($GLOBALS['is_ajax_request']) { PMA_ajaxResponse($message, $message->isSuccess()); } else { echo $message->getDisplay(); unset($_POST); } } } else { if (!empty($_GET['execute_dialog']) && !empty($_GET['item_name'])) { /** * Display the execute form for a routine. */ $routine = PMA_RTN_getDataFromName($_GET['item_name'], $_GET['item_type'], true); if ($routine !== false) { $form = PMA_RTN_getExecuteForm($routine); if ($GLOBALS['is_ajax_request'] == true) { $extra_data = array(); $extra_data['dialog'] = true; $extra_data['title'] = __("Execute routine") . " "; $extra_data['title'] .= PMA_backquote(htmlentities($_GET['item_name'], ENT_QUOTES)); PMA_ajaxResponse($form, true, $extra_data); } else { echo "\n\n<h2>" . __("Execute routine") . "</h2>\n\n"; echo $form; include './libraries/footer.inc.php'; // exit; } } else { if ($GLOBALS['is_ajax_request'] == true) { $message = __('Error in processing request') . ' : '; $message .= sprintf(PMA_RTE_getWord('not_found'), htmlspecialchars(PMA_backquote($_REQUEST['item_name'])), htmlspecialchars(PMA_backquote($db))); $message = PMA_message::error($message); PMA_ajaxResponse($message, false); } } } } }
/** * Creates the contents for a row in the list of routines * * @param array $routine An array of routine data * @param string $rowclass Empty or one of ['even'|'odd'] * * @return string HTML code of a row for the list of routines */ function PMA_RTN_getRowForList($routine, $rowclass = '') { global $ajax_class, $url_query, $db, $titles; $sql_drop = sprintf('DROP %s IF EXISTS %s', $routine['ROUTINE_TYPE'], PMA_backquote($routine['SPECIFIC_NAME'])); $type_link = "item_type={$routine['ROUTINE_TYPE']}"; $retval = " <tr class='noclick {$rowclass}'>\n"; $retval .= " <td>\n"; $retval .= " <span class='drop_sql hide'>{$sql_drop}</span>\n"; $retval .= " <strong>\n"; $retval .= " " . htmlspecialchars($routine['SPECIFIC_NAME']) . "\n"; $retval .= " </strong>\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; if ($routine['ROUTINE_DEFINITION'] !== null && PMA_currentUserHasPrivilege('ALTER ROUTINE', $db) && PMA_currentUserHasPrivilege('CREATE ROUTINE', $db)) { $retval .= ' <a ' . $ajax_class['edit'] . ' href="db_routines.php?' . $url_query . '&edit_item=1' . '&item_name=' . urlencode($routine['SPECIFIC_NAME']) . '&' . $type_link . '">' . $titles['Edit'] . "</a>\n"; } else { $retval .= " {$titles['NoEdit']}\n"; } $retval .= " </td>\n"; $retval .= " <td>\n"; if ($routine['ROUTINE_DEFINITION'] !== null && PMA_currentUserHasPrivilege('EXECUTE', $db)) { // Check if he routine has any input parameters. If it does, // we will show a dialog to get values for these parameters, // otherwise we can execute it directly. $routine_details = PMA_RTN_getDataFromName($routine['SPECIFIC_NAME'], $routine['ROUTINE_TYPE'], false); if ($routine !== false) { $execute_action = 'execute_routine'; for ($i = 0; $i < $routine_details['item_num_params']; $i++) { if ($routine_details['item_type'] == 'PROCEDURE' && $routine_details['item_param_dir'][$i] == 'OUT') { continue; } $execute_action = 'execute_dialog'; break; } $retval .= ' <a ' . $ajax_class['exec'] . ' href="db_routines.php?' . $url_query . '&' . $execute_action . '=1' . '&item_name=' . urlencode($routine['SPECIFIC_NAME']) . '&' . $type_link . '">' . $titles['Execute'] . "</a>\n"; } } else { $retval .= " {$titles['NoExecute']}\n"; } $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= ' <a ' . $ajax_class['export'] . ' href="db_routines.php?' . $url_query . '&export_item=1' . '&item_name=' . urlencode($routine['SPECIFIC_NAME']) . '&' . $type_link . '">' . $titles['Export'] . "</a>\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; if (PMA_currentUserHasPrivilege('ALTER ROUTINE', $db)) { $retval .= ' <a ' . $ajax_class['drop'] . ' href="sql.php?' . $url_query . '&sql_query=' . urlencode($sql_drop) . '&goto=db_routines.php' . urlencode("?db={$db}") . '" >' . $titles['Drop'] . "</a>\n"; } else { $retval .= " {$titles['NoDrop']}\n"; } $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= " {$routine['ROUTINE_TYPE']}\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= " " . htmlspecialchars($routine['DTD_IDENTIFIER']) . "\n"; $retval .= " </td>\n"; $retval .= " </tr>\n"; return $retval; }
/** * Creates the contents for a row in the list of routines * * @param array $routine An array of routine data * @param string $rowclass Empty or one of ['even'|'odd'] * * @return string HTML code of a row for the list of routines */ function PMA_RTN_getRowForList($routine, $rowclass = '') { global $ajax_class, $url_query, $db, $titles; $sql_drop = sprintf('DROP %s IF EXISTS %s', $routine['ROUTINE_TYPE'], PMA_Util::backquote($routine['SPECIFIC_NAME'])); $type_link = "item_type={$routine['ROUTINE_TYPE']}"; $retval = " <tr class='noclick {$rowclass}'>\n"; $retval .= " <td>\n"; $retval .= " <span class='drop_sql hide'>" . htmlspecialchars($sql_drop) . "</span>\n"; $retval .= " <strong>\n"; $retval .= " " . htmlspecialchars($routine['SPECIFIC_NAME']) . "\n"; $retval .= " </strong>\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; if ($routine['ROUTINE_DEFINITION'] !== null) { $retval .= ' <a ' . $ajax_class['edit'] . ' href="db_routines.php?' . $url_query . '&edit_item=1' . '&item_name=' . urlencode($routine['SPECIFIC_NAME']) . '&' . $type_link . '">' . $titles['Edit'] . "</a>\n"; } else { $retval .= " {$titles['NoEdit']}\n"; } $retval .= " </td>\n"; $retval .= " <td>\n"; // There is a problem with PMA_Util::currentUserHasPrivilege(): // it does not detect all kinds of privileges, for example // a direct privilege on a specific routine. So, at this point, // we show the Execute link, hoping that the user has the correct rights. // Also, information_schema might be hiding the ROUTINE_DEFINITION // but a routine with no input parameters can be nonetheless executed. // Check if he routine has any input parameters. If it does, // we will show a dialog to get values for these parameters, // otherwise we can execute it directly. $routine_details = PMA_RTN_getDataFromName($routine['SPECIFIC_NAME'], $routine['ROUTINE_TYPE'], false); if ($routine !== false) { $execute_action = 'execute_routine'; for ($i = 0; $i < $routine_details['item_num_params']; $i++) { if ($routine_details['item_type'] == 'PROCEDURE' && $routine_details['item_param_dir'][$i] == 'OUT') { continue; } $execute_action = 'execute_dialog'; break; } $retval .= ' <a ' . $ajax_class['exec'] . ' href="db_routines.php?' . $url_query . '&' . $execute_action . '=1' . '&item_name=' . urlencode($routine['SPECIFIC_NAME']) . '&' . $type_link . '">' . $titles['Execute'] . "</a>\n"; } $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= ' <a ' . $ajax_class['export'] . ' href="db_routines.php?' . $url_query . '&export_item=1' . '&item_name=' . urlencode($routine['SPECIFIC_NAME']) . '&' . $type_link . '">' . $titles['Export'] . "</a>\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= ' <a ' . $ajax_class['drop'] . ' href="sql.php?' . $url_query . '&sql_query=' . urlencode($sql_drop) . '&goto=db_routines.php' . urlencode("?db={$db}") . '" >' . $titles['Drop'] . "</a>\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= " {$routine['ROUTINE_TYPE']}\n"; $retval .= " </td>\n"; $retval .= " <td>\n"; $retval .= " " . htmlspecialchars($routine['DTD_IDENTIFIER']) . "\n"; $retval .= " </td>\n"; $retval .= " </tr>\n"; return $retval; }