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