Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 814 lines (758 sloc) 23.6 kb
667bfec Decomposition
jakubvrana authored
1 <?php
9a176b0 Comments
jakubvrana authored
2 /** Get database connection
3 * @return Min_DB
4 */
64d616c Rename get_dbh to connection
jakubvrana authored
5 function connection() {
6 // can be used in customization, $connection is minified
7 global $connection;
8 return $connection;
c64c4fd Adminer class
jakubvrana authored
9 }
10
9a176b0 Comments
jakubvrana authored
11 /** Unescape database identifier
12 * @param string text inside ``
13 * @return string
14 */
667bfec Decomposition
jakubvrana authored
15 function idf_unescape($idf) {
a29ac72 Improve drivers
jakubvrana authored
16 $last = substr($idf, -1);
17 return str_replace($last . $last, $last, substr($idf, 1, -1));
667bfec Decomposition
jakubvrana authored
18 }
19
5e01a62 Prepare for SQLite
jakubvrana authored
20 /** Escape string to use inside ''
21 * @param string
22 * @return string
23 */
24 function escape_string($val) {
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
25 return substr(q($val), 1, -1);
5e01a62 Prepare for SQLite
jakubvrana authored
26 }
27
72f4d9e @vrana Function parse_str respects magic_quotes_gpc (bug #3034575)
authored
28 /** Disable magic_quotes_gpc
29 * @param array e.g. (&$_GET, &$_POST, &$_COOKIE)
30 * @return null modified in place
31 */
32 function remove_slashes($process) {
33 if (get_magic_quotes_gpc()) {
34 while (list($key, $val) = each($process)) {
35 foreach ($val as $k => $v) {
36 unset($process[$key][$k]);
37 if (is_array($v)) {
38 $process[$key][stripslashes($k)] = $v;
39 $process[] = &$process[$key][stripslashes($k)];
40 } else {
41 $process[$key][stripslashes($k)] = ($filter ? $v : stripslashes($v));
42 }
43 }
44 }
45 }
46 }
47
9a176b0 Comments
jakubvrana authored
48 /** Escape or unescape string to use inside form []
49 * @param string
50 * @param bool
51 * @return string
52 */
667bfec Decomposition
jakubvrana authored
53 function bracket_escape($idf, $back = false) {
64ba924 Comments
jakubvrana authored
54 // escape brackets inside name="x[]"
73e8631 Move stuff to functions.inc.php
jakubvrana authored
55 static $trans = array(':' => ':1', ']' => ':2', '[' => ':3');
667bfec Decomposition
jakubvrana authored
56 return strtr($idf, ($back ? array_flip($trans) : $trans));
57 }
58
9a176b0 Comments
jakubvrana authored
59 /** Escape for HTML
60 * @param string
61 * @return string
62 */
689699a Shortcut for htmlspecialchars
jakubvrana authored
63 function h($string) {
64 return htmlspecialchars($string, ENT_QUOTES);
65 }
66
9a176b0 Comments
jakubvrana authored
67 /** Escape for TD
68 * @param string
69 * @return string
70 */
c196985 Function nbsp
jakubvrana authored
71 function nbsp($string) {
7352c28 Replace strlen() by != ""
jakubvrana authored
72 return (trim($string) != "" ? h($string) : "&nbsp;");
c196985 Function nbsp
jakubvrana authored
73 }
74
3f5b683 Reintegrate sqlite branch
jakubvrana authored
75 /** Convert \n to <br>
76 * @param string
77 * @return string
78 */
79 function nl_br($string) {
80 return str_replace("\n", "<br>", $string); // nl2br() uses XHTML before PHP 5.3
81 }
82
6b30cfa Separate checkbox
jakubvrana authored
83 /** Generate HTML checkbox
84 * @param string
85 * @param string
86 * @param bool
87 * @param string
88 * @param string
89 * @return string
90 */
91 function checkbox($name, $value, $checked, $label = "", $onclick = "") {
c4fe12a Clickable labels in IE6
jakubvrana authored
92 static $id = 0;
93 $id++;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
94 $return = "<input type='checkbox'" . ($name ? " name='$name' value='" . h($value) . "'" : "") . ($checked ? " checked" : "") . ($onclick ? " onclick=\"$onclick\"" : "") . " id='checkbox-$id'>";
7352c28 Replace strlen() by != ""
jakubvrana authored
95 return ($label != "" ? "<label for='checkbox-$id'>$return" . h($label) . "</label>" : $return);
6b30cfa Separate checkbox
jakubvrana authored
96 }
97
9a176b0 Comments
jakubvrana authored
98 /** Generate list of HTML options
99 * @param array array of strings or arrays (creates optgroup)
100 * @param mixed
101 * @param bool always use array keys for value="", otherwise only string keys are used
102 * @return string
103 */
1e4d11e Select from foreign keys in Editor
jakubvrana authored
104 function optionlist($options, $selected = null, $use_keys = false) {
667bfec Decomposition
jakubvrana authored
105 $return = "";
106 foreach ($options as $k => $v) {
107 if (is_array($v)) {
689699a Shortcut for htmlspecialchars
jakubvrana authored
108 $return .= '<optgroup label="' . h($k) . '">';
667bfec Decomposition
jakubvrana authored
109 }
ced9de9 Create single column foreign key in table structure
jakubvrana authored
110 foreach ((is_array($v) ? $v : array($k => $v)) as $key => $val) {
cb6d36c HTML instead of XHTML
jakubvrana authored
111 $return .= '<option' . ($use_keys || is_string($key) ? ' value="' . h($key) . '"' : '') . (($use_keys || is_string($key) ? (string) $key : $val) === $selected ? ' selected' : '') . '>' . h($val);
667bfec Decomposition
jakubvrana authored
112 }
113 if (is_array($v)) {
114 $return .= '</optgroup>';
115 }
116 }
117 return $return;
118 }
119
098b74b Move function
jakubvrana authored
120 /** Generate HTML radio list
121 * @param string
122 * @param array
123 * @param string
124 * @param string true for no onchange, false for radio
125 * @return string
126 */
127 function html_select($name, $options, $value = "", $onchange = true) {
128 if ($onchange) {
129 return "<select name='" . h($name) . "'" . (is_string($onchange) ? " onchange=\"$onchange\"" : "") . ">" . optionlist($options, $value) . "</select>";
130 }
131 $return = "";
132 foreach ($options as $key => $val) {
133 $return .= "<label><input type='radio' name='" . h($name) . "' value='" . h($key) . "'" . ($key == $value ? " checked" : "") . ">" . h($val) . "</label>";
134 }
135 return $return;
136 }
137
a93bc19 @vrana Create confirm function
authored
138 /** Get onclick confirmation
139 * @param string JavaScript expression
b7cd652 @vrana No AJAX in drop table, drop database and logout
authored
140 * @param bool stop event propagation
a93bc19 @vrana Create confirm function
authored
141 * @return string
142 */
b7cd652 @vrana No AJAX in drop table, drop database and logout
authored
143 function confirm($count = "", $stop = false) {
144 return " onclick=\"" . ($stop ? "eventStop(event); " : "") . "return confirm('" . lang('Are you sure?') . ($count ? " (' + $count + ')" : "") . "');\"";
a93bc19 @vrana Create confirm function
authored
145 }
146
28f21aa @vrana Escape JavaScript strings (bug #3093243)
authored
147 /** Escape string for JavaScript apostrophes
148 * @param string
149 * @return string
150 */
151 function js_escape($string) {
152 return addcslashes($string, "\r\n'\\/"); // slash for <script>
153 }
154
3f5b683 Reintegrate sqlite branch
jakubvrana authored
155 /** Get INI boolean value
156 * @param string
157 * @return bool
158 */
159 function ini_bool($ini) {
160 $val = ini_get($ini);
161 return (eregi('^(on|true|yes)$', $val) || (int) $val); // boolean values set by php_value are strings
162 }
163
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
164 function q($string) {
165 global $connection;
166 return $connection->quote($string);
167 }
168
9a176b0 Comments
jakubvrana authored
169 /** Get list of values from database
170 * @param string
171 * @param mixed
172 * @return array
173 */
0bd864e Allow specifying column in get_vals
jakubvrana authored
174 function get_vals($query, $column = 0) {
64d616c Rename get_dbh to connection
jakubvrana authored
175 global $connection;
7769f2c Separate get_vals
jakubvrana authored
176 $return = array();
64d616c Rename get_dbh to connection
jakubvrana authored
177 $result = $connection->query($query);
b84252f Display SQLite compile options
jakubvrana authored
178 if (is_object($result)) {
49f7886 SHOW DATABASES can be revoked
jakubvrana authored
179 while ($row = $result->fetch_row()) {
0bd864e Allow specifying column in get_vals
jakubvrana authored
180 $return[] = $row[$column];
49f7886 SHOW DATABASES can be revoked
jakubvrana authored
181 }
7769f2c Separate get_vals
jakubvrana authored
182 }
183 return $return;
184 }
185
3f5b683 Reintegrate sqlite branch
jakubvrana authored
186 /** Get keys from first column and values from second
187 * @param string
188 * @param Min_DB
189 * @return array
190 */
191 function get_key_vals($query, $connection2 = null) {
192 global $connection;
193 if (!is_object($connection2)) {
194 $connection2 = $connection;
195 }
196 $return = array();
197 $result = $connection2->query($query);
198 while ($row = $result->fetch_row()) {
199 $return[$row[0]] = $row[1];
200 }
201 return $return;
202 }
203
b0d637b @vrana Avoid fatal errors
authored
204 /** Get all rows of result
205 * @param string
206 * @return array associative
207 */
96544ba @vrana Report errors in get_rows()
authored
208 function get_rows($query, $connection2 = null, $error = "<p class='error'>") {
b0d637b @vrana Avoid fatal errors
authored
209 global $connection;
210 if (!is_object($connection2)) {
211 $connection2 = $connection;
212 }
213 $return = array();
214 $result = $connection2->query($query);
215 if (is_object($result)) { // can return true
216 while ($row = $result->fetch_assoc()) {
217 $return[] = $row;
218 }
8ce9ba6 @vrana Don't rely on headers_sent
authored
219 } elseif (!$result && $error && defined("PAGE_HEADER")) {
96544ba @vrana Report errors in get_rows()
authored
220 echo $error . error() . "\n";
b0d637b @vrana Avoid fatal errors
authored
221 }
222 return $return;
223 }
224
9a176b0 Comments
jakubvrana authored
225 /** Find unique identifier of a row
226 * @param array
227 * @param array result of indexes()
35ec64c Link COUNT(*) result to listing
jakubvrana authored
228 * @return array
9a176b0 Comments
jakubvrana authored
229 */
35ec64c Link COUNT(*) result to listing
jakubvrana authored
230 function unique_array($row, $indexes) {
720f5fc Restructure indexes
jakubvrana authored
231 foreach ($indexes as $index) {
4b3d569 Save bytes
jakubvrana authored
232 if (ereg("PRIMARY|UNIQUE", $index["type"])) {
720f5fc Restructure indexes
jakubvrana authored
233 $return = array();
234 foreach ($index["columns"] as $key) {
64ba924 Comments
jakubvrana authored
235 if (!isset($row[$key])) { // NULL is ambiguous
720f5fc Restructure indexes
jakubvrana authored
236 continue 2;
667bfec Decomposition
jakubvrana authored
237 }
35ec64c Link COUNT(*) result to listing
jakubvrana authored
238 $return[$key] = $row[$key];
667bfec Decomposition
jakubvrana authored
239 }
720f5fc Restructure indexes
jakubvrana authored
240 return $return;
667bfec Decomposition
jakubvrana authored
241 }
242 }
243 $return = array();
244 foreach ($row as $key => $val) {
26c9d64 Fix long SQL query crash (bug #2839231)
jakubvrana authored
245 if (!preg_match('~^(COUNT\\((\\*|(DISTINCT )?`(?:[^`]|``)+`)\\)|(AVG|GROUP_CONCAT|MAX|MIN|SUM)\\(`(?:[^`]|``)+`\\))$~', $key)) { //! columns looking like functions
35ec64c Link COUNT(*) result to listing
jakubvrana authored
246 $return[$key] = $val;
988a29f Don't use aggregation functions in unique_idf
jakubvrana authored
247 }
430034c Cottage homework
jakubvrana authored
248 }
249 return $return;
250 }
251
9a176b0 Comments
jakubvrana authored
252 /** Create SQL condition from parsed query string
253 * @param array parsed query string
254 * @return string
255 */
9ea3112 Mandatory $where in where()
jakubvrana authored
256 function where($where) {
1a8d7f1 @vrana Use LIKE for text comparison in MS SQL (bug #3088222)
authored
257 global $jush;
430034c Cottage homework
jakubvrana authored
258 $return = array();
341362a Driver specific INSERT INTO
jakubvrana authored
259 foreach ((array) $where["where"] as $key => $val) {
66ff153 Use bracket_escape function
jakubvrana authored
260 $return[] = idf_escape(bracket_escape($key, 1)) // 1 - back
1a8d7f1 @vrana Use LIKE for text comparison in MS SQL (bug #3088222)
authored
261 . (ereg('\\.', $val) || $jush == "mssql" ? " LIKE " . exact_value(addcslashes($val, "%_")) : " = " . exact_value($val)) // LIKE because of floats, but slow with ints, in MS SQL because of text
66ff153 Use bracket_escape function
jakubvrana authored
262 ; //! enum and set
341362a Driver specific INSERT INTO
jakubvrana authored
263 }
264 foreach ((array) $where["null"] as $key) {
265 $return[] = idf_escape($key) . " IS NULL";
667bfec Decomposition
jakubvrana authored
266 }
c16c57b E-mail sending
jakubvrana authored
267 return implode(" AND ", $return);
667bfec Decomposition
jakubvrana authored
268 }
269
9a176b0 Comments
jakubvrana authored
270 /** Create SQL condition from query string
271 * @param string
272 * @return string
273 */
0cd2afb Remove single item clone
jakubvrana authored
274 function where_check($val) {
275 parse_str($val, $check);
72f4d9e @vrana Function parse_str respects magic_quotes_gpc (bug #3034575)
authored
276 remove_slashes(array(&$check));
0cd2afb Remove single item clone
jakubvrana authored
277 return where($check);
278 }
279
9a176b0 Comments
jakubvrana authored
280 /** Create query string where condition from value
281 * @param int condition order
282 * @param string column identifier
283 * @param string
284 * @return string
186c058 Utilize where_link function
jakubvrana authored
285 * @return string
9a176b0 Comments
jakubvrana authored
286 */
186c058 Utilize where_link function
jakubvrana authored
287 function where_link($i, $column, $value, $operator = "=") {
288 return "&where%5B$i%5D%5Bcol%5D=" . urlencode($column) . "&where%5B$i%5D%5Bop%5D=" . urlencode($operator) . "&where%5B$i%5D%5Bval%5D=" . urlencode($value);
c42c46a Table relations
jakubvrana authored
289 }
290
319cba4 Save e-mail from to cookie
jakubvrana authored
291 /** Set cookie valid for 1 month
292 * @param string
293 * @param string
294 * @return bool
295 */
296 function cookie($name, $value) {
2cec758 @vrana Direct links from HTTPS to HTTP
authored
297 global $HTTPS;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
298 $params = array(
299 $name,
300 (ereg("\n", $value) ? "" : $value), // HTTP Response Splitting protection in PHP < 5.1.2
301 time() + 2592000, // 2592000 - 30 days
302 preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]),
303 "",
2cec758 @vrana Direct links from HTTPS to HTTP
authored
304 $HTTPS
3f5b683 Reintegrate sqlite branch
jakubvrana authored
305 );
c2334db Secure cookies
jakubvrana authored
306 if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
307 $params[] = true; // HttpOnly
308 }
309 return call_user_func_array('setcookie', $params);
319cba4 Save e-mail from to cookie
jakubvrana authored
310 }
311
f9a2023 Improve concurrency
jakubvrana authored
312 /** Restart stopped session
313 * @return null
314 */
315 function restart_session() {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
316 if (!ini_bool("session.use_cookies")) {
f9a2023 Improve concurrency
jakubvrana authored
317 session_start();
318 }
319 }
320
3f5b683 Reintegrate sqlite branch
jakubvrana authored
321 /** Get session variable for current server
322 * @param string
323 * @return mixed
324 */
325 function &get_session($key) {
326 return $_SESSION[$key][DRIVER][SERVER][$_GET["username"]];
327 }
328
329 /** Set session variable for current server
330 * @param string
331 * @param mixed
332 * @return mixed
333 */
334 function set_session($key, $val) {
335 $_SESSION[$key][DRIVER][SERVER][$_GET["username"]] = $val; // used also in auth.inc.php
336 }
337
605b093 @vrana List authentications
authored
338 /** Get authenticated URL
339 * @param string
340 * @param string
341 * @param string
342 * @return string
343 */
344 function auth_url($driver, $server, $username) {
345 global $drivers;
346 preg_match('~([^?]*)\\??(.*)~', remove_from_uri(implode("|", array_keys($drivers)) . "|username|" . session_name()), $match);
347 return "$match[1]?"
dea324f @vrana Store several permanent logins
authored
348 . (SID && !$_COOKIE ? SID . "&" : "")
605b093 @vrana List authentications
authored
349 . ($driver != "server" || $server != "" ? urlencode($driver) . "=" . urlencode($server) . "&" : "")
350 . "username=" . urlencode($username)
351 . ($match[2] ? "&$match[2]" : "")
352 ;
353 }
354
390e38b @vrana Load long texts for inline-edit by AJAX
authored
355 /** Find whether it is an AJAX request
356 * @return bool
357 */
358 function is_ajax() {
38894b2 @vrana Send all forms by AJAX
authored
359 return ($_SERVER["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" || $_GET["ajax"]);
390e38b @vrana Load long texts for inline-edit by AJAX
authored
360 }
361
9a176b0 Comments
jakubvrana authored
362 /** Send Location header and exit
9bb1909 Fix Save and continue edit
jakubvrana authored
363 * @param string null to only set a message
9a176b0 Comments
jakubvrana authored
364 * @param string
365 * @return null
366 */
430034c Cottage homework
jakubvrana authored
367 function redirect($location, $message = null) {
368 if (isset($message)) {
be49e08 Improve session restarting
jakubvrana authored
369 restart_session();
ff74bf0 Allow multiple messages
jakubvrana authored
370 $_SESSION["messages"][] = $message;
430034c Cottage homework
jakubvrana authored
371 }
de24145 @vrana Clear POST with AJAX redirect
authored
372 if (isset($location)) {
b535853 @vrana Full AJAX only with pushState to work correctly with history
authored
373 if ($location == "") {
374 $location = ".";
375 }
38894b2 @vrana Send all forms by AJAX
authored
376 header("Location: $location" . (is_ajax() ? (strpos($location, "?") !== false ? "&" : "?") . "ajax=1" : ""));
377 exit;
9bb1909 Fix Save and continue edit
jakubvrana authored
378 }
430034c Cottage homework
jakubvrana authored
379 }
380
9a176b0 Comments
jakubvrana authored
381 /** Execute query and redirect if successful
382 * @param string
383 * @param string
384 * @param string
385 * @param bool
386 * @param bool
387 * @param bool
388 * @return bool
389 */
748ee83 Print SQL command with multiple queries
jakubvrana authored
390 function query_redirect($query, $location, $message, $redirect = true, $execute = true, $failed = false) {
64d616c Rename get_dbh to connection
jakubvrana authored
391 global $connection, $error, $adminer;
f9a2023 Improve concurrency
jakubvrana authored
392 if ($execute) {
393 $failed = !$connection->query($query);
394 }
10bdbed Save queries to history
jakubvrana authored
395 $sql = "";
396 if ($query) {
c64c4fd Adminer class
jakubvrana authored
397 $sql = $adminer->messageQuery($query);
10bdbed Save queries to history
jakubvrana authored
398 }
748ee83 Print SQL command with multiple queries
jakubvrana authored
399 if ($failed) {
c1130ed Simplify SQL syntax errors everywhere
jakubvrana authored
400 $error = error() . $sql;
c48a017 Print SQL query by error
jakubvrana authored
401 return false;
f91b2c4 Print SQL query by message
jakubvrana authored
402 }
c48a017 Print SQL query by error
jakubvrana authored
403 if ($redirect) {
404 redirect($location, $message . $sql);
405 }
406 return true;
f91b2c4 Print SQL query by message
jakubvrana authored
407 }
408
9a176b0 Comments
jakubvrana authored
409 /** Execute and remember query
410 * @param string null to return remembered queries
411 * @return Min_Result
412 */
748ee83 Print SQL command with multiple queries
jakubvrana authored
413 function queries($query = null) {
64d616c Rename get_dbh to connection
jakubvrana authored
414 global $connection;
748ee83 Print SQL command with multiple queries
jakubvrana authored
415 static $queries = array();
416 if (!isset($query)) {
64ba924 Comments
jakubvrana authored
417 // return executed queries without parameter
36950eb Tables and views
jakubvrana authored
418 return implode(";\n", $queries);
748ee83 Print SQL command with multiple queries
jakubvrana authored
419 }
420 $queries[] = $query;
64d616c Rename get_dbh to connection
jakubvrana authored
421 return $connection->query($query);
748ee83 Print SQL command with multiple queries
jakubvrana authored
422 }
423
f9bb1c5 @vrana Introduce apply_queries function
authored
424 /** Apply command to all array items
425 * @param string
426 * @param array
427 * @param callback
428 * @return bool
429 */
430 function apply_queries($query, $tables, $escape = 'table') {
431 foreach ($tables as $table) {
432 if (!queries("$query " . $escape($table))) {
433 return false;
434 }
435 }
436 return true;
437 }
438
dbdd40a Introduce queries_redirect function
jakubvrana authored
439 /** Redirect by remembered queries
440 * @param string
441 * @param string
442 * @param bool
52b9820 @vrana Comment
authored
443 * @return bool
dbdd40a Introduce queries_redirect function
jakubvrana authored
444 */
445 function queries_redirect($location, $message, $redirect) {
446 return query_redirect(queries(), $location, $message, $redirect, false, !$redirect);
447 }
448
9a176b0 Comments
jakubvrana authored
449 /** Remove parameter from query string
450 * @param string
451 * @return string
452 */
d41d446 remove_from_uri()
jakubvrana authored
453 function remove_from_uri($param = "") {
483d7dc Remove session_name() only without SID (bug #2910681)
jakubvrana authored
454 return substr(preg_replace("~(?<=[?&])($param" . (SID ? "" : "|" . session_name()) . ")=[^&]*&~", '', "$_SERVER[REQUEST_URI]&"), 0, -1);
d41d446 remove_from_uri()
jakubvrana authored
455 }
456
9a176b0 Comments
jakubvrana authored
457 /** Generate page number for pagination
458 * @param int
459 * @return string
460 */
bd25295 Don't redirect from last page
jakubvrana authored
461 function pagination($page, $current) {
6585b23 @vrana Generic AJAX links
authored
462 return " " . ($page == $current ? $page + 1 : '<a href="' . h(remove_from_uri("page") . ($page ? "&page=$page" : "")) . '">' . ($page + 1) . "</a>");
1456283 Pages on last page
jakubvrana authored
463 }
464
3e9b1ba Don't store files in hidden fields
jakubvrana authored
465 /** Get file contents from $_FILES
9a176b0 Comments
jakubvrana authored
466 * @param string
467 * @param bool
3e9b1ba Don't store files in hidden fields
jakubvrana authored
468 * @return mixed int for error, string otherwise
9a176b0 Comments
jakubvrana authored
469 */
25f01d3 Compress export and import
jakubvrana authored
470 function get_file($key, $decompress = false) {
471 $file = $_FILES[$key];
472 if (!$file || $file["error"]) {
473 return $file["error"];
430034c Cottage homework
jakubvrana authored
474 }
0a2d81d Bzip2 import
jakubvrana authored
475 return file_get_contents($decompress && ereg('\\.gz$', $file["name"]) ? "compress.zlib://$file[tmp_name]"
476 : ($decompress && ereg('\\.bz2$', $file["name"]) ? "compress.bzip2://$file[tmp_name]"
477 : $file["tmp_name"]
478 )); //! may not be reachable because of open_basedir
430034c Cottage homework
jakubvrana authored
479 }
480
9a176b0 Comments
jakubvrana authored
481 /** Determine upload error
482 * @param int
483 * @return string
484 */
e2a03c0 Show upload_max_filesize
jakubvrana authored
485 function upload_error($error) {
486 $max_size = ($error == UPLOAD_ERR_INI_SIZE ? ini_get("upload_max_filesize") : null); // post_max_size is checked in index.php
b2a7c7a Execute SQL file stored on server disk
jakubvrana authored
487 return ($error ? lang('Unable to upload a file.') . ($max_size ? " " . lang('Maximum allowed file size is %sB.', $max_size) : "") : lang('File does not exist.'));
e2a03c0 Show upload_max_filesize
jakubvrana authored
488 }
489
9a176b0 Comments
jakubvrana authored
490 /** Generate class for odd rows
491 * @param string return this for odd rows, empty to reset counter
492 * @return string
493 */
494 function odd($return = ' class="odd"') {
4e5b126 Highlight odd and hover rows
jakubvrana authored
495 static $i = 0;
9a176b0 Comments
jakubvrana authored
496 if (!$return) { // reset counter
1b97f48 Reset odd() for each result
jakubvrana authored
497 $i = -1;
4e5b126 Highlight odd and hover rows
jakubvrana authored
498 }
9a176b0 Comments
jakubvrana authored
499 return ($i++ % 2 ? $return : '');
4e5b126 Highlight odd and hover rows
jakubvrana authored
500 }
501
c313dd8 @vrana Deferred operations by AJAX instead of JS (doesn't require sending token...
authored
502 /** Print one row in JSON object
503 * @param string or "" to close the object
504 * @param string
505 * @return null
506 */
507 function json_row($key, $val = null) {
508 static $first = true;
509 if ($first) {
510 echo "{";
511 }
512 if ($key != "") {
513 echo ($first ? "" : ",") . "\n\t\"" . addcslashes($key, '\\"') . '": ' . (isset($val) ? '"' . addcslashes($val, '\\"') . '"' : 'undefined');
514 $first = false;
515 } else {
516 echo "\n}\n";
517 $first = true;
518 }
519 }
520
9a176b0 Comments
jakubvrana authored
521 /** Check whether the string is in UTF-8
522 * @param string
523 * @return bool
524 */
017ffb5 Better UTF-8 detection
jakubvrana authored
525 function is_utf8($val) {
64ba924 Comments
jakubvrana authored
526 // don't print control chars except \t\r\n
017ffb5 Better UTF-8 detection
jakubvrana authored
527 return (preg_match('~~u', $val) && !preg_match('~[\\0-\\x8\\xB\\xC\\xE-\\x1F]~', $val));
528 }
529
9a176b0 Comments
jakubvrana authored
530 /** Shorten UTF-8 string
531 * @param string
532 * @param int
533 * @param string
534 * @return string escaped string with appended ...
535 */
cd07584 Save SQL query to history
jakubvrana authored
536 function shorten_utf8($string, $length = 80, $suffix = "") {
11982f1 Shorten printed SQL query
jakubvrana authored
537 if (!preg_match("(^([\t\r\n -\x{FFFF}]{0,$length})($)?)u", $string, $match)) { // ~s causes trash in $match[2] under some PHP versions, (.|\n) is slow
538 preg_match("(^([\t\r\n -~]{0,$length})($)?)", $string, $match);
95764b0 Shorten binary strings
jakubvrana authored
539 }
687b3fd @vrana Replace <strong> by <b> and <em> by <i>
authored
540 return h($match[1]) . $suffix . (isset($match[2]) ? "" : "<i>...</i>");
02a851c Shorten texts in PHP
jakubvrana authored
541 }
3920ebb Remove InnoDB table comment in Tables and views
jakubvrana authored
542
9a176b0 Comments
jakubvrana authored
543 /** Generate friendly URL
544 * @param string
545 * @return string
546 */
8251896 Downloaded file name
jakubvrana authored
547 function friendly_url($val) {
64ba924 Comments
jakubvrana authored
548 // used for blobs and export
8251896 Downloaded file name
jakubvrana authored
549 return preg_replace('~[^a-z0-9_]~i', '-', $val);
550 }
551
9a176b0 Comments
jakubvrana authored
552 /** Print hidden fields
553 * @param array
554 * @param array
555 * @return null
556 */
820c882 Bulk clone
jakubvrana authored
557 function hidden_fields($process, $ignore = array()) {
5d7071a Choose language through option-list
jakubvrana authored
558 while (list($key, $val) = each($process)) {
559 if (is_array($val)) {
560 foreach ($val as $k => $v) {
561 $process[$key . "[$k]"] = $v;
562 }
563 } elseif (!in_array($key, $ignore)) {
689699a Shortcut for htmlspecialchars
jakubvrana authored
564 echo '<input type="hidden" name="' . h($key) . '" value="' . h($val) . '">';
5d7071a Choose language through option-list
jakubvrana authored
565 }
566 }
567 }
61640ee Move common functions
jakubvrana authored
568
3f5b683 Reintegrate sqlite branch
jakubvrana authored
569 /** Print hidden fields for GET forms
570 * @return null
571 */
572 function hidden_fields_get() {
573 echo (SID && !$_COOKIE ? '<input type="hidden" name="' . session_name() . '" value="' . h(session_id()) . '">' : '');
574 echo (SERVER !== null ? '<input type="hidden" name="' . DRIVER . '" value="' . h(SERVER) . '">' : "");
575 echo '<input type="hidden" name="username" value="' . h($_GET["username"]) . '">';
576 }
577
9a176b0 Comments
jakubvrana authored
578 /** Find out foreign keys for each column
579 * @param string
580 * @return array array($col => array())
581 */
1e4d11e Select from foreign keys in Editor
jakubvrana authored
582 function column_foreign_keys($table) {
753909e @vrana Support for virtual foreign keys
authored
583 global $adminer;
1e4d11e Select from foreign keys in Editor
jakubvrana authored
584 $return = array();
753909e @vrana Support for virtual foreign keys
authored
585 foreach ($adminer->foreignKeys($table) as $foreign_key) {
1e4d11e Select from foreign keys in Editor
jakubvrana authored
586 foreach ($foreign_key["source"] as $val) {
587 $return[$val][] = $foreign_key;
588 }
589 }
590 return $return;
591 }
592
3f5b683 Reintegrate sqlite branch
jakubvrana authored
593 /** Print enum input field
594 * @param string "radio"|"checkbox"
595 * @param string
596 * @param array
597 * @param mixed int|string|array
598 * @return null
599 */
454c80f @vrana Save bytes
authored
600 function enum_input($type, $attrs, $field, $value) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
601 preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
fe06908 @vrana Allow redefining editInput for enum (bug #3048711)
authored
602 $return = "";
3f5b683 Reintegrate sqlite branch
jakubvrana authored
603 foreach ($matches[1] as $i => $val) {
604 $val = stripcslashes(str_replace("''", "'", $val));
605 $checked = (is_int($value) ? $value == $i+1 : (is_array($value) ? in_array($i+1, $value) : $value === $val));
fe06908 @vrana Allow redefining editInput for enum (bug #3048711)
authored
606 $return .= " <label><input type='$type'$attrs value='" . ($i+1) . "'" . ($checked ? ' checked' : '') . '>' . h($val) . '</label>';
3f5b683 Reintegrate sqlite branch
jakubvrana authored
607 }
fe06908 @vrana Allow redefining editInput for enum (bug #3048711)
authored
608 return $return;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
609 }
610
9a176b0 Comments
jakubvrana authored
611 /** Print edit input field
612 * @param array one field from fields()
613 * @param mixed
614 * @param string
615 * @return null
616 */
1e4d11e Select from foreign keys in Editor
jakubvrana authored
617 function input($field, $value, $function) {
e672694 @vrana Rename $driver to $jush
authored
618 global $types, $adminer, $jush;
689699a Shortcut for htmlspecialchars
jakubvrana authored
619 $name = h(bracket_escape($field["field"]));
61640ee Move common functions
jakubvrana authored
620 echo "<td class='function'>";
6758477 Hide NULL in Editor enum
jakubvrana authored
621 $functions = (isset($_GET["select"]) ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
454c80f @vrana Save bytes
authored
622 $attrs = " name='fields[$name]'";
61640ee Move common functions
jakubvrana authored
623 if ($field["type"] == "enum") {
fe06908 @vrana Allow redefining editInput for enum (bug #3048711)
authored
624 echo nbsp($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value);
61640ee Move common functions
jakubvrana authored
625 } else {
9903946 Use original values in Editor multi edit
jakubvrana authored
626 $first = 0;
627 foreach ($functions as $key => $val) {
628 if ($key === "" || !$val) {
629 break;
630 }
631 $first++;
632 }
28f21aa @vrana Escape JavaScript strings (bug #3093243)
authored
633 $onchange = ($first ? " onchange=\"var f = this.form['function[" . js_escape($name) . "]']; if ($first > f.selectedIndex) f.selectedIndex = $first;\"" : "");
454c80f @vrana Save bytes
authored
634 $attrs .= $onchange;
c5a1a77 @vrana Functions translation
authored
635 echo (count($functions) > 1 ? html_select("function[$name]", $functions, !isset($function) || in_array($function, $functions) || isset($functions[$function]) ? $function : "") : nbsp(reset($functions))) . '<td>';
a561252 Use distinct name for blob inputs
jakubvrana authored
636 $input = $adminer->editInput($_GET["edit"], $field, $attrs, $value); // usage in call is without a table
7352c28 Replace strlen() by != ""
jakubvrana authored
637 if ($input != "") {
e1abcda Treat tinyint(1) as boolean
jakubvrana authored
638 echo $input;
1e4d11e Select from foreign keys in Editor
jakubvrana authored
639 } elseif ($field["type"] == "set") { //! 64 bits
26c9d64 Fix long SQL query crash (bug #2839231)
jakubvrana authored
640 preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
61640ee Move common functions
jakubvrana authored
641 foreach ($matches[1] as $i => $val) {
642 $val = stripcslashes(str_replace("''", "'", $val));
643 $checked = (is_int($value) ? ($value >> $i) & 1 : in_array($val, explode(",", $value), true));
4cead56 Edit default values directly in table creation
jakubvrana authored
644 echo " <label><input type='checkbox' name='fields[$name][$i]' value='" . (1 << $i) . "'" . ($checked ? ' checked' : '') . "$onchange>" . h($val) . '</label>';
61640ee Move common functions
jakubvrana authored
645 }
5a73c01 @vrana Treat binary type as hex
authored
646 } elseif (ereg('blob|bytea|raw|file', $field["type"]) && ini_bool("file_uploads")) {
a561252 Use distinct name for blob inputs
jakubvrana authored
647 echo "<input type='file' name='fields-$name'$onchange>";
375a5c8 @vrana Non-MySQL binary types
authored
648 } elseif (ereg('text|lob', $field["type"])) {
71438d5 @vrana Handle keypress instead of keydown (bug #3112458)
authored
649 echo "<textarea " . ($jush != "sqlite" || ereg("\n", $value) ? "cols='50' rows='12'" : "cols='30' rows='1' style='height: 1.2em;'") . "$attrs onkeypress='return textareaKeypress(this, event);'>" . h($value) . '</textarea>'; // 1.2em - line-height
61640ee Move common functions
jakubvrana authored
650 } else {
651 // int(3) is only a display hint
5002b89 @vrana Big numbers without E
authored
652 $maxlength = (!ereg('int', $field["type"]) && preg_match('~^(\\d+)(,(\\d+))?$~', $field["length"], $match) ? ((ereg("binary", $field["type"]) ? 2 : 1) * $match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0));
5a73c01 @vrana Treat binary type as hex
authored
653 echo "<input value='" . h($value) . "'" . ($maxlength ? " maxlength='$maxlength'" : "") . (ereg('char|binary', $field["type"]) && $maxlength > 20 ? " size='40'" : "") . "$attrs>";
61640ee Move common functions
jakubvrana authored
654 }
655 }
656 }
657
9a176b0 Comments
jakubvrana authored
658 /** Process edit input field
659 * @param one field from fields()
660 * @return string
661 */
a0def47 Date localization
jakubvrana authored
662 function process_input($field) {
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
663 global $adminer;
a0def47 Date localization
jakubvrana authored
664 $idf = bracket_escape($field["field"]);
61640ee Move common functions
jakubvrana authored
665 $function = $_POST["function"][$idf];
666 $value = $_POST["fields"][$idf];
3f5b683 Reintegrate sqlite branch
jakubvrana authored
667 if ($field["type"] == "enum") {
668 if ($value == -1) {
669 return false;
670 }
671 if ($value == "") {
672 return "NULL";
673 }
04eccba @vrana Allow bigger numbers under 32 bits
authored
674 return +$value;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
675 }
676 if ($field["auto_increment"] && $value == "") {
677 return null;
678 }
679 if ($function == "orig") {
61640ee Move common functions
jakubvrana authored
680 return false;
3f5b683 Reintegrate sqlite branch
jakubvrana authored
681 }
682 if ($function == "NULL") {
61640ee Move common functions
jakubvrana authored
683 return "NULL";
3f5b683 Reintegrate sqlite branch
jakubvrana authored
684 }
685 if ($field["type"] == "set") {
4cead56 Edit default values directly in table creation
jakubvrana authored
686 return array_sum((array) $value);
3f5b683 Reintegrate sqlite branch
jakubvrana authored
687 }
5a73c01 @vrana Treat binary type as hex
authored
688 if (ereg('blob|bytea|raw|file', $field["type"]) && ini_bool("file_uploads")) {
a561252 Use distinct name for blob inputs
jakubvrana authored
689 $file = get_file("fields-$idf");
61640ee Move common functions
jakubvrana authored
690 if (!is_string($file)) {
691 return false; //! report errors
692 }
7e644b4 @vrana Save bytes ($connection->quote shortcut)
authored
693 return q($file);
61640ee Move common functions
jakubvrana authored
694 }
3f5b683 Reintegrate sqlite branch
jakubvrana authored
695 return $adminer->processInput($field, $value, $function);
61640ee Move common functions
jakubvrana authored
696 }
697
db07325 Search in all tables
jakubvrana authored
698 /** Print results of search in all tables
699 * @uses $_GET["where"][0]
700 * @uses $_POST["tables"]
701 * @return null
702 */
703 function search_tables() {
704 global $adminer, $connection;
dfa6cbf @vrana Show tables overview in Editor
authored
705 $_GET["where"][0]["op"] = "LIKE %%";
706 $_GET["where"][0]["val"] = $_POST["query"];
db07325 Search in all tables
jakubvrana authored
707 $found = false;
708 foreach (table_status() as $table => $table_status) {
709 $name = $adminer->tableName($table_status);
710 if (isset($table_status["Engine"]) && $name != "" && (!$_POST["tables"] || in_array($table, $_POST["tables"]))) {
ee3e045 @vrana Separate $where in limit function
authored
711 $result = $connection->query("SELECT" . limit("1 FROM " . table($table), " WHERE " . implode(" AND ", $adminer->selectSearchProcess(fields($table), array())), 1));
782921b @vrana Finish SQLite
authored
712 if ($result->fetch_row()) {
db07325 Search in all tables
jakubvrana authored
713 if (!$found) {
714 echo "<ul>\n";
715 $found = true;
716 }
717 echo "<li><a href='" . h(ME . "select=" . urlencode($table) . "&where[0][op]=" . urlencode($_GET["where"][0]["op"]) . "&where[0][val]=" . urlencode($_GET["where"][0]["val"])) . "'>" . h($name) . "</a>\n";
718 }
719 }
720 }
721 echo ($found ? "</ul>" : "<p class='message'>" . lang('No tables.')) . "\n";
722 }
723
9a176b0 Comments
jakubvrana authored
724 /** Print CSV row
725 * @param array
726 * @return null
727 */
61640ee Move common functions
jakubvrana authored
728 function dump_csv($row) {
729 foreach ($row as $key => $val) {
e225d22 @vrana TSV export and import (bug #3097657)
authored
730 if (preg_match("~[\"\n,;\t]~", $val) || $val === "") {
61640ee Move common functions
jakubvrana authored
731 $row[$key] = '"' . str_replace('"', '""', $val) . '"';
732 }
733 }
e225d22 @vrana TSV export and import (bug #3097657)
authored
734 echo implode(($_POST["format"] == "csv" ? "," : ($_POST["format"] == "tsv" ? "\t" : ";")), $row) . "\n";
61640ee Move common functions
jakubvrana authored
735 }
c16c57b E-mail sending
jakubvrana authored
736
9a176b0 Comments
jakubvrana authored
737 /** Apply SQL function
738 * @param string
739 * @param string escaped column identifier
740 * @return string
741 */
e331067 Move apply_sql_function
jakubvrana authored
742 function apply_sql_function($function, $column) {
3f5b683 Reintegrate sqlite branch
jakubvrana authored
743 return ($function ? ($function == "unixepoch" ? "DATETIME($column, '$function')" : ($function == "count distinct" ? "COUNT(DISTINCT " : strtoupper("$function(")) . "$column)") : $column);
e331067 Move apply_sql_function
jakubvrana authored
744 }
745
4ba2d85 @vrana Allow permanent login without customization
authored
746 /** Read password from file adminer.key in temporary directory or create one
747 * @return string or false if the file can not be created
748 */
749 function password_file() {
750 $dir = ini_get("upload_tmp_dir"); // session_save_path() may contain other storage path
751 if (!$dir) {
752 if (function_exists('sys_get_temp_dir')) {
753 $dir = sys_get_temp_dir();
754 } else {
755 $filename = @tempnam("", ""); // @ - temp directory can be disabled by open_basedir
756 if (!$filename) {
757 return false;
758 }
759 $dir = dirname($filename);
760 unlink($filename);
761 }
762 }
763 $filename = "$dir/adminer.key";
764 $return = @file_get_contents($filename); // @ - can not exist
765 if ($return) {
766 return $return;
767 }
768 $fp = @fopen($filename, "w"); // @ - can have insufficient rights //! is not atomic
769 if ($fp) {
770 $return = md5(uniqid(mt_rand(), true));
771 fwrite($fp, $return);
772 fclose($fp);
773 }
774 return $return;
775 }
776
9a176b0 Comments
jakubvrana authored
777 /** Check whether the string is e-mail address
778 * @param string
779 * @return bool
780 */
1cf374b @vrana Rename functions (avoid conflict with WordPress)
authored
781 function is_mail($email) {
c16c57b E-mail sending
jakubvrana authored
782 $atom = '[-a-z0-9!#$%&\'*+/=?^_`{|}~]'; // characters of local-name
783 $domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component
28e1dd2 Allow multiple e-mails
jakubvrana authored
784 $pattern = "$atom+(\\.$atom+)*@($domain?\\.)+$domain";
785 return preg_match("(^$pattern(,\\s*$pattern)*\$)i", $email);
c16c57b E-mail sending
jakubvrana authored
786 }
dc667ea Hide select export and import
jakubvrana authored
787
bc78866 Link URLs in select
jakubvrana authored
788 /** Check whether the string is URL address
789 * @param string
2cec758 @vrana Direct links from HTTPS to HTTP
authored
790 * @return string "http", "https" or ""
bc78866 Link URLs in select
jakubvrana authored
791 */
792 function is_url($string) {
2cec758 @vrana Direct links from HTTPS to HTTP
authored
793 $domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component //! IDN
5002b89 @vrana Big numbers without E
authored
794 return (preg_match("~^(https?)://($domain?\\.)+$domain(:\\d+)?(/.*)?(\\?.*)?(#.*)?\$~i", $string, $match) ? strtolower($match[1]) : ""); //! restrict path, query and fragment characters
bc78866 Link URLs in select
jakubvrana authored
795 }
796
dc667ea Hide select export and import
jakubvrana authored
797 /** Print header for hidden fieldset (close by </div></fieldset>)
798 * @param string
799 * @param string
800 * @param bool
801 * @return null
802 */
803 function print_fieldset($id, $legend, $visible = false) {
804 echo "<fieldset><legend><a href='#fieldset-$id' onclick=\"return !toggle('fieldset-$id');\">$legend</a></legend><div id='fieldset-$id'" . ($visible ? "" : " class='hidden'") . ">\n";
805 }
94a2be5 Highlight current links
jakubvrana authored
806
8ad4809 @vrana Use class="active" instead of <b>
authored
807 /** Return class='active' if $bold is true
94a2be5 Highlight current links
jakubvrana authored
808 * @param bool
809 * @return string
810 */
8ad4809 @vrana Use class="active" instead of <b>
authored
811 function bold($bold) {
812 return ($bold ? " class='active'" : "");
94a2be5 Highlight current links
jakubvrana authored
813 }
Something went wrong with that request. Please try again.