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