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