Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 803 lines (756 sloc) 28.917 kb
2c445a8 Extensibility basics
jakubvrana authored
1 <?php
c64c4fd Adminer class
jakubvrana authored
2 class Adminer {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
3 /** @var array operators used in select, null for all operators */
4 var $operators;
c64c4fd Adminer class
jakubvrana authored
5
6 /** Name in title and navigation
7 * @return string
8 */
9 function name() {
b349612 Remove useless translations
jakubvrana authored
10 return "Adminer";
c64c4fd Adminer class
jakubvrana authored
11 }
12
13 /** Connection parameters
14 * @return array ($server, $username, $password)
15 */
16 function credentials() {
49565e0 Jakub Vrána Rename variables to avoid conflict with Adminer 2 sessions and enabled r...
authored
17 return array(SERVER, $_GET["username"], get_session("pwds"));
c64c4fd Adminer class
jakubvrana authored
18 }
19
95b4ea4 Permanent login
jakubvrana authored
20 /** Get key used for permanent login
21 * @return string cryptic string which gets combined with password
22 */
23 function permanentLogin() {
4ba2d85 Jakub Vrána Allow permanent login without customization
authored
24 return password_file();
95b4ea4 Permanent login
jakubvrana authored
25 }
26
c64c4fd Adminer class
jakubvrana authored
27 /** Identifier of selected database
28 * @return string
29 */
30 function database() {
3022dcb Define DB
jakubvrana authored
31 // should be used everywhere instead of DB
32 return DB;
c64c4fd Adminer class
jakubvrana authored
33 }
34
9db4259 Jakub Vrána Introduce Adminer::headers method
authored
35 /** Headers to send before HTML output
36 * @return null
37 */
38 function headers() {
b127566 Jakub Vrána Comment
authored
39 header("X-Frame-Options: deny"); // ClickJacking protection in IE8, Safari 4, Chrome 2, Firefox 3.6.9
0f3a525 Jakub Vrána Uses own XSS protection
authored
40 header("X-XSS-Protection: 0"); // prevents introducing XSS in IE8 by removing safe parts of the page
9db4259 Jakub Vrána Introduce Adminer::headers method
authored
41 }
42
c64c4fd Adminer class
jakubvrana authored
43 /** Print login form
44 * @return null
45 */
3f5b683 Reintegrate sqlite branch
jakubvrana authored
46 function loginForm() {
b0d637b Jakub Vrána Avoid fatal errors
authored
47 global $drivers;
2faa08c Customize login and login form
jakubvrana authored
48 ?>
0205440 HTML whitespace
jakubvrana authored
49 <table cellspacing="0">
1d47454 Jakub Vrána Hide credentials for SQLite
authored
50 <tr><th><?php echo lang('System'); ?><td><?php echo html_select("driver", $drivers, DRIVER, "loginDriver(this);"); ?>
3f5b683 Reintegrate sqlite branch
jakubvrana authored
51 <tr><th><?php echo lang('Server'); ?><td><input name="server" value="<?php echo h(SERVER); ?>">
4269b7b Auto-focus user-name in login form
jakubvrana authored
52 <tr><th><?php echo lang('Username'); ?><td><input id="username" name="username" value="<?php echo h($_GET["username"]); ?>">
0205440 HTML whitespace
jakubvrana authored
53 <tr><th><?php echo lang('Password'); ?><td><input type="password" name="password">
54 </table>
4269b7b Auto-focus user-name in login form
jakubvrana authored
55 <script type="text/javascript">
1d47454 Jakub Vrána Hide credentials for SQLite
authored
56 var username = document.getElementById('username');
57 username.focus();
58 username.form['driver'].onchange();
4269b7b Auto-focus user-name in login form
jakubvrana authored
59 </script>
2faa08c Customize login and login form
jakubvrana authored
60 <?php
8474399 Move Login button to customization
jakubvrana authored
61 echo "<p><input type='submit' value='" . lang('Login') . "'>\n";
4ba2d85 Jakub Vrána Allow permanent login without customization
authored
62 echo checkbox("permanent", 1, $_COOKIE["adminer_permanent"], lang('Permanent login')) . "\n";
2faa08c Customize login and login form
jakubvrana authored
63 }
c64c4fd Adminer class
jakubvrana authored
64
65 /** Authorize the user
66 * @param string
67 * @param string
68 * @return bool
69 */
70 function login($login, $password) {
71 return true;
97b8c7b Display images in Editor
jakubvrana authored
72 }
c64c4fd Adminer class
jakubvrana authored
73
74 /** Table caption used in navigation and headings
75 * @param array result of SHOW TABLE STATUS
76 * @return string
77 */
78 function tableName($tableStatus) {
689699a Shortcut for htmlspecialchars
jakubvrana authored
79 return h($tableStatus["Name"]);
c64c4fd Adminer class
jakubvrana authored
80 }
81
82 /** Field caption used in select and edit
83 * @param array single field returned from fields()
6c97b80 Display only first five columns in Editor example
jakubvrana authored
84 * @param int order of column in select
c64c4fd Adminer class
jakubvrana authored
85 * @return string
86 */
6c97b80 Display only first five columns in Editor example
jakubvrana authored
87 function fieldName($field, $order = 0) {
689699a Shortcut for htmlspecialchars
jakubvrana authored
88 return '<span title="' . h($field["full_type"]) . '">' . h($field["field"]) . '</span>';
c64c4fd Adminer class
jakubvrana authored
89 }
90
f2ed237 Display table links above table structure
jakubvrana authored
91 /** Print links after select heading
c64c4fd Adminer class
jakubvrana authored
92 * @param array result of SHOW TABLE STATUS
294b10b Highlight current link
jakubvrana authored
93 * @param string new item options, NULL for no new item
f2ed237 Display table links above table structure
jakubvrana authored
94 * @return null
c64c4fd Adminer class
jakubvrana authored
95 */
f2ed237 Display table links above table structure
jakubvrana authored
96 function selectLinks($tableStatus, $set = "") {
294b10b Highlight current link
jakubvrana authored
97 echo '<p class="tabs">';
2d8a2de Change table operations descriptions
jakubvrana authored
98 $links = array("select" => lang('Select data'), "table" => lang('Show structure'));
da6f1f8 Jakub Vrána Driver specific view detection
authored
99 if (is_view($tableStatus)) {
294b10b Highlight current link
jakubvrana authored
100 $links["view"] = lang('Alter view');
3f5b683 Reintegrate sqlite branch
jakubvrana authored
101 } else {
102 $links["create"] = lang('Alter table');
f2ed237 Display table links above table structure
jakubvrana authored
103 }
104 if (isset($set)) {
294b10b Highlight current link
jakubvrana authored
105 $links["edit"] = lang('New item');
106 }
107 foreach ($links as $key => $val) {
8ad4809 Jakub Vrána Use class="active" instead of <b>
authored
108 echo " <a href='" . h(ME) . "$key=" . urlencode($tableStatus["Name"]) . ($key == "edit" ? $set : "") . "'" . bold(isset($_GET[$key])) . ">$val</a>";
f2ed237 Display table links above table structure
jakubvrana authored
109 }
110 echo "\n";
c64c4fd Adminer class
jakubvrana authored
111 }
112
753909e Jakub Vrána Support for virtual foreign keys
authored
113 /** Get foreign keys for table
114 * @param string
115 * @return array same format as foreign_keys()
116 */
117 function foreignKeys($table) {
118 return foreign_keys($table);
119 }
120
c64c4fd Adminer class
jakubvrana authored
121 /** Find backward keys for table
122 * @param string
09e93de Move backward keys to Editor
jakubvrana authored
123 * @param string
124 * @return array $return[$target_table]["keys"][$key_name][$target_column] = $source_column; $return[$target_table]["name"] = $this->tableName($target_table);
c64c4fd Adminer class
jakubvrana authored
125 */
09e93de Move backward keys to Editor
jakubvrana authored
126 function backwardKeys($table, $tableName) {
c64c4fd Adminer class
jakubvrana authored
127 return array();
128 }
129
09e93de Move backward keys to Editor
jakubvrana authored
130 /** Print backward keys for row
131 * @param array result of $this->backwardKeys()
132 * @param array
133 * @return null
134 */
135 function backwardKeysPrint($backwardKeys, $row) {
136 }
137
c64c4fd Adminer class
jakubvrana authored
138 /** Query printed in select before execution
139 * @param string query to be executed
140 * @return string
141 */
142 function selectQuery($query) {
e672694 Jakub Vrána Rename $driver to $jush
authored
143 global $jush;
6585b23 Jakub Vrána Generic AJAX links
authored
144 return "<p><a href='" . h(remove_from_uri("page")) . "&amp;page=last' title='" . lang('Last page') . "'>&gt;&gt;</a> <code class='jush-$jush'>" . h(str_replace("\n", " ", $query)) . "</code> <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>\n";
c64c4fd Adminer class
jakubvrana authored
145 }
146
147 /** Description of a row in a table
148 * @param string
149 * @return string SQL expression, empty string for no description
150 */
151 function rowDescription($table) {
152 return "";
153 }
154
155 /** Get descriptions of selected data
156 * @param array all data to print
157 * @param array
158 * @return array
159 */
160 function rowDescriptions($rows, $foreignKeys) {
161 return $rows;
162 }
163
164 /** Value printed in select table
a0def47 Date localization
jakubvrana authored
165 * @param string HTML-escaped value to print
c64c4fd Adminer class
jakubvrana authored
166 * @param string link to foreign key
167 * @param array single field returned from fields()
168 * @return string
169 */
170 function selectVal($val, $link, $field) {
c64557a Jakub Vrána Support 'character varying'
authored
171 $return = ($val != "<i>NULL</i>" && ereg("char|binary", $field["type"]) && !ereg("var", $field["type"]) ? "<code>$val</code>" : $val);
5a73c01 Jakub Vrána Treat binary type as hex
authored
172 if (ereg('blob|bytea|raw|file', $field["type"]) && !is_utf8($val)) {
7197ab1 Jakub Vrána Report correct length of blob (bug #3070569)
authored
173 $return = lang('%d byte(s)', strlen(html_entity_decode($val, ENT_QUOTES)));
4921235 Hide edit functions in Editor
jakubvrana authored
174 }
12c042c Function htmlspecialchars now uses ENT_QUOTES
jakubvrana authored
175 return ($link ? "<a href='$link'>$return</a>" : $return);
c64c4fd Adminer class
jakubvrana authored
176 }
177
a0def47 Date localization
jakubvrana authored
178 /** Value conversion used in select and edit
179 * @param string
180 * @param array single field returned from fields()
2011428 Use LIKE operator in Editor
jakubvrana authored
181 * @return string
a0def47 Date localization
jakubvrana authored
182 */
183 function editVal($val, $field) {
5a73c01 Jakub Vrána Treat binary type as hex
authored
184 return (ereg("binary", $field["type"]) ? reset(unpack("H*", $val)) : $val);
a0def47 Date localization
jakubvrana authored
185 }
186
d24ad78 Select boxes customization
jakubvrana authored
187 /** Print columns box in select
188 * @param array result of selectColumnsProcess()
189 * @param array selectable columns
190 * @return null
191 */
192 function selectColumnsPrint($select, $columns) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
193 global $functions, $grouping;
dc667ea Hide select export and import
jakubvrana authored
194 print_fieldset("select", lang('Select'), $select);
d24ad78 Select boxes customization
jakubvrana authored
195 $i = 0;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
196 $fun_group = array(lang('Functions') => $functions, lang('Aggregation') => $grouping);
d24ad78 Select boxes customization
jakubvrana authored
197 foreach ($select as $key => $val) {
198 $val = $_GET["columns"][$key];
0698409 Utilize html_select
jakubvrana authored
199 echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, $val["fun"]);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
200 echo "(<select name='columns[$i][col]'><option>" . optionlist($columns, $val["col"], true) . "</select>)</div>\n";
d24ad78 Select boxes customization
jakubvrana authored
201 $i++;
202 }
3f5b683 Reintegrate sqlite branch
jakubvrana authored
203 echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, "", "this.nextSibling.nextSibling.onchange();");
204 echo "(<select name='columns[$i][col]' onchange='selectAddRow(this);'><option>" . optionlist($columns, null, true) . "</select>)</div>\n";
d24ad78 Select boxes customization
jakubvrana authored
205 echo "</div></fieldset>\n";
206 }
207
208 /** Print search box in select
209 * @param array result of selectSearchProcess()
210 * @param array selectable columns
211 * @param array
212 * @return null
213 */
214 function selectSearchPrint($where, $columns, $indexes) {
dc667ea Hide select export and import
jakubvrana authored
215 print_fieldset("search", lang('Search'), $where);
d24ad78 Select boxes customization
jakubvrana authored
216 foreach ($indexes as $i => $index) {
217 if ($index["type"] == "FULLTEXT") {
689699a Shortcut for htmlspecialchars
jakubvrana authored
218 echo "(<i>" . implode("</i>, <i>", array_map('h', $index["columns"])) . "</i>) AGAINST";
219 echo " <input name='fulltext[$i]' value='" . h($_GET["fulltext"][$i]) . "'>";
6b30cfa Separate checkbox
jakubvrana authored
220 echo checkbox("boolean[$i]", 1, isset($_GET["boolean"][$i]), "BOOL");
d24ad78 Select boxes customization
jakubvrana authored
221 echo "<br>\n";
222 }
223 }
224 $i = 0;
225 foreach ((array) $_GET["where"] as $val) {
7352c28 Replace strlen() by != ""
jakubvrana authored
226 if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
227 echo "<div><select name='where[$i][col]'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, $val["col"], true) . "</select>";
0698409 Utilize html_select
jakubvrana authored
228 echo html_select("where[$i][op]", $this->operators, $val["op"]);
689699a Shortcut for htmlspecialchars
jakubvrana authored
229 echo "<input name='where[$i][val]' value='" . h($val["val"]) . "'></div>\n";
d24ad78 Select boxes customization
jakubvrana authored
230 $i++;
231 }
232 }
3f5b683 Reintegrate sqlite branch
jakubvrana authored
233 echo "<div><select name='where[$i][col]' onchange='selectAddRow(this);'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, null, true) . "</select>";
675ac01 Jakub Vrána Ability to search by expression in select (bug #3158017)
authored
234 echo html_select("where[$i][op]", $this->operators, "=");
d24ad78 Select boxes customization
jakubvrana authored
235 echo "<input name='where[$i][val]'></div>\n";
236 echo "</div></fieldset>\n";
237 }
238
239 /** Print order box in select
240 * @param array result of selectOrderProcess()
241 * @param array selectable columns
242 * @param array
243 * @return null
244 */
245 function selectOrderPrint($order, $columns, $indexes) {
dc667ea Hide select export and import
jakubvrana authored
246 print_fieldset("sort", lang('Sort'), $order);
d24ad78 Select boxes customization
jakubvrana authored
247 $i = 0;
248 foreach ((array) $_GET["order"] as $key => $val) {
249 if (isset($columns[$val])) {
250 echo "<div><select name='order[$i]'><option>" . optionlist($columns, $val, true) . "</select>";
6b30cfa Separate checkbox
jakubvrana authored
251 echo checkbox("desc[$i]", 1, isset($_GET["desc"][$key]), lang('descending')) . "</div>\n";
d24ad78 Select boxes customization
jakubvrana authored
252 $i++;
253 }
254 }
3c5c0f0 Use camelCase in JavaScript
jakubvrana authored
255 echo "<div><select name='order[$i]' onchange='selectAddRow(this);'><option>" . optionlist($columns, null, true) . "</select>";
6b30cfa Separate checkbox
jakubvrana authored
256 echo checkbox("desc[$i]", 1, 0, lang('descending')) . "</div>\n";
d24ad78 Select boxes customization
jakubvrana authored
257 echo "</div></fieldset>\n";
258 }
259
260 /** Print limit box in select
261 * @param string result of selectLimitProcess()
262 * @return null
263 */
264 function selectLimitPrint($limit) {
265 echo "<fieldset><legend>" . lang('Limit') . "</legend><div>"; // <div> for easy styling
689699a Shortcut for htmlspecialchars
jakubvrana authored
266 echo "<input name='limit' size='3' value='" . h($limit) . "'>";
d24ad78 Select boxes customization
jakubvrana authored
267 echo "</div></fieldset>\n";
268 }
269
270 /** Print text length box in select
271 * @param string result of selectLengthProcess()
272 * @return null
273 */
274 function selectLengthPrint($text_length) {
275 if (isset($text_length)) {
276 echo "<fieldset><legend>" . lang('Text length') . "</legend><div>";
689699a Shortcut for htmlspecialchars
jakubvrana authored
277 echo '<input name="text_length" size="3" value="' . h($text_length) . '">';
d24ad78 Select boxes customization
jakubvrana authored
278 echo "</div></fieldset>\n";
279 }
280 }
281
282 /** Print action box in select
283 * @return null
284 */
285 function selectActionPrint() {
286 echo "<fieldset><legend>" . lang('Action') . "</legend><div>";
287 echo "<input type='submit' value='" . lang('Select') . "'>";
288 echo "</div></fieldset>\n";
289 }
290
1a6a73a Rename selectExtra to selectEmail
jakubvrana authored
291 /** Print extra text in the end of a select form
292 * @param array fields holding e-mails
1e55d47 User interface for e-mail {$name}
jakubvrana authored
293 * @param array selectable columns
1a6a73a Rename selectExtra to selectEmail
jakubvrana authored
294 * @return null
295 */
1e55d47 User interface for e-mail {$name}
jakubvrana authored
296 function selectEmailPrint($emailFields, $columns) {
1a6a73a Rename selectExtra to selectEmail
jakubvrana authored
297 }
298
d24ad78 Select boxes customization
jakubvrana authored
299 /** Process columns box in select
300 * @param array selectable columns
1e55d47 User interface for e-mail {$name}
jakubvrana authored
301 * @param array
d24ad78 Select boxes customization
jakubvrana authored
302 * @return array (array(select_expressions), array(group_expressions))
303 */
304 function selectColumnsProcess($columns, $indexes) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
305 global $functions, $grouping;
d24ad78 Select boxes customization
jakubvrana authored
306 $select = array(); // select expressions, empty for *
307 $group = array(); // expressions without aggregation - will be used for GROUP BY if an aggregation function is used
308 foreach ((array) $_GET["columns"] as $key => $val) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
309 if ($val["fun"] == "count" || (isset($columns[$val["col"]]) && (!$val["fun"] || in_array($val["fun"], $functions) || in_array($val["fun"], $grouping)))) {
d24ad78 Select boxes customization
jakubvrana authored
310 $select[$key] = apply_sql_function($val["fun"], (isset($columns[$val["col"]]) ? idf_escape($val["col"]) : "*"));
3f5b683 Reintegrate sqlite branch
jakubvrana authored
311 if (!in_array($val["fun"], $grouping)) {
d24ad78 Select boxes customization
jakubvrana authored
312 $group[] = $select[$key];
313 }
314 }
315 }
316 return array($select, $group);
317 }
318
319 /** Process search box in select
320 * @param array
321 * @param array
322 * @return array expressions to join by AND
323 */
07e1ae1 FOUND_ROWS only with GROUP BY
jakubvrana authored
324 function selectSearchProcess($fields, $indexes) {
7e644b4 Jakub Vrána Save bytes ($connection->quote shortcut)
authored
325 global $jush;
d24ad78 Select boxes customization
jakubvrana authored
326 $return = array();
327 foreach ($indexes as $i => $index) {
7352c28 Replace strlen() by != ""
jakubvrana authored
328 if ($index["type"] == "FULLTEXT" && $_GET["fulltext"][$i] != "") {
7e644b4 Jakub Vrána Save bytes ($connection->quote shortcut)
authored
329 $return[] = "MATCH (" . implode(", ", array_map('idf_escape', $index["columns"])) . ") AGAINST (" . q($_GET["fulltext"][$i]) . (isset($_GET["boolean"][$i]) ? " IN BOOLEAN MODE" : "") . ")";
d24ad78 Select boxes customization
jakubvrana authored
330 }
331 }
332 foreach ((array) $_GET["where"] as $val) {
7352c28 Replace strlen() by != ""
jakubvrana authored
333 if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
334 $cond = " $val[op]";
335 if (ereg('IN$', $val["op"])) {
336 $in = process_length($val["val"]);
337 $cond .= " (" . ($in != "" ? $in : "NULL") . ")";
675ac01 Jakub Vrána Ability to search by expression in select (bug #3158017)
authored
338 } elseif (!$val["op"]) {
339 $cond .= $val["val"]; // SQL injection
3f5b683 Reintegrate sqlite branch
jakubvrana authored
340 } elseif ($val["op"] == "LIKE %%") {
341 $cond = " LIKE " . $this->processInput($fields[$val["col"]], "%$val[val]%");
342 } elseif (!ereg('NULL$', $val["op"])) {
343 $cond .= " " . $this->processInput($fields[$val["col"]], $val["val"]);
344 }
7352c28 Replace strlen() by != ""
jakubvrana authored
345 if ($val["col"] != "") {
98b88eb Remove fulltext search without index
jakubvrana authored
346 $return[] = idf_escape($val["col"]) . $cond;
d24ad78 Select boxes customization
jakubvrana authored
347 } else {
98b88eb Remove fulltext search without index
jakubvrana authored
348 // find anywhere
349 $cols = array();
350 foreach ($fields as $name => $field) {
351 if (is_numeric($val["val"]) || !ereg('int|float|double|decimal', $field["type"])) {
d79b160 Illegal mix of collations
jakubvrana authored
352 $name = idf_escape($name);
782921b Jakub Vrána Finish SQLite
authored
353 $cols[] = ($jush == "sql" && ereg('char|text|enum|set', $field["type"]) && !ereg('^utf8', $field["collation"]) ? "CONVERT($name USING utf8)" : $name);
d24ad78 Select boxes customization
jakubvrana authored
354 }
355 }
d79b160 Illegal mix of collations
jakubvrana authored
356 $return[] = ($cols ? "(" . implode("$cond OR ", $cols) . "$cond)" : "0");
d24ad78 Select boxes customization
jakubvrana authored
357 }
358 }
359 }
360 return $return;
361 }
362
363 /** Process order box in select
364 * @param array
365 * @param array
366 * @return array expressions to join by comma
367 */
07e1ae1 FOUND_ROWS only with GROUP BY
jakubvrana authored
368 function selectOrderProcess($fields, $indexes) {
d24ad78 Select boxes customization
jakubvrana authored
369 $return = array();
370 foreach ((array) $_GET["order"] as $key => $val) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
371 if (isset($fields[$val]) || preg_match('~^((COUNT\\(DISTINCT |[A-Z0-9_]+\\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\\)|COUNT\\(\\*\\))$~', $val)) { //! MS SQL uses []
372 $return[] = (isset($fields[$val]) ? idf_escape($val) : $val) . (isset($_GET["desc"][$key]) ? " DESC" : "");
d24ad78 Select boxes customization
jakubvrana authored
373 }
374 }
375 return $return;
376 }
377
378 /** Process limit box in select
379 * @return string expression to use in LIMIT, will be escaped
380 */
381 function selectLimitProcess() {
382 return (isset($_GET["limit"]) ? $_GET["limit"] : "30");
383 }
384
385 /** Process length box in select
386 * @return string number of characters to shorten texts, will be escaped
387 */
388 function selectLengthProcess() {
389 return (isset($_GET["text_length"]) ? $_GET["text_length"] : "100");
390 }
391
c64c4fd Adminer class
jakubvrana authored
392 /** Process extras in select form
393 * @param array AND conditions
dea345c Substitute foreign keys in e-mail fields
jakubvrana authored
394 * @param array
c64c4fd Adminer class
jakubvrana authored
395 * @return bool true if processed, false to process other parts of form
396 */
dea345c Substitute foreign keys in e-mail fields
jakubvrana authored
397 function selectEmailProcess($where, $foreignKeys) {
c64c4fd Adminer class
jakubvrana authored
398 return false;
399 }
400
401 /** Query printed after execution in the message
402 * @param string executed query
403 * @return string
404 */
405 function messageQuery($query) {
e672694 Jakub Vrána Rename $driver to $jush
authored
406 global $jush;
be49e08 Improve session restarting
jakubvrana authored
407 restart_session();
c64c4fd Adminer class
jakubvrana authored
408 $id = "sql-" . count($_SESSION["messages"]);
49565e0 Jakub Vrána Rename variables to avoid conflict with Adminer 2 sessions and enabled r...
authored
409 $history = &get_session("queries");
2bd9b39 Jakub Vrána Save database drop to global history
authored
410 $history[$_GET["db"]][] = (strlen($query) > 1e6 // not DB - reset in drop database
411 ? ereg_replace('[\x80-\xFF]+$', '', substr($query, 0, 1e6)) . "\n..." // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment
412 : $query
413 ); //! respect $_GET["ns"]
d8c7ea9 Jakub Vrána Highlighting only inside <code>
authored
414 return " <a href='#$id' onclick=\"return !toggle('$id');\">" . lang('SQL command') . "</a><div id='$id' class='hidden'><pre><code class='jush-$jush'>" . shorten_utf8($query, 1000) . '</code></pre><p><a href="' . h(str_replace("db=" . urlencode(DB), "db=" . urlencode($_GET["db"]), ME) . 'sql=&history=' . (count($history[$_GET["db"]]) - 1)) . '">' . lang('Edit') . '</a></div>';
c64c4fd Adminer class
jakubvrana authored
415 }
416
417 /** Functions displayed in edit form
418 * @param array single field from fields()
419 * @return array
420 */
421 function editFunctions($field) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
422 global $edit_functions;
02f7521 Fix input onchange
jakubvrana authored
423 $return = ($field["null"] ? "NULL/" : "");
3f5b683 Reintegrate sqlite branch
jakubvrana authored
424 foreach ($edit_functions as $key => $functions) {
425 if (!$key || (!isset($_GET["call"]) && (isset($_GET["select"]) || where($_GET)))) { // relative functions
426 foreach ($functions as $pattern => $val) {
427 if (!$pattern || ereg($pattern, $field["type"])) {
428 $return .= "/$val";
429 }
430 }
309f681 Relative function concat
jakubvrana authored
431 }
4921235 Hide edit functions in Editor
jakubvrana authored
432 }
3f5b683 Reintegrate sqlite branch
jakubvrana authored
433 return explode("/", $return);
4921235 Hide edit functions in Editor
jakubvrana authored
434 }
c64c4fd Adminer class
jakubvrana authored
435
436 /** Get options to display edit field
437 * @param string table name
438 * @param array single field from fields()
e1abcda Treat tinyint(1) as boolean
jakubvrana authored
439 * @param string attributes to use inside the tag
440 * @param string
441 * @return string custom input field or empty string for default
c64c4fd Adminer class
jakubvrana authored
442 */
e1abcda Treat tinyint(1) as boolean
jakubvrana authored
443 function editInput($table, $field, $attrs, $value) {
ec0282b Enum editing
jakubvrana authored
444 if ($field["type"] == "enum") {
fe06908 Jakub Vrána Allow redefining editInput for enum (bug #3048711)
authored
445 return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "")
446 . ($field["null"] ? "<label><input type='radio'$attrs value=''" . (isset($value) || isset($_GET["select"]) ? "" : " checked") . "><i>NULL</i></label> " : "")
684e70d Jakub Vrána Search for empty enum
authored
447 . enum_input("radio", $attrs, $field, $value, 0) // 0 - empty
ec0282b Enum editing
jakubvrana authored
448 ;
449 }
450 return "";
4921235 Hide edit functions in Editor
jakubvrana authored
451 }
c64c4fd Adminer class
jakubvrana authored
452
453 /** Process sent input
454 * @param array single field from fields()
a0def47 Date localization
jakubvrana authored
455 * @param string
456 * @param string
c64c4fd Adminer class
jakubvrana authored
457 * @return string expression to use in a query
458 */
a0def47 Date localization
jakubvrana authored
459 function processInput($field, $value, $function = "") {
460 $name = $field["field"];
7e644b4 Jakub Vrána Save bytes ($connection->quote shortcut)
authored
461 $return = q($value);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
462 if (ereg('^(now|getdate|uuid)$', $function)) {
c64c4fd Adminer class
jakubvrana authored
463 $return = "$function()";
e4df0c6 Jakub Vrána MS SQL functions
authored
464 } elseif (ereg('^current_(date|timestamp)$', $function)) {
465 $return = $function;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
466 } elseif (ereg('^([+-]|\\|\\|)$', $function)) {
c64c4fd Adminer class
jakubvrana authored
467 $return = idf_escape($name) . " $function $return";
468 } elseif (ereg('^[+-] interval$', $function)) {
5002b89 Jakub Vrána Big numbers without E
authored
469 $return = idf_escape($name) . " $function " . (preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+$~i", $value) ? $value : $return);
309f681 Relative function concat
jakubvrana authored
470 } elseif (ereg('^(addtime|subtime|concat)$', $function)) {
c64c4fd Adminer class
jakubvrana authored
471 $return = "$function(" . idf_escape($name) . ", $return)";
5a73c01 Jakub Vrána Treat binary type as hex
authored
472 } elseif (ereg('^(md5|sha1|password|encrypt|hex)$', $function)) {
c64c4fd Adminer class
jakubvrana authored
473 $return = "$function($return)";
474 }
5a73c01 Jakub Vrána Treat binary type as hex
authored
475 if (ereg("binary", $field["type"])) {
476 $return = "unhex($return)";
477 }
c64c4fd Adminer class
jakubvrana authored
478 return $return;
a78c941 Empty value in Editor as NULL
jakubvrana authored
479 }
c64c4fd Adminer class
jakubvrana authored
480
e40612a Use radio in export
jakubvrana authored
481 /** Returns export output options
be3410f Jakub Vrána Simplify dumpOutput, dumpFormat and dumpData methods
authored
482 * @return array
e40612a Use radio in export
jakubvrana authored
483 */
be3410f Jakub Vrána Simplify dumpOutput, dumpFormat and dumpData methods
authored
484 function dumpOutput() {
e40612a Use radio in export
jakubvrana authored
485 $return = array('text' => lang('open'), 'file' => lang('save'));
486 if (function_exists('gzencode')) {
487 $return['gz'] = 'gzip';
488 }
489 if (function_exists('bzcompress')) {
490 $return['bz2'] = 'bzip2';
491 }
492 // ZipArchive requires temporary file, ZIP can be created by gzcompress - see PEAR File_Archive
be3410f Jakub Vrána Simplify dumpOutput, dumpFormat and dumpData methods
authored
493 return $return;
e40612a Use radio in export
jakubvrana authored
494 }
495
496 /** Returns export format options
be3410f Jakub Vrána Simplify dumpOutput, dumpFormat and dumpData methods
authored
497 * @return array
e40612a Use radio in export
jakubvrana authored
498 */
be3410f Jakub Vrána Simplify dumpOutput, dumpFormat and dumpData methods
authored
499 function dumpFormat() {
e225d22 Jakub Vrána TSV export and import (bug #3097657)
authored
500 return array('sql' => 'SQL', 'csv' => 'CSV,', 'csv;' => 'CSV;', 'tsv' => 'TSV');
e40612a Use radio in export
jakubvrana authored
501 }
502
095d472 Jakub Vrána Customizable export
authored
503 /** Export table structure
504 * @param string
505 * @param string
506 * @param bool
507 * @return null prints data
508 */
509 function dumpTable($table, $style, $is_view = false) {
510 if ($_POST["format"] != "sql") {
511 echo "\xef\xbb\xbf"; // UTF-8 byte order mark
512 if ($style) {
513 dump_csv(array_keys(fields($table)));
514 }
515 } elseif ($style) {
516 $create = create_sql($table, $_POST["auto_increment"]);
517 if ($create) {
518 if ($style == "DROP+CREATE") {
519 echo "DROP " . ($is_view ? "VIEW" : "TABLE") . " IF EXISTS " . table($table) . ";\n";
520 }
521 if ($is_view) {
522 // remove DEFINER with current user
523 $create = preg_replace('~^([A-Z =]+) DEFINER=`' . str_replace("@", "`@`", logged_user()) . '`~', '\\1', $create); //! proper escaping of user
524 }
525 echo ($style != "CREATE+ALTER" ? $create : ($is_view ? substr_replace($create, " OR REPLACE", 6, 0) : substr_replace($create, " IF NOT EXISTS", 12, 0))) . ";\n\n";
526 }
527 if ($style == "CREATE+ALTER" && !$is_view) {
528 // create procedure which iterates over original columns and adds new and removes old
529 $query = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, COLLATION_NAME, COLUMN_TYPE, EXTRA, COLUMN_COMMENT FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = " . q($table) . " ORDER BY ORDINAL_POSITION";
530 echo "DELIMITER ;;
531 CREATE PROCEDURE adminer_alter (INOUT alter_command text) BEGIN
532 DECLARE _column_name, _collation_name, after varchar(64) DEFAULT '';
533 DECLARE _column_type, _column_default text;
534 DECLARE _is_nullable char(3);
535 DECLARE _extra varchar(30);
536 DECLARE _column_comment varchar(255);
537 DECLARE done, set_after bool DEFAULT 0;
538 DECLARE add_columns text DEFAULT '";
539 $fields = array();
540 $after = "";
541 foreach (get_rows($query) as $row) {
542 $default = $row["COLUMN_DEFAULT"];
543 $row["default"] = (isset($default) ? q($default) : "NULL");
544 $row["after"] = q($after); //! rgt AFTER lft, lft AFTER id doesn't work
545 $row["alter"] = escape_string(idf_escape($row["COLUMN_NAME"])
546 . " $row[COLUMN_TYPE]"
547 . ($row["COLLATION_NAME"] ? " COLLATE $row[COLLATION_NAME]" : "")
548 . (isset($default) ? " DEFAULT " . ($default == "CURRENT_TIMESTAMP" ? $default : $row["default"]) : "")
549 . ($row["IS_NULLABLE"] == "YES" ? "" : " NOT NULL")
550 . ($row["EXTRA"] ? " $row[EXTRA]" : "")
551 . ($row["COLUMN_COMMENT"] ? " COMMENT " . q($row["COLUMN_COMMENT"]) : "")
552 . ($after ? " AFTER " . idf_escape($after) : " FIRST")
553 );
554 echo ", ADD $row[alter]";
555 $fields[] = $row;
556 $after = $row["COLUMN_NAME"];
557 }
558 echo "';
559 DECLARE columns CURSOR FOR $query;
560 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
561 SET @alter_table = '';
562 OPEN columns;
563 REPEAT
564 FETCH columns INTO _column_name, _column_default, _is_nullable, _collation_name, _column_type, _extra, _column_comment;
565 IF NOT done THEN
566 SET set_after = 1;
567 CASE _column_name";
568 foreach ($fields as $row) {
569 echo "
570 WHEN " . q($row["COLUMN_NAME"]) . " THEN
571 SET add_columns = REPLACE(add_columns, ', ADD $row[alter]', '');
572 IF NOT (_column_default <=> $row[default]) OR _is_nullable != '$row[IS_NULLABLE]' OR _collation_name != '$row[COLLATION_NAME]' OR _column_type != " . q($row["COLUMN_TYPE"]) . " OR _extra != '$row[EXTRA]' OR _column_comment != " . q($row["COLUMN_COMMENT"]) . " OR after != $row[after] THEN
573 SET @alter_table = CONCAT(@alter_table, ', MODIFY $row[alter]');
574 END IF;"; //! don't replace in comment
575 }
576 echo "
577 ELSE
578 SET @alter_table = CONCAT(@alter_table, ', DROP ', _column_name);
579 SET set_after = 0;
580 END CASE;
581 IF set_after THEN
582 SET after = _column_name;
583 END IF;
584 END IF;
585 UNTIL done END REPEAT;
586 CLOSE columns;
587 IF @alter_table != '' OR add_columns != '' THEN
588 SET alter_command = CONCAT(alter_command, 'ALTER TABLE " . table($table) . "', SUBSTR(CONCAT(add_columns, @alter_table), 2), ';\\n');
589 END IF;
590 END;;
591 DELIMITER ;
592 CALL adminer_alter(@adminer_alter);
593 DROP PROCEDURE adminer_alter;
594
595 ";
596 //! indexes
597 }
598 }
599 }
600
601 /** Export table data
602 * @param string
603 * @param string
be3410f Jakub Vrána Simplify dumpOutput, dumpFormat and dumpData methods
authored
604 * @param string
095d472 Jakub Vrána Customizable export
authored
605 * @return null prints data
606 */
be3410f Jakub Vrána Simplify dumpOutput, dumpFormat and dumpData methods
authored
607 function dumpData($table, $style, $query) {
095d472 Jakub Vrána Customizable export
authored
608 global $connection, $jush;
609 $max_packet = ($jush == "sqlite" ? 0 : 1048576); // default, minimum is 1024
610 if ($style) {
611 if ($_POST["format"] == "sql" && $style == "TRUNCATE+INSERT") {
612 echo truncate_sql($table) . ";\n";
613 }
614 $fields = fields($table);
be3410f Jakub Vrána Simplify dumpOutput, dumpFormat and dumpData methods
authored
615 $result = $connection->query($query, 1); // 1 - MYSQLI_USE_RESULT //! enum and set as numbers
095d472 Jakub Vrána Customizable export
authored
616 if ($result) {
617 $insert = "";
618 $buffer = "";
619 while ($row = $result->fetch_assoc()) {
620 if ($_POST["format"] != "sql") {
621 dump_csv($row);
622 } else {
623 if (!$insert) {
624 $insert = "INSERT INTO " . table($table) . " (" . implode(", ", array_map('idf_escape', array_keys($row))) . ") VALUES";
625 }
626 foreach ($row as $key => $val) {
627 $row[$key] = (isset($val) ? (ereg('int|float|double|decimal', $fields[$key]["type"]) ? $val : q($val)) : "NULL"); //! columns looking like functions
628 }
629 $s = implode(",\t", $row);
630 if ($style == "INSERT+UPDATE") {
631 $set = array();
632 foreach ($row as $key => $val) {
633 $set[] = idf_escape($key) . " = $val";
634 }
635 echo "$insert ($s) ON DUPLICATE KEY UPDATE " . implode(", ", $set) . ";\n";
636 } else {
637 $s = ($max_packet ? "\n" : " ") . "($s)";
638 if (!$buffer) {
639 $buffer = $insert . $s;
640 } elseif (strlen($buffer) + 2 + strlen($s) < $max_packet) { // 2 - separator and terminator length
641 $buffer .= ",$s";
642 } else {
643 $buffer .= ";\n";
644 echo $buffer;
645 $buffer = $insert . $s;
646 }
647 }
648 }
649 }
650 if ($_POST["format"] == "sql" && $style != "INSERT+UPDATE" && $buffer) {
651 $buffer .= ";\n";
652 echo $buffer;
653 }
164cd3b Jakub Vrána Report errors in data export
authored
654 } elseif ($_POST["format"] == "sql") {
655 echo "-- " . str_replace("\n", " ", $connection->error) . "\n";
095d472 Jakub Vrána Customizable export
authored
656 }
657 }
658 }
659
660 /** Send headers for export
661 * @param string
662 * @param bool
663 * @return string extension
664 */
665 function dumpHeaders($identifier, $multi_table = false) {
666 $filename = ($identifier != "" ? friendly_url($identifier) : "adminer");
667 $output = $_POST["output"];
668 $ext = ($_POST["format"] == "sql" ? "sql" : ($multi_table ? "tar" : "csv")); // multiple CSV packed to TAR
669 header("Content-Type: " .
670 ($output == "bz2" ? "application/x-bzip" :
671 ($output == "gz" ? "application/x-gzip" :
672 ($ext == "tar" ? "application/x-tar" :
673 ($ext == "sql" || $output != "file" ? "text/plain" : "text/csv") . "; charset=utf-8"
674 ))));
675 if ($output != "text") {
676 header("Content-Disposition: attachment; filename=$filename.$ext" . ($output != "file" && !ereg('[^0-9a-z]', $output) ? ".$output" : ""));
677 }
678 session_write_close();
679 if ($_POST["output"] == "bz2") {
680 ob_start('bzcompress', 1e6);
681 }
682 if ($_POST["output"] == "gz") {
683 ob_start('gzencode', 1e6);
684 }
685 return $ext;
e40612a Use radio in export
jakubvrana authored
686 }
687
7416164 Jakub Vrána Homepage customization
authored
688 /** Print homepage
689 * @return bool whether to print default homepage
690 */
691 function homepage() {
692 echo '<p>' . ($_GET["ns"] == "" ? '<a href="' . h(ME) . 'database=">' . lang('Alter database') . "</a>\n" : "");
693 if (support("scheme")) {
694 echo "<a href='" . h(ME) . "scheme='>" . ($_GET["ns"] != "" ? lang('Alter schema') : lang('Create schema')) . "</a>\n";
695 }
696 return true;
697 }
698
c64c4fd Adminer class
jakubvrana authored
699 /** Prints navigation after Adminer title
d49903b Jakub Vrána Report invalid schema
authored
700 * @param string can be "auth" if there is no database connection, "db" if there is no database selected, "ns" with invalid schema
c64c4fd Adminer class
jakubvrana authored
701 * @return null
702 */
703 function navigation($missing) {
e672694 Jakub Vrána Rename $driver to $jush
authored
704 global $VERSION, $connection, $token, $jush, $drivers;
d3227c9 Move <h1> to $adminer->navigation
jakubvrana authored
705 ?>
706 <h1>
707 <a href="http://www.adminer.org/" id="h1"><?php echo $this->name(); ?></a>
708 <span class="version"><?php echo $VERSION; ?></span>
709 <a href="http://www.adminer.org/#download" id="version"><?php echo (version_compare($VERSION, $_COOKIE["adminer_version"]) < 0 ? h($_COOKIE["adminer_version"]) : ""); ?></a>
710 </h1>
711 <?php
605b093 Jakub Vrána List authentications
authored
712 if ($missing == "auth") {
713 $first = true;
49565e0 Jakub Vrána Rename variables to avoid conflict with Adminer 2 sessions and enabled r...
authored
714 foreach ((array) $_SESSION["pwds"] as $driver => $servers) {
605b093 Jakub Vrána List authentications
authored
715 foreach ($servers as $server => $usernames) {
716 foreach ($usernames as $username => $password) {
717 if (isset($password)) {
718 if ($first) {
9bb0fdc Jakub Vrána Display login in auth form (regression)
authored
719 echo "<p onclick='eventStop(event);'>\n";
605b093 Jakub Vrána List authentications
authored
720 $first = false;
721 }
e672694 Jakub Vrána Rename $driver to $jush
authored
722 echo "<a href='" . h(auth_url($driver, $server, $username)) . "'>($drivers[$driver]) " . h($username . ($server != "" ? "@$server" : "")) . "</a><br>\n";
605b093 Jakub Vrána List authentications
authored
723 }
724 }
725 }
726 }
727 } else {
c64c4fd Adminer class
jakubvrana authored
728 $databases = get_databases();
729 ?>
b95f24e Editor: User friendly data editor
jakubvrana authored
730 <form action="" method="post">
fde1171 Add CSS classes (thanks to cvicebni ubor)
jakubvrana authored
731 <p class="logout">
f7d4587 Jakub Vrána Hide SQL command link in case of an error
authored
732 <?php
9d47d1e Jakub Vrána Whitespace
authored
733 if (DB == "" || !$missing) {
8ad4809 Jakub Vrána Use class="active" instead of <b>
authored
734 echo "<a href='" . h(ME) . "sql='" . bold(isset($_GET["sql"])) . ">" . lang('SQL command') . "</a>\n";
9d47d1e Jakub Vrána Whitespace
authored
735 if (support("dump")) {
29d7d6c Jakub Vrána Modify dump link in AJAX
authored
736 echo "<a href='" . h(ME) . "dump=" . urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]) . "' id='dump'" . bold(isset($_GET["dump"])) . ">" . lang('Dump') . "</a>\n";
9d47d1e Jakub Vrána Whitespace
authored
737 }
738 }
739 ?>
3f5b683 Reintegrate sqlite branch
jakubvrana authored
740 <input type="hidden" name="token" value="<?php echo $token; ?>">
fbc668c Jakub Vrána Simplify JavaScript
authored
741 <input type="submit" name="logout" value="<?php echo lang('Logout'); ?>" onclick="eventStop(event);">
d2ba593 Browsers interpret <form><p></form> as <form><p></form></p>
jakubvrana authored
742 </p>
b95f24e Editor: User friendly data editor
jakubvrana authored
743 </form>
744 <form action="">
25cef1f Disable session.use_trans_sid to preserve export result
jakubvrana authored
745 <p>
3f5b683 Reintegrate sqlite branch
jakubvrana authored
746 <?php hidden_fields_get(); ?>
0698409 Utilize html_select
jakubvrana authored
747 <?php echo ($databases ? html_select("db", array("" => "(" . lang('database') . ")") + $databases, DB, "this.form.submit();") : '<input name="db" value="' . h(DB) . '">'); ?>
fbc668c Jakub Vrána Simplify JavaScript
authored
748 <input type="submit" value="<?php echo lang('Use'); ?>"<?php echo ($databases ? " class='hidden'" : ""); ?> onclick="eventStop(event);">
b95f24e Editor: User friendly data editor
jakubvrana authored
749 <?php
7352c28 Replace strlen() by != ""
jakubvrana authored
750 if ($missing != "db" && DB != "" && $connection->select_db(DB)) {
6420c58 Schema support for PostgreSQL
jakubvrana authored
751 if (support("scheme")) {
752 echo "<br>" . html_select("ns", array("" => "(" . lang('schema') . ")") + schemas(), $_GET["ns"], "this.form.submit();");
753 if ($_GET["ns"] != "") {
754 set_schema($_GET["ns"]);
8e81039 Link table names in SQL queries
jakubvrana authored
755 }
6420c58 Schema support for PostgreSQL
jakubvrana authored
756 }
f7d4587 Jakub Vrána Hide SQL command link in case of an error
authored
757 if ($_GET["ns"] !== "" && !$missing) {
8ad4809 Jakub Vrána Use class="active" instead of <b>
authored
758 echo '<p><a href="' . h(ME) . 'create="' . bold($_GET["create"] === "") . ">" . lang('Create new table') . "</a>\n";
6420c58 Schema support for PostgreSQL
jakubvrana authored
759 $tables = tables_list();
760 if (!$tables) {
761 echo "<p class='message'>" . lang('No tables.') . "\n";
762 } else {
763 $this->tablesPrint($tables);
764 $links = array();
765 foreach ($tables as $table => $type) {
766 $links[] = preg_quote($table, '/');
767 }
768 echo "<script type='text/javascript'>\n";
28f21aa Jakub Vrána Escape JavaScript strings (bug #3093243)
authored
769 echo "var jushLinks = { $jush: [ '" . js_escape(ME) . "table=\$&', /\\b(" . implode("|", $links) . ")\\b/g ] };\n";
6420c58 Schema support for PostgreSQL
jakubvrana authored
770 foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) {
e672694 Jakub Vrána Rename $driver to $jush
authored
771 echo "jushLinks.$val = jushLinks.$jush;\n";
6420c58 Schema support for PostgreSQL
jakubvrana authored
772 }
773 echo "</script>\n";
e5969d4 Shorten code
jakubvrana authored
774 }
df0c4bb Simplify tablesPrint
jakubvrana authored
775 }
776 }
6420c58 Schema support for PostgreSQL
jakubvrana authored
777 echo (isset($_GET["sql"]) ? '<input type="hidden" name="sql" value="">'
778 : (isset($_GET["schema"]) ? '<input type="hidden" name="schema" value="">'
779 : (isset($_GET["dump"]) ? '<input type="hidden" name="dump" value="">'
780 : "")));
60c7ed9 Jakub Vrána MS SQL schema support
authored
781 echo "</p></form>\n";
d3227c9 Move <h1> to $adminer->navigation
jakubvrana authored
782 }
783 }
784
785 /** Prints table list in menu
df0c4bb Simplify tablesPrint
jakubvrana authored
786 * @param array
d3227c9 Move <h1> to $adminer->navigation
jakubvrana authored
787 * @return null
788 */
df0c4bb Simplify tablesPrint
jakubvrana authored
789 function tablesPrint($tables) {
790 echo "<p id='tables'>\n";
3f5b683 Reintegrate sqlite branch
jakubvrana authored
791 foreach ($tables as $table => $type) {
8ad4809 Jakub Vrána Use class="active" instead of <b>
authored
792 echo '<a href="' . h(ME) . 'select=' . urlencode($table) . '"' . bold($_GET["select"] == $table) . ">" . lang('select') . "</a> ";
793 echo '<a href="' . h(ME) . 'table=' . urlencode($table) . '"' . bold($_GET["table"] == $table) . ">" . $this->tableName(array("Name" => $table)) . "</a><br>\n"; //! Adminer::tableName may work with full table status
b95f24e Editor: User friendly data editor
jakubvrana authored
794 }
795 }
c64c4fd Adminer class
jakubvrana authored
796
2c445a8 Extensibility basics
jakubvrana authored
797 }
464d84a Define functions unconditionally
jakubvrana authored
798
799 $adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
800 if (!isset($adminer->operators)) {
801 $adminer->operators = $operators;
802 }
Something went wrong with that request. Please try again.