· 5 years ago · Sep 09, 2020, 10:10 PM
1<?php
2/*
3 dbkiss - MySQL Connector
4 ViR Here
5 za všetko môže....
6*/
7
8// zlib conflicts with ob_gzhandler.
9ini_set('zlib.output_compression', 0); // can we set it during run-time? or php.ini only?
10ini_set('output_buffering', 0);
11
12if (ini_get('zlib.output_compression')) { // check it to be sure.
13 ob_start();
14} else {
15 ob_start('ob_gzhandler');
16}
17
18// Some of the features in the SQL editor require creating 'dbkiss_sql' directory,
19// where history of queries are kept and other data. If the script has permission
20// it will create that directory automatically, otherwise you need to create that
21// directory manually and make it writable. You can also set it to empty '' string,
22// but some of the features in the sql editor will not work (templates, pagination)
23
24if (!defined('DBKISS_SQL_DIR')) {
25 define('DBKISS_SQL_DIR', 'dbkiss_sql');
26}
27
28/*
29 An example configuration script that will automatically connect to localhost database.
30 This is useful on localhost if you don't want to see the "Connect" screen.
31
32 mysql_local.php:
33 ---------------------------------------------------------------------
34 define('COOKIE_PREFIX', str_replace('.php', '', basename(__FILE__)).'_');
35 define('DBKISS_SQL_DIR', 'dbkiss_mysql');
36
37 $cookie = array(
38 'db_driver' => 'mysql',
39 'db_server' => 'localhost',
40 'db_name' => 'test',
41 'db_user' => 'root',
42 'db_pass' => 'toor',
43 'db_charset' => 'latin2',
44 'page_charset' => 'iso-8859-2',
45 'remember' => 1
46 );
47
48 foreach ($cookie as $k => $v) {
49 if ('db_pass' == $k) { $v = base64_encode($v); }
50 $k = COOKIE_PREFIX.$k;
51 if (!isset($_COOKIE[$k])) {
52 $_COOKIE[$k] = $v;
53 }
54 }
55
56 require './dbkiss.php';
57 ---------------------------------------------------------------------
58*/
59
60/*
61 Changelog:
62
63 1.16
64 * Compatibility fixes for PHP 5.5.7
65 * Permanent links for saved SQL templates, the url in browser
66 includes template name (Issue 3)
67 * After connecting to database you will be redirected to the
68 url you came from
69 1.15
70 * Fixed Postgresql 9 bug on Linux, no data rows were displayed
71 for SELECT queries in the SQL editor (Issue 5).
72 1.14
73 * IIS server fixes: $_SERVER['SERVER_ADDR'] missing
74 1.13
75 * Table names and column names may start with numeric values ex. `52-644` as table name is now allowed.
76 1.12
77 * Fixed "order by" bug in views.
78 1.11
79 * Links in data output are now clickable. Clicking them does not reveal the location of your dbkiss script to external sites.
80 1.10
81 * Support for views in Postgresql (mysql had it already).
82 * Views are now displayed in a seperate listing, to the right of the tables on main page.
83 * Secure redirection - no referer header sent - when clicking external links (ex. powered by), so that the location of the dbkiss script on your site is not revealed.
84 1.09
85 * CSV export in sql editor and table view (feature sponsored by Patrick McGovern)
86 1.08
87 * date.timezone E_STRICT error fixed
88 1.07
89 * mysql tables with dash in the name generated errors, now all tables in mysql driver are
90 enquoted with backtick.
91 1.06
92 * postgresql fix
93 1.05
94 * export of all structure and data does take into account the table name filter on the main page,
95 so you can filter the tables that you want to export.
96 1.04
97 * exporting all structure/data didn't work (ob_gzhandler flush bug)
98 * cookies are now set using httponly option
99 * text editor complained about bad cr/lf in exported sql files
100 (mysql create table uses \n, so insert queries need to be seperated by \n and not \r\n)
101 1.03
102 * re-created array_walk_recursive for php4 compatibility
103 * removed stripping slashes from displayed content
104 * added favicon (using base64_encode to store the icon in php code, so it is still one-file database browser)
105 1.02
106 * works with short_open_tag disabled
107 * code optimizations/fixes
108 * postgresql error fix for large tables
109 1.01
110 * fix for mysql 3.23, which doesnt understand "LIMIT x OFFSET z"
111 1.00
112 * bug fixes
113 * minor feature enhancements
114 * this release is stable and can be used in production environment
115 0.61
116 * upper casing keywords in submitted sql is disabled (it also modified quoted values)
117 * sql error when displaying table with 0 rows
118 * could not connect to database that had upper case characters
119
120*/
121
122// todo: php error handler which cancels buffer output and exits on error
123// todo: XSS and CSRF protection.
124// todo: connect screen: [x] create database (if not exists) [charset]
125// todo: connect screen: database (optional, if none provided will select the first database the user has access to)
126// todo: mysqli driver (check if mysql extension is loaded, if not try to use mysqli)
127// todo: support for the enum field type when editing row
128// todo: search whole database form should appear also on main page
129// todo: improve detecting primary keys when editing row (querying information_schema , for mysql > 4)
130// todo: when dbkiss_sql dir is missing, display a message in sql editor that some features won't work (templates, pagination) currently it displays a message to create that dir and EXIT, but should allow basic operations
131// todo: "Insert" on table view page
132// todo: edit table structure
133
134error_reporting(E_ALL & ~E_STRICT & ~E_DEPRECATED);
135ini_set('display_errors', true);
136if (!ini_get('date.timezone')) {
137 ini_set('date.timezone', 'Europe/Warsaw');
138}
139
140// Fix IIS missing variables in $_SERVER:
141if (!isset($_SERVER['REQUEST_URI'])) {
142 $_SERVER['REQUEST_URI'] = $_SERVER['PHP_SELF'];
143 if (isset($_SERVER['QUERY_STRING'])) {
144 $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
145 }
146}
147if (!isset($_SERVER['SERVER_ADDR'])) {
148 if (isset($_SERVER['LOCAL_ADDR'])) {
149 $_SERVER['SERVER_ADDR'] = $_SERVER['LOCAL_ADDR'];
150 } else {
151 $_SERVER['SERVER_ADDR'] = 'unknown';
152 }
153}
154
155set_error_handler('errorHandler');
156register_shutdown_function('errorHandler_last');
157ini_set('display_errors', 1);
158global $Global_LastError;
159
160function errorHandler_last()
161{
162 if (function_exists("error_get_last")) {
163 $error = error_get_last();
164 if ($error) {
165 errorHandler($error['type'], $error['message'], $error['file'], $error['line']);
166 }
167 }
168}
169function errorHandler($errno, $errstr, $errfile, $errline)
170{
171 global $Global_LastError;
172 $Global_LastError = $errstr;
173
174 // Check with error_reporting, if statement is preceded with @ we have to ignore it.
175 if (!($errno & error_reporting())) {
176 return;
177 }
178
179 // Headers.
180 if (!headers_sent()) {
181 header('HTTP/1.0 503 Service Unavailable');
182 while (ob_get_level()) { ob_end_clean(); } // This will cancel ob_gzhandler, so later we set Content-encoding to none.
183 header('Content-Encoding: none'); // Fix gzip encoding header.
184 header("Content-Type: text/html; charset=utf-8");
185 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
186 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
187 header("Cache-Control: no-store, no-cache, must-revalidate");
188 header("Cache-Control: post-check=0, pre-check=0", false);
189 header("Pragma: no-cache");
190 }
191
192 // Error short message.
193 $errfile = basename($errfile);
194
195 $msg = sprintf('%s<br>In %s on line %d.', nl2br($errstr), $errfile, $errline);
196
197 // Display error.
198
199 printf("<!doctype html><html><head><meta charset=utf-8><title>PHP Error</title>");
200 printf("<meta name=\"robots\" content=\"noindex,nofollow\">");
201 printf("<link rel=\"shortcut icon\" href=\"{$_SERVER['PHP_SELF']}?dbkiss_favicon=1\">");
202 printf("<style type=text/css>");
203 printf("body { font: 12px Arial, Sans-serif; line-height: 17px; padding: 0em; margin: 2em 3em; }");
204 printf("h1 { font: bold 18px Tahoma; border-bottom: rgb(175, 50, 0) 1px solid; margin-bottom: 0.85em; padding-bottom: 0.25em; color: rgb(200, 50, 0); text-shadow: 1px 1px 1px #fff; }");
205 print("h2 { font: bold 15px Tahoma; margin-top: 1em; color: #000; text-shadow: 1px 1px 1px #fff; }");
206 printf("</style></head><body>");
207
208 printf("<h1>PHP Error</h1>");
209 printf($msg);
210
211 if ("127.0.0.1" == $_SERVER["SERVER_ADDR"] && "127.0.0.1" == $_SERVER["REMOTE_ADDR"])
212 {
213 // Showing backtrace only on localhost, cause it shows full arguments passed to functions,
214 // that would be a security hole to display such data, cause it could contain some sensitive
215 // data fetched from tables or could even contain a database connection user and password.
216
217 printf("<h2>Backtrace</h2>");
218 ob_start();
219 debug_print_backtrace();
220 $trace = ob_get_clean();
221 $trace = preg_replace("/^#0[\s\S]+?\n#1/", "#1", $trace); // Remove call to errorHandler() from trace.
222 $trace = trim($trace);
223 print nl2br($trace);
224 }
225
226 printf("</body></html>");
227
228 // Log error to file.
229 if ("127.0.0.1" == $_SERVER["SERVER_ADDR"] && "127.0.0.1" == $_SERVER["REMOTE_ADDR"]) {
230 error_log($msg);
231 }
232
233 // Email error.
234
235 exit();
236}
237
238// You can access this function only on localhost.
239
240if ("127.0.0.1" == $_SERVER["SERVER_ADDR"] && "127.0.0.1" == $_SERVER["REMOTE_ADDR"])
241{
242 function dump($data)
243 {
244 // @dump
245
246 if (!headers_sent()) {
247 header('HTTP/1.0 503 Service Unavailable');
248 while (ob_get_level()) { ob_end_clean(); } // This will cancel ob_gzhandler, so later we set Content-encoding to none.
249 header('Content-encoding: none'); // Fix gzip encoding header.
250 header("Content-type: text/html");
251 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
252 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
253 header("Cache-Control: no-store, no-cache, must-revalidate");
254 header("Cache-Control: post-check=0, pre-check=0", false);
255 header("Pragma: no-cache");
256 }
257
258 if (func_num_args() > 1) { $data = func_get_args(); }
259
260 if ($data && count($data) == 2 && isset($data[1]) && "windows-1250" == strtolower($data[1])) {
261 $charset = "windows-1250";
262 $data = $data[0];
263 } else if ($data && count($data) == 2 && isset($data[1]) && "iso-8859-2" == strtolower($data[1])) {
264 $charset = "iso-8859-2";
265 $data = $data[0];
266 } else {
267 $charset = "utf-8";
268 }
269
270 printf('<!doctype html><head><meta charset='.$charset.'><title>dump()</title></head><body>');
271 printf('<h1 style="color: rgb(150,15,225);">dump()</h1>');
272 ob_start();
273 print_r($data);
274 $html = ob_get_clean();
275 $html = htmlspecialchars($html);
276 printf('<pre>%s</pre>', $html);
277 printf('</body></html>');
278 exit();
279 }
280}
281
282if (isset($_GET['dbkiss_favicon'])) {
283 $favicon = 'AAABAAIAEBAAAAEACABoBQAAJgAAABAQAAABACAAaAQAAI4FAAAoAAAAEAAAACAAAAABAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wDQcRIAAGaZAL5mCwCZ//8Av24SAMVwEgCa//8AvmcLAKn//wAV0/8Awf//AErL5QDGcBIAvnESAHCpxgDf7PIA37aIAMNpDQDHcRIAZO7/AErl/wAdrNYAYMbZAI/1+QDouYkAO+D/AIT4/wDHcBIAjPr/AMJvEgDa//8AQIyzAMNvEgCfxdkA8v//AEzl/wB46fQAMLbZACms1gAAeaYAGou1AJfX6gAYo84AHrLbAN+zhgCXxtkAv/P5AI30+ADv9fkAFH2pABja/wDGaw4AwXASAAVwoQDjuIkAzXARADCmyQAAe64Ade35AMBxEgC+aQ0AAKnGACnw/wAngqwAxW8RABBwnwAAg6wAxW4QAL7w9wCG7PIAHKnSAMFsDwC/ZwwADnWkAASQwgAd1v8Aj7zSAMZvEQDv+fwABXSmABZ+qgAC6fIAAG+iAMhsDwAcz/kAvmsOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgICOTUTCQQECRMQEQACAgICVUpJEgEfBxRCJ1FOAgEBGgQ4AQEGAQEBDhZWAwICAgEEASIBBgEHFA4WTQMCAgECBAE2AQ8BDw89QDQDAgECAgQBVwEJAQQJPj9TKQIaAQEELgESBgEHHUU6N0QCAgICBA4iBgYfBx1PDUgDAAAAAAMcJQsLGxUeJg0XAwAAAAADHCULCxsVHiYNFwMAAAAAAzwtTDtUAwNLKiwDAAAAAAMoK0YMCggFRxgzAwAAAAADUCQgDAoIBQUFGQMAAAAAQzIkIAwKCAUFBRkDAAAAACNBLzAMCggFMRhSIwAAAAAAERAhAwMDAyEQEQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAAD4AQAAKAAAABAAAAAgAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMxmAO3MZgDtzGYA7cxmAO3MZgDtymYB78RmBvfCZgj6vmYK/r5mC/++Zgv/vmYK/sJmCPoAZpmPAGaZIAAAAADMZgDtzGYA7cxmAO3MZgDtxmYF9b9nDP/BbA//37aI///////CbxL/xXAS/8dxEv/FbxH/MLbZ/wV0pv8AZplwzGYA7f//////////57aF9r5mC//juIn///////////+/bhL/////////////////xnAS/0rl//8cz/n/AGaZ/8xmAO3MZgDtzGYA7f////++Zgv//////8NvEv//////v24S///////FcBL/x3ES/8ZwEv9K5f//Hdb//wBmmf/MZgDtzGYA7f/////MZgDtvmYL///////BcBL//////75xEv//////vnES/75xEv/AcRL/KfD//xja//8AZpn/zGYA7f/////MZgDtzGYA7b5mC///////vmsO//////++Zwv//////75mC/++Zwv/vmkN/wCpxv8C6fL/AHmm/8xmAO3ntoX2//////////++Zgv/37OG///////ftoj/v24S///////FcBL/x3AS/8VuEP8wpsn/BXCh/wCDrP/MZgDtzGYA7cxmAO3MZgDtvmYL/8ZwEv/DbxL/v24S/79uEv/CbxL/xXAS/8dwEv/GbxH/Ssvl/xyp0v8AZpn/AAAAAAAAAAAAAAAAAAAAAABmmf+E+P//TOX//xXT//8V0///O+D//2Tu//+M+v//eOn0/0rL5f8drNb/AGaZ/wAAAAAAAAAAAAAAAAAAAAAAZpn/hPj//0zl//8V0///FdP//zvg//9k7v//jPr//3jp9P9Ky+X/HazW/wBmmf8AAAAAAAAAAAAAAAAAAAAAAGaZ/3Xt+f8estv/BJDC/wB7rv8Ab6L/AGaZ/wBmmf8OdaT/Gou1/xijzv8AZpn/AAAAAAAAAAAAAAAAAAAAAABmmf8prNb/l9fq/77w9//B////qf///5r///+Z////huzy/2DG2f8Ufan/AGaZ/wAAAAAAAAAAAAAAAAAAAAAAZpn/7/n8//L////a////wf///6n///+a////mf///5n///+Z////j/X5/wBmmf8AAAAAAAAAAAAAAAAAAAAAAGaZ7+/1+f/y////2v///8H///+p////mv///5n///+Z////mf///4/1+f8AZpn/AAAAAAAAAAAAAAAAAAAAAABmmWAngqz/l8bZ/7/z+f/B////qf///5r///+Z////jfT4/2DG2f8Wfqr/AGaZYAAAAAAAAAAAAAAAAAAAAAAAAAAAAGaZIABmmY8AZpm/AGaZ/wBmmf8AZpn/AGaZ/wBmmb8AZpmPAGaZIAAAAAAAAQICAAA1EwAABAkAABEAAAACAgAASRIAAAcUAABRTvAAARrwAAEB8AABAfAAVgPwAAIB8AAiAfAABxT4AU0D';
284 header('Content-type: image/vnd.microsoft.icon');
285 echo base64_decode($favicon);
286 exit();
287}
288
289if (!function_exists('array_walk_recursive'))
290{
291 function array_walk_recursive(&$array, $func)
292 {
293 foreach ($array as $k => $v) {
294 if (is_array($v)) {
295 array_walk_recursive($array[$k], $func);
296 } else {
297 $func($array[$k], $k);
298 }
299 }
300 }
301}
302function create_links($text)
303{
304 // Protocols: http, https, ftp, irc, svn
305 // Parse emails also?
306
307 $text = preg_replace('#([a-z]+://[a-zA-Z0-9\.\,\;\:\[\]\{\}\-\_\+\=\!\@\#\%\&\(\)\/\?\`\~]+)#e', 'create_links_eval("\\1")', $text);
308
309 // Excaptions:
310
311 // 1) cut last char if link ends with ":" or ";" or "." or "," - cause in 99% cases that char doesnt belong to the link
312 // (check if previous char was "=" then let it stay cause that could be some variable in a query, some kind of separator)
313 // (should we add also "-" ? But it is a valid char in links and very common, many links might end with it when creating from some title of an article?)
314
315 // 2) brackets, the link could be inside one of 3 types of brackets:
316 // [http://...] , {http://...}
317 // and most common: (http://some.com/) OR http://some.com(some description of the link)
318 // In these cases regular expression will catch: "http://some.com/)" AND "http://some.com(some"
319 // So when we catch some kind of bracket in the link we will cut it unless there is also a closing bracket in the link:
320 // We will not cut brackets in this link: http://en.wikipedia.org/wiki/Common_(entertainer) - wikipedia often uses brackets.
321
322 return $text;
323}
324function create_links_eval($link)
325{
326 $orig_link = $link;
327 $cutted = "";
328
329 if (in_array($link[strlen($link)-1], array(":", ";", ".", ","))) {
330 $link = substr($link, 0, -1);
331 $cutted = $orig_link[strlen($orig_link)-1];
332 }
333
334 if (($pos = strpos($link, "(")) !== false) {
335 if (strpos($link, ")") === false) {
336 $link = substr($link, 0, $pos);
337 $cutted = substr($orig_link, $pos);
338 }
339 } else if (($pos = strpos($link, ")")) !== false) {
340 if (strpos($link, "(") === false) {
341 $link = substr($link, 0, $pos);
342 $cutted = substr($orig_link, $pos);
343 }
344 } else if (($pos = strpos($link, "[")) !== false) {
345 if (strpos($link, "]") === false) {
346 $link = substr($link, 0, $pos);
347 $cutted = substr($orig_link, $pos);
348 }
349 } else if (($pos = strpos($link, "]")) !== false) {
350 if (strpos($link, "[") === false) {
351 $link = substr($link, 0, $pos);
352 $cutted = substr($orig_link, $pos);
353 }
354 } else if (($pos = strpos($link, "{")) !== false) {
355 if (strpos($link, "}") === false) {
356 $link = substr($link, 0, $pos);
357 $cutted = substr($orig_link, $pos);
358 }
359 } else if (($pos = strpos($link, "}")) !== false) {
360 if (strpos($link, "{") === false) {
361 $link = substr($link, 0, $pos);
362 $cutted = substr($orig_link, $pos);
363 }
364 }
365 return "<a title=\"$link\" style=\"color: #000; text-decoration: none; border-bottom: #000 1px dotted;\" href=\"javascript:;\" onclick=\"link_noreferer('$link')\">$link</a>$cutted";
366}
367function truncate_html($string, $length, $break_words = false, $end_str = '..')
368{
369 // Does not break html tags whilte truncating, does not take into account chars inside tags: <b>a</b> = 1 char length.
370 // Break words is always TRUE - no breaking is not implemented.
371
372 // Limits: no handling of <script> tags.
373
374 $inside_tag = false;
375 $inside_amp = 0;
376 $finished = false; // finished but the loop is still running cause inside tag or amp.
377 $opened = 0;
378
379 $string_len = strlen($string);
380
381 $count = 0;
382 $ret = "";
383
384 for ($i = 0; $i < $string_len; $i++)
385 {
386 $char = $string[$i];
387 $nextchar = isset($string[$i+1]) ? $string[$i+1] : null;
388
389 if ('<' == $char && ('/' == $nextchar || ctype_alpha($nextchar))) {
390 if ('/' == $nextchar) {
391 $opened--;
392 } else {
393 $opened++;
394 }
395 $inside_tag = true;
396 }
397 if ('>' == $char) {
398 $inside_tag = false;
399 $ret .= $char;
400 continue;
401 }
402 if ($inside_tag) {
403 $ret .= $char;
404 continue;
405 }
406
407 if (!$finished)
408 {
409 if ('&' == $char) {
410 $inside_amp = 1;
411 $ret .= $char;
412 continue;
413 }
414 if (';' == $char && $inside_amp) {
415 $inside_amp = 0;
416 $count++;
417 $ret .= $char;
418 continue;
419 }
420 if ($inside_amp) {
421 $inside_amp++;
422 $ret .= $char;
423 if ('#' == $char || ctype_alnum($char)) {
424 if ($inside_amp > 7) {
425 $count += $inside_amp;
426 $inside_amp = 0;
427 }
428 } else {
429 $count += $inside_amp;
430 $inside_amp = 0;
431 }
432 continue;
433 }
434 }
435
436 $count++;
437
438 if (!$finished) {
439 $ret .= $char;
440 }
441
442 if ($count >= $length) {
443 if (!$inside_tag && !$inside_amp) {
444 if (!$finished) {
445 $ret .= $end_str;
446 $finished = true;
447 if (0 == $opened) {
448 break;
449 }
450 }
451 if (0 == $opened) {
452 break;
453 }
454 }
455 }
456 }
457 return $ret;
458}
459function table_filter($tables, $filter)
460{
461 $filter = trim($filter);
462 if ($filter) {
463 foreach ($tables as $k => $table) {
464 if (!str_has_any($table, $filter, $ignore_case = true)) {
465 unset($tables[$k]);
466 }
467 }
468 }
469 return $tables;
470}
471function get($key, $type='string')
472{
473 if (is_string($key)) {
474 $_GET[$key] = isset($_GET[$key]) ? $_GET[$key] : null;
475 if ('float' == $type) $_GET[$key] = str_replace(',','.',$_GET[$key]);
476 settype($_GET[$key], $type);
477 if ('string' == $type) $_GET[$key] = trim($_GET[$key]);
478 return $_GET[$key];
479 }
480 $vars = $key;
481 foreach ($vars as $key => $type) {
482 $_GET[$key] = isset($_GET[$key]) ? $_GET[$key] : null;
483 if ('float' == $type) $_GET[$key] = str_replace(',','.',$_GET[$key]);
484 settype($_GET[$key], $type);
485 if ('string' == $type) $_GET[$key] = trim($_GET[$key]);
486 $vars[$key] = $_GET[$key];
487 }
488 return $vars;
489}
490function post($key, $type='string')
491{
492 if (is_string($key)) {
493 $_POST[$key] = isset($_POST[$key]) ? $_POST[$key] : null;
494 if ('float' == $type) $_POST[$key] = str_replace(',','.',$_POST[$key]);
495 settype($_POST[$key], $type);
496 if ('string' == $type) $_POST[$key] = trim($_POST[$key]);
497 return $_POST[$key];
498 }
499 $vars = $key;
500 foreach ($vars as $key => $type) {
501 $_POST[$key] = isset($_POST[$key]) ? $_POST[$key] : null;
502 if ('float' == $type) $_POST[$key] = str_replace(',','.',$_POST[$key]);
503 settype($_POST[$key], $type);
504 if ('string' == $type) $_POST[$key] = trim($_POST[$key]);
505 $vars[$key] = $_POST[$key];
506 }
507 return $vars;
508}
509$_ENV['IS_GET'] = ('GET' == $_SERVER['REQUEST_METHOD']);
510$_ENV['IS_POST'] = ('POST' == $_SERVER['REQUEST_METHOD']);
511function req_gpc_has($str)
512{
513 /* finds if value exists in GPC data, used in filter_() functions, to check whether use html_tags_undo() on the data */
514 foreach ($_GET as $k => $v) {
515 if ($str == $v) {
516 return true;
517 }
518 }
519 foreach ($_POST as $k => $v) {
520 if ($str == $v) {
521 return true;
522 }
523 }
524 foreach ($_COOKIE as $k => $v) {
525 if ($str == $v) {
526 return true;
527 }
528 }
529 return false;
530}
531
532if (ini_get('magic_quotes_gpc')) {
533 ini_set('magic_quotes_runtime', 0);
534 array_walk_recursive($_GET, 'db_magic_quotes_gpc');
535 array_walk_recursive($_POST, 'db_magic_quotes_gpc');
536 array_walk_recursive($_COOKIE, 'db_magic_quotes_gpc');
537}
538function db_magic_quotes_gpc(&$val)
539{
540 $val = stripslashes($val);
541}
542
543$sql_font = 'font-size: 12px; font-family: courier new;';
544$sql_area = $sql_font.' width: 708px; height: 182px; border: #ccc 1px solid; background: #f9f9f9; padding: 3px;';
545
546if (!isset($db_name_style)) {
547 $db_name_style = '';
548}
549if (!isset($db_name_h1)) {
550 $db_name_h1 = '';
551}
552
553global $db_link, $db_name;
554
555if (!defined('COOKIE_PREFIX')) {
556 define('COOKIE_PREFIX', 'dbkiss_');
557}
558
559define('COOKIE_WEEK', 604800); // 3600*24*7
560define('COOKIE_SESS', 0);
561function cookie_get($key)
562{
563 $key = COOKIE_PREFIX.$key;
564 if (isset($_COOKIE[$key])) return $_COOKIE[$key];
565 return null;
566}
567function cookie_set($key, $val, $time = COOKIE_SESS)
568{
569 $key = COOKIE_PREFIX.$key;
570 $expire = $time ? time() + $time : 0;
571 if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
572 setcookie($key, $val, $expire, '', '', false, true);
573 } else {
574 setcookie($key, $val, $expire);
575 }
576 $_COOKIE[$key] = $val;
577}
578function cookie_del($key)
579{
580 $key = COOKIE_PREFIX.$key;
581 if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
582 setcookie($key, '', time()-3600*24, '', '', false, true);
583 } else {
584 setcookie($key, '', time()-3600*24);
585 }
586 unset($_COOKIE[$key]);
587}
588
589conn_modify('db_name');
590conn_modify('db_charset');
591conn_modify('page_charset');
592
593function conn_modify($key)
594{
595 if (array_key_exists($key, $_GET)) {
596 cookie_set($key, $_GET[$key], cookie_get('remember') ? COOKIE_WEEK : COOKIE_SESS);
597 if (isset($_GET['from']) && $_GET['from']) {
598 header('Location: '.$_GET['from']);
599 } else {
600 header('Location: '.$_SERVER['PHP_SELF']);
601 }
602 exit;
603 }
604}
605
606$db_driver = cookie_get('db_driver');
607$db_server = cookie_get('db_server');
608$db_name = cookie_get('db_name');
609$db_user = cookie_get('db_user');
610$db_pass = base64_decode(cookie_get('db_pass'));
611$db_charset = cookie_get('db_charset');
612$page_charset = cookie_get('page_charset');
613
614$charset1 = array('latin1', 'latin2', 'utf8', 'cp1250');
615$charset2 = array('iso-8859-1', 'iso-8859-2', 'utf-8', 'windows-1250');
616$charset1[] = $db_charset;
617$charset2[] = $page_charset;
618$charset1 = charset_assoc($charset1);
619$charset2 = charset_assoc($charset2);
620
621$driver_arr = array('mysql', 'pgsql');
622$driver_arr = array_assoc($driver_arr);
623
624function array_assoc($a)
625{
626 $ret = array();
627 foreach ($a as $v) {
628 $ret[$v] = $v;
629 }
630 return $ret;
631}
632function charset_assoc($arr)
633{
634 sort($arr);
635 $ret = array();
636 foreach ($arr as $v) {
637 if (!$v) { continue; }
638 $v = strtolower($v);
639 $ret[$v] = $v;
640 }
641 return $ret;
642}
643
644
645if (isset($_GET['disconnect']) && $_GET['disconnect'])
646{
647 cookie_del('db_pass');
648 header('Location: '.$_SERVER['PHP_SELF']);
649 exit;
650}
651
652if (!$db_pass || (!$db_driver || !$db_server || !$db_name || !$db_user))
653{
654 $original_url = post('original_url');
655 if (!$original_url) {
656 $original_url = $_SERVER['REQUEST_URI'];
657 }
658
659 if ('POST' == $_SERVER['REQUEST_METHOD'])
660 {
661 $db_driver = post('db_driver');
662 $db_server = post('db_server');
663 $db_name = post('db_name');
664 $db_user = post('db_user');
665 $db_pass = post('db_pass');
666 $db_charset = post('db_charset');
667 $page_charset = post('page_charset');
668
669 if ($db_driver && $db_server && $db_name && $db_user)
670 {
671 $db_test = true;
672 db_connect($db_server, $db_name, $db_user, $db_pass);
673 if (is_resource($db_link))
674 {
675 $time = post('remember') ? COOKIE_WEEK : COOKIE_SESS;
676 cookie_set('db_driver', $db_driver, $time);
677 cookie_set('db_server', $db_server, $time);
678 cookie_set('db_name', $db_name, $time);
679 cookie_set('db_user', $db_user, $time);
680 cookie_set('db_pass', base64_encode($db_pass), $time);
681 cookie_set('db_charset', $db_charset, $time);
682 cookie_set('page_charset', $page_charset, $time);
683 cookie_set('remember', post('remember'), $time);
684 $redirect_to = $_SERVER['PHP_SELF'];
685 if ($original_url) {
686 $redirect_to = $original_url;
687 }
688 header('Location: '.$redirect_to);
689 exit;
690 }
691 }
692 }
693 else
694 {
695 $_POST['db_driver'] = $db_driver;
696 $_POST['db_server'] = $db_server ? $db_server : 'localhost';
697 $_POST['db_name'] = $db_name;
698 $_POST['db_user'] = $db_user;
699 $_POST['db_charset'] = $db_charset;
700 $_POST['page_charset'] = $page_charset;
701 $_POST['db_driver'] = $db_driver;
702 }
703 ?>
704
705 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
706 <html>
707 <head>
708 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
709 <title>Connect</title>
710 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
711 </head>
712 <body>
713
714 <?php layout(); ?>
715
716 <h1>Connect</h1>
717
718 <?php if (isset($db_test) && is_string($db_test)): ?>
719 <div style="background: #ffffd7; padding: 0.5em; border: #ccc 1px solid; margin-bottom: 1em;">
720 <span style="color: red; font-weight: bold;">Error:</span>
721 <?php echo $db_test;?>
722 </div>
723 <?php endif; ?>
724
725 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
726 <input type="hidden" name="original_url" value="<?php echo htmlspecialchars($original_url); ?>">
727 <table class="ls ls2" cellspacing="1">
728 <tr>
729 <th>Driver:</th>
730 <td><select name="db_driver"><?php echo options($driver_arr, post('db_driver'));?></select></td>
731 </tr>
732 <tr>
733 <th>Server:</th>
734 <td><input type="text" name="db_server" value="<?php echo post('db_server');?>"></td>
735 </tr>
736 <tr>
737 <th>Database:</th>
738 <td><input type="text" name="db_name" value="<?php echo post('db_name');?>"></td>
739 </tr>
740 <tr>
741 <th>User:</th>
742 <td><input type="text" name="db_user" value="<?php echo post('db_user');?>"></td>
743 </tr>
744 <tr>
745 <th>Password:</th>
746 <td><input type="password" name="db_pass" value=""></td>
747 </tr>
748 <tr>
749 <th>Db charset:</th>
750 <td><input type="text" name="db_charset" value="<?php echo post('db_charset');?>" size="10"> (optional)</td>
751 </tr>
752 <tr>
753 <th>Page charset:</th>
754 <td><input type="text" name="page_charset" value="<?php echo post('page_charset');?>" size="10"> (optional)</td>
755 </tr>
756 <tr>
757 <td colspan="2" class="none" style="padding: 0; background: none; padding-top: 0.3em;">
758 <table cellspacing="0" cellpadding="0"><tr><td>
759 <input type="checkbox" name="remember" id="remember" value="1" <?php echo checked(post('remember'));?>></td><td>
760 <label for="remember">remember me on this computer</label></td></tr></table>
761 </td>
762 </tr>
763 <tr>
764 <td class="none" colspan="2" style="padding-top: 0.4em;"><input type="submit" value="Connect"></td>
765 </tr>
766 </table>
767 </form>
768
769 <?php powered_by(); ?>
770
771 </body>
772 </html>
773
774 <?php
775
776 exit;
777}
778
779db_connect($db_server, $db_name, $db_user, $db_pass);
780
781if ($db_charset && 'mysql' == $db_driver) {
782 db_exe("SET NAMES $db_charset");
783}
784
785if (isset($_GET['dump_all']) && 1 == $_GET['dump_all'])
786{
787 dump_all($data = false);
788}
789if (isset($_GET['dump_all']) && 2 == $_GET['dump_all'])
790{
791 dump_all($data = true);
792}
793if (isset($_GET['dump_table']) && $_GET['dump_table'])
794{
795 dump_table($_GET['dump_table']);
796}
797if (isset($_GET['export']) && 'csv' == $_GET['export'])
798{
799 export_csv(base64_decode($_GET['query']), $_GET['separator']);
800}
801if (isset($_POST['sqlfile']) && $_POST['sqlfile'])
802{
803 $files = sql_files_assoc();
804 if (!isset($files[$_POST['sqlfile']])) {
805 exit('File not found. md5 = '.$_POST['sqlfile']);
806 }
807 $sqlfile = $files[$_POST['sqlfile']];
808 layout();
809 echo '<div>Importing: <b>'.$sqlfile.'</b> ('.size(filesize($sqlfile)).')</div>';
810 echo '<div>Database: <b>'.$db_name.'</b></div>';
811 flush();
812 import($sqlfile, post('ignore_errors'), post('transaction'), post('force_myisam'), post('query_start','int'));
813 exit;
814}
815if (isset($_POST['drop_table']) && $_POST['drop_table'])
816{
817 $drop_table_enq = quote_table($_POST['drop_table']);
818 db_exe('DROP TABLE '.$drop_table_enq);
819 header('Location: '.$_SERVER['PHP_SELF']);
820 exit;
821}
822if (isset($_POST['drop_view']) && $_POST['drop_view'])
823{
824 $drop_view_enq = quote_table($_POST['drop_view']);
825 db_exe('DROP VIEW '.$drop_view_enq);
826 header('Location: '.$_SERVER['PHP_SELF']);
827 exit;
828}
829function db_connect($db_server, $db_name, $db_user, $db_pass)
830{
831 global $db_driver, $db_link, $db_test;
832 if (!extension_loaded($db_driver)) {
833 trigger_error($db_driver.' extension not loaded', E_USER_ERROR);
834 }
835 if ('mysql' == $db_driver)
836 {
837 $db_link = @mysql_connect($db_server, $db_user, $db_pass);
838 if (!is_resource($db_link)) {
839 if ($db_test) {
840 $db_test = 'mysql_connect() failed: '.db_error();
841 return;
842 } else {
843 cookie_del('db_pass');
844 cookie_del('db_name');
845 die('mysql_connect() failed: '.db_error());
846 }
847 }
848 if (!@mysql_select_db($db_name, $db_link)) {
849 $error = db_error();
850 db_close();
851 if ($db_test) {
852 $db_test = 'mysql_select_db() failed: '.$error;
853 return;
854 } else {
855 cookie_del('db_pass');
856 cookie_del('db_name');
857 die('mysql_select_db() failed: '.$error);
858 }
859 }
860 }
861 if ('pgsql' == $db_driver)
862 {
863 $conn = sprintf("host='%s' dbname='%s' user='%s' password='%s'", $db_server, $db_name, $db_user, $db_pass);
864 $db_link = @pg_connect($conn);
865 if (!is_resource($db_link)) {
866 if ($db_test) {
867 $db_test = 'pg_connect() failed: '.db_error();
868 return;
869 } else {
870 cookie_del('db_pass');
871 cookie_del('db_name');
872 die('pg_connect() failed: '.db_error());
873 }
874 }
875 }
876 register_shutdown_function('db_cleanup');
877}
878function db_cleanup()
879{
880 db_close();
881}
882function db_close()
883{
884 global $db_driver, $db_link;
885 if (is_resource($db_link)) {
886 if ('mysql' == $db_driver) {
887 mysql_close($db_link);
888 }
889 if ('pgsql' == $db_driver) {
890 pg_close($db_link);
891 }
892 }
893}
894function db_query($query, $dat = false)
895{
896 global $db_driver, $db_link;
897 $query = db_bind($query, $dat);
898 if (!db_is_safe($query)) {
899 return false;
900 }
901 if ('mysql' == $db_driver)
902 {
903 $rs = mysql_query($query, $db_link);
904 if (!$rs) {
905 trigger_error("mysql_query() failed: $query.<br>Error: ".db_error(), E_USER_ERROR);
906 }
907 return $rs;
908 }
909 if ('pgsql' == $db_driver)
910 {
911 $rs = pg_query($db_link, $query);
912 if (!$rs) {
913 trigger_error("pg_query() failed: $query.<br>Error: ".db_error(), E_USER_ERROR);
914 }
915 return $rs;
916 }
917}
918function db_is_safe($q, $ret = false)
919{
920 // currently only checks UPDATE's/DELETE's if WHERE condition is not missing
921 $upd = 'update';
922 $del = 'delete';
923
924 $q = ltrim($q);
925 if (strtolower(substr($q, 0, strlen($upd))) == $upd
926 || strtolower(substr($q, 0, strlen($del))) == $del) {
927 if (!preg_match('#\swhere\s#i', $q)) {
928 if ($ret) {
929 return false;
930 } else {
931 trigger_error(sprintf('db_is_safe() failed. Detected UPDATE/DELETE without WHERE condition. Query: %s.', $q), E_USER_ERROR);
932 return false;
933 }
934 }
935 }
936
937 return true;
938}
939function db_exe($query, $dat = false)
940{
941 $rs = db_query($query, $dat);
942 db_free($rs);
943}
944function db_one($query, $dat = false)
945{
946 $row = db_row_num($query, $dat);
947 if ($row) {
948 return $row[0];
949 } else {
950 return false;
951 }
952}
953function db_row($query, $dat = false)
954{
955 global $db_driver, $db_link;
956 if ('mysql' == $db_driver)
957 {
958 if (is_resource($query)) {
959 $rs = $query;
960 return mysql_fetch_assoc($rs);
961 } else {
962 $query = db_limit($query, 0, 1);
963 $rs = db_query($query, $dat);
964 $row = mysql_fetch_assoc($rs);
965 db_free($rs);
966 if ($row) {
967 return $row;
968 }
969 }
970 return false;
971 }
972 if ('pgsql' == $db_driver)
973 {
974 if (is_resource($query) || is_object($query)) {
975 $rs = $query;
976 return pg_fetch_assoc($rs);
977 } else {
978 $query = db_limit($query, 0, 1);
979 $rs = db_query($query, $dat);
980 $row = pg_fetch_assoc($rs);
981 db_free($rs);
982 if ($row) {
983 return $row;
984 }
985 }
986 return false;
987 }
988}
989function db_row_num($query, $dat = false)
990{
991 global $db_driver, $db_link;
992 if ('mysql' == $db_driver)
993 {
994 if (is_resource($query)) {
995 $rs = $query;
996 return mysql_fetch_row($rs);
997 } else {
998 $rs = db_query($query, $dat);
999 if (!$rs) {
1000 /*
1001 echo '<pre>';
1002 print_r($rs);
1003 echo "\r\n";
1004 print_r($query);
1005 echo "\r\n";
1006 print_r($dat);
1007 exit;
1008 */
1009 }
1010 $row = mysql_fetch_row($rs);
1011 db_free($rs);
1012 if ($row) {
1013 return $row;
1014 }
1015 return false;
1016 }
1017 }
1018 if ('pgsql' == $db_driver)
1019 {
1020 if (is_resource($query) || is_object($query)) {
1021 $rs = $query;
1022 return pg_fetch_row($rs);
1023 } else {
1024 $rs = db_query($query, $dat);
1025 $row = pg_fetch_row($rs);
1026 db_free($rs);
1027 if ($row) {
1028 return $row;
1029 }
1030 return false;
1031 }
1032 }
1033}
1034function db_list($query)
1035{
1036 global $db_driver, $db_link;
1037 $rs = db_query($query);
1038 $ret = array();
1039 if ('mysql' == $db_driver) {
1040 while ($row = mysql_fetch_assoc($rs)) {
1041 $ret[] = $row;
1042 }
1043 }
1044 if ('pgsql' == $db_driver) {
1045 while ($row = pg_fetch_assoc($rs)) {
1046 $ret[] = $row;
1047 }
1048 }
1049 db_free($rs);
1050 return $ret;
1051}
1052function db_assoc($query)
1053{
1054 global $db_driver, $db_link;
1055 $rs = db_query($query);
1056 $rows = array();
1057 $num = db_row_num($rs);
1058 if (!is_array($num)) {
1059 return array();
1060 }
1061 if (!array_key_exists(0, $num)) {
1062 return array();
1063 }
1064 if (1 == count($num)) {
1065 $rows[] = $num[0];
1066 while ($num = db_row_num($rs)) {
1067 $rows[] = $num[0];
1068 }
1069 return $rows;
1070 }
1071 if ('mysql' == $db_driver)
1072 {
1073 mysql_data_seek($rs, 0);
1074 }
1075 if ('pgsql' == $db_driver)
1076 {
1077 pg_result_seek($rs, 0);
1078 }
1079 $row = db_row($rs);
1080 if (!is_array($row)) {
1081 return array();
1082 }
1083 if (count($num) < 2) {
1084 trigger_error(sprintf('db_assoc() failed. Two fields required. Query: %s.', $query), E_USER_ERROR);
1085 }
1086 if (count($num) > 2 && count($row) <= 2) {
1087 trigger_error(sprintf('db_assoc() failed. If specified more than two fields, then each of them must have a unique name. Query: %s.', $query), E_USER_ERROR);
1088 }
1089 foreach ($row as $k => $v) {
1090 $first_key = $k;
1091 break;
1092 }
1093 if (count($row) > 2) {
1094 $rows[$row[$first_key]] = $row;
1095 while ($row = db_row($rs)) {
1096 $rows[$row[$first_key]] = $row;
1097 }
1098 } else {
1099 $rows[$num[0]] = $num[1];
1100 while ($num = db_row_num($rs)) {
1101 $rows[$num[0]] = $num[1];
1102 }
1103 }
1104 db_free($rs);
1105 return $rows;
1106}
1107function db_limit($query, $offset, $limit)
1108{
1109 global $db_driver;
1110
1111 $offset = (int) $offset;
1112 $limit = (int) $limit;
1113
1114 $query = trim($query);
1115 if (str_ends_with($query, ';')) {
1116 $query = str_cut_end($query, ';');
1117 }
1118
1119 $query = preg_replace('#^([\s\S]+)LIMIT\s+\d+\s+OFFSET\s+\d+\s*$#i', '$1', $query);
1120 $query = preg_replace('#^([\s\S]+)LIMIT\s+\d+\s*,\s*\d+\s*$#i', '$1', $query);
1121
1122 if ('mysql' == $db_driver) {
1123 // mysql 3.23 doesn't understand "LIMIT x OFFSET z"
1124 return $query." LIMIT $offset, $limit";
1125 } else {
1126 return $query." LIMIT $limit OFFSET $offset";
1127 }
1128}
1129function db_escape($value)
1130{
1131 global $db_driver, $db_link;
1132 if ('mysql' == $db_driver) {
1133 return mysql_real_escape_string($value, $db_link);
1134 }
1135 if ('pgsql' == $db_driver) {
1136 return pg_escape_string($value);
1137 }
1138}
1139function db_quote($s)
1140{
1141 switch (true) {
1142 case is_null($s): return 'NULL';
1143 case is_int($s): return $s;
1144 case is_float($s): return $s;
1145 case is_bool($s): return (int) $s;
1146 case is_string($s): return "'" . db_escape($s) . "'";
1147 case is_object($s): return $s->getValue();
1148 default:
1149 trigger_error(sprintf("db_quote() failed. Invalid data type: '%s'.", gettype($s)), E_USER_ERROR);
1150 return false;
1151 }
1152}
1153function db_strlen_cmp($a, $b)
1154{
1155 if (strlen($a) == strlen($b)) {
1156 return 0;
1157 }
1158 return strlen($a) > strlen($b) ? -1 : 1;
1159}
1160function db_bind($q, $dat)
1161{
1162 if (false === $dat) {
1163 return $q;
1164 }
1165 if (!is_array($dat)) {
1166 //return trigger_error('db_bind() failed. Second argument expects to be an array.', E_USER_ERROR);
1167 $dat = array($dat);
1168 }
1169
1170 $qBase = $q;
1171
1172 // special case: LIKE '%asd%', need to ignore that
1173 $q_search = array("'%", "%'");
1174 $q_replace = array("'\$", "\$'");
1175 $q = str_replace($q_search, $q_replace, $q);
1176
1177 preg_match_all('#%\w+#', $q, $match);
1178 if ($match) {
1179 $match = $match[0];
1180 }
1181 if (!$match || !count($match)) {
1182 return trigger_error('db_bind() failed. No binding keys found in the query.', E_USER_ERROR);
1183 }
1184 $keys = $match;
1185 usort($keys, 'db_strlen_cmp');
1186 $num = array();
1187
1188 foreach ($keys as $key)
1189 {
1190 $key2 = str_replace('%', '', $key);
1191 if (is_numeric($key2)) $num[$key] = true;
1192 if (!array_key_exists($key2, $dat)) {
1193 return trigger_error(sprintf('db_bind() failed. No data found for key: %s. Query: %s.', $key, $qBase), E_USER_ERROR);
1194 }
1195 $q = str_replace($key, db_quote($dat[$key2]), $q);
1196 }
1197 if (count($num)) {
1198 if (count($dat) != count($num)) {
1199 return trigger_error('db_bind() failed. When using numeric data binding you need to use all data passed to the query. You also cannot mix numeric and name binding.', E_USER_ERROR);
1200 }
1201 }
1202
1203 $q = str_replace($q_replace, $q_search, $q);
1204
1205 return $q;
1206}
1207function db_free($rs)
1208{
1209 global $db_driver;
1210 if (db_is_result($rs)) {
1211 if ('mysql' == $db_driver) return mysql_free_result($rs);
1212 if ('pgsql' == $db_driver) return pg_free_result($rs);
1213 }
1214}
1215function db_is_result($rs)
1216{
1217 global $db_driver;
1218 if ('mysql' == $db_driver) return is_resource($rs);
1219 if ('pgsql' == $db_driver) return is_object($rs) || is_resource($rs);
1220}
1221function db_error()
1222{
1223 global $db_driver, $db_link;
1224 if ('mysql' == $db_driver) {
1225 if (is_resource($db_link)) {
1226 if (mysql_error($db_link)) {
1227 return mysql_error($db_link). ' ('. mysql_errno($db_link).')';
1228 } else {
1229 return false;
1230 }
1231 } else {
1232 if (mysql_error()) {
1233 return mysql_error(). ' ('. mysql_errno().')';
1234 } else {
1235 return false;
1236 }
1237 }
1238 }
1239 if ('pgsql' == $db_driver) {
1240 if (is_resource($db_link)) {
1241 return pg_last_error($db_link);
1242 }
1243 }
1244}
1245function db_begin()
1246{
1247 global $db_driver;
1248 if ('mysql' == $db_driver) {
1249 db_exe('SET AUTOCOMMIT=0');
1250 db_exe('BEGIN');
1251 }
1252 if ('pgsql' == $db_driver) {
1253 db_exe('BEGIN');
1254 }
1255}
1256function db_end()
1257{
1258 global $db_driver;
1259 if ('mysql' == $db_driver) {
1260 db_exe('COMMIT');
1261 db_exe('SET AUTOCOMMIT=1');
1262 }
1263 if ('pgsql' == $db_driver) {
1264 db_exe('COMMIT');
1265 }
1266}
1267function db_rollback()
1268{
1269 global $db_driver;
1270 if ('mysql' == $db_driver) {
1271 db_exe('ROLLBACK');
1272 db_exe('SET AUTOCOMMIT=1');
1273 }
1274 if ('pgsql' == $db_driver) {
1275 db_exe('ROLLBACK');
1276 }
1277}
1278function db_in_array($arr)
1279{
1280 $in = '';
1281 foreach ($arr as $v) {
1282 if ($in) $in .= ',';
1283 $in .= db_quote($v);
1284 }
1285 return $in;
1286}
1287function db_where($where_array, $field_prefix = null, $omit_where = false)
1288{
1289 $field_prefix = str_replace('.', '', $field_prefix);
1290 $where = '';
1291 if (count($where_array)) {
1292 foreach ($where_array as $wh_k => $wh)
1293 {
1294 if (is_numeric($wh_k)) {
1295 if ($wh) {
1296 if ($field_prefix && !preg_match('#^\s*\w+\.#i', $wh) && !preg_match('#^\s*\w+\s*\(#i', $wh)) {
1297 $wh = $field_prefix.'.'.trim($wh);
1298 }
1299 if ($where) $where .= ' AND ';
1300 $where .= $wh;
1301 }
1302 } else {
1303 if ($wh_k) {
1304 if ($field_prefix && !preg_match('#^\s*\w+\.#i', $wh_k) && !preg_match('#^\s*\w+\s*\(#i', $wh)) {
1305 $wh_k = $field_prefix.'.'.$wh_k;
1306 }
1307 $wh = db_cond($wh_k, $wh);
1308 if ($where) $where .= ' AND ';
1309 $where .= $wh;
1310 }
1311 }
1312 }
1313 if ($where) {
1314 if (!$omit_where) {
1315 $where = ' WHERE '.$where;
1316 }
1317 }
1318 }
1319 return $where;
1320}
1321function db_insert($tbl, $dat)
1322{
1323 global $db_driver;
1324 if (!count($dat)) {
1325 trigger_error('db_insert() failed. Data is empty.', E_USER_ERROR);
1326 return false;
1327 }
1328 $cols = '';
1329 $vals = '';
1330 $first = true;
1331 foreach ($dat as $k => $v) {
1332 if ($first) {
1333 $cols .= $k;
1334 $vals .= db_quote($v);
1335 $first = false;
1336 } else {
1337 $cols .= ',' . $k;
1338 $vals .= ',' . db_quote($v);
1339 }
1340 }
1341 if ('mysql' == $db_driver) {
1342 $tbl = "`$tbl`";
1343 }
1344 $q = "INSERT INTO $tbl ($cols) VALUES ($vals)";
1345 db_exe($q);
1346}
1347// $wh = WHERE condition, might be (string) or (array)
1348function db_update($tbl, $dat, $wh)
1349{
1350 global $db_driver;
1351 if (!count($dat)) {
1352 trigger_error('db_update() failed. Data is empty.', E_USER_ERROR);
1353 return false;
1354 }
1355 $set = '';
1356 $first = true;
1357 foreach ($dat as $k => $v) {
1358 if ($first) {
1359 $set .= $k . '=' . db_quote($v);
1360 $first = false;
1361 } else {
1362 $set .= ',' . $k . '=' . db_quote($v);
1363 }
1364 }
1365 if (is_array($wh)) {
1366 $wh = db_where($wh, null, $omit_where = true);
1367 }
1368 if ('mysql' == $db_driver) {
1369 $tbl = "`$tbl`";
1370 }
1371 $q = "UPDATE $tbl SET $set WHERE $wh";
1372 return db_exe($q);
1373}
1374function db_insert_id($table = null, $pk = null)
1375{
1376 global $db_driver, $db_link;
1377 if ('mysql' == $db_driver) {
1378 return mysql_insert_id($_db['conn_id']);
1379 }
1380 if ('pgsql' == $db_driver) {
1381 if (!$table || !$pk) {
1382 trigger_error('db_insert_id(): table & pk required', E_USER_ERROR);
1383 }
1384 $seq_id = $table.'_'.$pk.'_seq';
1385 return db_seq_id($seq_id);
1386 }
1387}
1388function db_seq_id($seqName)
1389{
1390 return db_one('SELECT currval(%seqName)', array('seqName'=>$seqName));
1391}
1392function db_cond($k, $v)
1393{
1394 if (is_null($v)) return sprintf('%s IS NULL', $k);
1395 else return sprintf('%s = %s', $k, db_quote($v));
1396}
1397function list_dbs()
1398{
1399 global $db_driver, $db_link;
1400 if ('mysql' == $db_driver)
1401 {
1402 $result = mysql_query('SHOW DATABASES', $db_link);
1403 $ret = array();
1404 while ($row = mysql_fetch_row($result)) {
1405 $ret[$row[0]] = $row[0];
1406 }
1407 return $ret;
1408 }
1409 if ('pgsql' == $db_driver)
1410 {
1411 return db_assoc('SELECT datname, datname FROM pg_database');
1412 }
1413}
1414function views_supported()
1415{
1416 static $ret;
1417 if (isset($ret)) {
1418 return $ret;
1419 }
1420 global $db_driver, $db_link;
1421 if ('mysql' == $db_driver) {
1422 $version = mysql_get_server_info($db_link);
1423 if (strpos($version, "-") !== false) {
1424 $version = substr($version, 0, strpos($version, "-"));
1425 }
1426 if (version_compare($version, "5.0.2", ">=")) {
1427 // Views are available in 5.0.0 but we need SHOW FULL TABLES
1428 // and the FULL syntax was added in 5.0.2, FULL allows us to
1429 // to distinct between tables & views in the returned list by
1430 // by providing an additional column.
1431 $ret = true;
1432 return true;
1433 } else {
1434 $ret = false;
1435 return false;
1436 }
1437 }
1438 if ('pgsql' == $db_driver) {
1439 $ret = true;
1440 return true;
1441 }
1442}
1443function list_tables($views_mode=false)
1444{
1445 global $db_driver, $db_link, $db_name;
1446
1447 if ($views_mode && !views_supported()) {
1448 return array();
1449 }
1450
1451 static $cache_tables;
1452 static $cache_views;
1453
1454 if ($views_mode) {
1455 if (isset($cache_views)) {
1456 return $cache_views;
1457 }
1458 } else {
1459 if (isset($cache_tables)) {
1460 return $cache_tables;
1461 }
1462 }
1463
1464 static $all_tables; // tables and views
1465
1466 if ('mysql' == $db_driver)
1467 {
1468 if (!isset($all_tables)) {
1469 $all_tables = db_assoc("SHOW FULL TABLES");
1470 // assoc: table name => table type (BASE TABLE or VIEW)
1471 }
1472
1473 // This chunk of code is the same as in pgsql driver.
1474 if ($views_mode) {
1475 $views = array();
1476 foreach ($all_tables as $view => $type) {
1477 if ($type != 'VIEW') { continue; }
1478 $views[] = $view;
1479 }
1480 $cache_views = $views;
1481 return $views;
1482 } else {
1483 $tables = array();
1484 foreach ($all_tables as $table => $type) {
1485 if ($type != 'BASE TABLE') { continue; }
1486 $tables[] = $table;
1487 }
1488 $cache_tables = $tables;
1489 return $tables;
1490 }
1491 }
1492 if ('pgsql' == $db_driver)
1493 {
1494 if (!isset($all_tables)) {
1495 $query = "SELECT table_name, table_type ";
1496 $query .= "FROM information_schema.tables ";
1497 $query .= "WHERE table_schema = 'public' ";
1498 $query .= "AND (table_type = 'BASE TABLE' OR table_type = 'VIEW') ";
1499 $query .= "ORDER BY table_name ";
1500 $all_tables = db_assoc($query);
1501 }
1502
1503 // This chunk of code is the same as in mysql driver.
1504 if ($views_mode) {
1505 $views = array();
1506 foreach ($all_tables as $view => $type) {
1507 if ($type != 'VIEW') { continue; }
1508 $views[] = $view;
1509 }
1510 $cache_views = $views;
1511 return $views;
1512 } else {
1513 $tables = array();
1514 foreach ($all_tables as $table => $type) {
1515 if ($type != 'BASE TABLE') { continue; }
1516 $tables[] = $table;
1517 }
1518 $cache_tables = $tables;
1519 return $tables;
1520 }
1521 }
1522}
1523function IsTableAView($table)
1524{
1525 // There is no cache here, so call it only once!
1526
1527 global $db_driver, $db_name;
1528
1529 if ("mysql" == $db_driver) {
1530 // Views and information_schema is supported since 5.0
1531 if (views_supported()) {
1532 $query = "SELECT table_name FROM information_schema.tables WHERE table_schema=%0 AND table_name=%1 AND table_type='VIEW' ";
1533 $row = db_row($query, array($db_name, $table));
1534 return (bool) $row;
1535 }
1536 return false;
1537 }
1538 else if ("pgsql" == $db_driver) {
1539 $query = "SELECT table_name, table_type ";
1540 $query .= "FROM information_schema.tables ";
1541 $query .= "WHERE table_schema = 'public' ";
1542 $query .= "AND table_type = 'VIEW' AND table_name = %0 ";
1543 $row = db_row($query, $table);
1544 return (bool) $row;
1545 }
1546}
1547function quote_table($table)
1548{
1549 global $db_driver;
1550 if ('mysql' == $db_driver) {
1551 return "`$table`";
1552 } else {
1553 return "\"$table\"";
1554 }
1555}
1556function table_structure($table)
1557{
1558 global $db_driver;
1559 if ('mysql' == $db_driver)
1560 {
1561 $query = "SHOW CREATE TABLE `$table`";
1562 $row = db_row_num($query);
1563 echo $row[1].';';
1564 echo "\n\n";
1565 }
1566 if ('pgsql' == $db_driver)
1567 {
1568 return '';
1569 }
1570}
1571function table_data($table)
1572{
1573 global $db_driver;
1574 set_time_limit(0);
1575 if ('mysql' == $db_driver) {
1576 $query = "SELECT * FROM `$table`";
1577 } else {
1578 $query = "SELECT * FROM $table";
1579 }
1580 $result = db_query($query);
1581 $count = 0;
1582 while ($row = db_row($result))
1583 {
1584 if ('mysql' == $db_driver) {
1585 echo 'INSERT INTO `'.$table.'` VALUES (';
1586 }
1587 if ('pgsql' == $db_driver) {
1588 echo 'INSERT INTO '.$table.' VALUES (';
1589 }
1590 $x = 0;
1591 foreach($row as $key => $value)
1592 {
1593 if ($x == 1) { echo ', '; }
1594 else { $x = 1; }
1595 if (is_numeric($value)) { echo "'".$value."'"; }
1596 elseif (is_null($value)) { echo 'NULL'; }
1597 else { echo '\''. escape($value) .'\''; }
1598 }
1599 echo ");\n";
1600 $count++;
1601 if ($count % 100 == 0) { flush(); }
1602 }
1603 db_free($result);
1604 if ($count) {
1605 echo "\n";
1606 }
1607}
1608function table_status()
1609{
1610 // Size is not supported for Views, only for Tables.
1611
1612 global $db_driver, $db_link, $db_name;
1613 if ('mysql' == $db_driver)
1614 {
1615 $status = array();
1616 $status['total_size'] = 0;
1617 $result = mysql_query("SHOW TABLE STATUS FROM `$db_name`", $db_link);
1618 while ($row = mysql_fetch_assoc($result)) {
1619 if (!is_numeric($row['Data_length'])) {
1620 // Data_length for Views is NULL.
1621 continue;
1622 }
1623 $status['total_size'] += $row['Data_length']; // + Index_length
1624 $status[$row['Name']]['size'] = $row['Data_length'];
1625 $status[$row['Name']]['count'] = $row['Rows'];
1626 }
1627 return $status;
1628 }
1629 if ('pgsql' == $db_driver)
1630 {
1631 $status = array();
1632 $status['total_size'] = 0;
1633 $tables = list_tables(); // only tables, not views
1634 if (!count($tables)) {
1635 return $status;
1636 }
1637 $tables_in = db_in_array($tables);
1638 $rels = db_list("SELECT relname, reltuples, (relpages::decimal + 1) * 8 * 2 * 1024 AS relsize FROM pg_class WHERE relname IN ($tables_in)");
1639 foreach ($rels as $rel) {
1640 $status['total_size'] += $rel['relsize'];
1641 $status[$rel['relname']]['size'] = $rel['relsize'];
1642 $status[$rel['relname']]['count'] = $rel['reltuples'];
1643 }
1644 return $status;
1645 }
1646}
1647function table_columns($table)
1648{
1649 global $db_driver;
1650 static $cache = array();
1651 if (isset($cache[$table])) {
1652 return $cache[$table];
1653 }
1654 if ('mysql' == $db_driver) {
1655 $row = db_row("SELECT * FROM `$table`");
1656 } else {
1657 $row = db_row("SELECT * FROM $table");
1658 }
1659 if (!$row) {
1660 $cache[$table] = array();
1661 return array();
1662 }
1663 foreach ($row as $k => $v) {
1664 $row[$k] = $k;
1665 }
1666 $cache[$table] = $row;
1667 return $row;
1668}
1669function table_types($table)
1670{
1671 global $db_driver;
1672 if ('mysql' == $db_driver)
1673 {
1674 $rows = db_list("SHOW COLUMNS FROM `$table`");
1675 $types = array();
1676 foreach ($rows as $row) {
1677 $type = $row['Type'];
1678 $types[$row['Field']] = $type;
1679 }
1680 return $types;
1681 }
1682 if ('pgsql' == $db_driver)
1683 {
1684 return db_assoc("SELECT column_name, udt_name FROM information_schema.columns WHERE table_name ='$table' ORDER BY ordinal_position");
1685 }
1686}
1687function table_types2($table)
1688{
1689 global $db_driver;
1690 if ('mysql' == $db_driver)
1691 {
1692 $types = array();
1693 $rows = @db_list("SHOW COLUMNS FROM `$table`");
1694 if (!($rows && count($rows))) {
1695 return false;
1696 }
1697 foreach ($rows as $row) {
1698 $type = $row['Type'];
1699 preg_match('#^[a-z]+#', $type, $match);
1700 $type = $match[0];
1701 $types[$row['Field']] = $type;
1702 }
1703 }
1704 if ('pgsql' == $db_driver)
1705 {
1706 $types = db_assoc("SELECT column_name, udt_name FROM information_schema.columns WHERE table_name ='$table' ORDER BY ordinal_position");
1707 if (!count($types)) {
1708 return false;
1709 }
1710 foreach ($types as $col => $type) {
1711 // "_" also in regexp - error when retrieving column info from "pg_class",
1712 // udt_name might be "_aclitem" / "_text".
1713 preg_match('#^[a-z_]+#', $type, $match);
1714 $type = $match[0];
1715 $types[$col] = $type;
1716 }
1717 }
1718 foreach ($types as $col => $type) {
1719 if ('varchar' == $type) { $type = 'char'; }
1720 if ('integer' == $type) { $type = 'int'; }
1721 if ('timestamp' == $type) { $type = 'time'; }
1722 $types[$col] = $type;
1723 }
1724 return $types;
1725}
1726function table_types_group($types)
1727{
1728 foreach ($types as $k => $type) {
1729 preg_match('#^\w+#', $type, $match);
1730 $type = $match[0];
1731 $types[$k] = $type;
1732 }
1733 $types = array_unique($types);
1734 $types = array_values($types);
1735 $types2 = array();
1736 foreach ($types as $type) {
1737 $types2[$type] = $type;
1738 }
1739 return $types2;
1740}
1741function table_pk($table)
1742{
1743 $cols = table_columns($table);
1744 if (!$cols) return null;
1745 foreach ($cols as $col) {
1746 return $col;
1747 }
1748}
1749function escape($text)
1750{
1751 $text = addslashes($text);
1752 $search = array("\r", "\n", "\t");
1753 $replace = array('\r', '\n', '\t');
1754 return str_replace($search, $replace, $text);
1755}
1756function ob_cleanup()
1757{
1758 while (ob_get_level()) {
1759 ob_end_clean();
1760 }
1761 if (headers_sent()) {
1762 return;
1763 }
1764 if (function_exists('headers_list')) {
1765 foreach (headers_list() as $header) {
1766 if (preg_match('/Content-Encoding:/i', $header)) {
1767 header('Content-encoding: none');
1768 break;
1769 }
1770 }
1771 } else {
1772 header('Content-encoding: none');
1773 }
1774}
1775function query_color($query)
1776{
1777 $color = 'red';
1778 $words = array('SELECT', 'UPDATE', 'DELETE', 'FROM', 'LIMIT', 'OFFSET', 'AND', 'LEFT JOIN', 'WHERE', 'SET',
1779 'ORDER BY', 'GROUP BY', 'GROUP', 'DISTINCT', 'COUNT', 'COUNT\(\*\)', 'IS', 'NULL', 'IS NULL', 'AS', 'ON', 'INSERT INTO', 'VALUES', 'BEGIN', 'COMMIT', 'CASE', 'WHEN', 'THEN', 'END', 'ELSE', 'IN', 'NOT', 'LIKE', 'ILIKE', 'ASC', 'DESC', 'LOWER', 'UPPER');
1780 $words = implode('|', $words);
1781
1782 $query = preg_replace("#^({$words})(\s)#i", '<font color="'.$color.'">$1</font>$2', $query);
1783 $query = preg_replace("#(\s)({$words})$#i", '$1<font color="'.$color.'">$2</font>', $query);
1784 // replace twice, some words when preceding other are not replaced
1785 $query = preg_replace("#([\s\(\),])({$words})([\s\(\),])#i", '$1<font color="'.$color.'">$2</font>$3', $query);
1786 $query = preg_replace("#([\s\(\),])({$words})([\s\(\),])#i", '$1<font color="'.$color.'">$2</font>$3', $query);
1787 $query = preg_replace("#^($words)$#i", '<font color="'.$color.'">$1</font>', $query);
1788
1789 preg_match_all('#<font[^>]+>('.$words.')</font>#i', $query, $matches);
1790 foreach ($matches[0] as $k => $font) {
1791 $font2 = str_replace($matches[1][$k], strtoupper($matches[1][$k]), $font);
1792 $query = str_replace($font, $font2, $query);
1793 }
1794
1795 return $query;
1796}
1797function query_upper($sql)
1798{
1799 return $sql;
1800 // todo: don't upper quoted ' and ' values
1801 $queries = preg_split("#;(\s*--[ \t\S]*)?(\r\n|\n|\r)#U", $sql);
1802 foreach ($queries as $k => $query) {
1803 $strip = query_strip($query);
1804 $color = query_color($strip);
1805 $sql = str_replace($strip, $color, $sql);
1806 }
1807 $sql = preg_replace('#<font color="\w+">([^>]+)</font>#iU', '$1', $sql);
1808 return $sql;
1809}
1810function html_spaces($string)
1811{
1812 $inside_tag = false;
1813 for ($i = 0; $i < strlen($string); $i++)
1814 {
1815 $c = $string{$i};
1816 if ('<' == $c) {
1817 $inside_tag = true;
1818 }
1819 if ('>' == $c) {
1820 $inside_tag = false;
1821 }
1822 if (' ' == $c && !$inside_tag) {
1823 $string = substr($string, 0, $i).' '.substr($string, $i+1);
1824 $i += strlen(' ')-1;
1825 }
1826 }
1827 return $string;
1828}
1829function query_cut($query)
1830{
1831 // removes sub-queries and string values from query
1832 $brace_start = '(';
1833 $brace_end = ')';
1834 $quote = "'";
1835 $inside_brace = false;
1836 $inside_quote = false;
1837 $depth = 0;
1838 $ret = '';
1839 $query = str_replace('\\\\', '', $query);
1840
1841 for ($i = 0; $i < strlen($query); $i++)
1842 {
1843 $prev_char = isset($query{$i-1}) ? $query{$i-1} : null;
1844 $char = $query{$i};
1845 if ($char == $brace_start) {
1846 if (!$inside_quote) {
1847 $depth++;
1848 }
1849 }
1850 if ($char == $brace_end) {
1851 if (!$inside_quote) {
1852 $depth--;
1853 if ($depth == 0) {
1854 $ret .= '(...)';
1855 }
1856 continue;
1857 }
1858 }
1859 if ($char == $quote) {
1860 if ($inside_quote) {
1861 if ($prev_char != '\\') {
1862 $inside_quote = false;
1863 if (!$depth) {
1864 $ret .= "'...'";
1865 }
1866 continue;
1867 }
1868 } else {
1869 $inside_quote = true;
1870 }
1871 }
1872 if (!$depth && !$inside_quote) {
1873 $ret .= $char;
1874 }
1875 }
1876 return $ret;
1877}
1878function table_from_query($query)
1879{
1880 if (preg_match('#\sFROM\s+["`]?(\w+)["`]?#i', $query, $match)) {
1881 $cut = query_cut($query);
1882 if (preg_match('#\sFROM\s+["`]?(\w+)["`]?#i', $cut, $match2)) {
1883 $table = $match2[1];
1884 } else {
1885 $table = $match[1];
1886 }
1887 } else if (preg_match('#UPDATE\s+"?(\w+)"?#i', $query, $match)) {
1888 $table = $match[1];
1889 } else if (preg_match('#INSERT\s+INTO\s+"?(\w+)"?#', $query, $match)) {
1890 $table = $match[1];
1891 } else {
1892 $table = false;
1893 }
1894 return $table;
1895}
1896function is_select($query)
1897{
1898 return preg_match('#^\s*SELECT\s+#i', $query);
1899}
1900function query_strip($query)
1901{
1902 // strip comments and ';' from the end of query
1903 $query = trim($query);
1904 if (str_ends_with($query, ';')) {
1905 $query = str_cut_end($query, ';');
1906 }
1907 $lines = preg_split("#(\r\n|\n|\r)#", $query);
1908 foreach ($lines as $k => $line) {
1909 $line = trim($line);
1910 if (!$line || str_starts_with($line, '--')) {
1911 unset($lines[$k]);
1912 }
1913 }
1914 $query = implode("\r\n", $lines);
1915 return $query;
1916}
1917function dump_table($table)
1918{
1919 ob_cleanup();
1920 define('DEBUG_CONSOLE_HIDE', 1);
1921 set_time_limit(0);
1922 global $db_name;
1923 header("Cache-control: private");
1924 header("Content-type: application/octet-stream");
1925 header('Content-Disposition: attachment; filename='.$db_name.'_'.$table.'.sql');
1926 table_structure($table);
1927 table_data($table);
1928 exit;
1929}
1930function dump_all($data = false)
1931{
1932 global $db_name;
1933
1934 ob_cleanup();
1935 define('DEBUG_CONSOLE_HIDE', 1);
1936 set_time_limit(0);
1937
1938 $tables = list_tables();
1939 $table_filter = get('table_filter');
1940 $tables = table_filter($tables, $table_filter);
1941
1942 header("Cache-control: private");
1943 header("Content-type: application/octet-stream");
1944 header('Content-Disposition: attachment; filename='.date('Ymd').'_'.$db_name.'.sql');
1945
1946 foreach ($tables as $key => $table)
1947 {
1948 table_structure($table);
1949 if ($data) {
1950 table_data($table);
1951 }
1952 flush();
1953 }
1954 exit;
1955}
1956function export_csv($query, $separator)
1957{
1958 ob_cleanup();
1959 set_time_limit(0);
1960
1961 if (!is_select($query)) {
1962 trigger_error('export_csv() failed: not a SELECT query: '.$query, E_USER_ERROR);
1963 }
1964
1965 $table = table_from_query($query);
1966 if (!$table) {
1967 $table = 'unknown';
1968 }
1969
1970 header("Cache-control: private");
1971 header("Content-type: application/octet-stream");
1972 header('Content-Disposition: attachment; filename='.$table.'_'.date('Ymd').'.csv');
1973
1974 $rs = db_query($query);
1975 $first = true;
1976
1977 while ($row = db_row($rs)) {
1978 if ($first) {
1979 echo csv_row(array_keys($row), $separator);
1980 $first = false;
1981 }
1982 echo csv_row($row, $separator);
1983 flush();
1984 }
1985
1986 exit();
1987}
1988function csv_row($row, $separator)
1989{
1990 foreach ($row as $key => $val) {
1991 $enquote = false;
1992 if (false !== strpos($val, $separator)) {
1993 $enquote = true;
1994 }
1995 if (false !== strpos($val, "\"")) {
1996 $enquote = true;
1997 $val = str_replace("\"", "\"\"", $val);
1998 }
1999 if (false !== strpos($val, "\r") || false !== strpos($val, "\n")) {
2000 $enquote = true;
2001 $val = preg_replace('#(\r\n|\r|\n)#', "\n", $val); // excel needs \n instead of \r\n
2002 }
2003 if ($enquote) {
2004 $row[$key] = "\"".$val."\"";
2005 }
2006 }
2007 $out = implode($separator, $row);
2008 $out .= "\r\n";
2009 return $out;
2010}
2011function import($file, $ignore_errors = false, $transaction = false, $force_myisam = false, $query_start = false)
2012{
2013 global $db_driver, $db_link, $db_charset;
2014 if ($ignore_errors && $transaction) {
2015 echo '<div>You cannot select both: ignoring errors and transaction</div>';
2016 exit;
2017 }
2018
2019 $count_errors = 0;
2020 set_time_limit(0);
2021 $fp = fopen($file, 'r');
2022 if (!$fp) { exit('fopen('.$file.') failed'); }
2023 flock($fp, 1);
2024 $text = trim(fread($fp, filesize($file)));
2025 flock($fp, 3);
2026 fclose($fp);
2027 if ($db_charset == 'latin2') {
2028 $text = charset_fix($text);
2029 }
2030 if ($force_myisam) {
2031 $text = preg_replace('#TYPE\s*=\s*InnoDB#i', 'TYPE=MyISAM', $text);
2032 }
2033 $text = preg_split("#;(\r\n|\n|\r)#", $text);
2034 $x = 0;
2035 echo '<div>Ignoring errors: <b>'.($ignore_errors?'Yes':'No').'</b></div>';
2036 echo '<div>Transaction: <b>'.($transaction?'Yes':'No').'</b></div>';
2037 echo '<div>Force MyIsam: <b>'.($force_myisam?'Yes':'No').'</b></div>';
2038 echo '<div>Query start: <b>#'.$query_start.'</b></div>';
2039 echo '<div>Queries found: <b>'.count($text).'</b></div>';
2040 echo '<div>Executing ...</div>';
2041 flush();
2042
2043 if ($transaction) {
2044 echo '<div>BEGIN;</div>';
2045 db_begin();
2046 }
2047
2048 $time = time_start();
2049 $query_start = (int) $query_start;
2050 if (!$query_start) {
2051 $query_start = 1;
2052 }
2053 $query_no = 0;
2054
2055 foreach($text as $key => $value)
2056 {
2057 $x++;
2058 $query_no++;
2059 if ($query_start > $query_no) {
2060 continue;
2061 }
2062
2063 if ('mysql' == $db_driver)
2064 {
2065 $result = @mysql_query($value.';', $db_link);
2066 }
2067 if ('pgsql' == $db_driver)
2068 {
2069 $result = @pg_query($db_link, $value.';');
2070 }
2071 if(!$result) {
2072 $x--;
2073 if (!$count_errors) {
2074 echo '<table class="ls" cellspacing="1"><tr><th width="25%">Error</th><th>Query</th></tr>';
2075 }
2076 $count_errors++;
2077 echo '<tr><td>#'.$query_no.' '.db_error() .')'.'</td><td>'.nl2br(html_once($value)).'</td></tr>';
2078 flush();
2079 if (!$ignore_errors) {
2080 echo '</table>';
2081 echo '<div><span style="color: red;"><b>Import failed.</b></span></div>';
2082 echo '<div>Queries executed: <b>'.($x-$query_start+1).'</b>.</div>';
2083 if ($transaction) {
2084 echo '<div>ROLLBACK;</div>';
2085 db_rollback();
2086 }
2087 echo '<br><div><a href="'.$_SERVER['PHP_SELF'].'?import=1"><< go back</a></div>';
2088 exit;
2089 }
2090 }
2091 }
2092 if ($count_errors) {
2093 echo '</table>';
2094 }
2095 if ($transaction) {
2096 echo '<div>COMMIT;</div>';
2097 db_end();
2098 }
2099 echo '<div><span style="color: green;"><b>Import finished.</b></span></div>';
2100 echo '<div>Queries executed: <b>'.($x-$query_start+1).'</b>.</div>';
2101 echo '<div>Time: <b>'.time_end($time).'</b> sec</div>';
2102 echo '<br><div><a href="'.$_SERVER['PHP_SELF'].'?import=1"><< go back</a></div>';
2103}
2104function layout()
2105{
2106 global $sql_area;
2107 ?>
2108 <style>
2109 body,table,input,select,textarea { font-family: tahoma; font-size: 11px; }
2110 body { margin: 1em; padding: 0; margin-top: 0.5em; }
2111 h1, h2 { font-family: arial; margin: 1em 0; }
2112 h1 { font-size: 150%; margin: 0.7em 0; }
2113 h2 { font-size: 125%; }
2114 .ls th { background: #ccc; }
2115 .ls th th { background-color: none; }
2116 .ls td { background: #f5f5f5; }
2117 .ls td td { background-color: none; }
2118 .ls th, .ls td { padding: 0.1em 0.5em; }
2119 .ls th th, .ls td td { padding: 0; }
2120 .ls2 th { text-align: left; vertical-align: top; line-height: 1.7em; background: #e0e0e0; font-weight: normal; }
2121 .ls2 th th { line-height: normal; background-color: none; }
2122 p { margin: 0.8em 0; }
2123 form { margin: 0; }
2124 form th { text-align: left; }
2125 a, a:visited { text-decoration: none; }
2126 a:hover { text-decoration: underline; }
2127 a, a.blue { color: blue; }
2128 a:visited { color: purple; }
2129 a.blue:visited { color: blue; }
2130 form .none td, form .none th { background: none; padding: 0 0.25em; }
2131 label { padding-left: 2px; padding-right: 4px; }
2132 .checkbox { padding-left: 0; margin-left: 0; margin-top: 1px; }
2133 .none, .ls .none { background: none; padding-top: 0.4em; }
2134 .button { cursor: pointer; }
2135 .button_click { background: #e0e0e0; }
2136 .error { background: #ffffd7; padding: 0.5em; border: #ccc 1px solid; margin-bottom: 1em; margin-top: 1em; }
2137 .msg { background: #eee; padding: 0.5em; border: #ccc 1px solid; margin-bottom: 1em; margin-top: 1em; }
2138 .sql_area { <?php echo $sql_area;?> }
2139 div.query { background: #eee; padding: 0.35em; border: #ccc 1px solid; margin-bottom: 1em; margin-top: 1em; }
2140 </style>
2141 <script>
2142 function mark_col(td)
2143 {
2144 }
2145 function popup(url, width, height, more)
2146 {
2147 if (!width) width = 750;
2148 if (!height) height = 500;
2149 var x = (screen.width/2-width/2);
2150 var y = (screen.height/2-height/2);
2151 window.open(url, "", "scrollbars=yes,resizable=yes,width="+width+",height="+height+",screenX="+(x)+",screenY="+y+",left="+x+",top="+y+(more ? ","+more : ""));
2152 }
2153 function is_ie()
2154 {
2155 return navigator.appVersion.indexOf("MSIE") != -1;
2156 }
2157 function event_add(el, event, func)
2158 {
2159 if (is_ie()) {
2160 if (el.attachEvent) {
2161 el.attachEvent("on"+event, func);
2162 }
2163 } else {
2164 if (el.addEventListener) {
2165 el.addEventListener(event, func, false);
2166 } else if (el.attachEvent) {
2167 el.attachEvent("on"+event, func);
2168 } else {
2169 var oldfunc = el["on"+event];
2170 el["on"+event] = function() { oldfunc(); func(); }
2171 }
2172 }
2173 }
2174 function event_target(event)
2175 {
2176 var el;
2177 if (window.event) el = window.event.srcElement;
2178 else if (event) el = event.target;
2179 if (el.nodeType == 3) el = el.parentNode;
2180 return el;
2181 }
2182
2183 function button_init()
2184 {
2185 // dependency: event_add(), event_target()
2186 event_add(window, "load", function() {
2187 for (var i = 0; i < document.forms.length; i++) {
2188 event_add(document.forms[i], "submit", function(event) {
2189 var form = event_target(event);
2190 if (form.tagName != 'FORM') form = this;
2191 for (var k = 0; k < form.elements.length; k++) {
2192 if ("button" == form.elements[k].type || "submit" == form.elements[k].type) {
2193 button_click(form.elements[k], true);
2194 }
2195 }
2196 });
2197 var form = document.forms[i];
2198 for (var j = 0; j < form.elements.length; j++) {
2199 if ("button" == form.elements[j].type || "submit" == form.elements[j].type) {
2200 event_add(form.elements[j], "click", button_click);
2201 }
2202 }
2203 }
2204 var inputs = document.getElementsByTagName('INPUT');
2205 for (var i = 0; i < inputs.length; i++) {
2206 if (('button' == inputs[i].type || 'submit' == inputs[i].type) && !inputs[i].form) {
2207 event_add(inputs[i], 'click', button_click);
2208 }
2209 }
2210 });
2211 }
2212 function button_click(but, calledFromOnSubmit)
2213 {
2214 but = but.nodeName ? but : event_target(but);
2215 if ('button' == this.type || 'submit' == this.type) {
2216 but = this;
2217 }
2218 if (but.getAttribute('button_click') == 1 || but.form && but.form.getAttribute("button_click") == 1) {
2219 return;
2220 }
2221 if (button_click_sess_done(but)) {
2222 return;
2223 }
2224 if ("button" == but.type) {
2225 if (but.getAttribute("wait")) {
2226 button_wait(but);
2227 but.setAttribute("button_click", 1);
2228 if (but.form) {
2229 but.form.setAttribute("button_click", 1); // only when WAIT = other buttons in the form Choose From Pop etc.
2230 }
2231 }
2232 } else if ("submit" == but.type) {
2233 if (but.getAttribute("wait")) {
2234 button_wait(but);
2235 but.setAttribute("button_click", 1);
2236 }
2237 if (but.form) {
2238 but.form.setAttribute("button_click", 1);
2239 }
2240 if (calledFromOnSubmit) {
2241 if (but.getAttribute("block")) {
2242 button_disable(but);
2243 }
2244 } else {
2245 if (!but.form.getAttribute('button_disable_onsubmit'))
2246 {
2247 event_add(but.form, "submit", function(event) {
2248 var form = event_target(event);
2249 if (form.tagName != 'FORM') form = this;
2250 if (!button_disable_sess_done(form)) {
2251 for (var i = 0; i < form.elements.length; i++) {
2252 if (form.elements[i].getAttribute("block")) {
2253 button_disable(form.elements[i]);
2254 }
2255 }
2256 }
2257 });
2258 but.form.setAttribute('button_disable_onsubmit', 1);
2259 }
2260 }
2261 } else {
2262 //return alert("button_click() failed, unknown button type");
2263 }
2264 }
2265 function button_click_sess_done(but)
2266 {
2267 if (but.getAttribute('button_click_sess_done') == 1 || but.form && but.form.getAttribute('button_click_sess_done') == 1) {
2268 if (but.getAttribute('button_click_sess_done') == 1) {
2269 but.setAttribute('button_click_sess_done', 0);
2270 }
2271 if (but.form && but.form.getAttribute('button_click_sess_done') == 1) {
2272 but.form.setAttribute('button_click_sess_done', 0);
2273 }
2274 return true;
2275 }
2276 return false;
2277 }
2278 function button_disable_sess_done(but)
2279 {
2280 if (but.getAttribute('button_disable_sess_done') == 1 || but.form && but.form.getAttribute('button_disable_sess_done') == 1) {
2281 if (but.getAttribute('button_disable_sess_done') == 1) {
2282 but.setAttribute('button_disable_sess_done', 0);
2283 }
2284 if (but.form && but.form.getAttribute('button_disable_sess_done') == 1) {
2285 but.form.setAttribute('button_disable_sess_done', 0);
2286 }
2287 return true;
2288 }
2289 return false;
2290 }
2291 function button_disable(button)
2292 {
2293 button.disabled = true;
2294 if (button.name)
2295 {
2296
2297 var form = button.form;
2298 var input = document.createElement('input');
2299 input.setAttribute('type', 'hidden');
2300 input.setAttribute('name', button.name);
2301 input.setAttribute('value', button.value);
2302 form.appendChild(input);
2303 }
2304 }
2305 function button_wait(but)
2306 {
2307 //but.value += " ..";
2308 but.className = but.className + ' button_click';
2309 }
2310 function button_clear(but)
2311 {
2312 if (but.tagName == 'FORM') {
2313 var form = but;
2314 for (var i = 0; i < form.elements.length; i++) {
2315 button_clear(form.elements[i]);
2316 }
2317 form.setAttribute('button_click', 0);
2318 form.setAttribute('button_click_sess_done', 1);
2319 form.setAttribute('button_disable_sess_done', 1);
2320 } else {
2321 if (but.type == 'submit' || but.type == 'button')
2322 {
2323 if (but.getAttribute('button_click') == 1) {
2324 //but.value = but.value.replace(/[ ]?\.{2,}$/, '');
2325 but.className = but.className.replace('button_click', '');
2326 but.setAttribute('button_click', 0);
2327 but.setAttribute('button_click_sess_done', 1);
2328 but.setAttribute('button_disable_sess_done', 1);
2329 }
2330 if (but.form && but.form.getAttribute('button_click') == 1) {
2331 but.form.setAttribute('button_click', 0);
2332 but.form.setAttribute('button_click_sess_done', 1);
2333 but.form.setAttribute('button_disable_sess_done', 1);
2334 }
2335 }
2336 }
2337 }
2338 button_init();
2339 </script>
2340 <?php
2341}
2342function conn_info()
2343{
2344 global $db_driver, $db_server, $db_name, $db_user, $db_charset, $page_charset, $charset1, $charset2;
2345 $dbs = list_dbs();
2346 $db_name = $db_name;
2347 ?>
2348 <p>
2349 Driver: <b><?php echo $db_driver;?></b>
2350 -
2351 Server: <b><?php echo $db_server;?></b>
2352 -
2353 User: <b><?php echo $db_user;?></b>
2354 -
2355 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?execute_sql=1">Execute SQL</a>
2356 ( open in <a class=blue href="javascript:void(0)" onclick="popup('<?php echo $_SERVER['PHP_SELF'];?>?execute_sql=1&popup=1')">Popup</a> )
2357 -
2358 Database: <select name="db_name" onchange="location='<?php echo $_SERVER['PHP_SELF'];?>?db_name='+this.value"><?php echo options($dbs, $db_name);?></select>
2359 -
2360 Db charset: <select name="db_charset" onchange="location='<?php echo $_SERVER['PHP_SELF'];?>?db_charset='+this.value+'&from=<?php echo urlencode($_SERVER['REQUEST_URI']);?>'">
2361 <option value=""></option><?php echo options($charset1, $db_charset);?></select>
2362 -
2363 Page charset: <select name="page_charset" onchange="location='<?php echo $_SERVER['PHP_SELF'];?>?page_charset='+this.value+'&from=<?php echo urlencode($_SERVER['REQUEST_URI']);?>'">
2364 <option value=""></option><?php echo options($charset2, $page_charset);?></select>
2365 -
2366 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?disconnect=1">Disconnect</a>
2367 </p>
2368 <?php
2369}
2370function size($bytes)
2371{
2372 return number_format(ceil($bytes / 1024),0,'',',').' KB';
2373}
2374function html($s)
2375{
2376 $html = array(
2377 '&' => '&',
2378 '<' => '<',
2379 '>' => '>',
2380 '"' => '"',
2381 '\'' => '''
2382 );
2383 $s = preg_replace('/&#(\d+)/', '@@@@@#$1', $s);
2384 $s = str_replace(array_keys($html), array_values($html), $s);
2385 $s = preg_replace('/@@@@@#(\d+)/', '&#$1', $s);
2386 return trim($s);
2387}
2388function html_undo($s)
2389{
2390 $html = array(
2391 '&' => '&',
2392 '<' => '<',
2393 '>' => '>',
2394 '"' => '"',
2395 '\'' => '''
2396 );
2397 return str_replace(array_values($html), array_keys($html), $s);
2398}
2399function html_once($s)
2400{
2401 $s = str_replace(array('<','>','&lt;','&gt;'),array('<','>','<','>'),$s);
2402 return str_replace(array('<','>','<','>'),array('&lt;','&gt;','<','>'),$s);
2403}
2404function html_tags($s)
2405{
2406 // succession of str_replace array is important! double escape bug..
2407 return str_replace(array('<','>','<','>'), array('&lt;','&gt;','<','>'), $s);
2408}
2409function html_tags_undo($s)
2410{
2411 return str_replace(array('<','>','&lt;', '&gt;'), array('<','>','<','>'), $s);
2412}
2413function html_allow_tags($s, $allow)
2414{
2415 $s = html_once(trim($s));
2416 preg_match_all('#<([a-z]+)>#i', $allow, $match);
2417 foreach ($match[1] as $tag) {
2418 $s = preg_replace('#<'.$tag.'\s+style\s*=\s*"([^"<>]+)"\s*>#i', '<'.$tag.' style="$1">', $s);
2419 $s = str_replace('<'.$tag.'>', '<'.$tag.'>', $s);
2420 $s = str_replace('</'.$tag.'>', '</'.$tag.'>', $s);
2421 }
2422 return $s;
2423}
2424function str_truncate($string, $length, $etc = ' ..', $break_words = true)
2425{
2426 if ($length == 0) {
2427 return '';
2428 }
2429 if (strlen($string) > $length + strlen($etc)) {
2430 if (!$break_words) {
2431 $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
2432 }
2433 return substr($string, 0, $length) . $etc;
2434 }
2435 return $string;
2436}
2437function str_bind($s, $dat = array(), $strict = false, $recur = 0)
2438{
2439 if (!is_array($dat)) {
2440 return trigger_error('str_bind() failed. Second argument expects to be an array.', E_USER_ERROR);
2441 }
2442 if ($strict) {
2443 foreach ($dat as $k => $v) {
2444 if (strpos($s, "%$k%") === false) {
2445 return trigger_error(sprintf('str_bind() failed. Strict mode On. Key not found = %s. String = %s. Data = %s.', $k, $s, print_r($dat, 1)), E_USER_ERROR);
2446 }
2447 $s = str_replace("%$k%", $v, $s);
2448 }
2449 if (preg_match('#%\w+%#', $s, $match)) {
2450 return trigger_error(sprintf('str_bind() failed. Unassigned data for = %s. String = %s.', $match[0], $sBase), E_USER_ERROR);
2451 }
2452 return $s;
2453 }
2454
2455 $sBase = $s;
2456 preg_match_all('#%\w+%#', $s, $match);
2457 $keys = $match[0];
2458 $num = array();
2459
2460 foreach ($keys as $key)
2461 {
2462 $key2 = str_replace('%', '', $key);
2463 if (is_numeric($key2)) $num[$key] = true;
2464 /* ignore!
2465 if (!array_key_exists($key2, $dat)) {
2466 return trigger_error(sprintf('str_bind() failed. No data found for key: %s. String: %s.', $key, $sBase), E_USER_ERROR);
2467 }
2468 */
2469 $val = $dat[$key2];
2470 /* insecure!
2471 if (preg_match('#%\w+%#', $val) && $recur < 5) {
2472 $val = str_bind($val, $dat, $strict, ++$recur);
2473 }
2474 */
2475 $s = str_replace($key, $val, $s);
2476 }
2477 if (count($num)) {
2478 if (count($dat) != count($num)) {
2479 return trigger_error('str_bind() failed. When using numeric data binding you need to use all data passed to the string. You also cannot mix numeric and name binding.', E_USER_ERROR);
2480 }
2481 }
2482
2483 if (preg_match('#%\w+%#', $s, $match)) {
2484 /* ignore! return trigger_error(sprintf('str_bind() failed. Unassigned data for = %s. String = %s. Data = %s.', $match[0], htmlspecialchars(print_r($sBase, true)), print_r($dat, true)), E_USER_ERROR);*/
2485 }
2486
2487 return $s;
2488}
2489function dir_read($dir, $ignore_ext = array(), $allow_ext = array(), $sort = null)
2490{
2491 if (is_null($ignore_ext)) $ignore_ext = array();
2492 if (is_null($allow_ext)) $allow_ext = array();
2493 foreach ($allow_ext as $k => $ext) {
2494 $allow_ext[$k] = str_replace('.', '', $ext);
2495 }
2496
2497 $ret = array();
2498 if ($handle = opendir($dir)) {
2499 while (($file = readdir($handle)) !== false) {
2500 if ($file != '.' && $file != '..') {
2501 $ignore = false;
2502 foreach ($ignore_ext as $ext) {
2503 if (file_ext_has($file, $ext)) {
2504 $ignore = true;
2505 }
2506 }
2507 if (is_array($allow_ext) && count($allow_ext) && !in_array(file_ext($file), $allow_ext)) {
2508 $ignore = true;
2509 }
2510 if (!$ignore) {
2511 $ret[] = array(
2512 'file' => $dir.'/'.$file,
2513 'time' => filemtime($dir.'/'.$file)
2514 );
2515 }
2516 }
2517 }
2518 closedir($handle);
2519 }
2520 if ('date_desc' == $sort) {
2521 $ret = array_sort_desc($ret, 'time');
2522 }
2523 return array_col($ret, 'file');
2524}
2525function array_col($arr, $col)
2526{
2527 $ret = array();
2528 foreach ($arr as $k => $row) {
2529 $ret[] = $row[$col];
2530 }
2531 return $ret;
2532}
2533function array_sort($arr, $col_key)
2534{
2535 if (is_array($col_key)) {
2536 foreach ($arr as $k => $v) {
2537 $arr[$k]['__array_sort'] = '';
2538 foreach ($col_key as $col) {
2539 $arr[$k]['__array_sort'] .= $arr[$k][$col].'_';
2540 }
2541 }
2542 $col_key = '__array_sort';
2543 }
2544 uasort($arr, create_function('$a,$b', 'if (is_null($a["'.$col_key.'"]) && !is_null($b["'.$col_key.'"])) return 1; if (!is_null($a["'.$col_key.'"]) && is_null($b["'.$col_key.'"])) return -1; return strnatcasecmp($a["'.$col_key.'"], $b["'.$col_key.'"]);'));
2545 if ('__array_sort' == $col_key) {
2546 foreach ($arr as $k => $v) {
2547 unset($arr[$k]['__array_sort']);
2548 }
2549 }
2550 return $arr;
2551}
2552function array_sort_desc($arr, $col_key)
2553{
2554 if (is_array($col_key)) {
2555 foreach ($arr as $k => $v) {
2556 $arr[$k]['__array_sort'] = '';
2557 foreach ($col_key as $col) {
2558 $arr[$k]['__array_sort'] .= $arr[$k][$col].'_';
2559 }
2560 }
2561 $col_key = '__array_sort';
2562 }
2563 uasort($arr, create_function('$a,$b', 'return strnatcasecmp($b["'.$col_key.'"], $a["'.$col_key.'"]);'));
2564 if ('__array_sort' == $col_key) {
2565 foreach ($arr as $k => $v) {
2566 unset($arr[$k]['__array_sort']);
2567 }
2568 }
2569 return $arr;
2570}
2571function options($options, $selected = null, $ignore_type = false)
2572{
2573 $ret = '';
2574 foreach ($options as $k => $v) {
2575 //str_replace('"', '\"', $k)
2576 $ret .= '<option value="'.$k.'"';
2577 if ((is_array($selected) && in_array($k, $selected)) || (!is_array($selected) && $k == $selected && $selected !== '' && $selected !== null)) {
2578 if ($ignore_type) {
2579 $ret .= ' selected="selected"';
2580 } else {
2581 if (!(is_numeric($k) xor is_numeric($selected))) {
2582 $ret .= ' selected="selected"';
2583 }
2584 }
2585 }
2586 $ret .= '>'.$v.' </option>';
2587 }
2588 return $ret;
2589}
2590function sql_files()
2591{
2592 $files = dir_read('.', null, array('.sql'));
2593 $files2 = array();
2594 foreach ($files as $file) {
2595 $files2[md5($file)] = $file.sprintf(' (%s)', size(filesize($file)));
2596 }
2597 return $files2;
2598}
2599function sql_files_assoc()
2600{
2601 $files = dir_read('.', null, array('.sql'));
2602 $files2 = array();
2603 foreach ($files as $file) {
2604 $files2[md5($file)] = $file;
2605 }
2606 return $files2;
2607}
2608function file_ext($name)
2609{
2610 $ext = null;
2611 if (($pos = strrpos($name, '.')) !== false) {
2612 $len = strlen($name) - ($pos+1);
2613 $ext = substr($name, -$len);
2614 if (!preg_match('#^[a-z0-9]+$#i', $ext)) {
2615 return null;
2616 }
2617 }
2618 return $ext;
2619}
2620function checked($bool)
2621{
2622 if ($bool) return 'checked="checked"';
2623}
2624function radio_assoc($checked, $assoc, $input_name, $link = false)
2625{
2626 $ret = '<table cellspacing="0" cellpadding="0"><tr>';
2627 foreach ($assoc as $id => $name)
2628 {
2629 $params = array(
2630 'id' => $id,
2631 'name' => $name,
2632 'checked' => checked($checked == $id),
2633 'input_name' => $input_name
2634 );
2635 if ($link) {
2636 if (is_array($link)) {
2637 $params['link'] = $link[$id];
2638 } else {
2639 $params['link'] = sprintf($link, $id, $name);
2640 }
2641 $ret .= str_bind('<td><input class="checkbox" type="radio" name="%input_name%" id="%input_name%_%id%" value="%id%" %checked%></td><td>%link% </td>', $params);
2642 } else {
2643 $ret .= str_bind('<td><input class="checkbox" type="radio" name="%input_name%" id="%input_name%_%id%" value="%id%" %checked%></td><td><label for="%input_name%_%id%">%name%</label> </td>', $params);
2644 }
2645 }
2646 $ret .= '</tr></table>';
2647 return $ret;
2648}
2649function self($cut_query = false)
2650{
2651 $uri = $_SERVER['REQUEST_URI'];
2652 if ($cut_query) {
2653 $before = str_before($uri, '?');
2654 if ($before) {
2655 return $before;
2656 }
2657 }
2658 return $uri;
2659}
2660function url($script, $params = array())
2661{
2662 $query = '';
2663
2664 /* remove from script url, actual params if exist */
2665 foreach ($params as $k => $v) {
2666 $exp = sprintf('#(\?|&)%s=[^&]*#i', $k);
2667 if (preg_match($exp, $script)) {
2668 $script = preg_replace($exp, '', $script);
2669 }
2670 }
2671
2672 /* repair url like 'script.php&id=12&asd=133' */
2673 $exp = '#\?\w+=[^&]*#i';
2674 $exp2 = '#&(\w+=[^&]*)#i';
2675 if (!preg_match($exp, $script) && preg_match($exp2, $script)) {
2676 $script = preg_replace($exp2, '?$1', $script, 1);
2677 }
2678
2679 foreach ($params as $k => $v) {
2680 if (!strlen($v)) continue;
2681 if ($query) { $query .= '&'; }
2682 else {
2683 if (strpos($script, '?') === false) {
2684 $query .= '?';
2685 } else {
2686 $query .= '&';
2687 }
2688 }
2689 if ('%s' != $v) {
2690 $v = urlencode($v);
2691 }
2692 $v = preg_replace('#%25(\w+)%25#i', '%$1%', $v); // %id_news% etc. used in listing
2693 $query .= sprintf('%s=%s', $k, $v);
2694 }
2695 return $script.$query;
2696}
2697function url_offset($offset, $params = array())
2698{
2699 $url = $_SERVER['REQUEST_URI'];
2700 if (preg_match('#&offset=\d+#', $url)) {
2701 $url = preg_replace('#&offset=\d+#', '&offset='.$offset, $url);
2702 } else {
2703 $url .= '&offset='.$offset;
2704 }
2705 return $url;
2706}
2707function str_wrap($s, $width, $break = ' ', $omit_tags = false)
2708{
2709 //$restart = array(' ', "\t", "\r", "\n");
2710 $restart = array();
2711 $cnt = 0;
2712 $ret = '';
2713 $open_tag = false;
2714 $inside_link = false;
2715 for ($i=0; $i<strlen($s); $i++)
2716 {
2717 $char = $s[$i];
2718 $nextchar = isset($s[$i+1]) ? $s[$i+1] : null;
2719 $nextchar2 = isset($s[$i+2]) ? $s[$i+2] : null;
2720
2721 if ($omit_tags)
2722 {
2723 if ($char == '<') {
2724 $open_tag = true;
2725 if ('a' == $nextchar) {
2726 $inside_link = true;
2727 } else if ('/' == $nextchar && 'a' == $nextchar2) {
2728 $inside_link = false;
2729 }
2730 }
2731 if ($char == '>') {
2732 $open_tag = false;
2733 }
2734 if ($open_tag) {
2735 $ret .= $char;
2736 continue;
2737 }
2738 }
2739
2740 if (in_array($char, $restart)) {
2741 $cnt = 0;
2742 } else {
2743 $cnt++;
2744 }
2745 $ret .= $char;
2746 if ($cnt > $width) {
2747 if (!$inside_link) {
2748 // Inside link, do not break it.
2749 $ret .= $break;
2750 $cnt = 0;
2751 }
2752 }
2753 }
2754 return $ret;
2755}
2756function time_micro()
2757{
2758 list($usec, $sec) = explode(" ", microtime());
2759 return ((float)$usec + (float)$sec);
2760}
2761function time_start()
2762{
2763 return time_micro();
2764}
2765function time_end($start)
2766{
2767 $end = time_micro();
2768 $end = round($end - $start, 3);
2769 $end = pad_zeros($end, 3);
2770 return $end;
2771}
2772function str_has($str, $needle, $ignore_case = false)
2773{
2774 if (is_array($needle)) {
2775 foreach ($needle as $n) {
2776 if (!str_has($str, $n, $ignore_case)) {
2777 return false;
2778 }
2779 }
2780 return true;
2781 }
2782 if ($ignore_case) {
2783 $str = str_lower($str);
2784 $needle = str_lower($needle);
2785 }
2786 return strpos($str, $needle) !== false;
2787}
2788function str_has_any($str, $arr_needle, $ignore_case = false)
2789{
2790 if (is_string($arr_needle)) {
2791 $arr_needle = preg_replace('#\s+#', ' ', $arr_needle);
2792 $arr_needle = explode(' ', $arr_needle);
2793 }
2794 foreach ($arr_needle as $needle) {
2795 if (str_has($str, $needle, $ignore_case)) {
2796 return true;
2797 }
2798 }
2799 return false;
2800}
2801function str_before($str, $needle)
2802{
2803 $pos = strpos($str, $needle);
2804 if ($pos !== false) {
2805 $before = substr($str, 0, $pos);
2806 return strlen($before) ? $before : false;
2807 } else {
2808 return false;
2809 }
2810}
2811function pad_zeros($number, $zeros)
2812{
2813 if (str_has($number, '.')) {
2814 preg_match('#\.(\d+)$#', $number, $match);
2815 $number .= str_repeat('0', $zeros-strlen($match[1]));
2816 return $number;
2817 } else {
2818 return $number.'.'.str_repeat('0', $zeros);
2819 }
2820}
2821function charset_fix_invalid($s)
2822{
2823 $fix = '€â“„¢ž˜™”Ã';
2824 $s = str_replace(str_array($fix), '', $s);
2825 return $s;
2826}
2827function charset_is_invalid($s)
2828{
2829 $fix = '€â“„¢ž˜™”Ã';
2830 $fix = str_array($fix);
2831 foreach ($fix as $char) {
2832 if (str_has($s, $char)) {
2833 return true;
2834 }
2835 }
2836 return false;
2837}
2838function charset_fix($string)
2839{
2840 // UTF-8 && WIN-1250 => ISO-8859-2
2841 // todo: is checking required? redundant computing?
2842 if (charset_win_is($string)) {
2843 $string = charset_win_fix($string);
2844 }
2845 if (charset_utf_is($string)) {
2846 $string = charset_utf_fix($string);
2847 }
2848 return $string;
2849}
2850function charset_win_is($string)
2851{
2852 $win = '¹¥æÆêʳ£ñÑóÓœŒŸ¿¯';
2853 $iso = '±¡æÆêʳ£ñÑóÓ¶¦¼¬¿¯';
2854 for ($i=0; $i<strlen($win); $i++) {
2855 if ($win{$i} != $iso{$i}) {
2856 if (strstr($string, $win{$i}) !== false) {
2857 return true;
2858 }
2859 }
2860 }
2861 return false;
2862}
2863function charset_win_fix($string)
2864{
2865 $win = '¹¥æÆêʳ£ñÑóÓœŒŸ¿¯';
2866 $iso = '±¡æÆêʳ£ñÑóÓ¶¦¼¬¿¯';
2867 $srh = array();
2868 $rpl = array();
2869 for ($i = 0; $i < strlen($win); $i++) {
2870 if ($win{$i} != $iso{$i}) {
2871 $srh[] = $win{$i};
2872 $rpl[] = $iso{$i};
2873 }
2874 }
2875 $string = str_replace($srh, $rpl, $string);
2876 return $string;
2877}
2878function charset_utf_is($string)
2879{
2880 $utf_iso = array(
2881 "\xc4\x85" => "\xb1",
2882 "\xc4\x84" => "\xa1",
2883 "\xc4\x87" => "\xe6",
2884 "\xc4\x86" => "\xc6",
2885 "\xc4\x99" => "\xea",
2886 "\xc4\x98" => "\xca",
2887 "\xc5\x82" => "\xb3",
2888 "\xc5\x81" => "\xa3",
2889 "\xc3\xb3" => "\xf3",
2890 "\xc3\x93" => "\xd3",
2891 "\xc5\x9b" => "\xb6",
2892 "\xc5\x9a" => "\xa6",
2893 "\xc5\xba" => "\xbc",
2894 "\xc5\xb9" => "\xac",
2895 "\xc5\xbc" => "\xbf",
2896 "\xc5\xbb" => "\xaf",
2897 "\xc5\x84" => "\xf1",
2898 "\xc5\x83" => "\xd1",
2899 // xmlhttprequest utf-8 encoding
2900 "%u0104" => "\xA1",
2901 "%u0106" => "\xC6",
2902 "%u0118" => "\xCA",
2903 "%u0141" => "\xA3",
2904 "%u0143" => "\xD1",
2905 "%u00D3" => "\xD3",
2906 "%u015A" => "\xA6",
2907 "%u0179" => "\xAC",
2908 "%u017B" => "\xAF",
2909 "%u0105" => "\xB1",
2910 "%u0107" => "\xE6",
2911 "%u0119" => "\xEA",
2912 "%u0142" => "\xB3",
2913 "%u0144" => "\xF1",
2914 "%u00D4" => "\xF3",
2915 "%u015B" => "\xB6",
2916 "%u017A" => "\xBC",
2917 "%u017C" => "\xBF"
2918 );
2919 foreach ($utf_iso as $k => $v) {
2920 if (strpos($string, $k) !== false) {
2921 return true;
2922 }
2923 }
2924 return false;
2925}
2926function charset_utf_fix($string)
2927{
2928 $utf_iso = array(
2929 "\xc4\x85" => "\xb1",
2930 "\xc4\x84" => "\xa1",
2931 "\xc4\x87" => "\xe6",
2932 "\xc4\x86" => "\xc6",
2933 "\xc4\x99" => "\xea",
2934 "\xc4\x98" => "\xca",
2935 "\xc5\x82" => "\xb3",
2936 "\xc5\x81" => "\xa3",
2937 "\xc3\xb3" => "\xf3",
2938 "\xc3\x93" => "\xd3",
2939 "\xc5\x9b" => "\xb6",
2940 "\xc5\x9a" => "\xa6",
2941 "\xc5\xba" => "\xbc",
2942 "\xc5\xb9" => "\xac",
2943 "\xc5\xbc" => "\xbf",
2944 "\xc5\xbb" => "\xaf",
2945 "\xc5\x84" => "\xf1",
2946 "\xc5\x83" => "\xd1",
2947 // xmlhttprequest uses different encoding
2948 "%u0104" => "\xA1",
2949 "%u0106" => "\xC6",
2950 "%u0118" => "\xCA",
2951 "%u0141" => "\xA3",
2952 "%u0143" => "\xD1",
2953 "%u00D3" => "\xD3",
2954 "%u015A" => "\xA6",
2955 "%u0179" => "\xAC",
2956 "%u017B" => "\xAF",
2957 "%u0105" => "\xB1",
2958 "%u0107" => "\xE6",
2959 "%u0119" => "\xEA",
2960 "%u0142" => "\xB3",
2961 "%u0144" => "\xF1",
2962 "%u00D4" => "\xF3",
2963 "%u015B" => "\xB6",
2964 "%u017A" => "\xBC",
2965 "%u017C" => "\xBF"
2966 );
2967 return str_replace(array_keys($utf_iso), array_values($utf_iso), $string);
2968}
2969function str_starts_with($str, $start, $ignore_case = false)
2970{
2971 if ($ignore_case) {
2972 $str = str_upper($str);
2973 $start = str_upper($start);
2974 }
2975 if (!strlen($str) && !strlen($start)) {
2976 return true;
2977 }
2978 if (!strlen($start)) {
2979 trigger_error('str_starts_with() failed, start arg cannot be empty', E_USER_ERROR);
2980 }
2981 if (strlen($start) > strlen($str)) {
2982 return false;
2983 }
2984 for ($i = 0; $i < strlen($start); $i++) {
2985 if ($start{$i} != $str{$i}) {
2986 return false;
2987 }
2988 }
2989 return true;
2990}
2991function str_ends_with($str, $end, $ignore_case = false)
2992{
2993 if ($ignore_case) {
2994 $str = str_upper($str);
2995 $end = str_upper($end);
2996 }
2997 if (!strlen($str) && !strlen($end)) {
2998 return true;
2999 }
3000 if (!strlen($end)) {
3001 trigger_error('str_ends_with() failed, end arg cannot be empty', E_USER_ERROR);
3002 }
3003 if (strlen($end) > strlen($str)) {
3004 return false;
3005 }
3006 return str_starts_with(strrev($str), strrev($end));
3007 return true;
3008}
3009function str_cut_start($str, $start)
3010{
3011 if (str_starts_with($str, $start)) {
3012 $str = substr($str, strlen($start));
3013 }
3014 return $str;
3015}
3016function str_cut_end($str, $end)
3017{
3018 if (str_ends_with($str, $end)) {
3019 $str = substr($str, 0, -strlen($end));
3020 }
3021 return $str;
3022}
3023function file_get($file)
3024{
3025 return file_get_contents($file);
3026}
3027function file_put($file, $s)
3028{
3029 $fp = fopen($file, 'wb') or trigger_error('fopen() failed: '.$file, E_USER_ERROR);
3030 if ($fp) {
3031 fwrite($fp, $s);
3032 fclose($fp);
3033 }
3034}
3035function file_date($file)
3036{
3037 return date('Y-m-d H:i:s', filemtime($file));
3038}
3039function dir_exists($dir)
3040{
3041 return file_exists($dir) && !is_file($dir);
3042}
3043function dir_delete_old_files($dir, $ext = array(), $sec)
3044{
3045 // NOT USED right now.
3046 // older than x seconds
3047 $files = dir_read($dir, null, $ext);
3048 $time = time() - $sec;
3049 foreach ($files as $file) {
3050 if (file_time($file) < $time) {
3051 unlink($file);
3052 }
3053 }
3054}
3055global $_error, $_error_style;
3056$_error = array();
3057$_error_style = '';
3058
3059function error($msg = null)
3060{
3061 if (isset($msg) && func_num_args() > 1) {
3062 $args = func_get_args();
3063 $msg = call_user_func_array('sprintf', $args);
3064 }
3065 global $_error, $_error_style;
3066 if (isset($msg)) {
3067 $_error[] = $msg;
3068 }
3069 if (!count($_error)) {
3070 return null;
3071 }
3072 if (count($_error) == 1) {
3073 return sprintf('<div class="error" style="%s">%s</div>', $_error_style, $_error[0]);
3074 }
3075 $ret = '<div class="error" style="'.$_error_style.'">Following errors appeared:<ul>';
3076 foreach ($_error as $msg) {
3077 $ret .= sprintf('<li>%s</li>', $msg);
3078 }
3079 $ret .= '</ul></div>';
3080 return $ret;
3081}
3082function timestamp($time, $span = true)
3083{
3084 $time_base = $time;
3085 $time = substr($time, 0, 16);
3086 $time2 = substr($time, 0, 10);
3087 $today = date('Y-m-d');
3088 $yesterday = date('Y-m-d', time()-3600*24);
3089 if ($time2 == $today) {
3090 if (substr($time_base, -8) == '00:00:00') {
3091 $time = 'Today';
3092 } else {
3093 $time = 'Today'.substr($time, -6);
3094 }
3095 } else if ($time2 == $yesterday) {
3096 $time = 'Yesterday'.substr($time, -6);
3097 }
3098 return '<span style="white-space: nowrap;">'.$time.'</span>';
3099}
3100function str_lower($str)
3101{
3102 /* strtolower iso-8859-2 compatible */
3103 $lower = str_array(iso_chars_lower());
3104 $upper = str_array(iso_chars_upper());
3105 $str = str_replace($upper, $lower, $str);
3106 $str = strtolower($str);
3107 return $str;
3108}
3109function str_upper($str)
3110{
3111 /* strtoupper iso-8859-2 compatible */
3112 $lower = str_array(iso_chars_lower());
3113 $upper = str_array(iso_chars_upper());
3114 $str = str_replace($lower, $upper, $str);
3115 $str = strtoupper($str);
3116 return $str;
3117}
3118function str_array($str)
3119{
3120 $arr = array();
3121 for ($i = 0; $i < strlen($str); $i++) {
3122 $arr[$i] = $str{$i};
3123 }
3124 return $arr;
3125}
3126function iso_chars()
3127{
3128 return iso_chars_lower().iso_chars_upper();
3129}
3130function iso_chars_lower()
3131{
3132 return '±æê³ñ󶼿';
3133}
3134function iso_chars_upper()
3135{
3136 return '¡ÆÊ£ÑÓ¦¬¯';
3137}
3138function array_first_key($arr)
3139{
3140 $arr2 = $arr;
3141 reset($arr);
3142 list($key, $val) = each($arr);
3143 return $key;
3144}
3145function array_first($arr)
3146{
3147 return array_first_value($arr);
3148}
3149function array_first_value($arr)
3150{
3151 $arr2 = $arr;
3152 return array_shift($arr2);
3153}
3154function array_col_values($arr, $col)
3155{
3156 $ret = array();
3157 foreach ($arr as $k => $row) {
3158 $ret[] = $row[$col];
3159 }
3160 return $ret;
3161}
3162function array_col_values_unique($arr, $col)
3163{
3164 return array_unique(array_col_values($arr, $col));
3165}
3166function array_col_match($rows, $col, $pattern)
3167{
3168 if (!count($rows)) {
3169 trigger_error('array_col_match(): array is empty', E_USER_ERROR);
3170 }
3171 $ret = true;
3172 foreach ($rows as $row) {
3173 if (!preg_match($pattern, $row[$col])) {
3174 return false;
3175 }
3176 }
3177 return true;
3178}
3179function array_col_match_unique($rows, $col, $pattern)
3180{
3181 if (!array_col_match($rows, $col, $pattern)) {
3182 return false;
3183 }
3184 return count($rows) == count(array_col_values_unique($rows, $col));
3185}
3186function redirect($url)
3187{
3188 $url = url($url);
3189 header("Location: $url");
3190 exit;
3191}
3192function redirect_notify($url, $msg)
3193{
3194 if (strpos($msg, '<') === false) {
3195 $msg = sprintf('<b>%s</b>', $msg);
3196 }
3197 cookie_set('flash_notify', $msg);
3198 redirect($url);
3199}
3200function redirect_ok($url, $msg)
3201{
3202 if (strpos($msg, '<') === false) {
3203 $msg = sprintf('<b>%s</b>', $msg);
3204 }
3205 cookie_set('flash_ok', $msg);
3206 redirect($url);
3207}
3208function redirect_error($url, $msg)
3209{
3210 if (strpos($msg, '<') === false) {
3211 $msg = sprintf('<b>%s</b>', $msg);
3212 }
3213 cookie_set('flash_error', $msg);
3214 redirect($url);
3215}
3216function flash()
3217{
3218 static $is_style = false;
3219
3220 $flash_error = cookie_get('flash_error');
3221 $flash_ok = cookie_get('flash_ok');
3222 $flash_notify = cookie_get('flash_notify');
3223
3224 $flash_error = filter_allow_tags($flash_error, '<b><i><u><br><span>');
3225 $flash_ok = filter_allow_tags($flash_ok, '<b><i><u><br><span>');
3226 $flash_notify = filter_allow_tags($flash_notify, '<b><i><u><br><span>');
3227
3228 if (!($flash_error || $flash_ok || $flash_notify)) {
3229 return false;
3230 }
3231
3232 ob_start();
3233 ?>
3234
3235 <?php if (!$is_style): ?>
3236 <style type="text/css">
3237 #flash { background: #ffffd7; padding: 0.3em; padding-bottom: 0.15em; border: #ddd 1px solid; margin-bottom: 1em; }
3238 #flash div { padding: 0em 0em; }
3239 #flash table { font-weight: normal; }
3240 #flash td { text-align: left; }
3241 </style>
3242 <?php endif; ?>
3243
3244 <div id="flash" ondblclick="document.getElementById('flash').style.display='none';">
3245 <table width="100%" ondblclick="document.getElementById('flash').style.display='none';"><tr>
3246 <td style="line-height: 14px;"><?php echo $flash_error ? $flash_error : ($flash_ok ? $flash_ok : $flash_notify); ?></td></tr></table>
3247 </div>
3248
3249 <?php
3250 $cont = ob_get_contents();
3251 ob_end_clean();
3252
3253 if ($flash_error) cookie_del('flash_error');
3254 else if ($flash_ok) cookie_del('flash_ok');
3255 else if ($flash_notify) cookie_del('flash_notify');
3256
3257 $is_style = true;
3258
3259 return $cont;
3260}
3261function filter($post, $filters)
3262{
3263 if (is_string($filters))
3264 {
3265 $filter = $filters;
3266 $func = 'filter_'.$filter;
3267 foreach ($post as $key => $val) {
3268 $post[$key] = call_user_func($func, $post[$key]);
3269 }
3270 return $post;
3271 }
3272 foreach ($filters as $key => $filter)
3273 {
3274 if (!array_key_exists($key, $post)) {
3275 return trigger_error(sprintf('filter() failed. Key missing = %s.', $key), E_USER_ERROR);
3276 }
3277 $func = 'filter_'.$filter;
3278 if (!function_exists($func)) {
3279 return trigger_error(sprintf('filter() failed. Filter missing = %s.', $func), E_USER_ERROR);
3280 }
3281 $post[$key] = call_user_func($func, $post[$key]);
3282 }
3283 return $post;
3284}
3285function filter_html($s)
3286{
3287 if (req_gpc_has($s)) {
3288 $s = html_tags_undo($s);
3289 }
3290 return html(trim($s));
3291}
3292function filter_allow_tags($s, $allow)
3293{
3294 if (req_gpc_has($s)) {
3295 $s = html_tags_undo($s);
3296 }
3297 return html_allow_tags($s, $allow);
3298}
3299function filter_allow_html($s)
3300{
3301 global $SafeHtml;
3302 if (!isset($SafeHtml)) {
3303 include_once 'inc/SafeHtml.php';
3304 }
3305 if (req_gpc_has($s)) {
3306 $s = html_tags_undo($s);
3307 }
3308 if (in_array(trim(strtolower($s)), array('<br>', '<p> </p>'))) {
3309 return '';
3310 }
3311 $SafeHtml->clear();
3312 $s = $SafeHtml->parse($s);
3313 return trim($s);
3314}
3315function filter_allow_html_script($s)
3316{
3317 if (in_array(trim(strtolower($s)), array('<br>', '<p> </p>'))) {
3318 return '';
3319 }
3320 if (req_gpc_has($s)) {
3321 $s = html_tags_undo($s);
3322 }
3323 return trim($s);
3324}
3325function filter_editor($s)
3326{
3327 return filter_allow_html($s);
3328}
3329function date_now()
3330{
3331 return date('Y-m-d H:i:s');
3332}
3333function guess_pk($rows)
3334{
3335 if (!count($rows)) {
3336 return false;
3337 }
3338 $patterns = array('#^\d+$#', '#^[^\s]+$#');
3339 $row = array_first($rows);
3340 foreach ($patterns as $pattern)
3341 {
3342 foreach ($row as $col => $v) {
3343 if ($v && preg_match($pattern, $v)) {
3344 if (array_col_match_unique($rows, $col, $pattern)) {
3345 return $col;
3346 }
3347 }
3348 }
3349 }
3350 return false;
3351}
3352function layout_start($title='')
3353{
3354 global $page_charset;
3355 $flash = flash();
3356 ?>
3357
3358 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
3359 <html>
3360 <head>
3361 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $page_charset;?>">
3362 <title><?php echo $title;?></title>
3363 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
3364 <script>
3365 function $(id)
3366 {
3367 if (typeof id == 'string') return document.getElementById(id);
3368 return id;
3369 }
3370 </script>
3371 </head>
3372 <body>
3373
3374 <?php layout(); ?>
3375
3376 <?php if ($flash) { echo $flash; } ?>
3377
3378 <?php
3379}
3380function layout_end()
3381{
3382 ?>
3383 <?php powered_by(); ?>
3384 </body>
3385 </html>
3386 <?php
3387}
3388function powered_by()
3389{
3390 ?>
3391 <script>
3392 function link_noreferer(link)
3393 {
3394 // Tested: Chrome, Firefox, Inetrnet Explorer, Opera.
3395 var w = window.open("about:blank", "_blank");
3396 w.document.open();
3397 w.document.write("<"+"!doctype html>");
3398 w.document.write("<"+"html><"+"head>");
3399 w.document.write("<"+"title>Secure redirection</title>");
3400 w.document.write("<"+"style>body { font: 11px Tahoma; }<"+"/style>");
3401 w.document.write("<"+"meta http-equiv=refresh content='10;url="+link+"'>");
3402 // Meta.setAttribute() doesn't work on firefox.
3403 // Firefox: needs document.write('<meta>')
3404 // IE: the firefox workaround doesn't work on ie, but we can use a normal redirection
3405 // as IE is already not sending the referer because it does not do it when using
3406 // open.window, besides the blank url in address bar works fine (about:blank).
3407 // Opera: firefox fix works.
3408 w.document.write("<"+"script>function redirect() { if (navigator.userAgent.indexOf('MSIE') != -1) { location.replace('"+link+"'); } else { document.open(); document.write('<"+"meta http-equiv=refresh content=\"0;"+link+"\">'); document.close(); } }<"+"/script>");
3409 w.document.write("<"+"/head><"+"body>");
3410 w.document.write("<"+"h1>Secure redirection<"+"/h1>");
3411 w.document.write("<"+"p>This is a secure redirection that hides the HTTP REFERER header - using javascript and meta refresh combination.");
3412 w.document.write("<br>The site you are being redirected will not know the location of the dbkiss script on your site.<"+"/p>");
3413 w.document.write("<"+"p>In 10 seconds you will be redirected to the following address: <"+"a href='javascript:void(0)' onclick='redirect()'>"+link+"<"+"/a><br>");
3414 w.document.write("Clicking the link is also secure, so if you do not wish to wait, then click it.<"+"/p>");
3415 w.document.write("<"+"/body><"+"/html>");
3416 w.document.close();
3417 }
3418 </script>
3419 <div style="text-align: center; margin-top: 2em; border-top: #ccc 1px solid; padding-top: 0.5em;">Powered by <a href="javascript:void(0)" onclick="link_noreferer('https://code.google.com/p/dbkiss/')">dbkiss</a></div>
3420 <?php
3421}
3422
3423?>
3424<?php if (get('import')): ?>
3425
3426 <?php
3427
3428 // ----------------------------------------------------------------
3429 // IMPORT
3430 // ----------------------------------------------------------------
3431
3432 ?>
3433
3434 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
3435 <html>
3436 <head>
3437 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $page_charset;?>">
3438 <title><?php echo $db_name_h1?$db_name_h1:$db_name;?> > Import</title>
3439 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
3440 </head>
3441 <body>
3442
3443 <?php layout(); ?>
3444 <h1><a class=blue style="<?php echo $db_name_style;?>" href="<?php echo $_SERVER['PHP_SELF'];?>"><?php echo $db_name_h1?$db_name_h1:$db_name;?></a> > Import</h1>
3445 <?php conn_info(); ?>
3446
3447 <?php $files = sql_files(); ?>
3448
3449 <?php if (count($files)): ?>
3450 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
3451 <table class="none" cellspacing="0" cellpadding="0">
3452 <tr>
3453 <td>SQL file:</th>
3454 <td><select name="sqlfile"><option value="" selected="selected"></option><?php echo options($files);?></select></td>
3455 <td><input type="checkbox" name="ignore_errors" id="ignore_errors" value="1"></td>
3456 <td><label for="ignore_errors">ignore errors</label></td>
3457 <td><input type="checkbox" name="transaction" id="transaction" value="1"></td>
3458 <td><label for="transaction">transaction</label></td>
3459 <td><input type="checkbox" name="force_myisam" id="force_myisam" value="1"></td>
3460 <td><label for="force_myisam">force myisam</label></td>
3461 <td><input type="text" size="5" name="query_start" value=""></td>
3462 <td>query start</td>
3463 <td><input type="submit" value="Import"></td>
3464 </tr>
3465 </table>
3466 </form>
3467 <br>
3468 <?php else: ?>
3469 No sql files found in current directory.
3470 <?php endif; ?>
3471
3472 <?php powered_by(); ?>
3473
3474 </body></html>
3475
3476<?php exit; endif; ?>
3477<?php if ('editrow' == get('action')): ?>
3478<?php
3479 function dbkiss_filter_id($id)
3480 {
3481 # mysql allows table names of: `62-511`
3482 # also, columns might be numeric ex. `62`
3483 if (preg_match('#^[_a-z0-9][a-z0-9_\-]*$#i', $id)) {
3484 return $id;
3485 }
3486 return false;
3487 }
3488
3489 $get = get(array(
3490 'table' => 'string',
3491 'pk' => 'string',
3492 'id' => 'string'
3493 ));
3494
3495 $get['table'] = html_once($get['table']);
3496 $get['pk'] = html_once($get['pk']);
3497
3498 $title_edit = sprintf('Edit row (%s=%s)', $get['pk'], $get['id']);
3499 $title = ' > '.$get['table'].' > '.$title_edit;
3500
3501 if (!dbkiss_filter_id($get['table'])) {
3502 error('Invalid table name');
3503 }
3504 if (!dbkiss_filter_id($get['pk'])) {
3505 error('Invalid pk');
3506 }
3507
3508 $row = false;
3509
3510 if (!error())
3511 {
3512 $table_enq = quote_table($get['table']);
3513 $test = db_row("SELECT * FROM $table_enq");
3514 if ($test) {
3515 if (!array_key_exists($get['pk'], $test)) {
3516 error('Invalid pk');
3517 }
3518 }
3519 if (!error())
3520 {
3521 $table_enq = quote_table($get['table']);
3522 $query = db_bind("SELECT * FROM $table_enq WHERE {$get['pk']} = %0", $get['id']);
3523 $query = db_limit($query, 0, 2);
3524 $rows = db_list($query);
3525 if (count($rows) > 1) {
3526 error('Invalid pk: found more than one row with given id');
3527 } else if (count($rows) == 0) {
3528 error('Row not found');
3529 } else {
3530 $row = $rows[0];
3531 $row_id = $row[$get['pk']];
3532 }
3533 }
3534 }
3535
3536 if ($row) {
3537 $types = table_types2($get['table']);
3538 }
3539
3540 $edit_actions_assoc = array(
3541 'update' => 'Update',
3542 'update_pk' => 'Overwrite pk',
3543 'insert' => 'Copy row (insert)',
3544 'delete' => 'Delete'
3545 );
3546
3547 $edit_action = post('dbkiss_action');
3548
3549 if ($_ENV['IS_GET'])
3550 {
3551 $edit_action = array_first_key($edit_actions_assoc);
3552 $post = $row;
3553 }
3554
3555 if ($_ENV['IS_POST'])
3556 {
3557 if (!array_key_exists($edit_action, $edit_actions_assoc)) {
3558 $edit_action = '';
3559 error('Invalid action');
3560 }
3561
3562 $post = array();
3563 foreach ($row as $k => $v) {
3564 if (array_key_exists($k, $_POST)) {
3565 $val = (string) $_POST[$k];
3566 if ('null' == $val) {
3567 $val = null;
3568 }
3569 if ('int' == $types[$k]) {
3570 if (!strlen($val)) {
3571 $val = null;
3572 }
3573 if (!(preg_match('#^-?\d+$#', $val) || is_null($val))) {
3574 error('%s: invalid value', $k);
3575 }
3576 }
3577 if ('float' == $types[$k]) {
3578 if (!strlen($val)) {
3579 $val = null;
3580 }
3581 $val = str_replace(',', '.', $val);
3582 if (!(is_numeric($val) || is_null($val))) {
3583 error('%s: invalid value', $k);
3584 }
3585 }
3586 if ('time' == $types[$k]) {
3587 if (!strlen($val)) {
3588 $val = null;
3589 }
3590 if ('now' == $val) {
3591 $val = date_now();
3592 }
3593 }
3594 $post[$k] = $val;
3595 } else {
3596 error('Missing key: %s in POST', $k);
3597 }
3598 }
3599
3600 if ('update' == $edit_action)
3601 {
3602 if ($post[$get['pk']] != $row[$get['pk']]) {
3603 if (count($row) != 1) { // Case: more than 1 column
3604 error('%s: cannot change pk on UPDATE', $get['pk']);
3605 }
3606 }
3607 }
3608 if ('update_pk' == $edit_action)
3609 {
3610 if ($post[$get['pk']] == $row[$get['pk']]) {
3611 error('%s: selected action Overwrite pk, but pk value has not changed', $get['pk']);
3612 }
3613 }
3614 if ('insert' == $edit_action)
3615 {
3616 if (strlen($post[$get['pk']])) {
3617 $table_enq = quote_table($get['table']);
3618 $test = db_row("SELECT * FROM $table_enq WHERE {$get['pk']} = %0", array($post[$get['pk']]));
3619 if ($test) {
3620 error('%s: there is already a record with that id', $get['pk']);
3621 }
3622 }
3623 }
3624
3625 if (!error())
3626 {
3627 $post2 = $post;
3628 if ('update' == $edit_action)
3629 {
3630 if (count($row) != 1) { // Case: more than 1 column
3631 unset($post2[$get['pk']]);
3632 }
3633 db_update($get['table'], $post2, array($get['pk'] => $row_id));
3634 if (db_error()) {
3635 error('<font color="red"><b>DB error</b></font>: '.db_error());
3636 } else {
3637 if (count($row) == 1) { // Case: only 1 column
3638 redirect_ok(url(self(), array('id'=>$post[$get['pk']])), 'Row updated');
3639 } else {
3640 redirect_ok(self(), 'Row updated');
3641 }
3642 }
3643 }
3644 if ('update_pk' == $edit_action)
3645 {
3646 @db_update($get['table'], $post2, array($get['pk'] => $row_id));
3647 if (db_error()) {
3648 error('<font color="red"><b>DB error</b></font>: '.db_error());
3649 } else {
3650 $url = url(self(), array('id' => $post[$get['pk']]));
3651 redirect_ok($url, 'Row updated (pk overwritten)');
3652 }
3653 }
3654 if ('insert' == $edit_action)
3655 {
3656 $new_id = false;
3657 if (!strlen($post2[$get['pk']])) {
3658 unset($post2[$get['pk']]);
3659 } else {
3660 $new_id = $post2[$get['pk']];
3661 }
3662 @db_insert($get['table'], $post2);
3663 if (db_error()) {
3664 error('<font color="red"><b>DB error</b></font>: '.db_error());
3665 } else {
3666 if (!$new_id) {
3667 $new_id = db_insert_id($get['table'], $get['pk']);
3668 }
3669 $url = url(self(), array('id'=>$new_id));
3670 $msg = sprintf('Row inserted (%s=%s)', $get['pk'], $new_id);
3671 redirect_ok($url, $msg);
3672 }
3673 }
3674 if ('delete' == $edit_action)
3675 {
3676 $table_enq = quote_table($get['table']);
3677 @db_exe("DELETE FROM $table_enq WHERE {$get['pk']} = %0", $get['id']);
3678 if (db_error()) {
3679 error('<font color="red"><b>DB error</b></font>: '.db_error());
3680 } else {
3681 redirect_ok(self(), 'Row deleted');
3682 }
3683 }
3684 }
3685 }
3686
3687 ?>
3688<?php layout_start($title_edit); ?>
3689 <h1><span style="<?php echo $db_name_style;?>"><?php echo $db_name_h1?$db_name_h1:$db_name;?></span><?php echo $title;?></h1>
3690
3691 <?php echo error();?>
3692
3693 <?php if ($row): ?>
3694
3695 <form action="<?php echo self();?>" method="post">
3696
3697 <?php echo radio_assoc($edit_action, $edit_actions_assoc, 'dbkiss_action');?></td>
3698 <br>
3699
3700 <table cellspacing="1" class="ls ls2">
3701 <?php foreach ($post as $k => $v): if (is_null($v)) { $v = 'null'; } $v = htmlspecialchars($v); ?>
3702 <tr>
3703 <th><?php echo $k;?>:</th>
3704 <td>
3705 <?php if ('int' == $types[$k]): ?>
3706 <input type="text" name="<?php echo $k;?>" value="<?php echo html_once($v);?>" size="11">
3707 <?php elseif ('char' == $types[$k]): ?>
3708 <input type="text" name="<?php echo $k;?>" value="<?php echo html_once($v);?>" size="50">
3709 <?php elseif (in_array($types[$k], array('text', 'mediumtext', 'longtext')) || str_has($types[$k], 'blob')): ?>
3710 <textarea name="<?php echo $k;?>" cols="80" rows="<?php echo $k=='notes'?10:10;?>"><?php echo html_once($v);?></textarea>
3711 <?php else: ?>
3712 <input type="text" name="<?php echo $k;?>" value="<?php echo html_once($v);?>" size="30">
3713 <?php endif; ?>
3714 </td>
3715 <td valign="top"><?php echo $types[$k];?></td>
3716 </tr>
3717 <?php endforeach; ?>
3718 <tr>
3719 <td colspan="3" class="none">
3720 <input type="submit" wait="1" block="1" class="button" value="Edit">
3721 </td>
3722 </tr>
3723 </table>
3724
3725 </form>
3726
3727 <?php endif; ?>
3728
3729 <?php layout_end(); ?>
3730
3731<?php exit; endif; ?>
3732<?php if (isset($_GET['execute_sql']) && $_GET['execute_sql']): ?>
3733<?php
3734
3735function listing($base_query, $md5_get = false)
3736{
3737 global $db_driver, $db_link;
3738
3739 $md5_i = false;
3740 if ($md5_get) {
3741 preg_match('#_(\d+)$#', $md5_get, $match);
3742 $md5_i = $match[1];
3743 }
3744
3745 $base_query = trim($base_query);
3746 $base_query = str_cut_end($base_query, ';');
3747
3748 $query = $base_query;
3749 $ret = array('msg'=>'', 'error'=>'', 'data_html'=>false);
3750 $limit = 25;
3751 $offset = get('offset','int');
3752 $page = floor($offset / $limit + 1);
3753
3754 if ($query) {
3755 if (is_select($query) && !preg_match('#\s+LIMIT\s+\d+#i', $query) && !preg_match('#into\s+outfile\s+#', $query)) {
3756 $query = db_limit($query, $offset, $limit);
3757 } else {
3758 $limit = false;
3759 }
3760 $time = time_start();
3761 if (!db_is_safe($query, true)) {
3762 $ret['error'] = 'Detected UPDATE/DELETE without WHERE condition (put WHERE 1=1 if you want to execute this query)';
3763 return $ret;
3764 }
3765 $rs = @db_query($query);
3766 if ($rs) {
3767 if ($rs === true) {
3768 if ('mysql' == $db_driver)
3769 {
3770 $affected = mysql_affected_rows($db_link);
3771 $time = time_end($time);
3772 $ret['data_html'] = '<b>'.$affected.'</b> rows affected.<br>Time: <b>'.$time.'</b> sec';
3773 return $ret;
3774 }
3775 } else {
3776 if ('pgsql' == $db_driver)
3777 {
3778 // Since Postgresql 9 on Linux pg_affected_rows()
3779 // returns >= 0 for SELECT queries
3780 if (!preg_match('#^\s*SELECT\s+#i', $query)) {
3781 $affected = @pg_affected_rows($rs);
3782 if ($affected || preg_match('#^\s*(DELETE|UPDATE)\s+#i', $query)) {
3783 $time = time_end($time);
3784 $ret['data_html'] = '<p><b>'.$affected.'</b> rows affected. Time: <b>'.$time.'</b> sec</p>';
3785 return $ret;
3786 }
3787 }
3788 }
3789 }
3790
3791 $rows = array();
3792 while ($row = db_row($rs)) {
3793 $rows[] = $row;
3794 if ($limit) {
3795 if (count($rows) == $limit) { break; }
3796 }
3797 }
3798 db_free($rs);
3799
3800 if (is_select($base_query)) {
3801 $found = @db_one("SELECT COUNT(*) FROM ($base_query) AS sub");
3802 if (!is_numeric($found) || (count($rows) && !$found)) {
3803 global $COUNT_ERROR;
3804 $COUNT_ERROR = ' (COUNT ERROR) ';
3805 $found = count($rows);
3806 }
3807 } else {
3808 if (count($rows)) {
3809 $found = count($rows);
3810 } else {
3811 $found = false;
3812 }
3813 }
3814 if ($limit) {
3815 $pages = ceil($found / $limit);
3816 } else {
3817 $pages = 1;
3818 }
3819 $time = time_end($time);
3820
3821 } else {
3822 $ret['error'] = db_error();
3823 return $ret;
3824 }
3825 } else {
3826 $ret['error'] = 'No query found.';
3827 return $ret;
3828 }
3829
3830 ob_start();
3831?>
3832 <?php if (is_numeric($found)): ?>
3833 <p>
3834 Found: <b><?php echo $found;?></b><?php echo isset($GLOBALS['COUNT_ERROR'])?$GLOBALS['COUNT_ERROR']:'';?>.
3835 Time: <b><?php echo $time;?></b> sec.
3836 <?php
3837 $params = array('md5'=>$md5_get, 'offset'=>get('offset','int'));
3838 if (get('only_marked') || post('only_marked')) { $params['only_marked'] = 1; }
3839 if (get('only_select') || post('only_select')) { $params['only_select'] = 1; }
3840 ?>
3841 / <a href="<?php echo url(self(), $params);?>">Refetch</a>
3842 / Export to CSV:
3843
3844 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode('|');?>&query=<?php echo base64_encode($base_query); ?>">pipe</a>
3845 -
3846 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode("\t");?>&query=<?php echo base64_encode($base_query); ?>">tab</a>
3847 -
3848 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode(',');?>&query=<?php echo base64_encode($base_query); ?>">comma</a>
3849 -
3850 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode(';');?>&query=<?php echo base64_encode($base_query); ?>">semicolon</a>
3851 </p>
3852 <?php else: ?>
3853 <p>Result: <b>OK</b>. Time: <b><?php echo $time;?></b> sec</p>
3854 <?php endif; ?>
3855
3856 <?php if (is_numeric($found)): ?>
3857
3858 <?php if ($pages > 1): ?>
3859 <p>
3860 <?php if ($page > 1): ?>
3861 <?php $ofs = ($page-1)*$limit-$limit; ?>
3862 <?php
3863 $params = array('md5'=>$md5_get, 'offset'=>$ofs);
3864 if (get('only_marked') || post('only_marked')) { $params['only_marked'] = 1; }
3865 if (get('only_select') || post('only_select')) { $params['only_select'] = 1; }
3866 ?>
3867 <a href="<?php echo url(self(), $params);?>"><< Prev</a>
3868 <?php endif; ?>
3869 Page <b><?php echo $page;?></b> of <b><?php echo $pages;?></b>
3870 <?php if ($pages > $page): ?>
3871 <?php $ofs = $page*$limit; ?>
3872 <?php
3873 $params = array('md5'=>$md5_get, 'offset'=>$ofs);
3874 if (get('only_marked') || post('only_marked')) { $params['only_marked'] = 1; }
3875 if (get('only_select') || post('only_select')) { $params['only_select'] = 1; }
3876 ?>
3877 <a href="<?php echo url(self(), $params);?>">Next >></a>
3878 <?php endif; ?>
3879 </p>
3880 <?php endif; ?>
3881
3882 <script>
3883 function mark_row(tr)
3884 {
3885 var els = tr.getElementsByTagName('td');
3886 if (tr.marked) {
3887 for (var i = 0; i < els.length; i++) {
3888 els[i].style.backgroundColor = '';
3889 }
3890 tr.marked = false;
3891 } else {
3892 tr.marked = true;
3893 for (var i = 0; i < els.length; i++) {
3894 els[i].style.backgroundColor = '#ddd';
3895 }
3896 }
3897 }
3898 </script>
3899
3900 <?php if ($found): ?>
3901
3902 <?php
3903 $edit_table = table_from_query($base_query);
3904 if ($edit_table) {
3905 $edit_pk = array_first_key($rows[0]);
3906 if (is_numeric($edit_pk)) { $edit_table = false; }
3907 }
3908 if ($edit_table) {
3909 $types = table_types2($edit_table);
3910 if ($types && count($types)) {
3911 if (in_array($edit_pk, array_keys($types))) {
3912 if (!array_col_match_unique($rows, $edit_pk, '#^\d+$#')) {
3913 $edit_pk = guess_pk($rows);
3914 if (!$edit_pk) {
3915 $edit_table = false;
3916 }
3917 }
3918 } else {
3919 $edit_table = false;
3920 }
3921 } else {
3922 $edit_table = false;
3923 }
3924 }
3925 $edit_url = '';
3926 if ($edit_table) {
3927 $edit_url = url(self(true), array('action'=>'editrow', 'table'=>$edit_table, 'pk'=>$edit_pk, 'id'=>'%s'));
3928 }
3929 ?>
3930
3931 <table class="ls" cellspacing="1">
3932 <tr>
3933 <?php if ($edit_url): ?><th>#</th><?php endif; ?>
3934 <?php foreach ($rows[0] as $col => $v): ?>
3935 <th><?php echo $col;?></th>
3936 <?php endforeach; ?>
3937 </tr>
3938 <?php foreach ($rows as $row): ?>
3939 <tr ondblclick="mark_row(this)">
3940 <?php if ($edit_url): ?>
3941 <td><a href="javascript:void(0)" onclick="popup('<?php echo sprintf($edit_url, $row[$edit_pk]);?>', 620, 500)">Edit</a> </td>
3942 <?php endif; ?>
3943 <?php
3944 $count_cols = 0;
3945 foreach ($row as $v) { $count_cols++; }
3946 ?>
3947 <?php foreach ($row as $k => $v): ?>
3948 <?php
3949 if (preg_match('#^\s*<a[^>]+>[^<]+</a>\s*$#iU', $v) && strlen(strip_tags($v)) < 50) {
3950 $v = strip_tags($v, '<a>');
3951 $v = create_links($v);
3952 } else {
3953 $v = strip_tags($v);
3954 $v = str_replace(' ', ' ', $v);
3955 $v = preg_replace('#[ ]+#', ' ', $v);
3956 $v = create_links($v);
3957 if (!get('full_content') && strlen($v) > 50) {
3958 if (1 == $count_cols) {
3959 $v = truncate_html($v, 255);
3960 } else {
3961 $v = truncate_html($v, 50);
3962 }
3963 }
3964 // $v = html_once($v); - create_links() disabling
3965 }
3966 $nl2br = get('nl2br');
3967 if (get('full_content')) {
3968 $v = str_wrap($v, 80, '<br>', true);
3969 }
3970 if (get('nl2br')) {
3971 $v = nl2br($v);
3972 }
3973 //$v = stripslashes(stripslashes($v));
3974 if (@$types[$k] == 'int' && (preg_match('#time#i', $k) || preg_match('#date#i', $k))
3975 && preg_match('#^\d+$#', $v))
3976 {
3977 $tmp = @date('Y-m-d H:i', $v);
3978 if ($tmp) {
3979 $v = $tmp;
3980 }
3981 }
3982 global $post;
3983 if (str_has($post['sql'], '@gethostbyaddr') && (preg_match('#^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $v))) {
3984 $v = $v.'<br>'.@gethostbyaddr($v);
3985 }
3986 ?>
3987 <td onclick="mark_col(this)" <?php echo $nl2br?'valign="top"':'';?> nowrap><?php echo is_null($row[$k])?'-':$v;?></td>
3988 <?php endforeach; ?>
3989 </tr>
3990 <?php endforeach; ?>
3991 </table>
3992
3993 <?php endif; ?>
3994
3995 <?php if ($pages > 1): ?>
3996 <p>
3997 <?php if ($page > 1): ?>
3998 <?php $ofs = ($page-1)*$limit-$limit; ?>
3999 <?php
4000 $params = array('md5'=>$md5_get, 'offset'=>$ofs);
4001 if (get('only_marked') || post('only_marked')) { $params['only_marked'] = 1; }
4002 if (get('only_select') || post('only_select')) { $params['only_select'] = 1; }
4003 ?>
4004 <a href="<?php echo url(self(), $params);?>"><< Prev</a>
4005 <?php endif; ?>
4006 Page <b><?php echo $page;?></b> of <b><?php echo $pages;?></b>
4007 <?php if ($pages > $page): ?>
4008 <?php $ofs = $page*$limit; ?>
4009 <?php
4010 $params = array('md5'=>$md5_get, 'offset'=>$ofs);
4011 if (get('only_marked') || post('only_marked')) { $params['only_marked'] = 1; }
4012 if (get('only_select') || post('only_select')) { $params['only_select'] = 1; }
4013 ?>
4014 <a href="<?php echo url(self(), $params);?>">Next >></a>
4015 <?php endif; ?>
4016 </p>
4017 <?php endif; ?>
4018
4019 <?php endif; ?>
4020
4021<?php
4022 $cont = ob_get_contents();
4023 ob_end_clean();
4024 $ret['data_html'] = $cont;
4025 return $ret;
4026}
4027
4028?>
4029<?php
4030
4031 // ----------------------------------------------------------------
4032 // EXECUTE SQL
4033 // ----------------------------------------------------------------
4034
4035 set_time_limit(0);
4036
4037 $template = get('template');
4038 $msg = '';
4039 $error = '';
4040 $top_html = '';
4041 $data_html = '';
4042
4043 $get = get(array(
4044 'popup'=> 'int',
4045 'md5' => 'string',
4046 'only_marked' => 'bool',
4047 'only_select' => 'bool',
4048 'sql_template' => 'string'
4049 ));
4050 $post = post(array(
4051 'sql' => 'string',
4052 'perform' => 'string',
4053 'only_marked' => 'bool',
4054 'only_select' => 'bool',
4055 'save_as' => 'string',
4056 ));
4057
4058 if ($get['md5']) {
4059 $get['only_select'] = true;
4060 $post['only_select'] = true;
4061 }
4062
4063 if ($get['only_marked']) { $post['only_marked'] = 1; }
4064 if ($get['only_select']) { $post['only_select'] = 1; }
4065
4066 $sql_dir = false;
4067 if (defined('DBKISS_SQL_DIR')) {
4068 $sql_dir = DBKISS_SQL_DIR;
4069 }
4070
4071 if ($sql_dir) {
4072 if (!(dir_exists($sql_dir) && is_writable($sql_dir))) {
4073 if (!dir_exists($sql_dir) && is_writable('.')) {
4074 mkdir($sql_dir);
4075 } else {
4076 exit('You must create "'.$sql_dir.'" directory with write permission.');
4077 }
4078 }
4079 if (!file_exists($sql_dir.'/.htaccess')) {
4080 file_put($sql_dir.'/.htaccess', 'deny from all');
4081 }
4082 if (!file_exists($sql_dir.'/index.html')) {
4083 file_put($sql_dir.'/index.html', '');
4084 }
4085 }
4086
4087 if ('GET' == $_SERVER['REQUEST_METHOD']) {
4088 if ($sql_dir)
4089 {
4090 if ($get['md5'] && preg_match('#^(\w{32,32})_(\d+)$#', $get['md5'], $match)) {
4091 $md5_i = $match[2];
4092 $md5_tmp = sprintf($sql_dir.'/zzz_%s.dat', $match[1]);
4093 $post['sql'] = file_get($md5_tmp);
4094 $_SERVER['REQUEST_METHOD'] = 'POST';
4095 $post['perform'] = 'execute';
4096 } else if ($get['md5'] && preg_match('#^(\w{32,32})$#', $get['md5'], $match)) {
4097 $md5_tmp = sprintf($sql_dir.'/zzz_%s.dat', $match[1]);
4098 $post['sql'] = file_get($md5_tmp);
4099 $get['md5'] = '';
4100 } else {
4101 if ($get['md5']) {
4102 trigger_error('invalid md5', E_USER_ERROR);
4103 }
4104 }
4105 }
4106 } else {
4107 $get['md5'] = '';
4108 }
4109
4110 if (str_has($post['sql'], '@nl2br')) {
4111 $_GET['nl2br'] = 1;
4112 }
4113 if (str_has($post['sql'], '@full_content')) {
4114 $_GET['full_content'] = 1;
4115 }
4116
4117 $post['sql'] = trim($post['sql']);
4118 $md5 = md5($post['sql']);
4119 $md5_file = sprintf($sql_dir.'/zzz_%s.dat', $md5);
4120 if ($sql_dir && $post['sql']) {
4121 file_put($md5_file, $post['sql']);
4122 }
4123
4124 if ($sql_dir && 'save' == $post['perform'] && $post['save_as'] && $post['sql'])
4125 {
4126 $post['save_as'] = str_replace('.sql', '', $post['save_as']);
4127 if (preg_match('#^[\w ]+$#', $post['save_as'])) {
4128 $file = $sql_dir.'/'.$post['save_as'].'.sql';
4129 $overwrite = '';
4130 if (file_exists($file)) {
4131 $overwrite = ' - <b>overwritten</b>';
4132 $bak = $sql_dir.'/zzz_'.$post['save_as'].'_'.md5(file_get($file)).'.dat';
4133 copy($file, $bak);
4134 }
4135 $msg .= sprintf('<div>Sql saved: %s %s</div>', basename($file), $overwrite);
4136 file_put($file, $post['sql']);
4137 } else {
4138 error('Saving sql failed: only alphanumeric chars are allowed');
4139 }
4140 }
4141
4142 if ($sql_dir) {
4143 $sql_templates = dir_read($sql_dir, null, array('.sql'), 'date_desc');
4144 }
4145 $sql_templates_assoc = array();
4146 if ($sql_dir) {
4147 foreach ($sql_templates as $file) {
4148 $file_path = $file;
4149 $file = basename($file);
4150 $sql_templates_assoc[$file] = '('.substr(file_date($file_path), 0, 10).')'.' ' .$file;
4151 }
4152 }
4153
4154 if ($sql_dir && $get['sql_template'])
4155 {
4156 $file = $sql_dir.'/'.$get['sql_template'];
4157 if (array_key_exists($get['sql_template'], $sql_templates_assoc) && file_exists($file)) {
4158 $msg .= sprintf('<div>Sql loaded: %s (%s)</div>', basename($file), timestamp(file_date($file)));
4159 $post['sql'] = file_get($file);
4160 $post['save_as'] = basename($file);
4161 $post['save_as'] = str_replace('.sql', '', $post['save_as']);
4162 } else {
4163 error('<div>File not found: %s</div>', $file);
4164 }
4165 }
4166
4167 // after load - md5 may change
4168 $md5 = md5($post['sql']);
4169
4170 if ($sql_dir && 'load' == $post['perform'] && !error()) {
4171 $md5_tmp = sprintf($sql_dir.'/zzz_%s.dat', $md5);
4172 file_put($md5_tmp, $post['sql']);
4173 }
4174
4175 $is_sel = false;
4176
4177 $queries = preg_split("#;(\s*--[ \t\S]*)?(\r\n|\n|\r)#U", $post['sql']);
4178 foreach ($queries as $k => $query) {
4179 $query = query_strip($query);
4180 if (str_starts_with($query, '@')) {
4181 $is_sel = true;
4182 }
4183 $queries[$k] = $query;
4184 if (!trim($query)) { unset($queries[$k]); }
4185 }
4186
4187 $sql_assoc = array();
4188 $sql_selected = false;
4189 $i = 0;
4190
4191 $params = array(
4192 'md5' => $md5,
4193 'only_marked' => $post['only_marked'],
4194 'only_select' => $post['only_select'],
4195 'offset' => ''
4196 );
4197 $sql_main_url = url(self(), $params);
4198
4199 foreach ($queries as $query) {
4200 $i++;
4201 $query = str_cut_start($query, '@');
4202 if (!is_select($query)) {
4203 continue;
4204 }
4205 $query = preg_replace('#\s+#', ' ', $query);
4206 $params = array(
4207 'md5' => $md5.'_'.$i,
4208 'only_marked' => $post['only_marked'],
4209 'only_select' => $post['only_select'],
4210 'offset' => ''
4211 );
4212 $url = url(self(), $params);
4213 if ($get['md5'] && $get['md5'] == $params['md5']) {
4214 $sql_selected = $url;
4215 }
4216 $sql_assoc[$url] = str_truncate(strip_tags($query), 80);
4217 }
4218
4219 if ('POST' == $_SERVER['REQUEST_METHOD'])
4220 {
4221 if (!$post['perform']) {
4222 $error = 'No action selected.';
4223 }
4224 if (!$error)
4225 {
4226 $time = time_start();
4227 switch ($post['perform']) {
4228 case 'execute':
4229 $i = 0;
4230 db_begin();
4231 $commit = true;
4232 foreach ($queries as $query)
4233 {
4234 $i++;
4235 if ($post['only_marked'] && !$is_sel) {
4236 if (!$get['md5']) { continue; }
4237 }
4238 if ($is_sel) {
4239 if (str_starts_with($query, '@')) {
4240 $query = str_cut_start($query, '@');
4241 } else {
4242 if (!$get['md5']) { continue; }
4243 }
4244 }
4245 if ($post['only_select'] && !is_select($query)) {
4246 continue;
4247 }
4248 if ($get['md5'] && $i != $md5_i) {
4249 continue;
4250 }
4251 if ($get['md5'] && $i == $md5_i) {
4252 if (!is_select($query)) {
4253 trigger_error('not select query', E_USER_ERROR);
4254 }
4255 }
4256
4257 $exec = listing($query, $md5.'_'.$i);
4258 $query_trunc = str_truncate(html_once($query), 1000);
4259 $query_trunc = query_color($query_trunc);
4260 $query_trunc = nl2br($query_trunc);
4261 $query_trunc = html_spaces($query_trunc);
4262 if ($exec['error']) {
4263 $exec['error'] = preg_replace('#error:#i', '', $exec['error']);
4264 $top_html .= sprintf('<div style="background: #ffffd7; padding: 0.5em; border: #ccc 1px solid; margin-bottom: 1em; margin-top: 1em;"><b style="color:red">Error</b>: %s<div style="margin-top: 0.25em;"><b>Query %s</b>: %s</div></div>', $exec['error'], $i, $query_trunc);
4265 $commit = false;
4266 break;
4267 } else {
4268 $query_html = sprintf('<div class="query"><b style="font-size: 10px;">Query %s</b>:<div style="'.$sql_font.' margin-top: 0.35em;">%s</div></div>', $i, $query_trunc);
4269 $data_html .= $query_html;
4270 $data_html .= $exec['data_html'];
4271 }
4272 }
4273 if ($commit) {
4274 db_end();
4275 } else {
4276 db_rollback();
4277 }
4278 break;
4279 }
4280 $time = time_end($time);
4281 }
4282 }
4283
4284 if ($post['only_marked'] && !$is_sel) {
4285 error('No queries marked');
4286 }
4287
4288?>
4289<?php layout_start(($db_name_h1?$db_name_h1:$db_name).' > Execute SQL'); ?>
4290 <?php if ($get['popup']): ?>
4291 <h1><span style="<?php echo $db_name_style;?>"><?php echo $db_name_h1?$db_name_h1:$db_name;?></span> > Execute SQL</h1>
4292 <?php else: ?>
4293 <h1><a class=blue style="<?php echo $db_name_style;?>" href="<?php echo $_SERVER['PHP_SELF'];?>"><?php echo $db_name_h1?$db_name_h1:$db_name;?></a> > Execute SQL</h1>
4294 <?php endif; ?>
4295
4296 <?php echo error();?>
4297
4298 <script>
4299 function sql_submit(form)
4300 {
4301 if (form.perform.value.length) {
4302 return true;
4303 }
4304 return false;
4305 }
4306 function sql_execute(form)
4307 {
4308 form.perform.value='execute';
4309 form.submit();
4310 }
4311 function sql_preview(form)
4312 {
4313 form.perform.value='preview';
4314 form.submit();
4315 }
4316 function sql_save(form)
4317 {
4318 form.perform.value='save';
4319 form.submit();
4320 }
4321 function sql_load(form)
4322 {
4323 if (form.sql_template.selectedIndex)
4324 {
4325 currentUrl = window.location.href;
4326 currentUrl = currentUrl.replace(/&sql_template=[^&]*/g, '');
4327 window.location = currentUrl + "&sql_template=" +
4328 escape(form.sql_template.value)
4329 return true;
4330 }
4331 button_clear(form);
4332 return false;
4333 }
4334 </script>
4335
4336 <?php if ($msg): ?>
4337 <div class="msg"><?php echo $msg;?></div>
4338 <?php endif; ?>
4339
4340 <?php echo $top_html;?>
4341
4342 <?php if (count($sql_assoc)): ?>
4343 <p>
4344 SELECT queries:
4345 <select name="sql_assoc" onchange="if (this.value.length) location=this.value">
4346 <option value="<?php echo html_once($sql_main_url);?>"></option>
4347 <?php echo options($sql_assoc, $sql_selected);?>
4348 </select>
4349 </p>
4350 <?php endif; ?>
4351
4352 <?php if ($get['md5']): ?>
4353 <?php echo $data_html;?>
4354 <?php endif; ?>
4355
4356 <form action="<?php echo $_SERVER['PHP_SELF'];?>?execute_sql=1&popup=<?php echo $get['popup'];?>" method="post" onsubmit="return sql_submit(this);" style="margin-top: 1em;">
4357 <input type="hidden" name="perform" value="">
4358 <div style="margin-bottom: 0.25em;">
4359 <textarea id="sql_area" name="sql" class="sql_area"><?php echo htmlspecialchars(query_upper($post['sql']));?></textarea>
4360 </div>
4361 <table cellspacing="0" cellpadding="0"><tr>
4362 <td nowrap>
4363 <input type="button" wait="1" class="button" value="Execute" onclick="sql_execute(this.form); ">
4364 </td>
4365 <td nowrap>
4366
4367 <input type="button" wait="1" class="button" value="Preview" onclick="sql_preview(this.form); ">
4368 </td>
4369 <td nowrap>
4370
4371 <input type="checkbox" name="only_marked" id="only_marked" value="1" <?php echo checked($post['only_marked'] || $get['only_marked']);?>>
4372 </td>
4373 <td nowrap>
4374 <label for="only_marked">only marked</label>
4375 </td>
4376 <td nowrap>
4377
4378 <input type="checkbox" name="only_select" id="only_select" value="1" <?php echo checked($post['only_select'] || $get['only_select']);?>>
4379 </td>
4380 <td nowrap>
4381 <label for="only_select">only SELECT</label>
4382
4383 </td>
4384 <td nowrap>
4385 <input type="text" name="save_as" value="<?php echo html_once($post['save_as']);?>">
4386
4387 </td>
4388 <td nowrap>
4389 <input type="button" wait="1" class="button" value="Save" onclick="sql_save(this.form); ">
4390
4391 </td>
4392 <td nowrap>
4393 <select name="sql_template" style="width: 140px;"><option value=""></option><?php echo options($sql_templates_assoc);?></select>
4394
4395 </td>
4396 <td nowrap>
4397 <input type="button" wait="1" class="button" value="Load" onclick="return sql_load(this.form);">
4398 </td>
4399 </tr></table>
4400 </form>
4401
4402 <?php
4403
4404 if ('preview' == $post['perform'])
4405 {
4406 echo '<h2>Preview</h2>';
4407 $i = 0;
4408 foreach ($queries as $query)
4409 {
4410 $i++;
4411 $query = str_cut_start($query, '@');
4412 $query = html_once($query);
4413 $query = query_color($query);
4414 $query = nl2br($query);
4415 $query = html_spaces($query);
4416 printf('<div class="query"><b style="font-size: 10px;">Query %s</b>:<div style="'.$sql_font.' margin-top: 0.35em;">%s</div></div>', $i, $query);
4417 }
4418 }
4419
4420 ?>
4421
4422 <?php if (!$get['md5']): ?>
4423 <script>$('sql_area').focus();</script>
4424 <?php echo $data_html;?>
4425 <?php endif; ?>
4426
4427 <?php layout_end(); ?>
4428
4429<?php exit; endif; ?>
4430<?php if (isset($_GET['viewtable']) && $_GET['viewtable']): ?>
4431
4432 <?php
4433
4434 set_time_limit(0);
4435
4436 // ----------------------------------------------------------------
4437 // VIEW TABLE
4438 // ----------------------------------------------------------------
4439
4440 $table = $_GET['viewtable'];
4441 $table_enq = quote_table($table);
4442 $count = db_one("SELECT COUNT(*) FROM $table_enq");
4443
4444 $types = table_types2($table);
4445 $columns = table_columns($table);
4446 if (!count($columns)) {
4447 $columns = array_assoc(array_keys($types));
4448 }
4449 $columns2 = $columns;
4450
4451 foreach ($columns2 as $k => $v) {
4452 $columns2[$k] = $v.' ('.$types[$k].')';
4453 }
4454 $types_group = table_types_group($types);
4455 $_GET['search'] = get('search');
4456
4457 $where = '';
4458 $found = $count;
4459 if ($_GET['search']) {
4460 $search = $_GET['search'];
4461 $cols2 = array();
4462
4463 if (get('column')) {
4464 $cols2[] = $_GET['column'];
4465 } else {
4466 $cols2 = $columns;
4467 }
4468 $where = '';
4469 $search = db_escape($search);
4470
4471 $column_type = '';
4472 if (!get('column')) {
4473 $column_type = get('column_type');
4474 } else {
4475 $_GET['column_type'] = '';
4476 }
4477
4478 $ignore_int = false;
4479 $ignore_time = false;
4480
4481 foreach ($columns as $col)
4482 {
4483 if (!get('column') && $column_type) {
4484 if ($types[$col] != $column_type) {
4485 continue;
4486 }
4487 }
4488 if (!$column_type && !is_numeric($search) && str_has($types[$col], 'int')) {
4489 $ignore_int = true;
4490 continue;
4491 }
4492 if (!$column_type && is_numeric($search) && str_has($types[$col], 'time')) {
4493 $ignore_time = true;
4494 continue;
4495 }
4496 if (get('column') && $col != $_GET['column']) {
4497 continue;
4498 }
4499 if ($where) { $where .= ' OR '; }
4500 if (is_numeric($search)) {
4501 $where .= "$col = '$search'";
4502 } else {
4503 if ('mysql' == $db_driver) {
4504 $where .= "$col LIKE '%$search%'";
4505 } else if ('pgsql' == $db_driver) {
4506 $where .= "$col ILIKE '%$search%'";
4507 } else {
4508 trigger_error('db_driver not implemented');
4509 }
4510 }
4511 }
4512 if (($ignore_int || $ignore_time) && !$where) {
4513 $where .= ' 1=2 ';
4514 }
4515 $where = 'WHERE '.$where;
4516 }
4517
4518 if ($where) {
4519 $table_enq = quote_table($table);
4520 $found = db_one("SELECT COUNT(*) FROM $table_enq $where");
4521 }
4522
4523 $limit = 50;
4524 $offset = get('offset','int');
4525 $page = floor($offset / $limit + 1);
4526 $pages = ceil($found / $limit);
4527
4528 $pk = table_pk($table);
4529
4530 $order = "ORDER BY";
4531 if (get('order_by')) {
4532 $order .= ' '.$_GET['order_by'];
4533 } else {
4534 if ($pk) {
4535 if (IsTableAView($table)) {
4536 $order = '';
4537 } else {
4538 $order .= ' '.$pk;
4539 }
4540 } else {
4541 $order = '';
4542 }
4543 }
4544 if (get('order_desc')) { $order .= ' DESC'; }
4545
4546 $table_enq = quote_table($table);
4547 $base_query = "SELECT * FROM $table_enq $where $order";
4548 $rs = db_query(db_limit($base_query, $offset, $limit));
4549
4550 if ($count && $rs) {
4551 $rows = array();
4552 while ($row = db_row($rs)) {
4553 $rows[] = $row;
4554 }
4555 db_free($rs);
4556 if (count($rows) && !array_col_match_unique($rows, $pk, '#^\d+$#')) {
4557 $pk = guess_pk($rows);
4558 }
4559 }
4560
4561 function indenthead($str)
4562 {
4563 if (is_array($str)) {
4564 $str2 = '';
4565 foreach ($str as $k => $v) {
4566 $str2 .= sprintf('%s: %s'."\r\n", $k, $v);
4567 }
4568 $str = $str2;
4569 }
4570 $lines = explode("\n", $str);
4571 $max_len = 0;
4572 foreach ($lines as $k => $line) {
4573 $lines[$k] = trim($line);
4574 if (preg_match('#^[^:]+:#', $line, $match)) {
4575 if ($max_len < strlen($match[0])) {
4576 $max_len = strlen($match[0]);
4577 }
4578 }
4579 }
4580 foreach ($lines as $k => $line) {
4581 if (preg_match('#^[^:]+:#', $line, $match)) {
4582 $lines[$k] = str_replace($match[0], $match[0].str_repeat(' ', $max_len - strlen($match[0])), $line);
4583 }
4584 }
4585 return implode("\r\n", $lines);
4586 }
4587
4588 if (get('indenthead')) {
4589 echo '<pre>';
4590 echo 'Table: '.get('viewtable')."\r\n";
4591 echo str_repeat('-', 80)."\r\n";
4592 foreach ($rows as $row) {
4593 echo indenthead($row);
4594 echo str_repeat('-', 80)."\r\n";
4595 }
4596 echo '</pre>';
4597 exit;
4598 }
4599 ?>
4600
4601<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4602<html>
4603<head>
4604 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $page_charset;?>">
4605 <title><?php echo $db_name_h1?$db_name_h1:$db_name;?> > Table: <?php echo $table;?></title>
4606 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
4607</head>
4608<body>
4609
4610 <?php layout(); ?>
4611
4612 <h1><a class=blue style="<?php echo $db_name_style;?>" href="<?php echo $_SERVER['PHP_SELF'];?>"><?php echo $db_name_h1?$db_name_h1:$db_name;?></a> > Table: <?php echo $table;?></h1>
4613
4614 <?php conn_info(); ?>
4615
4616 <p>
4617 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>">All tables</a>
4618 >
4619 <a href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $table;?>"><b><?php echo $table;?></b></a> (<?php echo $count;?>)
4620 /
4621
4622 Export to CSV:
4623
4624 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode('|');?>&query=<?php echo base64_encode($base_query); ?>">pipe</a>
4625 -
4626 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode("\t");?>&query=<?php echo base64_encode($base_query); ?>">tab</a>
4627 -
4628 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode(',');?>&query=<?php echo base64_encode($base_query); ?>">comma</a>
4629 -
4630 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode(';');?>&query=<?php echo base64_encode($base_query); ?>">semicolon</a>
4631
4632 /
4633 Functions:
4634 <a href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $table;?>&indenthead=1">indenthead()</a>
4635 </p>
4636
4637 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="get" style="margin-bottom: 1em;">
4638 <input type="hidden" name="viewtable" value="<?php echo $table;?>">
4639 <table class="ls" cellspacing="1">
4640 <tr>
4641 <td><input type="text" name="search" value="<?php echo html_once(get('search'));?>"></td>
4642 <td><select name="column"><option value=""></option><?php echo options($columns2, get('column'));?></select></td>
4643 <td><select name="column_type"><option value=""></option><?php echo options($types_group, get('column_type'));?></select></td>
4644 <td><input type="submit" value="Search"></td>
4645 <td>
4646 order by:
4647 <select name="order_by"><option value=""></option><?php echo options($columns, get('order_by'));?></select>
4648 <input type="checkbox" name="order_desc" id="order_desc" value="1" <?php echo checked(get('order_desc'));?>>
4649 <label for="order_desc">desc</label>
4650 </td>
4651 <td>
4652 <input type="checkbox" name="full_content" id="full_content" <?php echo checked(get('full_content'));?>>
4653 <label for="full_content">full content</label>
4654 </td>
4655 <td>
4656 <input type="checkbox" name="nl2br" id="nl2br" <?php echo checked(get('nl2br'));?>>
4657 <label for="nl2br">nl2br</label>
4658 </td>
4659 </tr>
4660 </table>
4661 </form>
4662
4663 <?php if ($count): ?>
4664
4665 <?php if ($count && $count != $found): ?>
4666 <p>Found: <b><?php echo $found;?></b></p>
4667 <?php endif; ?>
4668
4669 <?php if ($found): ?>
4670
4671 <?php if ($pages > 1): ?>
4672 <p>
4673 <?php if ($page > 1): ?>
4674 <a href="<?php echo url_offset(($page-1)*$limit-$limit);?>"><< Prev</a>
4675 <?php endif; ?>
4676 Page <b><?php echo $page;?></b> of <b><?php echo $pages;?></b>
4677 <?php if ($pages > $page): ?>
4678 <a href="<?php echo url_offset($page*$limit);?>">Next >></a>
4679 <?php endif; ?>
4680 </p>
4681 <?php endif; ?>
4682
4683 <script>
4684 function mark_row(tr)
4685 {
4686 var els = tr.getElementsByTagName('td');
4687 if (tr.marked) {
4688 for (var i = 0; i < els.length; i++) {
4689 els[i].style.backgroundColor = '';
4690 }
4691 tr.marked = false;
4692 } else {
4693 tr.marked = true;
4694 for (var i = 0; i < els.length; i++) {
4695 els[i].style.backgroundColor = '#ddd';
4696 }
4697 }
4698 }
4699 </script>
4700
4701 <table class="ls" cellspacing="1">
4702 <tr>
4703 <?php if ($pk): ?><th>#</th><?php endif; ?>
4704 <?php foreach ($columns as $col): ?>
4705 <?php
4706 $params = array('order_by'=>$col);
4707 $params['order_desc'] = 0;
4708 if (get('order_by') == $col) {
4709 $params['order_desc'] = get('order_desc') ? 0 : 1;
4710 }
4711 ?>
4712 <th><a style="color: #000;" href="<?php echo url(self(), $params);?>"><?php echo $col;?></a></th>
4713 <?php endforeach; ?>
4714 </tr>
4715 <?php
4716 $get_full_content = get('full_content');
4717 $get_nl2br = get('nl2br');
4718 $get_search = get('search');
4719 ?>
4720 <?php
4721 $edit_url_tpl = url(self(true), array('action'=>'editrow', 'table'=>$table, 'pk'=>$pk, 'id'=>'%s'));
4722 ?>
4723 <?php foreach ($rows as $row): ?>
4724 <tr ondblclick="mark_row(this)">
4725 <?php if ($pk): ?>
4726 <?php $edit_url = sprintf($edit_url_tpl, $row[$pk]); ?>
4727 <td><a href="javascript:void(0)" onclick="popup('<?php echo $edit_url;?>', 620, 500)">Edit</a> </td>
4728 <?php endif; ?>
4729 <?php foreach ($row as $k => $v): ?>
4730 <?php
4731 $v = strip_tags($v);
4732 $v = create_links($v);
4733 if (!$get_full_content) {
4734 $v = truncate_html($v, 50);
4735 }
4736 //$v = html_once($v);
4737 //$v = htmlspecialchars($v); -- create_links() disabling
4738 $nl2br = $get_nl2br;
4739 if ($get_full_content) {
4740 $v = str_wrap($v, 80, '<br>', true);
4741 }
4742 if ($get_nl2br) {
4743 $v = nl2br($v);
4744 }
4745 //$v = stripslashes(stripslashes($v));
4746 if ($get_search) {
4747 $search = $_GET['search'];
4748 $search_quote = preg_quote($search);
4749 $v = preg_replace('#('.$search_quote.')#i', '<span style="background: yellow;">$1</span>', $v);
4750 }
4751 if ($types[$k] == 'int' && (preg_match('#time#i', $k) || preg_match('#date#i', $k))
4752 && preg_match('#^\d+$#', $v))
4753 {
4754 $tmp = @date('Y-m-d H:i', $v);
4755 if ($tmp) {
4756 $v = $tmp;
4757 }
4758 }
4759 ?>
4760 <td onclick="mark_col(this)" <?php echo $nl2br?'valign="top"':'';?> nowrap><?php echo is_null($row[$k])?'-':$v;?></td>
4761 <?php endforeach; ?>
4762 </tr>
4763 <?php endforeach; ?>
4764 </table>
4765
4766 <?php if ($pages > 1): ?>
4767 <p>
4768 <?php if ($page > 1): ?>
4769 <a href="<?php echo url_offset(($page-1)*$limit-$limit);?>"><< Prev</a>
4770 <?php endif; ?>
4771 Page <b><?php echo $page;?></b> of <b><?php echo $pages;?></b>
4772 <?php if ($pages > $page): ?>
4773 <a href="<?php echo url_offset($page*$limit);?>">Next >></a>
4774 <?php endif; ?>
4775 </p>
4776 <?php endif; ?>
4777
4778 <?php endif; ?>
4779
4780 <?php endif; ?>
4781
4782<?php powered_by(); ?>
4783</body>
4784</html>
4785<?php exit; endif; ?>
4786<?php if (get('searchdb')): ?>
4787<?php
4788
4789 // ----------------------------------------------------------------
4790 // SEARCH DB
4791 // ----------------------------------------------------------------
4792
4793 $get = get(array(
4794 'types' => 'array',
4795 'search' => 'string',
4796 'md5' => 'bool',
4797 'table_filter' => 'string'
4798 ));
4799 $get['search'] = trim($get['search']);
4800
4801 $tables = list_tables();
4802
4803 if ($get['table_filter']) {
4804 foreach ($tables as $k => $table) {
4805 if (!str_has_any($table, $get['table_filter'], $ignore_case = true)) {
4806 unset($tables[$k]);
4807 }
4808 }
4809 }
4810
4811 $all_types = array();
4812 $columns = array();
4813 foreach ($tables as $table) {
4814 $types = table_types2($table);
4815 $columns[$table] = $types;
4816 $types = array_values($types);
4817 $all_types = array_merge($all_types, $types);
4818 }
4819 $all_types = array_unique($all_types);
4820
4821 if ($get['search'] && $get['md5']) {
4822 $get['search'] = md5($get['search']);
4823 }
4824
4825?>
4826<?php layout_start(sprintf('%s > Search', $db_name)); ?>
4827 <h1><a class=blue style="<?php echo $db_name_style;?>" href="<?php echo $_SERVER['PHP_SELF'];?>"><?php echo $db_name_h1?$db_name_h1:$db_name;?></a> > Search</h1>
4828 <?php conn_info(); ?>
4829
4830 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="get">
4831 <input type="hidden" name="searchdb" value="1">
4832 <table class="ls" cellspacing="1">
4833 <tr>
4834 <th>Search:</th>
4835 <td>
4836 <input type="text" name="search" value="<?php echo html_once($get['search']);?>" size="40">
4837 <?php if ($get['search'] && $get['md5']): ?>
4838 md5(<?php echo html_once(get('search'));?>)
4839 <?php endif; ?>
4840 <input type="checkbox" name="md5" id="md5_label" value="1">
4841 <label for="md5_label">md5</label>
4842 </td>
4843 </tr>
4844 <tr>
4845 <th>Table filter:</th>
4846 <td><input type="text" name="table_filter" value="<?php echo html_once($get['table_filter']);?>">
4847 </tr>
4848 <tr>
4849 <th>Columns:</th>
4850 <td>
4851 <?php foreach ($all_types as $type): ?>
4852 <input type="checkbox" id="type_<?php echo $type;?>" name="types[<?php echo $type;?>]" value="1" <?php echo checked(isset($get['types'][$type]));?>>
4853 <label for="type_<?php echo $type;?>"><?php echo $type;?></label>
4854 <?php endforeach; ?>
4855 </td>
4856 </tr>
4857 <tr>
4858 <td colspan="2" class="none">
4859 <input type="submit" value="Search">
4860 </td>
4861 </tr>
4862 </table>
4863 </form>
4864
4865 <?php if ($get['search'] && !count($get['types'])): ?>
4866 <p>No columns selected.</p>
4867 <?php endif; ?>
4868
4869 <?php if ($get['search'] && count($get['types'])): ?>
4870
4871 <p>Searching <b><?php echo count($tables);?></b> tables for: <b><?php echo html_once($get['search']);?></b></p>
4872
4873 <?php $found_any = false; ?>
4874
4875 <?php set_time_limit(0); ?>
4876
4877 <?php foreach ($tables as $table): ?>
4878 <?php
4879
4880 $where = '';
4881 $cols2 = array();
4882
4883 $where = '';
4884 $search = db_escape($get['search']);
4885
4886 foreach ($columns[$table] as $col => $type)
4887 {
4888 if (!in_array($type, array_keys($get['types']))) {
4889 continue;
4890 }
4891 if ($where) {
4892 $where .= ' OR ';
4893 }
4894 if (is_numeric($search)) {
4895 $where .= "$col = '$search'";
4896 } else {
4897 if ('mysql' == $db_driver) {
4898 $where .= "$col LIKE '%$search%'";
4899 } else if ('pgsql' == $db_driver) {
4900 $where .= "$col ILIKE '%$search%'";
4901 } else {
4902 trigger_error('db_driver not implemented');
4903 }
4904 }
4905 }
4906
4907 $found = false;
4908
4909 if ($where) {
4910 $where = 'WHERE '.$where;
4911 $table_enq = quote_table($table);
4912 $found = db_one("SELECT COUNT(*) FROM $table_enq $where");
4913 }
4914
4915 if ($found) {
4916 $found_any = true;
4917 }
4918
4919 ?>
4920
4921 <?php
4922 if ($where && $found) {
4923 $limit = 10;
4924 $offset = 0;
4925 $pk = table_pk($table);
4926
4927 $order = "ORDER BY $pk";
4928 $table_enq = quote_table($table);
4929 $rs = db_query(db_limit("SELECT * FROM $table_enq $where $order", $offset, $limit));
4930
4931 $rows = array();
4932 while ($row = db_row($rs)) {
4933 $rows[] = $row;
4934 }
4935 db_free($rs);
4936 if (count($rows) && !array_col_match_unique($rows, $pk, '#^\d+$#')) {
4937 $pk = guess_pk($rows);
4938 }
4939 }
4940 ?>
4941
4942 <?php if ($where && $found): ?>
4943
4944 <p>
4945 Table: <a href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $table;?>&search=<?php echo urlencode($get['search']);?>"><b><?php echo $table;?></b></a><br>
4946 Found: <b><?php echo $found;?></b>
4947 <?php if ($found > $limit): ?>
4948 <a href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $table;?>&search=<?php echo urlencode($get['search']);?>">show all >></a>
4949 <?php endif; ?>
4950 </p>
4951
4952 <table class="ls" cellspacing="1">
4953 <tr>
4954 <?php if ($pk): ?><th>#</th><?php endif; ?>
4955 <?php foreach ($columns[$table] as $col => $type): ?>
4956 <th><?php echo $col;?></th>
4957 <?php endforeach; ?>
4958 </tr>
4959 <?php foreach ($rows as $row): ?>
4960 <tr>
4961 <?php if ($pk): ?>
4962 <?php $edit_url = url(self(true), array('action'=>'editrow', 'table'=>$table, 'pk'=>$pk, 'id'=>$row[$pk])); ?>
4963 <td><a href="javascript:void(0)" onclick="popup('<?php echo $edit_url;?>', 620, 500)">Edit</a> </td>
4964 <?php endif; ?>
4965 <?php foreach ($row as $k => $v): ?>
4966 <?php
4967 $v = str_truncate($v, 50);
4968 $v = html_once($v);
4969 //$v = stripslashes(stripslashes($v));
4970 $search = $get['search'];
4971 $search_quote = preg_quote($search);
4972 if ($columns[$table][$k] == 'int' && (preg_match('#time#i', $k) || preg_match('#date#i', $k)) && preg_match('#^\d+$#', $v)) {
4973 $tmp = @date('Y-m-d H:i', $v);
4974 if ($tmp) {
4975 $v = $tmp;
4976 }
4977 }
4978 $v = preg_replace('#('.$search_quote.')#i', '<span style="background: yellow;">$1</span>', $v);
4979 ?>
4980 <td nowrap><?php echo $v;?></td>
4981 <?php endforeach; ?>
4982 </tr>
4983 <?php endforeach; ?>
4984 </table>
4985
4986 <?php endif; ?>
4987
4988 <?php endforeach; ?>
4989
4990 <?php if (!$found_any): ?>
4991 <p>No rows found.</p>
4992 <?php endif; ?>
4993
4994 <?php endif; ?>
4995
4996 <?php layout_end(); ?>
4997<?php exit; endif; ?>
4998
4999<?php
5000
5001// ----------------------------------------------------------------
5002// LIST TABLES
5003// ----------------------------------------------------------------
5004
5005$get = get(array('table_filter'=>'string'));
5006
5007?>
5008
5009<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
5010<html>
5011<head>
5012 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $page_charset;?>">
5013 <title><?php echo $db_name_h1?$db_name_h1:$db_name;?></title>
5014 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
5015</head>
5016<body>
5017
5018<?php layout(); ?>
5019<h1 style="<?php echo $db_name_style;?>"><?php echo $db_name_h1?$db_name_h1:$db_name;?></h1>
5020
5021<?php conn_info(); ?>
5022
5023<?php $tables = list_tables(); ?>
5024<?php $status = table_status(); ?>
5025<?php $views = list_tables(true); ?>
5026
5027<p>
5028 Tables: <b><?php echo count($tables);?></b>
5029 -
5030 Total size: <b><?php echo number_format(ceil($status['total_size']/1024),0,'',',').' KB';?></b>
5031 -
5032 Views: <b><?php echo count($views);?></b>
5033 -
5034
5035 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?searchdb=1&table_filter=<?php echo html_once($get['table_filter']);?>">Search</a>
5036 -
5037 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?import=1">Import</a>
5038 -
5039 Export all:
5040
5041 <?php if ('pgsql' == $db_driver): ?>
5042 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?dump_all=2&table_filter=<?php echo urlencode(html_once($get['table_filter']));?>">Data only</a>
5043 <?php else: ?>
5044 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?dump_all=1&table_filter=<?php echo urlencode(html_once($get['table_filter']));?>">Structure</a> ,
5045 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?dump_all=2&table_filter=<?php echo urlencode(html_once($get['table_filter']));?>">Data & structure</a>
5046 <?php endif; ?>
5047</p>
5048
5049<form action="<?php echo $_SERVER['PHP_SELF'];?>" method="get" name=table_filter_form style="margin-bottom: 0.5em;">
5050<table cellspacing="0" cellpadding="0"><tr>
5051<td style="padding-right: 3px;">Table or View:</td>
5052<td style="padding-right: 3px;"><input type="text" name="table_filter" id=table_filter value="<?php echo html_once($get['table_filter']);?>"></td>
5053<td style="padding-right: 3px;"><input type="submit" class="button" wait="1" value="Filter"> <a href="javascript:void(0)" onclick="alert('You just start typing on the page and the Input will be focused automatically. ALT+R will Reset the Input and submit the form.')">[?]</a></td>
5054</tr></table>
5055</form>
5056
5057<script>
5058function table_filter_keydown(e)
5059{
5060 if (!e) { e = window.event; }
5061 if (e.keyCode == 27 || e.keyCode == 33 || e.keyCode == 34 || e.keyCode == 38 || e.keyCode == 40) {
5062 document.getElementById('table_filter').blur();
5063 return;
5064 }
5065 // alt + r - reset filter input
5066 if (e.keyCode == 82 && e.altKey) {
5067 document.getElementById('table_filter').value = "";
5068 document.forms["table_filter_form"].submit();
5069 return;
5070 }
5071 // 0-9
5072 if (e.keyCode >= 48 && e.keyCode <= 57 && !e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey) {
5073 document.getElementById('table_filter').focus();
5074 }
5075 // a-z
5076 if (e.keyCode >= 65 && e.keyCode <= 90 && !e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey) {
5077 document.getElementById('table_filter').focus();
5078 }
5079}
5080document.onkeydown = table_filter_keydown;
5081</script>
5082
5083<div style="float: left;">
5084
5085 <?php
5086 $tables = table_filter($tables, $get['table_filter']);
5087 ?>
5088
5089 <?php if ($get['table_filter']): ?>
5090 <p>Tables found: <b><?php echo count($tables);?></b></p>
5091 <?php endif; ?>
5092
5093 <table class="ls" cellspacing="1">
5094 <tr>
5095 <th>Table</th>
5096 <th>Count</th>
5097 <th>Size</th>
5098 <th>Options</th>
5099 </tr>
5100 <?php foreach ($tables as $table): ?>
5101 <tr>
5102 <td><a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $table;?>"><?php echo $table;?></a></td>
5103 <?php
5104 if ('mysql' == $db_driver) {
5105 // $table_enq = quote_table($table);
5106 // $count = db_one("SELECT COUNT(*) FROM $table_enq");
5107 $count = $status[$table]['count'];
5108 }
5109 if ('pgsql' == $db_driver) {
5110 $count = $status[$table]['count'];
5111 if (!$count) {
5112 $table_enq = quote_table($table);
5113 $count = db_one("SELECT COUNT(*) FROM $table_enq");
5114 }
5115 }
5116 ?>
5117 <td align="right"><?php echo number_format($count,0,'',',');?></td>
5118 <td align="right"><?php echo number_format(ceil($status[$table]['size']/1024),0,'',',').' KB';?></td>
5119 <td>
5120 <a href="<?php echo $_SERVER['PHP_SELF'];?>?dump_table=<?php echo $table;?>">Export</a>
5121 -
5122 <?php $table_enq = quote_table($table); ?>
5123 <form action="<?php echo $_SERVER['PHP_SELF'];?>" name="drop_<?php echo $table;?>" method="post" style="display: inline;"><input type="hidden" name="drop_table" value="<?php echo $table;?>"></form>
5124 <a href="javascript:void(0)" onclick="if (confirm('DROP TABLE <?php echo $table;?> ?')) document.forms['drop_<?php echo $table;?>'].submit();">Drop</a>
5125 </td>
5126 </tr>
5127 <?php endforeach; ?>
5128 </table>
5129 <?php unset($table); ?>
5130
5131</div>
5132
5133<?php if (views_supported() && count($views)): ?>
5134<div style="float: left; margin-left: 2em;">
5135
5136 <?php
5137 $views = table_filter($views, $get['table_filter']);
5138 ?>
5139
5140 <?php if ($get['table_filter']): ?>
5141 <p>Views found: <b><?php echo count($views);?></b></p>
5142 <?php endif; ?>
5143
5144 <table class="ls" cellspacing="1">
5145 <tr>
5146 <th>View</th>
5147 <th><a class=blue href="<?php echo $_SERVER['PHP_SELF']; ?>?table_filter=<?php echo urlencode($get['table_filter']);?>&views_count=<?php echo (isset($_GET['views_count']) && $_GET['views_count']) ? 0 : 1; ?>" style="color: #000; text-decoration: underline;" title="Click to enable/disable counting in Views">Count</a></th>
5148 <th>Options</th>
5149 </tr>
5150 <?php foreach ($views as $view): ?>
5151 <?php $view_enq = quote_table($view); ?>
5152 <tr>
5153 <td><a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $view;?>"><?php echo $view;?></a></td>
5154 <?php
5155 if (isset($_GET['views_count']) && $_GET['views_count']) {
5156 $count = db_one("SELECT COUNT(*) FROM $view_enq");
5157 } else {
5158 $count = null;
5159 }
5160 ?>
5161 <td align=right><?php echo isset($count) ? $count : '-'; ?></td>
5162 <td>
5163 <a href="<?php echo $_SERVER['PHP_SELF'];?>?dump_table=<?php echo $view;?>">Export</a>
5164 -
5165 <form action="<?php echo $_SERVER['PHP_SELF'];?>" name="drop_<?php echo $view;?>" method="post" style="display: inline;">
5166 <input type="hidden" name="drop_view" value="<?php echo $view;?>"></form>
5167 <a href="javascript:void(0)" onclick="if (confirm('DROP VIEW <?php echo $view;?> ?')) document.forms['drop_<?php echo $view;?>'].submit();">Drop</a>
5168 </td>
5169 </tr>
5170 <?php endforeach; ?>
5171 </table>
5172
5173</div>
5174<?php endif; ?>
5175
5176<div style="clear: both;"></div>
5177
5178<?php powered_by(); ?>
5179</body>
5180</html>