· 9 years ago · Feb 23, 2017, 07:54 PM
1<?php
2/*
3 DBKiss 2.00 Beta (2012-01-07)
4 Author: Czarek Tomczak [czarek.tomczak#gmail.com]
5 Web site: http://www.gosu.pl/dbkiss/
6 License: GPL v3
7*/
8
9define("DBKISS_VERSION", "2.00 Beta");
10
11// ----------------------------------------------------------------
12// SQLite configuration.
13// ----------------------------------------------------------------
14
15/* Option 1: require authentication to access the database. */
16
17//define("SQLITE_FILE", "./mydatabase.sqlite");
18//define("SQLITE_USER", "myuser"); // put here any username you like.
19//define("SQLITE_PASSWORD", md5("mypassword")); // md5 hash here, not plain text.
20
21/* Option 2: do not require any authentication, use it with caution. */
22
23//define("SQLITE_FILE", "./mydatabase.sqlite");
24//define("SQLITE_INSECURE", 1);
25
26/* Option 3: define above constants in a separate file */
27
28// Create a php file in which you define these constants and then
29// include "./dbkiss.php" file. In future, when you update to a new
30// version of dbkiss script, you won't have to edit dbkiss file again.
31
32// ----------------------------------------------------------------
33// SQLite optional.
34// ----------------------------------------------------------------
35
36/* This option says that for big files on tables list an estimation of records
37 will be displayed, instead of doing COUNT(*), cause it could slow down application
38 significantly. Estimation means that MAX(rowid) will be used instead, which
39 may be inaccurate when some records in the table has been deleted. When you enter
40 the table view, then precise counting is always done. */
41
42//define("SQLITE_ESTIMATE_COUNT", 50*1024*1024); // This is the default (50 MB).
43
44// ----------------------------------------------------------------
45// DBKISS_SQL directory.
46// ----------------------------------------------------------------
47
48// Some of the features in the SQL Editor require creating 'dbkiss_sql' directory,
49// where history of queries are kept and other data. If the script has permission
50// it will create that directory automatically, otherwise you need to create that
51// directory manually and make it writable. You can also set it to empty '' string,
52// but some of the features in the sql editor will not work (templates, pagination)
53
54if (!defined('DBKISS_SQL_DIR')) {
55 define('DBKISS_SQL_DIR', 'zzz_sql');
56}
57
58// ----------------------------------------------------------------
59// Auto connection script for MySQL and PostgreSQL
60// ----------------------------------------------------------------
61
62// An example configuration script that will automatically connect to localhost database.
63// This is useful on localhost if you don't want to see the "Connect" screen.
64
65// "mysql_local.php" source below:
66
67/*
68 define('COOKIE_PREFIX', str_replace('.php', '', basename(__FILE__)).'_');
69 define('DBKISS_SQL_DIR', 'dbkiss_mysql');
70 $cookie = array(
71 'db_driver' => 'mysql',
72 'db_server' => 'localhost',
73 'db_name' => 'test',
74 'db_user' => 'root',
75 'db_pass' => 'toor',
76 'db_charset' => 'latin2',
77 'page_charset' => 'iso-8859-2',
78 'remember' => 1
79 );
80 foreach ($cookie as $k => $v) {
81 if ('db_pass' == $k) { $v = base64_encode($v); }
82 $k = COOKIE_PREFIX.$k;
83 if (!isset($_COOKIE[$k])) {
84 $_COOKIE[$k] = $v;
85 }
86 }
87 require './dbkiss.php';
88*/
89
90// ----------------------------------------------------------------
91// Popups - width and height.
92// ----------------------------------------------------------------
93
94define("SQL_POPUP_WIDTH", 800);
95define("SQL_POPUP_HEIGHT", 600);
96
97define("EDITROW_POPUP_WIDTH", 620);
98define("EDITROW_POPUP_HEIGHT", 600);
99
100// ----------------------------------------------------------------
101// CHANGELOG
102// ----------------------------------------------------------------
103
104/*
105
1062.00
107* Support for SQLite file databases was added. To use it edit dbkiss.php file and add 3 constants
108 at the top of the file: SQLITE_FILE, SQLITE_USER, SQLITE_PASSWORD. Sqlite requires "pdo_sqlite" extension.
109* User interface has a new modern look now.
110* CSRF protection using Origin header, currently only Chrome browser supports this featue - other browsers are not protected.
111* Postgresql bug fixed: case sensitivity in table names and columns is now supported, identifiers are now enquoted with double quotes.
112* Mysql bug fixed: column names are now enquoted with backticks, table names have already been backticked.
113* Mysql enhancement: SHOW syntax is treated the same as SELECT in SQL editor
114* SQL editor minor enhancements, better wrapping in data view, full_content is calling nl2br by default
115* Export All: includes Views declarations now.
116* Editing row: you can use natural time strings when editing fields of type INT and TIMESTAMP, TIME.
117 Natural time strings are: "Yesterday 11:00", "+5 days" and many more, click "Help" to see all
118 supported syntax. In fields of type INT an unix timestamp will be generated.
119* Fixed a bug that broke listing in table view when colored search phrase inside an anchor tag.
120* Bug fixed: when changed sorting the old offset of the paging was kept.
121* Mysql and postgresql connection timeouts are set to 3 seconds so that a meaningfull error message is displayed now if timeout.
122* Fixed bug: column sorting in table view was case sensitive, it now uses LOWER(column_name) in ORDER BY.
123* Table names and column names are now allowed to start with numeric values ex. `62-511` or `62`
124
1251.11
126* Links in data output are now clickable. Clicking them does not reveal the location of your dbkiss script to external sites.
127
1281.10
129* Support for views in Postgresql (mysql had it already).
130* Views are now displayed in a seperate listing, to the right of the tables on main page.
131* 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.
132
1331.09
134* CSV export in sql editor and table view (feature sponsored by Patrick McGovern)
135
1361.08
137* date.timezone E_STRICT error fixed
138
1391.07
140* mysql tables with dash in the name generated errors, now all tables in mysql driver are
141 enquoted with backtick.
142
1431.06
144* postgresql fix
145
1461.05
147* export of all structure and data does take into account the table name filter on the main page,
148 so you can filter the tables that you want to export.
149
1501.04
151* exporting all structure/data didn't work (ob_gzhandler flush bug)
152* cookies are now set using httponly option
153* text editor complained about bad cr/lf in exported sql files
154 (mysql create table uses \n, so insert queries need to be seperated by \n and not \r\n)
155
1561.03
157* re-created array_walk_recursive for php4 compatibility
158* removed stripping slashes from displayed content
159* added favicon (using base64_encode to store the icon in php code, so it is still one-file database browser)
160
1611.02
162* works with short_open_tag disabled
163* code optimizations/fixes
164* postgresql error fix for large tables
165
1661.01
167* fix for mysql 3.23, which doesnt understand "LIMIT x OFFSET z"
168
1691.00
170* bug fixes
171* minor feature enhancements
172* this release is stable and can be used in production environment
173
1740.61
175* upper casing keywords in submitted sql is disabled (it also modified quoted values)
176* sql error when displaying table with 0 rows
177* could not connect to database that had upper case characters
178
179*/
180
181// ----------------------------------------------------------------
182// DBKiss internal code from now on - DO NOT EDIT.
183// ----------------------------------------------------------------
184
185ob_start('ob_gzhandler');
186
187// ----------------------------
188// @errorhandler
189// ----------------------------
190
191error_reporting(-1);
192ini_set('display_errors', 1);
193ini_set("html_errors", 0);
194if (!ini_get('date.timezone')) {
195 ini_set('date.timezone', 'Europe/Warsaw');
196}
197if ("127.0.0.1" == $_SERVER["SERVER_ADDR"] && "127.0.0.1" == $_SERVER["REMOTE_ADDR"]) {
198 ini_set("log_errors", 1);
199 ini_set("error_log", "./!phperror.log");
200}
201
202if (ini_get('register_globals')) {
203 header('HTTP/1.0 503 Service Unavailable');
204 exit("ERROR: register_globals is On.");
205}
206
207if (version_compare(PHP_VERSION, '4.3.0', '<')) {
208 header('HTTP/1.0 503 Service Unavailable');
209 exit("ERROR: old php version detected: ".PHP_VERSION.". You need at least 4.3.0.");
210}
211
212set_error_handler('errorHandler');
213register_shutdown_function('errorHandler_last');
214ini_set('display_errors', 1);
215global $Global_LastError;
216
217function errorHandler_last()
218{
219 if (function_exists("error_get_last")) {
220 $error = error_get_last();
221 if ($error) {
222 errorHandler($error['type'], $error['message'], $error['file'], $error['line']);
223 }
224 }
225}
226function errorHandler($errno, $errstr, $errfile, $errline)
227{
228 global $Global_LastError;
229 $Global_LastError = $errstr;
230
231 // Check with error_reporting, if statement is preceded with @ we have to ignore it.
232 if (!($errno & error_reporting())) {
233 return;
234 }
235
236 // Mysql shows error using locale, but it doesn't use UTF-8 charset, some fix for that.
237 $errstr = ConvertPolishToUTF8($errstr);
238
239 // Headers.
240 if (!headers_sent()) {
241 header('HTTP/1.0 503 Service Unavailable');
242 while (ob_get_level()) { ob_end_clean(); } // This will cancel ob_gzhandler, so later we set Content-encoding to none.
243 header('Content-Encoding: none'); // Fix gzip encoding header.
244 header("Content-Type: text/html; charset=utf-8");
245 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
246 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
247 header("Cache-Control: no-store, no-cache, must-revalidate");
248 header("Cache-Control: post-check=0, pre-check=0", false);
249 header("Pragma: no-cache");
250 }
251
252 // Error short message.
253 $errfile = basename($errfile);
254
255 $msg = sprintf('%s<br>In %s on line %d.', nl2br($errstr), $errfile, $errline);
256
257 // Display error.
258
259 printf("<!doctype html><html><head><meta charset=utf-8><title>PHP Error</title>");
260 printf("<meta name=\"robots\" content=\"noindex,nofollow\">");
261 printf("<link rel=\"shortcut icon\" href=\"{$_SERVER['PHP_SELF']}?dbkiss_favicon=1\">");
262 printf("<style type=text/css>");
263 printf("body { font: 11px Tahoma; line-height: 1.4em; padding: 0; margin: 1em 1.5em; }");
264 printf("h1 { font: bold 15px 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; }");
265 print("h2 { font: bold 13px Tahoma; margin-top: 1em; color: #000; text-shadow: 1px 1px 1px #fff; }");
266 printf("</style></head><body>");
267
268 printf("<h1>PHP Error</h1>");
269 printf($msg);
270
271 if ("127.0.0.1" == $_SERVER["SERVER_ADDR"] && "127.0.0.1" == $_SERVER["REMOTE_ADDR"])
272 {
273 // Showing backtrace only on localhost, cause it shows full arguments passed to functions,
274 // that would be a security hole to display such data, cause it could contain some sensitive
275 // data fetched from tables or could even contain a database connection user and password.
276
277 printf("<h2>Backtrace</h2>");
278 ob_start();
279 debug_print_backtrace();
280 $trace = ob_get_clean();
281 $trace = preg_replace("/^#0[\s\S]+?\n#1/", "#1", $trace); // Remove call to errorHandler() from trace.
282 $trace = trim($trace);
283 print nl2br($trace);
284 }
285
286 printf("</body></html>");
287
288 // Log error to file.
289 if ("127.0.0.1" == $_SERVER["SERVER_ADDR"] && "127.0.0.1" == $_SERVER["REMOTE_ADDR"]) {
290 error_log($msg);
291 }
292
293 // Email error.
294
295 exit();
296}
297
298// @erroronconnect
299
300function ConnectError($msg)
301{
302 // Display an error message, use this instead of exit("text...").
303
304 // Mysql shows error using locale, but it doesn't use UTF-8 charset, some fix for that.
305 $msg = ConvertPolishToUTF8($msg);
306
307 printf("<!doctype html><html><head><meta charset=utf-8><title>Connect Error</title>");
308 printf("<meta name=\"robots\" content=\"noindex,nofollow\">");
309 printf("<link rel=\"shortcut icon\" href=\"{$_SERVER['PHP_SELF']}?dbkiss_favicon=1\">");
310 printf("<style type=text/css>");
311 printf("body { font: 11px Tahoma; line-height: 1.4em; padding: 0em; margin: 1em 1.5em; }");
312 printf("h1 { font: bold 15px 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; }");
313 print("h2 { font: bold 13px Tahoma; margin-top: 1em; color: #000; text-shadow: 1px 1px 1px #fff; }");
314 printf("</style></head><body>");
315
316 printf("<h1>Connect Error</h1>");
317 print $msg;
318
319 exit();
320}
321
322// -----------------------------
323// @debug
324// -----------------------------
325
326// You can access this function only on localhost.
327
328if ("127.0.0.1" == $_SERVER["SERVER_ADDR"] && "127.0.0.1" == $_SERVER["REMOTE_ADDR"])
329{
330 function dump($data)
331 {
332 // @dump
333
334 if (!headers_sent()) {
335 header('HTTP/1.0 503 Service Unavailable');
336 while (ob_get_level()) { ob_end_clean(); } // This will cancel ob_gzhandler, so later we set Content-encoding to none.
337 header('Content-encoding: none'); // Fix gzip encoding header.
338 header("Content-type: text/html");
339 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
340 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
341 header("Cache-Control: no-store, no-cache, must-revalidate");
342 header("Cache-Control: post-check=0, pre-check=0", false);
343 header("Pragma: no-cache");
344 }
345
346 if (func_num_args() > 1) { $data = func_get_args(); }
347
348 if ($data && count($data) == 2 && isset($data[1]) && "windows-1250" == strtolower($data[1])) {
349 $charset = "windows-1250";
350 $data = $data[0];
351 } else if ($data && count($data) == 2 && isset($data[1]) && "iso-8859-2" == strtolower($data[1])) {
352 $charset = "iso-8859-2";
353 $data = $data[0];
354 } else {
355 $charset = "utf-8";
356 }
357
358 printf('<!doctype html><head><meta charset='.$charset.'><title>dump()</title></head><body>');
359 printf('<h1 style="color: rgb(150,15,225);">dump()</h1>');
360 ob_start();
361 print_r($data);
362 $html = ob_get_clean();
363 $html = htmlspecialchars($html);
364 printf('<pre>%s</pre>', $html);
365 printf('</body></html>');
366 exit();
367 }
368}
369
370// --------------------
371// @CSRF protection.
372// --------------------
373
374// Currenly only Chrome supports Origin header.
375
376if ("POST" == $_SERVER["REQUEST_METHOD"]) {
377 if (isset($_SERVER["HTTP_ORIGIN"])) {
378 $origin = $_SERVER["HTTP_ORIGIN"];
379 $origin = str_replace("https://", "http://", $origin);
380 $address = "http://".$_SERVER["SERVER_NAME"];
381 if ($_SERVER["SERVER_PORT"] != 80) {
382 $address .= ":".$_SERVER["SERVER_PORT"];
383 }
384 if (strpos($origin, $address) !== 0) {
385 trigger_error("CSRF protection in POST request: detected invalid Origin header: ".$_SERVER["HTTP_ORIGIN"],
386 E_USER_ERROR);
387 exit();
388 }
389 }
390}
391
392// ----------------------------
393// @gpc
394// ----------------------------
395
396function GET($key, $type)
397{
398 // GET("export", "string")
399 // is an equivalent of:
400 // $_GET["export"] = isset($_GET["export"]) ? (string) $_GET["export"] : "";
401
402 if ("string" == $type) {
403 $_GET[$key] = isset($_GET[$key]) ? (string) $_GET[$key] : "";
404 } else if ("int" == $type) {
405 $_GET[$key] = isset($_GET[$key]) ? (int) $_GET[$key] : 0;
406 } else if ("bool" == $type) {
407 $_GET[$key] = isset($_GET[$key]) ? (bool) $_GET[$key] : false;
408 } else if ("array" == $type) {
409 $_GET[$key] = isset($_GET[$key]) ? (array) $_GET[$key] : array();
410 } else {
411 trigger_error("GET() failed: key=$key, type=$type", E_USER_ERROR);
412 }
413 return $_GET[$key];
414}
415function POST($key, $type)
416{
417 // POST("export", "string")
418 // is an equivalent of:
419 // $_POST["export"] = isset($_POST["export"]) ? (string) $_POST["export"] : "";
420
421 if ("string" == $type) {
422 $_POST[$key] = isset($_POST[$key]) ? (string) $_POST[$key] : "";
423 } else if ("int" == $type) {
424 $_POST[$key] = isset($_POST[$key]) ? (int) $_POST[$key] : 0;
425 } else if ("bool" == $type) {
426 $_POST[$key] = isset($_POST[$key]) ? (bool) $_POST[$key] : false;
427 } else if ("array" == $type) {
428 $_POST[$key] = isset($_POST[$key]) ? (array) $_POST[$key] : array();
429 } else {
430 trigger_error("POST() failed: key=$key, type=$type", E_USER_ERROR);
431 }
432 return $_POST[$key];
433}
434
435// ----------------------------
436// @favicon
437// ----------------------------
438
439GET("dbkiss_favicon", "bool");
440
441if ($_GET['dbkiss_favicon'])
442{
443 if (defined("SQLITE_FILE")) {
444 $favicon = 'AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAMztMwDM7TMAzO0zAMztMwDM7TIAye82BsT3NgjC+joKv/47C7//Owu//zoKv/42CML6jJkAj4yZACAAAAAAMwDM7TMAzO0zAMztMwDM7TYGx/U7C7//PxDC/6CH3v//////QxHC/0QSxP9CEsf/QRLE/9nQMP+bpgX/jJkAcDMAzO3//////////5+H6PY7C7//oIjj////////////QxG//////////////////0ISx///7Ur/+usb/4yZAP8zAMztMwDM7TMAzO3/////Owu///////9DEcL//////0MRv///////RBLE/0ISx/9CEsf//+1K///wHP+MmQD/MwDM7TMAzO3/////MwDM7TsLv///////QxHC//////9FEb///////0URv/9FEb//RRG////YKf//7Bf/jJkA/zMAzO3/////MwDM7TMAzO07C7///////0ANv///////Owu///////87C7//Owu//z0Nv//HswD/8r4C/6OmAP8zAMztn4fo9v//////////Owu//5uF3v//////oIfe/0MRv///////RBLE/0ISx/9AEMT/yccw/5ahBf+rqAD/MwDM7TMAzO0zAMztMwDM7TsLv/9CEsf/QxHC/0MRv/9DEb//QxHC/0QSxP9CEsf/QhLH/+bYSf/Rzhv/jJkA/wAAAAAAAAAAAAAAAAAAAACMmQD//+eF///tTP//7xT//+8U///rO///6mP//+iM//XgeP/m2En/1tMe/4yZAP8AAAAAAAAAAAAAAAAAAAAAjJkA///nhf//7Uz//+8U///vFP//6zv//+pj///ojP/14Hj/5thJ/9bTHv+MmQD/AAAAAAAAAAAAAAAAAAAAAIyZAP/65HX/29Uf/7/CBP+lrQD/mKMA/4yZAP+MmQD/maMP/7K1Gf/PzBn/jJkA/wAAAAAAAAAAAAAAAAAAAACMmQD/1tYp/+vpmP/38L7///DC///pqP//5pn//+aZ//Lchf/ZzV//oagU/4yZAP8AAAAAAAAAAAAAAAAAAAAAjJkA//z88P///PL///XZ///wwv//6aj//+aZ///mmf//5pn//+aZ//rjjv+MmQD/AAAAAAAAAAAAAAAAAAAAAIyZAO/4+vD///zy///12f//8ML//+mo///mmf//5pn//+aZ///mmf/6447/jJkA/wAAAAAAAAAAAAAAAAAAAACMmQBgoqsn/9fZmP/68cD///DC///pqP//5pn//+aZ//fgjf/ZzV//o6sW/4yZAGAAAAAAAAAAAAAAAAAAAAAAAAAAAIyZACCMmQCPjJkAv4yZAP+MmQD/jJkA/4yZAP+MmQC/jJkAj4yZACAAAAAAAAGsQQAArEEAAKxBAACsQQAArEEAAKxBAACsQQAArEHwAKxB8ACsQfAArEHwAKxB8ACsQfAArEHwAKxB+AGsQQ==';
445 } else {
446 $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';
447 }
448 header('Content-type: image/vnd.microsoft.icon');
449 echo base64_decode($favicon);
450 exit();
451}
452
453// ----------------------------
454// @sqlite CHECKS
455// ----------------------------
456
457// Do all the initial checks for the sqlite database.
458
459SQLite_DoChecks();
460
461function SQLite_DoChecks()
462{
463 if (defined("SQLITE_FILE") || defined("SQLITE_USER") || defined("SQLITE_PASSWORD") || defined("SQLITE_INSECURE"))
464 {
465 // Verify all required constants are defined.
466
467 if (!defined("SQLITE_FILE")) {
468 trigger_error("SQLITE_FILE is not defined.", E_USER_ERROR);
469 }
470
471 if (defined("SQLITE_INSECURE"))
472 {
473 if (defined("SQLITE_USER") || defined("SQLITE_PASSWORD")) {
474 trigger_error("SQLITE_INSECURE is defined, but SQLITE_USER and SQLITE_PASSWORD have also been defined - that is not allowed.", E_USER_ERROR);
475 }
476 if (!SQLITE_INSECURE) {
477 trigger_error("SQLITE_INSECURE has been set to 0 - that is an invalid use of this constant, you can only set it to 1 or do not define it at all.", E_USER_ERROR);
478 }
479 }
480 else
481 {
482 if (!defined("SQLITE_USER")) {
483 trigger_error("SQLITE_USER is not defined.", E_USER_ERROR);
484 }
485 if (!defined("SQLITE_PASSWORD")) {
486 trigger_error("SQLITE_PASSWORD is not defined.", E_USER_ERROR);
487 }
488 }
489
490 // Check whether the PDO and PDO_SQLITE extensions are loaded.
491
492 if (!extension_loaded("pdo")) {
493 trigger_error("PDO extension is not loaded", E_USER_ERROR);
494 }
495 if (!extension_loaded("pdo_sqlite")) {
496 trigger_error("PDO_SQLITE extension is not loaded.", E_USER_ERROR);
497 }
498
499 // User and password cannot use the default values provided in the example.
500
501 if (defined("SQLITE_INSECURE"))
502 {
503 // No authentication required.
504 // No check required here.
505 }
506 else
507 {
508 if (!trim(SQLITE_USER)) {
509 trigger_error("SQLITE_USER cannot be empty.", E_USER_ERROR);
510 }
511
512 if (SQLITE_USER == "myuser") {
513 trigger_error("SQLITE: you cannot use the default username `myuser`, change it to some other name.", E_USER_ERROR);
514 }
515 if (SQLITE_PASSWORD == "34819d7beeabb9260a5c854bc85b3e44") {
516 trigger_error("SQLITE: you cannot use the default md5 hash of a password that was provided with the example.", E_USER_ERROR);
517 }
518 if (strlen(SQLITE_PASSWORD) != 32) {
519 trigger_error("SQLITE: the length of md5 hash of a password defined in SQLITE_PASSWORD is not 32 chars, this is not a valid m5 hash.", E_USER_ERROR);
520 }
521 }
522
523 // Whether database file exists and is readable/writable.
524 // The file does not have to exist - if it does not exist sqlite will create a new database.
525
526 if (is_dir(SQLITE_FILE)) {
527 trigger_error("SQLITE_FILE is a directory.", E_USER_ERROR);
528 }
529
530 if (file_exists(SQLITE_FILE))
531 {
532 if (!is_readable(SQLITE_FILE)) {
533 trigger_error("SQLITE_FILE is not readable.", E_USER_ERROR);
534 }
535 if (!is_writable(SQLITE_FILE)) {
536 trigger_error("SQLITE_FILE is not writable.", E_USER_ERROR);
537 }
538 }
539
540 // The directory containing the file must be writable.
541 if (!is_writable(dirname(SQLITE_FILE))) {
542 trigger_error("SQLITE_FILE directory must be writable.", E_USER_ERROR);
543 }
544
545 // Optional constants, default values.
546
547 if (!defined("SQLITE_ESTIMATE_COUNT")) {
548 define("SQLITE_ESTIMATE_COUNT", 50*1024*1024);
549 }
550
551 // A constant for sqlite-enabled detection used later in the script.
552
553 define("SQLITE_USED", 1);
554 }
555 else
556 {
557 define("SQLITE_USED", 0);
558 }
559}
560
561// --------------------------
562// @pdo
563// --------------------------
564
565// Remember about slow INSERTs in SQLite when not in transaction.
566
567function PDO_Connect($dsn, $user="", $password="")
568{
569 global $PDO;
570 $PDO = new PDO($dsn, $user, $password);
571 $PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
572}
573function PDO_FetchOne($query, $params=null)
574{
575 global $PDO;
576 if (isset($params)) {
577 $stmt = $PDO->prepare($query);
578 $stmt->execute($params);
579 } else {
580 $stmt = $PDO->query($query);
581 }
582 $row = $stmt->fetch(PDO::FETCH_NUM);
583 if ($row) {
584 return $row[0];
585 } else {
586 return false;
587 }
588}
589function PDO_FetchRow($query, $params=null)
590{
591 global $PDO;
592 if (isset($params)) {
593 $stmt = $PDO->prepare($query);
594 $stmt->execute($params);
595 } else {
596 $stmt = $PDO->query($query);
597 }
598 return $stmt->fetch(PDO::FETCH_ASSOC);
599}
600function PDO_FetchAll($query, $params=null)
601{
602 global $PDO;
603 if (isset($params)) {
604 $stmt = $PDO->prepare($query);
605 $stmt->execute($params);
606 } else {
607 $stmt = $PDO->query($query);
608 }
609 return $stmt->fetchAll(PDO::FETCH_ASSOC);
610}
611function PDO_FetchAssoc($query, $params=null)
612{
613 global $PDO;
614 if (isset($params)) {
615 $stmt = $PDO->prepare($query);
616 $stmt->execute($params);
617 } else {
618 $stmt = $PDO->query($query);
619 }
620 $rows = $stmt->fetchAll(PDO::FETCH_NUM);
621 $assoc = array();
622 $columns = null;
623 foreach ($rows as $row) {
624 if (!isset($columns)) {
625 $columns = count($row);
626 }
627 if (1 == $columns) { // When 1 column that is not really an assoc, the array keys are numeric.
628 $assoc[] = $row[0];
629 } else if (2 == $columns) {
630 $assoc[$row[0]] = $row[1];
631 } else {
632 $assoc[$row[0]] = $row;
633 }
634 }
635 return $assoc;
636}
637function PDO_Execute($query, $params=null)
638{
639 global $PDO;
640 if (isset($params)) {
641 $stmt = $PDO->prepare($query);
642 $stmt->execute($params);
643 } else {
644 $PDO->query($query);
645 }
646}
647function PDO_InsertId()
648{
649 global $PDO;
650 return $PDO->lastInsertId();
651}
652
653// --------------------------
654// @authenticate SQLITE
655// --------------------------
656
657if (SQLITE_USED)
658{
659 if (defined("SQLITE_INSECURE") && SQLITE_INSECURE)
660 {
661 // Do not require any authentication.
662 assert(!defined("SQLITE_USER") && !defined("SQLITE_PASSWORD"));
663 }
664 else
665 {
666 assert(!defined("SQLITE_INSECURE"));
667
668 define("HT_USER", SQLITE_USER);
669 define("HT_PASSWORD", SQLITE_PASSWORD);
670
671 define("HT_PATH", "");
672 define("HT_DOMAIN", "");
673
674 define("HT_PREFIX", "");
675 define("HT_SECURE", false);
676
677 ht_controller();
678 }
679}
680
681function ht_controller()
682{
683 if (isset($_GET['ht_logout']) && $_GET['ht_logout']) {
684 ht_logout();
685 }
686 if (ht_authorize()) {
687 return 1;
688 }
689 ht_authenticate();
690 exit();
691}
692function ht_user()
693{
694 // To display username on site.
695
696 if (isset($_COOKIE['ht_user']) && HT_USER == $_COOKIE['ht_user']) {
697 return $_COOKIE['ht_user'];
698 }
699}
700function ht_authorize()
701{
702 $c_user = isset($_COOKIE['ht_user']) ? $_COOKIE['ht_user'] : null;
703 $c_password = isset($_COOKIE['ht_password']) ? $_COOKIE['ht_password'] : null;
704
705 if (HT_USER == $c_user && HT_PASSWORD == $c_password) {
706 return 1;
707 } else {
708 return 0;
709 }
710}
711function ht_logout()
712{
713 $time = time() - 3600*48;
714 if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
715 setcookie(HT_PREFIX.'ht_user', '', $time, HT_PATH, HT_DOMAIN, HT_SECURE, true);
716 setcookie(HT_PREFIX.'ht_password', '', $time, HT_PATH, HT_DOMAIN, HT_SECURE, true);
717 } else {
718 setcookie(HT_PREFIX.'ht_user', '', $time, HT_PATH, HT_DOMAIN, HT_SECURE);
719 setcookie(HT_PREFIX.'ht_password', '', $time, HT_PATH, HT_DOMAIN, HT_SECURE);
720 }
721 unset($_COOKIE['ht_user']);
722 unset($_COOKIE['ht_password']);
723
724 $loc = $_SERVER['REQUEST_URI'];
725 $loc = preg_replace('#[\?\&]ht\_logout=1#', '', $loc);
726 if (isset($_SERVER['HTTP_REFERER'])) {
727 $loc = $_SERVER['HTTP_REFERER'];
728 }
729 header('Location: '.$loc);
730
731 exit();
732}
733function ht_authenticate()
734{
735 $p_user = isset($_POST['ht_user']) ? $_POST['ht_user'] : null;
736 $p_password = isset($_POST['ht_password']) ? $_POST['ht_password'] : null;
737 $p_remember = isset($_POST['ht_remember']) ? (bool) $_POST['ht_remember'] : null;
738 $p_referer = isset($_POST['ht_referer']) ? $_POST['ht_referer'] : null;
739
740 if ('POST' == $_SERVER['REQUEST_METHOD']) {
741 if (strtolower($p_user) == strtolower(HT_USER) && md5($p_password) == HT_PASSWORD) {
742 $time = 0;
743 if ($p_remember) {
744 $time = time() + 3600*24*14;
745 }
746 if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
747 setcookie(HT_PREFIX.'ht_user', HT_USER, $time, HT_PATH, HT_DOMAIN, HT_SECURE, true);
748 setcookie(HT_PREFIX.'ht_password', md5($p_password), $time, HT_PATH, HT_DOMAIN, HT_SECURE, true);
749 } else {
750 setcookie(HT_PREFIX.'ht_user', HT_USER, $time, HT_PATH, HT_DOMAIN, HT_SECURE);
751 setcookie(HT_PREFIX.'ht_password', md5($p_password), $time, HT_PATH, HT_DOMAIN, HT_SECURE);
752 }
753 header('Location: '.$p_referer);
754 exit();
755 }
756 } else {
757 $p_referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
758 if (!$p_referer) {
759 $p_referer = $_SERVER['REQUEST_URI'];
760 }
761
762 }
763
764 ht_loginform(array(
765 "p_referer" => $p_referer,
766 "p_user" => $p_user,
767 "p_remember" => $p_remember
768 ));
769
770 exit();
771}
772function ht_loginform($vars)
773{
774 extract($vars, EXTR_SKIP);
775?>
776 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
777 <html>
778 <head>
779 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
780 <meta name="robots" content="noindex, nofollow">
781 <title>SQLite authentication</title>
782 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
783 <meta name="robots" content="noindex,nofollow">
784 <style type="text/css">
785 body {
786 font: 11px Tahoma;
787 line-height: 1.4em;
788 }
789 input {
790 font: 11px Tahoma;
791 }
792 body {
793 margin: 1em 1.5em;
794 padding: 0em;
795 }
796 h1 {
797 font: bold 15px Tahoma;
798 text-shadow: 1px 1px 1px #fff;
799 color: #000;
800 margin-bottom: 0.85em;
801 border-bottom: #999 1px solid;
802 padding-bottom: 0.25em;
803 }
804 div.submit {
805 margin-top: 1em;
806 }
807 div.error {
808 margin: 1em 0em;
809 color: rgb(225,0,0);
810 }
811 div.remember {
812 margin-top: 0.5em;
813 }
814 </style>
815 </head>
816 <body>
817
818 <h1>SQLite authentication</h1>
819
820 <?php if ('POST' == $_SERVER['REQUEST_METHOD']): ?>
821 <div class="error">
822 Invalid credentials provided. Try again.
823 </div>
824 <?php endif; ?>
825
826 <form action="<?php echo strip_tags($_SERVER['REQUEST_URI']); ?>" method="post">
827 <input type="hidden" name="ht_referer" value="<?php echo htmlspecialchars($p_referer); ?>">
828 <label>User:</label>
829 <div><input type="text" name="ht_user" id="ht_user" value="<?php echo htmlspecialchars($p_user); ?>"></div>
830 <label>Password:</label>
831 <div><input type="password" name="ht_password" id="ht_password" value=""></div>
832 <div class="remember">
833 <input type="checkbox" name="ht_remember" id="ht_remember"
834 value="1" <?php if ($p_remember): ?>checked="checked"<?php endif; ?>>
835 <label for="ht_remember">remember me (2 weeks)</label>
836 </div>
837 <div class="submit">
838 <input class="button" type="submit" value="Log in">
839 </div>
840 </form>
841
842 <script>
843 window.onload = function()
844 {
845 var user = document.getElementById('ht_user');
846 var password = document.getElementById('ht_password');
847 if (user.value.length) {
848 password.focus();
849 } else {
850 user.focus();
851 }
852 }
853 </script>
854
855 </body>
856 </html>
857
858<?php
859}
860
861// ------------------------------
862// @html
863// ------------------------------
864
865function AttributeValue($value)
866{
867 // Html attribute's value cannot contain double quotes and sometimes
868 // even single quotes, so we remove them both.
869 return str_replace(array("\"", "'"), array("", ""), $value);
870}
871if (!function_exists('array_walk_recursive'))
872{
873 function array_walk_recursive(&$array, $func)
874 {
875 foreach ($array as $k => $v) {
876 if (is_array($v)) {
877 array_walk_recursive($array[$k], $func);
878 } else {
879 $func($array[$k], $k);
880 }
881 }
882 }
883}
884function create_links($text)
885{
886 // Protocols: http, https, ftp, irc, svn
887 // Parse emails also?
888
889 $text = preg_replace('#([a-z]+://[a-zA-Z0-9\.\,\;\:\[\]\{\}\-\_\+\=\!\@\#\%\&\(\)\/\?\`\~]+)#e', 'create_links_eval("\\1")', $text);
890
891 // Excaptions:
892
893 // 1) cut last char if link ends with ":" or ";" or "." or "," - cause in 99% cases that char doesnt belong to the link
894 // (check if previous char was "=" then let it stay cause that could be some variable in a query, some kind of separator)
895 // (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?)
896
897 // 2) brackets, the link could be inside one of 3 types of brackets:
898 // [http://...] , {http://...}
899 // and most common: (http://some.com/) OR http://some.com(some description of the link)
900 // In these cases regular expression will catch: "http://some.com/)" AND "http://some.com(some"
901 // 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:
902 // We will not cut brackets in this link: http://en.wikipedia.org/wiki/Common_(entertainer) - wikipedia often uses brackets.
903
904 return $text;
905}
906function create_links_eval($link)
907{
908 $orig_link = $link;
909 $cutted = "";
910
911 if (in_array($link[strlen($link)-1], array(":", ";", ".", ","))) {
912 $link = substr($link, 0, -1);
913 $cutted = $orig_link[strlen($orig_link)-1];
914 }
915
916 if (($pos = strpos($link, "(")) !== false) {
917 if (strpos($link, ")") === false) {
918 $link = substr($link, 0, $pos);
919 $cutted = substr($orig_link, $pos);
920 }
921 } else if (($pos = strpos($link, ")")) !== false) {
922 if (strpos($link, "(") === false) {
923 $link = substr($link, 0, $pos);
924 $cutted = substr($orig_link, $pos);
925 }
926 } else if (($pos = strpos($link, "[")) !== false) {
927 if (strpos($link, "]") === false) {
928 $link = substr($link, 0, $pos);
929 $cutted = substr($orig_link, $pos);
930 }
931 } else if (($pos = strpos($link, "]")) !== false) {
932 if (strpos($link, "[") === false) {
933 $link = substr($link, 0, $pos);
934 $cutted = substr($orig_link, $pos);
935 }
936 } else if (($pos = strpos($link, "{")) !== false) {
937 if (strpos($link, "}") === false) {
938 $link = substr($link, 0, $pos);
939 $cutted = substr($orig_link, $pos);
940 }
941 } else if (($pos = strpos($link, "}")) !== false) {
942 if (strpos($link, "{") === false) {
943 $link = substr($link, 0, $pos);
944 $cutted = substr($orig_link, $pos);
945 }
946 }
947 return "<a title=\"$link\" style=\"color: #000; text-decoration: none; border-bottom: #000 1px dotted;\" href=\"javascript:;\" onclick=\"link_noreferer('$link')\">$link</a>$cutted";
948}
949function truncate_html($string, $length, $break_words = false, $end_str = '..')
950{
951 // Does not break html tags whilte truncating, does not take into account chars inside tags: <b>a</b> = 1 char length.
952 // Break words is always TRUE - no breaking is not implemented.
953
954 // Limits: no handling of <script> tags.
955
956 $inside_tag = false;
957 $inside_amp = 0;
958 $finished = false; // finished but the loop is still running cause inside tag or amp.
959 $opened = 0;
960
961 $string_len = strlen($string);
962
963 $count = 0;
964 $ret = "";
965
966 for ($i = 0; $i < $string_len; $i++)
967 {
968 $char = $string[$i];
969 $nextchar = isset($string[$i+1]) ? $string[$i+1] : null;
970
971 if ('<' == $char && ('/' == $nextchar || ctype_alpha($nextchar))) {
972 if ('/' == $nextchar) {
973 $opened--;
974 } else {
975 $opened++;
976 }
977 $inside_tag = true;
978 }
979 if ('>' == $char) {
980 $inside_tag = false;
981 $ret .= $char;
982 continue;
983 }
984 if ($inside_tag) {
985 $ret .= $char;
986 continue;
987 }
988
989 if (!$finished)
990 {
991 if ('&' == $char) {
992 $inside_amp = 1;
993 $ret .= $char;
994 continue;
995 }
996 if (';' == $char && $inside_amp) {
997 $inside_amp = 0;
998 $count++;
999 $ret .= $char;
1000 continue;
1001 }
1002 if ($inside_amp) {
1003 $inside_amp++;
1004 $ret .= $char;
1005 if ('#' == $char || ctype_alnum($char)) {
1006 if ($inside_amp > 7) {
1007 $count += $inside_amp;
1008 $inside_amp = 0;
1009 }
1010 } else {
1011 $count += $inside_amp;
1012 $inside_amp = 0;
1013 }
1014 continue;
1015 }
1016 }
1017
1018 $count++;
1019
1020 if (!$finished) {
1021 $ret .= $char;
1022 }
1023
1024 if ($count >= $length) {
1025 if (!$inside_tag && !$inside_amp) {
1026 if (!$finished) {
1027 $ret .= $end_str;
1028 $finished = true;
1029 if (0 == $opened) {
1030 break;
1031 }
1032 }
1033 if (0 == $opened) {
1034 break;
1035 }
1036 }
1037 }
1038 }
1039 return $ret;
1040}
1041function html_spaces($string)
1042{
1043 $inside_tag = false;
1044 for ($i = 0; $i < strlen($string); $i++)
1045 {
1046 $c = $string{$i};
1047 if ('<' == $c) {
1048 $inside_tag = true;
1049 }
1050 if ('>' == $c) {
1051 $inside_tag = false;
1052 }
1053 if (' ' == $c && !$inside_tag) {
1054 $string = substr($string, 0, $i).' '.substr($string, $i+1);
1055 $i += strlen(' ')-1;
1056 }
1057 }
1058 return $string;
1059}
1060function html_once($s)
1061{
1062 $s = str_replace(array('<','>','&lt;','&gt;'),array('<','>','<','>'),$s);
1063 return str_replace(array('<','>','<','>'),array('&lt;','&gt;','<','>'),$s);
1064}
1065function str_truncate($string, $length, $etc = ' ..', $break_words = true)
1066{
1067 if ($length == 0) {
1068 return '';
1069 }
1070 if (strlen($string) > $length + strlen($etc)) {
1071 if (!$break_words) {
1072 $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
1073 }
1074 return substr($string, 0, $length) . $etc;
1075 }
1076 return $string;
1077}
1078function options($options, $selected = null, $ignore_type = false)
1079{
1080 $ret = '';
1081 foreach ($options as $k => $v) {
1082 //str_replace('"', '\"', $k)
1083 $ret .= '<option value="'.$k.'"';
1084 if ((is_array($selected) && in_array($k, $selected)) || (!is_array($selected) && $k == $selected && $selected !== '' && $selected !== null)) {
1085 if ($ignore_type) {
1086 $ret .= ' selected="selected"';
1087 } else {
1088 if (!(is_numeric($k) xor is_numeric($selected))) {
1089 $ret .= ' selected="selected"';
1090 }
1091 }
1092 }
1093 $ret .= '>'.$v.' </option>';
1094 }
1095 return $ret;
1096}
1097function checked($bool)
1098{
1099 if ($bool) return 'checked="checked"';
1100}
1101function radio_assoc($checked, $assoc, $input_name, $link = false)
1102{
1103 $ret = '<table cellspacing="0" cellpadding="0"><tr>';
1104 foreach ($assoc as $id => $name)
1105 {
1106 $params = array(
1107 'id' => $id,
1108 'name' => $name,
1109 'checked' => checked($checked == $id),
1110 'input_name' => $input_name
1111 );
1112 if ($link) {
1113 if (is_array($link)) {
1114 $params['link'] = $link[$id];
1115 } else {
1116 $params['link'] = sprintf($link, $id, $name);
1117 }
1118 $ret .= sprintf('<td><input class="checkbox" type="radio" name="%s" id="%s_%s" value="%s" %s></td><td>%s </td>', $params["input_name"], $params["input_name"], $params["id"], $params["id"], $params["checked"], $params["link"]);
1119 } else {
1120 $ret .= sprintf('<td><input class="checkbox" type="radio" name="%s" id="%s_%s" value="%s" %s></td><td><label for="%s_%s">%s</label> </td>', $params["input_name"], $params["input_name"], $params["id"], $params["id"], $params["checked"], $params["input_name"], $params["id"], $params["name"]);
1121 }
1122 }
1123 $ret .= '</tr></table>';
1124 return $ret;
1125}
1126function str_wrap($s, $width, $break = ' ', $omit_tags = false)
1127{
1128 //$restart = array(' ', "\t", "\r", "\n");
1129
1130 if (!isset($_GET["full_content"]) || !isset($_POST["content"])) {
1131 GET("full_content", "bool");
1132 POST("full_content", "bool");
1133 }
1134
1135 $full_content = ($_GET["full_content"] || $_POST["full_content"]);
1136
1137 if ($full_content) {
1138 // If full_content then after wrapping, nl2br() will be called.
1139 $restart = array("\r", "\n");
1140 } else {
1141 $restart = array();
1142 }
1143 $cnt = 0;
1144 $ret = '';
1145 $open_tag = false;
1146 $inside_link = false;
1147
1148 $A = ord("A");
1149 $Z = ord("Z");
1150
1151 for ($i=0; $i<strlen($s); $i++)
1152 {
1153 $char = $s[$i];
1154 $nextchar = isset($s[$i+1]) ? $s[$i+1] : null;
1155 $nextchar2 = isset($s[$i+2]) ? $s[$i+2] : null;
1156
1157 if ($omit_tags)
1158 {
1159 if ($char == '<') {
1160 $open_tag = true;
1161 if ('a' == $nextchar) {
1162 $inside_link = true;
1163 } else if ('/' == $nextchar && 'a' == $nextchar2) {
1164 $inside_link = false;
1165 }
1166 }
1167 if ($char == '>') {
1168 $open_tag = false;
1169 }
1170 if ($open_tag) {
1171 $ret .= $char;
1172 continue;
1173 }
1174 }
1175
1176 if (in_array($char, $restart)) {
1177 $cnt = 0;
1178 } else {
1179 $char_ord = ord($char);
1180 if ($char_ord >= $A && $char_ord <= $Z) {
1181 // uppercase chars are counted as 1.5
1182 $cnt += 1.5;
1183 } else {
1184 // lowercase chars are counted as 1
1185 $cnt++;
1186 }
1187 }
1188 $ret .= $char;
1189 if ($cnt > $width) {
1190 if (1 || !$inside_link) {
1191 // Inside link, do not break it.
1192 $ret .= $break;
1193 $cnt = 0;
1194 }
1195 }
1196 }
1197 return $ret;
1198}
1199function ColorSearchPhrase($html, $search)
1200{
1201 // Do not replace text inside tags. For example searrching for "html":
1202 // <a href="test.html">Html file</a>
1203 // "test.html" should not be changed in that example.
1204
1205 // We search the string for tags, then replace each of the tag
1206 // with a special unique string, then we replace
1207
1208 if (strstr($html, "<")) {
1209
1210 preg_match_all("#<[^<>]+>#", $html, $matches);
1211 $id = 0;
1212 $uniqueArray = array();
1213
1214 // First we hide all tags by replacing with some unique string.
1215 foreach ($matches[0] as $tag) {
1216 $id++;
1217 $uniqueString = "@@@@@$id@@@@@";
1218 $uniqueArray[$uniqueString] = $tag;
1219 $html = str_replace($tag, $uniqueString, $html);
1220 }
1221
1222 // Than we color the search phrase.
1223 $search = preg_quote($search);
1224 $html = preg_replace('#('.$search.')#i', '<span style="background: #ffff96;">$1</span>', $html);
1225
1226 // We get back all the tags by replacing unique strings with their corresponding tag.
1227 foreach ($uniqueArray as $uniqueString => $tag) {
1228 $html = str_replace($uniqueString, $tag, $html);
1229 }
1230
1231 return $html;
1232
1233 } else {
1234 $search = preg_quote($search);
1235 $html = preg_replace('#('.$search.')#i', '<span style="background: #ffff96;">$1</span>', $html);
1236 return $html;
1237 }
1238}
1239
1240// ~~ @htmlend
1241
1242// --------------------------------
1243// @filter
1244// --------------------------------
1245
1246function table_filter($tables, $filter)
1247{
1248 $filter = trim($filter);
1249 if ($filter) {
1250 foreach ($tables as $k => $table) {
1251 if (!stristr($table, $filter)) {
1252 unset($tables[$k]);
1253 }
1254 }
1255 }
1256 return $tables;
1257}
1258
1259// -------------------------------
1260// @dbquotes
1261// -------------------------------
1262
1263if (ini_get('magic_quotes_gpc')) {
1264 ini_set('magic_quotes_runtime', 0);
1265 array_walk_recursive($_GET, 'db_magic_quotes_gpc');
1266 array_walk_recursive($_POST, 'db_magic_quotes_gpc');
1267 array_walk_recursive($_COOKIE, 'db_magic_quotes_gpc');
1268}
1269function db_magic_quotes_gpc(&$val)
1270{
1271 $val = stripslashes($val);
1272}
1273
1274// -------------------------------
1275// @sqleditor SIZE
1276// -------------------------------
1277
1278$sql_font = 'font: 12px Courier New;';
1279$sql_area = $sql_font.' width: 708px; height: 179px; border: #ccc 1px solid; background: #f9f9f9; padding: 4px 6px; ';
1280$sql_area .= 'border-radius: 4px; box-shadow: 1px 1px 2px #ddd; margin-bottom: 6px;';
1281
1282// -------------------------------
1283// @db_name STYLE
1284// -------------------------------
1285
1286if (!isset($db_name_style)) {
1287 $db_name_style = '';
1288}
1289if (!isset($db_name_h1)) {
1290 $db_name_h1 = '';
1291}
1292
1293// ------------------------------
1294// @cookies
1295// ------------------------------
1296
1297if (!defined('COOKIE_PREFIX')) {
1298 define('COOKIE_PREFIX', 'dbkiss_');
1299}
1300
1301define('COOKIE_WEEK', 604800); // 3600*24*7
1302define('COOKIE_SESS', 0);
1303
1304function cookie_get($key)
1305{
1306 $key = COOKIE_PREFIX.$key;
1307 if (isset($_COOKIE[$key])) return $_COOKIE[$key];
1308 return null;
1309}
1310function cookie_set($key, $val, $time = COOKIE_SESS)
1311{
1312 $key = COOKIE_PREFIX.$key;
1313 $expire = $time ? time() + $time : 0;
1314 if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
1315 setcookie($key, $val, $expire, '', '', false, true);
1316 } else {
1317 setcookie($key, $val, $expire);
1318 }
1319 $_COOKIE[$key] = $val;
1320}
1321function cookie_del($key)
1322{
1323 $key = COOKIE_PREFIX.$key;
1324 if (version_compare(PHP_VERSION, '5.2.0', '>=')) {
1325 setcookie($key, '', time()-3600*24, '', '', false, true);
1326 } else {
1327 setcookie($key, '', time()-3600*24);
1328 }
1329 unset($_COOKIE[$key]);
1330}
1331if (!SQLITE_USED)
1332{
1333 conn_modify('db_name');
1334 conn_modify('db_charset');
1335 conn_modify('page_charset');
1336}
1337function conn_modify($key)
1338{
1339 if (!isset($_GET["from"])) {
1340 GET("from", "string");
1341 }
1342
1343 if (array_key_exists($key, $_GET)) {
1344 cookie_set($key, $_GET[$key], cookie_get('remember') ? COOKIE_WEEK : COOKIE_SESS);
1345 if ($_GET['from']) {
1346 header('Location: '.$_GET['from']);
1347 } else {
1348 header('Location: '.$_SERVER['PHP_SELF']);
1349 }
1350 exit;
1351 }
1352}
1353
1354// --------------------------------
1355// @connection PARAMETERS
1356// --------------------------------
1357
1358if (SQLITE_USED)
1359{
1360 $db_driver = "sqlite";
1361 $db_server = SQLITE_FILE;
1362 $db_name = basename(SQLITE_FILE);
1363 $db_name = preg_replace("#\.\w+$#", "", $db_name);
1364 if (!$db_name) { // Could be ".mydatabase" file.
1365 $db_name = basename(SQLITE_FILE);
1366 }
1367 if (defined("SQLITE_INSECURE")) {
1368 $db_user = "No authentication required.";
1369 } else {
1370 $db_user = SQLITE_USER;
1371 }
1372 $db_pass = "void";
1373 $db_charset = "utf8";
1374 $page_charset = "utf-8";
1375}
1376else
1377{
1378 $db_driver = cookie_get('db_driver');
1379 $db_server = cookie_get('db_server');
1380 $db_name = cookie_get('db_name');
1381 $db_user = cookie_get('db_user');
1382 $db_pass = base64_decode(cookie_get('db_pass'));
1383 $db_charset = cookie_get('db_charset');
1384 $page_charset = cookie_get('page_charset');
1385}
1386
1387$charset1 = array('latin1', 'latin2', 'utf8', 'cp1250');
1388$charset2 = array('iso-8859-1', 'iso-8859-2', 'utf-8', 'windows-1250');
1389$charset1[] = $db_charset;
1390$charset2[] = $page_charset;
1391$charset1 = charset_assoc($charset1);
1392$charset2 = charset_assoc($charset2);
1393
1394$driver_arr = array('mysql', 'pgsql');
1395$driver_arr = array_assoc($driver_arr);
1396
1397function charset_assoc($arr)
1398{
1399 sort($arr);
1400 $ret = array();
1401 foreach ($arr as $v) {
1402 if (!$v) { continue; }
1403 $v = strtolower($v);
1404 $ret[$v] = $v;
1405 }
1406 return $ret;
1407}
1408
1409// --------------------------------
1410// @disconnect
1411// --------------------------------
1412
1413GET("disconnect", "bool");
1414
1415if ($_GET['disconnect'])
1416{
1417 if (SQLITE_USED) {
1418 ht_logout();
1419 }
1420 cookie_del('db_pass');
1421 header('Location: '.$_SERVER['PHP_SELF']);
1422 exit;
1423}
1424
1425// --------------------------------------------
1426// @authenticate MYSQL, PGSQL
1427// --------------------------------------------
1428
1429if (!$db_pass || (!$db_driver || !$db_server || !$db_name || !$db_user))
1430{
1431 assert(!SQLITE_USED);
1432
1433 POST("db_driver", "string");
1434 POST("db_server", "string");
1435 POST("db_name", "string");
1436 POST("db_user", "string");
1437 POST("db_pass", "string");
1438 POST("db_charset", "string");
1439 POST("page_charset", "string");
1440 POST("remember", "bool");
1441
1442 if ('POST' == $_SERVER['REQUEST_METHOD'])
1443 {
1444 $db_driver = $_POST['db_driver'];
1445 $db_server = $_POST['db_server'];
1446 $db_name = $_POST['db_name'];
1447 $db_user = $_POST['db_user'];
1448 $db_pass = $_POST['db_pass'];
1449 $db_charset = $_POST['db_charset'];
1450 $page_charset = $_POST['page_charset'];
1451
1452 if ($db_driver && $db_server && $db_name && $db_user)
1453 {
1454 $db_test = true;
1455 db_connect($db_server, $db_name, $db_user, $db_pass);
1456 if (is_resource($db_link))
1457 {
1458 $time = $_POST['remember'] ? COOKIE_WEEK : COOKIE_SESS;
1459 cookie_set('db_driver', $db_driver, $time);
1460 cookie_set('db_server', $db_server, $time);
1461 cookie_set('db_name', $db_name, $time);
1462 cookie_set('db_user', $db_user, $time);
1463 cookie_set('db_pass', base64_encode($db_pass), $time);
1464 cookie_set('db_charset', $db_charset, $time);
1465 cookie_set('page_charset', $page_charset, $time);
1466 cookie_set('remember', $_POST['remember'], $time);
1467 header('Location: '.$_SERVER['PHP_SELF']);
1468 exit;
1469 }
1470 }
1471 }
1472 else
1473 {
1474 $_POST['db_driver'] = $db_driver;
1475 $_POST['db_server'] = $db_server ? $db_server : 'localhost';
1476 $_POST['db_name'] = $db_name;
1477 $_POST['db_user'] = $db_user;
1478 $_POST['db_charset'] = $db_charset;
1479 $_POST['page_charset'] = $page_charset;
1480 $_POST['db_driver'] = $db_driver;
1481 }
1482 ?>
1483
1484 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
1485 <html>
1486 <head>
1487 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1488 <meta name="robots" content="noindex, nofollow">
1489 <title>Connect</title>
1490 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
1491 </head>
1492 <body>
1493
1494 <?php layout(); ?>
1495
1496 <h1>Connect</h1>
1497
1498 <?php if (isset($db_test) && is_string($db_test)): ?>
1499 <div style="background: #ffffd7; padding: 0.5em; border: #ccc 1px solid; margin-bottom: 1em;">
1500 <span style="color: red; font-weight: bold;">Error:</span>
1501 <?php echo $db_test;?>
1502 </div>
1503 <?php endif; ?>
1504
1505 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
1506 <table class="ls2" cellspacing="1">
1507 <tr>
1508 <th>Driver:</th>
1509 <td><select name="db_driver"><?php echo options($driver_arr, $_POST['db_driver']);?></select></td>
1510 </tr>
1511 <tr>
1512 <th>Server:</th>
1513 <td><input type="text" name="db_server" value="<?php echo $_POST['db_server'];?>"></td>
1514 </tr>
1515 <tr>
1516 <th>Database:</th>
1517 <td><input type="text" name="db_name" value="<?php echo $_POST['db_name'];?>"></td>
1518 </tr>
1519 <tr>
1520 <th>User:</th>
1521 <td><input type="text" name="db_user" value="<?php echo $_POST['db_user'];?>"></td>
1522 </tr>
1523 <tr>
1524 <th>Password:</th>
1525 <td><input type="password" name="db_pass" value=""></td>
1526 </tr>
1527 <tr>
1528 <th>Db charset:</th>
1529 <td><input type="text" name="db_charset" value="<?php echo $_POST['db_charset'];?>" size="10"> (optional)</td>
1530 </tr>
1531 <tr>
1532 <th>Page charset:</th>
1533 <td><input type="text" name="page_charset" value="<?php echo $_POST['page_charset'];?>" size="10"> (optional)</td>
1534 </tr>
1535 <tr>
1536 <td colspan="2" class="none" style="padding: 0; background: none; padding-top: 0.3em;">
1537 <table cellspacing="0" cellpadding="0"><tr><td>
1538 <input type="checkbox" name="remember" id="remember" value="1" <?php echo checked($_POST['remember']);?>></td><td>
1539 <label for="remember">remember me on this computer</label></td></tr></table>
1540 </td>
1541 </tr>
1542 <tr>
1543 <td class="none" colspan="2" style="padding-top: 0.4em;"><input type="submit" value="Connect"></td>
1544 </tr>
1545 </table>
1546 </form>
1547
1548 </body>
1549 </html>
1550
1551 <?php
1552
1553 exit;
1554}
1555
1556// -------------------------------
1557// @connect
1558// -------------------------------
1559
1560if (SQLITE_USED) {
1561 PDO_Connect("sqlite:".SQLITE_FILE);
1562} else {
1563 db_connect($db_server, $db_name, $db_user, $db_pass);
1564}
1565
1566if ($db_charset && "mysql" == $db_driver) {
1567 db_exe("SET NAMES $db_charset");
1568}
1569
1570// -------------------------------
1571// @dump
1572// -------------------------------
1573
1574GET("dump_all", "int");
1575
1576if (1 == $_GET['dump_all']) {
1577 // @structure
1578 dump_all($data = false);
1579}
1580else if (2 == $_GET['dump_all']) {
1581 // @data
1582 dump_all($data = true);
1583}
1584
1585// ------------------------------
1586// @export
1587// ------------------------------
1588
1589GET("dump_table", "string");
1590GET("type", "string");
1591
1592if ($_GET['dump_table']) {
1593 $type = $_GET["type"] ? $_GET["type"] : "table";
1594 dump_table($_GET['dump_table'], $type);
1595}
1596
1597// ------------------------------
1598// @csv
1599// ------------------------------
1600
1601GET("export", "string");
1602GET("query", "string");
1603GET("separator", "string");
1604
1605if ('csv' == $_GET['export']) {
1606 export_csv(base64_decode($_GET['query']), $_GET['separator']);
1607}
1608
1609// ------------------------------
1610// @import PHP
1611// ------------------------------
1612
1613POST("sqlfile", "string");
1614POST("ignore_errors", "bool");
1615POST("transaction", "bool");
1616POST("force_myisam", "bool");
1617POST("query_start", "int");
1618
1619if ($_POST['sqlfile'])
1620{
1621 $files = sql_files_assoc();
1622 if (!isset($files[$_POST['sqlfile']])) {
1623 exit('File not found. md5 = '.$_POST['sqlfile']);
1624 }
1625 $sqlfile = $files[$_POST['sqlfile']];
1626 layout();
1627 echo '<div>Importing: <b>'.$sqlfile.'</b> ('.size(filesize($sqlfile)).')</div>';
1628 echo '<div>Database: <b>'.$db_name.'</b></div>';
1629 flush();
1630 import($sqlfile, $_POST['ignore_errors'], $_POST['transaction'], $_POST['force_myisam'], $_POST['query_start']);
1631 exit;
1632}
1633
1634// -----------------------------
1635// @drop TABLE
1636// -----------------------------
1637
1638POST("drop_table", "string");
1639
1640if ($_POST['drop_table'])
1641{
1642 $drop_table_enq = quote_table($_POST['drop_table']);
1643 db_exe('DROP TABLE '.$drop_table_enq);
1644 header('Location: '.$_SERVER['PHP_SELF']);
1645 exit;
1646}
1647
1648// -----------------------------
1649// @drop VIEW
1650// -----------------------------
1651
1652POST("drop_view", "string");
1653
1654if ($_POST['drop_view'])
1655{
1656 $drop_view_enq = quote_table($_POST['drop_view']);
1657 db_exe('DROP VIEW '.$drop_view_enq);
1658 header('Location: '.$_SERVER['PHP_SELF']);
1659 exit;
1660}
1661
1662// ------------------------------
1663// @connect MYSQL, PGSQL
1664// ------------------------------
1665
1666function db_connect($db_server, $db_name, $db_user, $db_pass)
1667{
1668 // This function is for mysql and postgresql only.
1669 // It is not called when connecting to sqlite.
1670
1671 global $db_driver, $db_link, $db_test;
1672
1673 if (!extension_loaded($db_driver)) {
1674 trigger_error($db_driver.' extension not loaded', E_USER_ERROR);
1675 }
1676
1677 if ('mysql' == $db_driver)
1678 {
1679 // If we do not set the mysql timeout then it timeouts together with php after 30 secs,
1680 // but a php timeout will generate a fatal error, and by using @ we will get no error at all
1681 // and a white page will be displayed.
1682
1683 ini_set("mysql.connect_timeout", 3);
1684
1685 // We do not have to use "@" for mysql_connect, we can just ignore all errors by setting error_reporting to 0.
1686 // This way we do not see a blank page on fatal error.
1687
1688 error_reporting(E_ERROR); // Only Fatal run-time errors.
1689 $db_link = mysql_connect($db_server, $db_user, $db_pass);
1690 error_reporting(-1);
1691
1692 if (!is_resource($db_link)) {
1693 if ($db_test) {
1694 $db_test = 'mysql_connect() failed: '.ConvertPolishToUTF8(db_error());
1695 return;
1696 } else {
1697 cookie_del('db_pass');
1698 cookie_del('db_name');
1699 ConnectError('mysql_connect() failed: '.db_error());
1700 }
1701 }
1702 if (!@mysql_select_db($db_name, $db_link)) {
1703 $error = db_error();
1704 db_close();
1705 if ($db_test) {
1706 $db_test = 'mysql_select_db() failed: '.ConvertPolishToUTF8($error);
1707 return;
1708 } else {
1709 cookie_del('db_pass');
1710 cookie_del('db_name');
1711 ConnectError('mysql_select_db() failed: '.$error);
1712 }
1713 }
1714 }
1715 else if ('pgsql' == $db_driver)
1716 {
1717 $conn = sprintf("host='%s' connect_timeout=3 dbname='%s' user='%s' password='%s'", $db_server, $db_name, $db_user, $db_pass);
1718
1719 error_reporting(E_ERROR); // Only Fatal run-time errors.
1720 $db_link = pg_connect($conn);
1721 error_reporting(-1);
1722
1723 if (!is_resource($db_link)) {
1724 if ($db_test) {
1725 $db_test = db_error();
1726 return;
1727 } else {
1728 cookie_del('db_pass');
1729 cookie_del('db_name');
1730 ConnectError(db_error());
1731 }
1732 }
1733 }
1734 register_shutdown_function('db_cleanup');
1735}
1736function db_cleanup()
1737{
1738 // This func is called only for mysql and postgresql databases,
1739 // sqlite uses a different model.
1740
1741 db_close();
1742}
1743function db_close()
1744{
1745 // This func is called only for mysql and postgresql databases,
1746 // sqlite uses a different model.
1747
1748 global $db_driver, $db_link;
1749
1750 if (is_resource($db_link)) {
1751 if ('mysql' == $db_driver) {
1752 mysql_close($db_link);
1753 }
1754 if ('pgsql' == $db_driver) {
1755 pg_close($db_link);
1756 }
1757 }
1758}
1759function db_query($query, $dat = false)
1760{
1761 global $db_driver, $db_link;
1762
1763 $query = db_bind($query, $dat);
1764
1765 if (!db_is_safe($query)) {
1766 return false;
1767 }
1768
1769 if ("mysql" == $db_driver) {
1770 $rs = mysql_query($query, $db_link);
1771 if (!$rs) {
1772 trigger_error("mysql_query() failed: $query.<br>Error: ".db_error(), E_USER_ERROR);
1773 }
1774 return $rs;
1775 }
1776 else if ("pgsql" == $db_driver) {
1777 $rs = pg_query($db_link, $query);
1778 if (!$rs) {
1779 trigger_error("pg_query() failed: $query.<br>Error: ".db_error(), E_USER_ERROR);
1780 }
1781 return $rs;
1782 }
1783 else if ("sqlite" == $db_driver) {
1784 global $PDO;
1785 $stmt = $PDO->query($query);
1786 return $stmt;
1787 }
1788}
1789function db_is_safe($q, $ret = false)
1790{
1791 // currently only checks UPDATE's/DELETE's if WHERE condition is not missing
1792 $upd = 'update';
1793 $del = 'delete';
1794
1795 $q = ltrim($q);
1796 if (strtolower(substr($q, 0, strlen($upd))) == $upd
1797 || strtolower(substr($q, 0, strlen($del))) == $del) {
1798 if (!preg_match('#\swhere\s#i', $q)) {
1799 if ($ret) {
1800 return false;
1801 } else {
1802 trigger_error(sprintf('db_is_safe() failed. Detected UPDATE/DELETE without WHERE condition. Query: %s.', $q), E_USER_ERROR);
1803 return false;
1804 }
1805 }
1806 }
1807
1808 return true;
1809}
1810function db_exe($query, $dat = false)
1811{
1812 $rs = db_query($query, $dat);
1813 db_free($rs);
1814}
1815function db_one($query, $dat = false)
1816{
1817 $row = db_row_num($query, $dat);
1818 if ($row) {
1819 return $row[0];
1820 } else {
1821 return false;
1822 }
1823}
1824function db_row($query, $dat = false)
1825{
1826 global $db_driver, $db_link;
1827 if ('mysql' == $db_driver)
1828 {
1829 if (is_resource($query)) {
1830 $rs = $query;
1831 return mysql_fetch_assoc($rs);
1832 } else {
1833 $query = db_limit($query, 0, 1);
1834 $rs = db_query($query, $dat);
1835 $row = mysql_fetch_assoc($rs);
1836 db_free($rs);
1837 if ($row) {
1838 return $row;
1839 }
1840 }
1841 return false;
1842 }
1843 else if ('pgsql' == $db_driver)
1844 {
1845 if (is_resource($query) || is_object($query)) {
1846 $rs = $query;
1847 return pg_fetch_assoc($rs);
1848 } else {
1849 $query = db_limit($query, 0, 1);
1850 $rs = db_query($query, $dat);
1851 $row = pg_fetch_assoc($rs);
1852 db_free($rs);
1853 if ($row) {
1854 return $row;
1855 }
1856 }
1857 return false;
1858 }
1859 else if ("sqlite" == $db_driver)
1860 {
1861 global $PDO;
1862 if (is_object($query)) { // PDOStatement object.
1863 $stmt = $query;
1864 return $stmt->fetch(PDO::FETCH_ASSOC);
1865 } else {
1866 $query = db_limit($query, 0, 1);
1867 $stmt = db_query($query, $dat);
1868 $row = $stmt->fetch(PDO::FETCH_ASSOC);
1869 $stmt = null; // db_free
1870 if ($row) {
1871 return $row;
1872 }
1873 }
1874 return false;
1875 }
1876}
1877function db_row_num($query, $dat = false)
1878{
1879 global $db_driver, $db_link;
1880 if ('mysql' == $db_driver)
1881 {
1882 if (is_resource($query)) {
1883 $rs = $query;
1884 return mysql_fetch_row($rs);
1885 } else {
1886 $rs = db_query($query, $dat);
1887 $row = mysql_fetch_row($rs);
1888 db_free($rs);
1889 if ($row) {
1890 return $row;
1891 }
1892 return false;
1893 }
1894 }
1895 else if ('pgsql' == $db_driver)
1896 {
1897 if (is_resource($query) || is_object($query)) {
1898 $rs = $query;
1899 return pg_fetch_row($rs);
1900 } else {
1901 $rs = db_query($query, $dat);
1902 $row = pg_fetch_row($rs);
1903 db_free($rs);
1904 if ($row) {
1905 return $row;
1906 }
1907 return false;
1908 }
1909 }
1910 else if ("sqlite" == $db_driver)
1911 {
1912 if (is_object($query)) {
1913 $stmt = $query;
1914 return $stmt->fetch(PDO::FETCH_NUM);
1915 } else {
1916 $stmt = db_query($query, $dat);
1917 $row = $stmt->fetch(PDO::FETCH_NUM);
1918 $stmt = null; // db_free
1919 if ($row) {
1920 return $row;
1921 }
1922 return false;
1923 }
1924 }
1925}
1926function db_list($query)
1927{
1928 global $db_driver, $db_link;
1929
1930 $rs = db_query($query);
1931 $ret = array();
1932
1933 if ('mysql' == $db_driver) {
1934 while ($row = mysql_fetch_assoc($rs)) {
1935 $ret[] = $row;
1936 }
1937 }
1938 else if ('pgsql' == $db_driver) {
1939 while ($row = pg_fetch_assoc($rs)) {
1940 $ret[] = $row;
1941 }
1942 }
1943 else if ("sqlite" == $db_driver) {
1944 return $rs->fetchAll(PDO::FETCH_ASSOC);
1945 }
1946
1947 db_free($rs);
1948
1949 return $ret;
1950}
1951function db_assoc($query)
1952{
1953 global $db_driver, $db_link;
1954
1955 if ("sqlite" == $db_driver)
1956 {
1957 global $PDO;
1958 $stmt = db_query($query);
1959 $rows = $stmt->fetchAll(PDO::FETCH_NUM);
1960 $assoc = array();
1961 $columns = null;
1962 foreach ($rows as $row) {
1963 if (!isset($columns)) {
1964 $columns = count($row);
1965 }
1966 // Not supporting 1 column, cause that would be incompatible with mysql and pgsql.
1967 // Use instead PDO_FetchAssoc() which supports 1 column as assoc.
1968 if (2 == $columns) {
1969 $assoc[$row[0]] = $row[1];
1970 } else {
1971 $assoc[$row[0]] = $row;
1972 }
1973 }
1974 return $assoc;
1975 }
1976
1977 $rs = db_query($query);
1978 $rows = array();
1979 $num = db_row_num($rs);
1980
1981 if (!is_array($num)) {
1982 return array();
1983 }
1984 if (!array_key_exists(0, $num)) {
1985 return array();
1986 }
1987 if (1 == count($num)) {
1988 $rows[] = $num[0];
1989 while ($num = db_row_num($rs)) {
1990 $rows[] = $num[0];
1991 }
1992 return $rows;
1993 }
1994 if ('mysql' == $db_driver) {
1995 mysql_data_seek($rs, 0);
1996 }
1997 else if ('pgsql' == $db_driver) {
1998 pg_result_seek($rs, 0);
1999 }
2000 $row = db_row($rs);
2001 if (!is_array($row)) {
2002 return array();
2003 }
2004 if (count($num) < 2) {
2005 trigger_error(sprintf('db_assoc() failed. Two fields required. Query: %s.', $query), E_USER_ERROR);
2006 }
2007 if (count($num) > 2 && count($row) <= 2) {
2008 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);
2009 }
2010 foreach ($row as $k => $v) {
2011 $first_key = $k;
2012 break;
2013 }
2014 if (count($row) > 2) {
2015 $rows[$row[$first_key]] = $row;
2016 while ($row = db_row($rs)) {
2017 $rows[$row[$first_key]] = $row;
2018 }
2019 } else {
2020 $rows[$num[0]] = $num[1];
2021 while ($num = db_row_num($rs)) {
2022 $rows[$num[0]] = $num[1];
2023 }
2024 }
2025 db_free($rs);
2026 return $rows;
2027}
2028function db_limit($query, $offset, $limit)
2029{
2030 global $db_driver;
2031
2032 $offset = (int) $offset;
2033 $limit = (int) $limit;
2034
2035 $query = trim($query);
2036 if (";" == substr($query, -1)) {
2037 $query = substr($query, 0, -1);
2038 }
2039
2040 $query = preg_replace('#^([\s\S]+)LIMIT\s+\d+\s+OFFSET\s+\d+\s*$#i', '$1', $query);
2041 $query = preg_replace('#^([\s\S]+)LIMIT\s+\d+\s*,\s*\d+\s*$#i', '$1', $query);
2042
2043 if ('mysql' == $db_driver) {
2044 // mysql 3.23 doesn't understand "LIMIT x OFFSET z"
2045 return $query." LIMIT $offset, $limit";
2046 } else {
2047 // pgsql, sqlite
2048 return $query." LIMIT $limit OFFSET $offset";
2049 }
2050}
2051function db_escape($value)
2052{
2053 global $db_driver, $db_link;
2054
2055 if ('mysql' == $db_driver) {
2056 return mysql_real_escape_string($value, $db_link);
2057 }
2058 else if ('pgsql' == $db_driver) {
2059 return pg_escape_string($value);
2060 }
2061 else if ("sqlite" == $db_driver) {
2062 // Sqlite allows only quoting, we find a way around by removing
2063 // the quotes around the string.
2064 global $PDO;
2065 $value = $PDO->quote($value);
2066 $length = strlen($value);
2067 if ('\'' == $value[0] && '\'' == $value[$length-1]) {
2068 return substr($value, 1, $length-2);
2069 }
2070 return $value;
2071 }
2072}
2073function db_quote($s)
2074{
2075 global $db_driver;
2076
2077 switch (true) {
2078 case is_null($s): return 'NULL';
2079 case is_int($s): return $s;
2080 case is_float($s): return $s;
2081 case is_bool($s): return (int) $s;
2082 case is_string($s):
2083 if ("sqlite" == $db_driver) {
2084 global $PDO;
2085 return $PDO->quote($s);
2086 } else {
2087 return "'" . db_escape($s) . "'";
2088 }
2089 case is_object($s): return $s->getValue();
2090 default:
2091 trigger_error(sprintf("db_quote() failed. Invalid data type: '%s'.", gettype($s)), E_USER_ERROR);
2092 return false;
2093 }
2094}
2095function db_strlen_cmp($a, $b)
2096{
2097 if (strlen($a) == strlen($b)) {
2098 return 0;
2099 }
2100 return strlen($a) > strlen($b) ? -1 : 1;
2101}
2102function db_bind($q, $dat)
2103{
2104 if (false === $dat) {
2105 return $q;
2106 }
2107 if (!is_array($dat)) {
2108 //return trigger_error('db_bind() failed. Second argument expects to be an array.', E_USER_ERROR);
2109 $dat = array($dat);
2110 }
2111
2112 $qBase = $q;
2113
2114 // special case: LIKE '%asd%', need to ignore that
2115 $q_search = array("'%", "%'");
2116 $q_replace = array("'\$", "\$'");
2117 $q = str_replace($q_search, $q_replace, $q);
2118
2119 preg_match_all('#%\w+#', $q, $match);
2120 if ($match) {
2121 $match = $match[0];
2122 }
2123 if (!$match || !count($match)) {
2124 return trigger_error('db_bind() failed. No binding keys found in the query.', E_USER_ERROR);
2125 }
2126 $keys = $match;
2127 usort($keys, 'db_strlen_cmp');
2128 $num = array();
2129
2130 foreach ($keys as $key)
2131 {
2132 $key2 = str_replace('%', '', $key);
2133 if (is_numeric($key2)) $num[$key] = true;
2134 if (!array_key_exists($key2, $dat)) {
2135 return trigger_error(sprintf('db_bind() failed. No data found for key: %s. Query: %s.', $key, $qBase), E_USER_ERROR);
2136 }
2137 $q = str_replace($key, db_quote($dat[$key2]), $q);
2138 }
2139 if (count($num)) {
2140 if (count($dat) != count($num)) {
2141 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);
2142 }
2143 }
2144
2145 $q = str_replace($q_replace, $q_search, $q);
2146
2147 return $q;
2148}
2149function db_free($rs)
2150{
2151 global $db_driver;
2152 if (db_is_result($rs)) {
2153 if ('mysql' == $db_driver) return mysql_free_result($rs);
2154 else if ('pgsql' == $db_driver) return pg_free_result($rs);
2155 else if ("sqlite" == $db_driver) return 1; // There is no such function in PDO, it is probably freed when you destroy the "$stmt" variable.
2156 }
2157}
2158function db_is_result($rs)
2159{
2160 global $db_driver;
2161 if ('mysql' == $db_driver) return is_resource($rs);
2162 else if ('pgsql' == $db_driver) return is_object($rs) || is_resource($rs);
2163 else if ("sqlite" == $db_driver) return is_object($rs);
2164
2165}
2166function db_error()
2167{
2168 // @db_error
2169 global $db_driver, $db_link;
2170
2171 if ('mysql' == $db_driver) {
2172 if (is_resource($db_link)) {
2173 if (mysql_error($db_link)) {
2174 $error = mysql_error($db_link);
2175 return $error . ' ('. mysql_errno($db_link).')';
2176 } else {
2177 return false;
2178 }
2179 } else {
2180 if (mysql_error()) {
2181 return mysql_error(). ' ('. mysql_errno().')';
2182 } else {
2183 return false;
2184 }
2185 }
2186 }
2187 else if ('pgsql' == $db_driver) {
2188 if (is_resource($db_link)) {
2189 return pg_last_error($db_link);
2190 } else {
2191 global $Global_LastError;
2192 return $Global_LastError;
2193 }
2194 }
2195 else if ("sqlite" == $db_driver) {
2196 global $PDO;
2197 if ($PDO) {
2198 $error = $PDO->errorInfo();
2199 if ("00000" != $error[0] || $error[1]) {
2200 return "($error[0]) ($error[1]) $error[2]";
2201 } else {
2202 return false;
2203 }
2204 }
2205 }
2206}
2207function db_begin()
2208{
2209 global $db_driver;
2210 if ('mysql' == $db_driver) {
2211 db_exe('SET AUTOCOMMIT=0');
2212 db_exe('BEGIN');
2213 }
2214 else if ('pgsql' == $db_driver) {
2215 db_exe('BEGIN');
2216 }
2217 else if ("sqlite" == $db_driver) {
2218 db_exe("BEGIN TRANSACTION");
2219 }
2220}
2221function db_end()
2222{
2223 global $db_driver;
2224 if ('mysql' == $db_driver) {
2225 db_exe('COMMIT');
2226 db_exe('SET AUTOCOMMIT=1');
2227 }
2228 else if ('pgsql' == $db_driver) {
2229 db_exe('COMMIT');
2230 }
2231 else if ("sqlite" == $db_driver) {
2232 db_exe("COMMIT TRANSACTION");
2233 }
2234}
2235function db_rollback()
2236{
2237 global $db_driver;
2238 if ('mysql' == $db_driver) {
2239 db_exe('ROLLBACK');
2240 db_exe('SET AUTOCOMMIT=1');
2241 }
2242 else if ('pgsql' == $db_driver) {
2243 db_exe('ROLLBACK');
2244 }
2245 else if ("sqlite" == $db_driver) {
2246 db_exe("ROLLBACK TRANSACTION");
2247 }
2248}
2249function db_in_array($arr)
2250{
2251 $in = '';
2252 foreach ($arr as $v) {
2253 if ($in) $in .= ',';
2254 $in .= db_quote($v);
2255 }
2256 return $in;
2257}
2258function db_where($where_array, $field_prefix = null, $omit_where = false)
2259{
2260 global $db_driver;
2261
2262 $field_prefix = str_replace('.', '', $field_prefix);
2263 $where = '';
2264 if (count($where_array)) {
2265 foreach ($where_array as $wh_k => $wh)
2266 {
2267 if (is_numeric($wh_k)) {
2268 if ($wh) {
2269 if ($field_prefix && !preg_match('#^\s*\w+\.#i', $wh) && !preg_match('#^\s*\w+\s*\(#i', $wh)) {
2270 if ("mysql" == $db_driver)
2271 $wh = "`$field_prefix`".'.'.trim($wh);
2272 else
2273 $wh = "\"$field_prefix\"".'.'.trim($wh);
2274 }
2275 if ($where) $where .= ' AND ';
2276 $where .= $wh;
2277 }
2278 } else {
2279 if ($wh_k) {
2280 if ($field_prefix && !preg_match('#^\s*\w+\.#i', $wh_k) && !preg_match('#^\s*\w+\s*\(#i', $wh)) {
2281 if ("mysql" == $db_driver)
2282 $wh_k = "`$field_prefix`".'.'.$wh_k;
2283 else
2284 $wh_k = "\"$field_prefix\"".'.'.$wh_k;
2285 }
2286 $wh = db_cond($wh_k, $wh);
2287 if ($where) $where .= ' AND ';
2288 $where .= $wh;
2289 }
2290 }
2291 }
2292 if ($where) {
2293 if (!$omit_where) {
2294 $where = ' WHERE '.$where;
2295 }
2296 }
2297 }
2298 return $where;
2299}
2300function db_insert($tbl, $dat)
2301{
2302 global $db_driver;
2303 if (!count($dat)) {
2304 trigger_error('db_insert() failed. Data is empty.', E_USER_ERROR);
2305 return false;
2306 }
2307 $cols = '';
2308 $vals = '';
2309 $first = true;
2310 foreach ($dat as $k => $v) {
2311 if ($first) {
2312 $cols .= quote_column($k);
2313 $vals .= db_quote($v);
2314 $first = false;
2315 } else {
2316 $cols .= ',' . quote_column($k);
2317 $vals .= ',' . db_quote($v);
2318 }
2319 }
2320 if ('mysql' == $db_driver) {
2321 $tbl = "`$tbl`";
2322 } else {
2323 // pgsql, sqlite
2324 $tbl = "\"$tbl\"";
2325 }
2326 $q = "INSERT INTO $tbl ($cols) VALUES ($vals)";
2327 db_exe($q);
2328}
2329// $wh = WHERE condition, might be (string) or (array)
2330function db_update($tbl, $dat, $wh)
2331{
2332 global $db_driver;
2333 if (!count($dat)) {
2334 trigger_error('db_update() failed. Data is empty.', E_USER_ERROR);
2335 return false;
2336 }
2337 $set = '';
2338 $first = true;
2339 foreach ($dat as $k => $v) {
2340 if ($first) {
2341 $set .= quote_column($k) . '=' . db_quote($v);
2342 $first = false;
2343 } else {
2344 $set .= ',' . quote_column($k) . '=' . db_quote($v);
2345 }
2346 }
2347 if (is_array($wh)) {
2348 $wh = db_where($wh, null, $omit_where = true);
2349 }
2350 if ('mysql' == $db_driver) {
2351 $tbl = "`$tbl`";
2352 } else {
2353 $tbl = "\"$tbl\"";
2354 }
2355 $q = "UPDATE $tbl SET $set WHERE $wh";
2356 return db_exe($q);
2357}
2358function db_insert_id($table = null, $pk = null)
2359{
2360 global $db_driver, $db_link;
2361 if ('mysql' == $db_driver) {
2362 return mysql_insert_id($_db['conn_id']);
2363 }
2364 else if ('pgsql' == $db_driver) {
2365 if (!$table || !$pk) {
2366 trigger_error('db_insert_id(): table & pk required', E_USER_ERROR);
2367 }
2368 $seq_id = $table.'_'.$pk.'_seq';
2369 return db_seq_id($seq_id);
2370 }
2371 else if ("sqlite" == $db_driver) {
2372 global $PDO;
2373 return $PDO->lastInsertId();
2374 }
2375}
2376function db_seq_id($seqName)
2377{
2378 return db_one('SELECT currval(%seqName)', array('seqName'=>$seqName));
2379}
2380function db_cond($k, $v)
2381{
2382 $k_enq = quote_column($k);
2383 if (is_null($v)) {
2384 return "$k_enq IS NULL";
2385 } else {
2386 $v = db_quote($v);
2387 return "$k_enq = $v";
2388 }
2389}
2390function list_dbs()
2391{
2392 // @databases
2393
2394 global $db_driver, $db_link;
2395 if ('mysql' == $db_driver)
2396 {
2397 $result = mysql_query('SHOW DATABASES', $db_link);
2398 $ret = array();
2399 while ($row = mysql_fetch_row($result)) {
2400 $ret[$row[0]] = $row[0];
2401 }
2402 return $ret;
2403 }
2404 else if ('pgsql' == $db_driver)
2405 {
2406 return db_assoc('SELECT datname, datname FROM pg_database');
2407 }
2408 else if ("sqlite" == $db_driver)
2409 {
2410 // There is only 1 database in sqlite database file.
2411 return array("void" => "void");
2412 }
2413}
2414function views_supported()
2415{
2416 static $ret;
2417 if (isset($ret)) {
2418 return $ret;
2419 }
2420
2421 global $db_driver, $db_link;
2422
2423 if ('mysql' == $db_driver) {
2424 $version = mysql_get_server_info($db_link);
2425 if (strpos($version, "-") !== false) {
2426 $version = substr($version, 0, strpos($version, "-"));
2427 }
2428 if (version_compare($version, "5.0.2", ">=")) {
2429 // Views are available in 5.0.0 but we need SHOW FULL TABLES
2430 // and the FULL syntax was added in 5.0.2, FULL allows us to
2431 // to distinct between tables & views in the returned list by
2432 // by providing an additional column.
2433 $ret = true;
2434 return true;
2435 } else {
2436 $ret = false;
2437 return false;
2438 }
2439 }
2440 else if ('pgsql' == $db_driver) {
2441 return true;
2442 }
2443 else if ("sqlite" == $db_driver) {
2444 return true;
2445 }
2446
2447}
2448function list_tables($views_mode=false)
2449{
2450 // @tables
2451 // @views
2452
2453 global $db_driver, $db_link, $db_name;
2454
2455 if ($views_mode && !views_supported()) {
2456 return array();
2457 }
2458
2459 static $cache_tables;
2460 static $cache_views;
2461
2462 if ($views_mode) {
2463 if (isset($cache_views)) {
2464 return $cache_views;
2465 }
2466 } else {
2467 if (isset($cache_tables)) {
2468 return $cache_tables;
2469 }
2470 }
2471
2472 static $all_tables; // tables and views
2473
2474 if ('mysql' == $db_driver)
2475 {
2476 if (!isset($all_tables)) {
2477 $all_tables = db_assoc("SHOW FULL TABLES");
2478 // assoc: table name => table type (BASE TABLE or VIEW)
2479 }
2480
2481 // This chunk of code is the same as in pgsql driver.
2482 if ($views_mode) {
2483 $views = array();
2484 foreach ($all_tables as $view => $type) {
2485 if ($type != 'VIEW') { continue; }
2486 $views[] = $view;
2487 }
2488 $cache_views = $views;
2489 return $views;
2490 } else {
2491 $tables = array();
2492 foreach ($all_tables as $table => $type) {
2493 if ($type != 'BASE TABLE') { continue; }
2494 $tables[] = $table;
2495 }
2496 $cache_tables = $tables;
2497 return $tables;
2498 }
2499 }
2500 else if ('pgsql' == $db_driver)
2501 {
2502 if (!isset($all_tables)) {
2503 $query = "SELECT table_name, table_type ";
2504 $query .= "FROM information_schema.tables ";
2505 $query .= "WHERE table_schema = 'public' ";
2506 $query .= "AND (table_type = 'BASE TABLE' OR table_type = 'VIEW') ";
2507 $query .= "ORDER BY table_name ";
2508 $all_tables = db_assoc($query);
2509 }
2510
2511 // This chunk of code is the same as in mysql driver.
2512 if ($views_mode) {
2513 $views = array();
2514 foreach ($all_tables as $view => $type) {
2515 if ($type != 'VIEW') { continue; }
2516 $views[] = $view;
2517 }
2518 $cache_views = $views;
2519 return $views;
2520 } else {
2521 $tables = array();
2522 foreach ($all_tables as $table => $type) {
2523 if ($type != 'BASE TABLE') { continue; }
2524 $tables[] = $table;
2525 }
2526 $cache_tables = $tables;
2527 return $tables;
2528 }
2529 }
2530 else if ("sqlite" == $db_driver)
2531 {
2532 if ($views_mode) {
2533 $views = PDO_FetchAssoc("SELECT name FROM sqlite_master WHERE type = 'view' AND name NOT LIKE 'sqlite_%' ORDER BY name");
2534 $cache_views = $views;
2535 return $views;
2536 } else {
2537 $tables = PDO_FetchAssoc("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name");
2538 $cache_tables = $tables;
2539 return $tables;
2540 }
2541 }
2542}
2543function IsTableAView($table)
2544{
2545 // There is no cache here, so call it only once!
2546
2547 global $db_driver, $db_name;
2548
2549 if ("mysql" == $db_driver) {
2550 // Views and information_schema is supported since 5.0
2551 if (views_supported()) {
2552 $query = "SELECT table_name FROM information_schema.tables WHERE table_schema=%0 AND table_name=%1 AND table_type='VIEW' ";
2553 $row = db_row($query, array($db_name, $table));
2554 return (bool) $row;
2555 }
2556 return false;
2557 }
2558 else if ("pgsql" == $db_driver) {
2559 $query = "SELECT table_name, table_type ";
2560 $query .= "FROM information_schema.tables ";
2561 $query .= "WHERE table_schema = 'public' ";
2562 $query .= "AND table_type = 'VIEW' AND table_name = %0 ";
2563 $row = db_row($query, $table);
2564 return (bool) $row;
2565 }
2566}
2567function quote_table($table)
2568{
2569 global $db_driver;
2570
2571 if ('mysql' == $db_driver) {
2572 return "`$table`";
2573 } else {
2574 return "\"$table\"";;
2575 }
2576}
2577function quote_column($column)
2578{
2579 global $db_driver;
2580
2581 if ('mysql' == $db_driver) {
2582 return "`$column`";
2583 } else {
2584 return "\"$column\"";;
2585 }
2586}
2587function table_structure($table, $type="table")
2588{
2589 // @dump
2590 // @export
2591 // @structure
2592
2593 global $db_driver;
2594
2595 if ('mysql' == $db_driver)
2596 {
2597 if ("table" == $type) {
2598 $query = "SHOW CREATE TABLE `$table`";
2599 $row = db_row_num($query);
2600 echo $row[1].';';
2601 echo "\n\n";
2602 } else if ("view" == $type) {
2603 $query = "SHOW CREATE VIEW `$table`";
2604 $row = db_row_num($query);
2605 echo $row[1].';';
2606 echo "\n\n";
2607 } else {
2608 assert(0);
2609 }
2610 }
2611 else if ('pgsql' == $db_driver)
2612 {
2613 return;
2614 }
2615 else if ("sqlite" == $db_driver)
2616 {
2617 if ("table" == $type) {
2618 $sql = PDO_FetchOne("SELECT sql FROM sqlite_master WHERE name = :name AND type='table' ",
2619 array(":name"=>$table));
2620 $sql = str_replace("\r\n", "\n", $sql); // editplus invalid line endings, strange
2621 echo "$sql;\n";
2622 } else if ("view" == $type) {
2623 $sql = PDO_FetchOne("SELECT sql FROM sqlite_master WHERE name = :name AND type='view' ",
2624 array(":name"=>$table));
2625 $sql = str_replace("\r\n", "\n", $sql); // editplus invalid line endings, strange
2626 echo "$sql;\n";
2627 } else {
2628 assert(0);
2629 }
2630 unset($sql);
2631
2632 if ("table" == $type) {
2633 $indexes = PDO_FetchAll("SELECT * FROM sqlite_master WHERE tbl_name = :tbl_name AND type='index' ",
2634 array(":tbl_name"=>$table));
2635 foreach ($indexes as $index) {
2636 if ($index["sql"]) { // autoindexes have column "sql" empty
2637 echo "\n-- INDEX: \"{$index['name']}\"\n\n";
2638 echo "{$index['sql']};\n";
2639 }
2640 }
2641 }
2642
2643 echo "\n";
2644 }
2645}
2646function table_data($table)
2647{
2648 // @dump
2649 // @export
2650 // @data
2651
2652 global $db_driver;
2653 set_time_limit(0);
2654 if ('mysql' == $db_driver) {
2655 $query = "SELECT * FROM `$table` ";
2656 } else {
2657 // pgsql, sqlite
2658 $query = "SELECT * FROM \"$table\" ";
2659 }
2660 $result = db_query($query);
2661 $count = 0;
2662 while ($row = db_row($result))
2663 {
2664 if ('mysql' == $db_driver) {
2665 echo 'INSERT INTO `'.$table.'` VALUES (';
2666 } else {
2667 // pgsql, sqlite
2668 echo 'INSERT INTO "'.$table.'" VALUES (';
2669 }
2670 $x = 0;
2671 foreach($row as $key => $value)
2672 {
2673 if ($x == 1) { echo ', '; }
2674 else { $x = 1; }
2675 if (is_numeric($value)) { echo "'".$value."'"; }
2676 elseif (is_null($value)) { echo 'NULL'; }
2677 else { echo '\''. escape($value) .'\''; }
2678 }
2679 echo ");\n";
2680 $count++;
2681 if ($count % 100 == 0) { flush(); }
2682 }
2683 db_free($result);
2684 if ($count) {
2685 echo "\n";
2686 }
2687}
2688function table_status()
2689{
2690 // @table
2691 // @status
2692
2693 // Size is not supported for Views, only for Tables.
2694
2695 global $db_driver, $db_link, $db_name;
2696 if ('mysql' == $db_driver)
2697 {
2698 $status = array();
2699 $status['total_size'] = 0;
2700 $result = mysql_query("SHOW TABLE STATUS FROM `$db_name`", $db_link);
2701 while ($row = mysql_fetch_assoc($result)) {
2702 if (!is_numeric($row['Data_length'])) {
2703 // Data_length for Views is NULL.
2704 continue;
2705 }
2706 $status['total_size'] += $row['Data_length']; // + Index_length
2707 $status[$row['Name']]['size'] = $row['Data_length'];
2708 $status[$row['Name']]['count'] = $row['Rows'];
2709 }
2710 return $status;
2711 }
2712 else if ('pgsql' == $db_driver)
2713 {
2714 $status = array();
2715 $status['total_size'] = 0;
2716 $tables = list_tables(); // only tables, not views
2717 if (!count($tables)) {
2718 return $status;
2719 }
2720 $tables_in = db_in_array($tables);
2721 $rels = db_list("SELECT relname, reltuples, (relpages::decimal + 1) * 8 * 2 * 1024 AS relsize FROM pg_class WHERE relname IN ($tables_in)");
2722 foreach ($rels as $rel) {
2723 $status['total_size'] += $rel['relsize'];
2724 $status[$rel['relname']]['size'] = $rel['relsize'];
2725 $status[$rel['relname']]['count'] = $rel['reltuples'];
2726 }
2727 return $status;
2728 }
2729 else if ("sqlite" == $db_driver)
2730 {
2731 global $db_server;
2732 $status = array();
2733 $status["total_size"] = filesize($db_server);
2734 return $status;
2735 }
2736}
2737
2738//dump(db_list("PRAGMA table_info(\"test22\")"));
2739//dump(db_list("SHOW COLUMNS FROM nwuser2"));
2740
2741//db_exe("CREATE TABLE some33 (id integer PRIMARY KEY, name varchar(30)) ");
2742//dump(db_list("SELECT * FROM information_schema.columns WHERE table_name = 'some33' ORDER BY ordinal_position"));
2743//dump(db_list("SELECT * FROM information_schema.table_constraints WHERE table_name = 'some33'"));
2744//dump(db_list("SELECT * FROM information_schema.key_column_usage WHERE table_name = 'some33'"));
2745
2746$global_columns = array();
2747
2748function ColumnType($type)
2749{
2750 // @column
2751
2752 if ('varchar' == $type) { $type = 'char'; }
2753 else if ('integer' == $type) { $type = 'int'; }
2754 else if ('tinyint' == $type) { $type = 'int'; }
2755 else if ('smallint' == $type) { $type = 'int'; }
2756 else if ('mediumint' == $type) { $type = 'int'; }
2757 else if ('bigint' == $type) { $type = 'int'; }
2758
2759 return $type;
2760}
2761
2762function table_columns($table)
2763{
2764 // @columns
2765
2766 global $db_driver, $global_columns;
2767
2768 static $cache_columns = array();
2769 if (isset($cache_columns[$table])) {
2770 return $cache_columns[$table];
2771 }
2772
2773 if ('mysql' == $db_driver)
2774 {
2775 $columns = array();
2776 $rows = @db_list("SHOW COLUMNS FROM `$table`");
2777 /*
2778 [Field] => id
2779 [Type] => int(11)
2780 [Null] => NO
2781 [Key] => PRI
2782 [Default] =>
2783 [Extra] =>
2784 */
2785 if (!($rows && count($rows))) {
2786 return false;
2787 }
2788 if (!isset($global_columns[$table])) {
2789 $global_columns[$table] = array();
2790 }
2791 foreach ($rows as $row)
2792 {
2793 $type = $row['Type']; // for example "VARCHAR(50)"
2794 preg_match('#^[a-z]+#i', $type, $match);
2795 $type = strtolower($match[0]);
2796 $type = ColumnType($type);
2797
2798 $columns[$row['Field']] = $type;
2799
2800 $global_columns[$table][] = array(
2801 "name" => $row["Field"],
2802 "type" => $type,
2803 "pk" => $row["Key"] == "PRI" || $row["Key"] == "UNI",
2804 "notnull" => $row["Null"] == "NO",
2805 "default" => $row["Default"]
2806 );
2807 }
2808 }
2809 else if ('pgsql' == $db_driver)
2810 {
2811 $columns = db_list("SELECT column_name, udt_name, column_default, is_nullable FROM information_schema.columns WHERE table_name = '$table' ORDER BY ordinal_position");
2812 dump($columns);
2813
2814 // column_name
2815 // udt_name
2816 // column_default - default value
2817 // is_nullable
2818
2819 /*
2820 [table_catalog] => test
2821 [table_schema] => public
2822 [table_name] => some22
2823 [column_name] => id
2824 [ordinal_position] => 1
2825 [column_default] =>
2826 [is_nullable] => NO
2827 [data_type] => integer
2828 [character_maximum_length] =>
2829 [udt_catalog] => test
2830 [udt_schema] => pg_catalog
2831 [udt_name] => int4
2832 [dtd_identifier] => 1
2833 [is_self_referencing] => NO
2834 [is_identity] => NO
2835 [is_generated] => NEVER
2836 [is_updatable] => YES
2837 */
2838
2839 // To get primary key for a table in postgresql:
2840 //db_exe("CREATE TABLE some33 (id integer PRIMARY KEY, name varchar(30)) ");
2841 //dump(db_list("SELECT * FROM information_schema.table_constraints WHERE table_name = 'some33'"));
2842 //dump(db_list("SELECT * FROM information_schema.key_column_usage WHERE table_name = 'some33'"));
2843
2844 if (!count($columns)) {
2845 return false;
2846 }
2847 foreach ($columns as $col => $type) {
2848 // "_" also in regexp - error when retrieving column info from "pg_class" - through a Custom query in SQL Editor POPUP.
2849 // udt_name might be "_aclitem" / "_text".
2850
2851 // $type == for example "VARCHAR(50)"
2852 preg_match('#^[a-z_]+#i', $type, $match);
2853 $type = strtolower($match[0]);
2854 $type = ColumnType($type);
2855
2856 $columns[$col] = $type;
2857 }
2858 }
2859 else if ("sqlite" == $db_driver)
2860 {
2861 $rawColumns = db_list("PRAGMA table_info(\"$table\")");
2862 /*
2863 [cid] => 0
2864 [name] => id
2865 [type] => INTEGER
2866 [notnull] => 0
2867 [dflt_value] =>
2868 [pk] => 1
2869 */
2870 if (!count($rawColumns)) {
2871 return false;
2872 }
2873 foreach ($rawColumns as $row) {
2874 if ($row["type"]) {
2875 preg_match("#^[a-z]+#i", $row["type"], $match);
2876 $type = strtolower($match[0]);
2877 $type = ColumnType($type);
2878 } else {
2879 // type might be empty: sqlite_sequence table
2880 // Solved by not querying sqlite_ special: AND name NOT LIKE 'sqlite_%'
2881 $type = "";
2882 }
2883 $col = $row["name"];
2884 $columns[$col] = $type;
2885
2886 $global_columns[$table][] = array(
2887 "name" => $row["name"],
2888 "type" => $type,
2889 "pk" => (int) $row["pk"],
2890 "notnull" => (int) $row["notnull"],
2891 "default" => $row["dflt_value"]
2892 );
2893 }
2894 }
2895
2896 $cache_columns[$table] = $columns;
2897
2898 return $columns;
2899}
2900function IsTimestampColumn($column, $value)
2901{
2902 // @column
2903 // @istime
2904
2905 if (ctype_digit($value) && preg_match('#(time|date|unix|data|czas)#i', $column) && $value > 100000000)
2906 {
2907 // 100 000 000 == 1973-03-03 10:46:40
2908 // Only big integers change to dates, so a low one like "1054"
2909 // does not get changed into a date, cause that would probably be wrong.
2910 return true;
2911 }
2912 return false;
2913}
2914function table_columns_group($types)
2915{
2916 // @columns
2917
2918 foreach ($types as $k => $type) {
2919 if ($type) {
2920 preg_match('#^\w+#', $type, $match);
2921 $type = $match[0];
2922 } else {
2923 $type = "";
2924 }
2925 $types[$k] = $type;
2926 }
2927 $types = array_unique($types);
2928 $types = array_values($types);
2929 $types2 = array();
2930 foreach ($types as $type) {
2931 $types2[$type] = $type;
2932 }
2933 return $types2;
2934}
2935function table_pk($table)
2936{
2937 // @pk
2938
2939 $table_columns = table_columns($table);
2940 if (!$table_columns) return null;
2941
2942 $pk = "";
2943
2944 global $global_columns;
2945
2946 foreach ($global_columns[$table] as $column) {
2947 if ($column["pk"]) {
2948 if ($pk) {
2949 $pk .= ":".$column["name"];
2950 } else {
2951 $pk = $column["name"];
2952 }
2953 }
2954 }
2955
2956 if ($pk) {
2957 // Possible returns: "col1", "col1:col2", "col1:col2:col3"
2958 return $pk;
2959 }
2960
2961 global $db_driver;
2962
2963 if ("sqlite" == $db_driver)
2964 {
2965 // Detect PK for:
2966 // UNIQUE (nagroda, id_gracza)
2967
2968 // When there are multiple pks there is no info about it in PRAGMA table_info.pk,
2969 // we need to get it from the SQL string that was used to create the table.
2970
2971 $sql = PDO_FetchOne("SELECT sql FROM sqlite_master WHERE type = 'view' OR type='table' AND name = :name ",
2972 array(":name" => $table));
2973
2974 if (preg_match("#UNIQUE\s*\(\s*(\"?\w+\"?(\s*,\s*\"?\w+\"?)*)\s*\)#i", $sql, $match)) {
2975 $cols = $match[1];
2976 $cols = str_replace("\"", "", $cols);
2977 $cols = preg_replace("#\s+#", "", $cols);
2978 $cols = str_replace(",", ":", $cols);
2979 return $cols; // "nagroda:id_gracza"
2980 }
2981 }
2982
2983 foreach ($table_columns as $col => $type) {
2984 return $col;
2985 }
2986}
2987function guess_pk($rows)
2988{
2989 // @pk
2990
2991 if (!count($rows)) {
2992 return false;
2993 }
2994 $patterns = array('#^\d+$#', '#^[^\s]+$#');
2995 $row = array_first($rows);
2996 foreach ($patterns as $pattern)
2997 {
2998 foreach ($row as $col => $v) {
2999 if ($v && preg_match($pattern, $v)) {
3000 if (array_col_match_unique($rows, $col, $pattern)) {
3001 return $col;
3002 }
3003 }
3004 }
3005 }
3006 return false;
3007}
3008function QuotePkeys($pkeys)
3009{
3010 // Quotes multiple primary keys.
3011 // nagroda, id_gracza => "nagroda", "id_gracza"
3012
3013 $pkeys_enq = $pkeys;
3014 unset($pkeys);
3015
3016 if (is_array($pkeys_enq)) {
3017 $pkeys_enq = implode(",", $pkeys_enq);
3018 } else {
3019 $pkeys_enq = str_replace(":", ",", $pkeys_enq);
3020 }
3021
3022 $pkeys_enq = preg_replace("#(\w+)#i", "\"\$1\"", $pkeys_enq);
3023 return $pkeys_enq;
3024}
3025function FirstFromPkeys($pkeys)
3026{
3027 if (is_array($pkeys)) {
3028 return $pkeys[0];
3029 } else {
3030 $arr = explode(":", $pkeys);
3031 return $arr[0];
3032 }
3033}
3034function EncodeRowId($row, $pk, $pkeys)
3035{
3036 // We need to escape ":" colons that are used to represent many primary keys for the table.
3037 // It also creates and Id using the arguments passed depending whether pkeys is not empty.
3038
3039 if ($pkeys) {
3040 $cols = explode(":", $pkeys);
3041 $rowid = array();
3042 foreach ($cols as $col) {
3043 $rowid[] = str_replace(":", "::", $row[$col]);
3044 }
3045 $rowid = implode(":", $rowid);
3046 return $rowid;
3047 } else {
3048 return str_replace(":", "::", $row[$pk]);
3049 }
3050}
3051function DecodeRowId($id)
3052{
3053 // We unescape colons.
3054 // Returns: "12" or array("12", "15");
3055
3056 $id = str_replace("::", ":", $id);
3057
3058 if (strstr($id, ":")) {
3059 $values = explode(":", $id);
3060 return $values;
3061 } else {
3062 return $id;
3063 }
3064}
3065function escape($text)
3066{
3067 $text = addslashes($text);
3068 $search = array("\r", "\n", "\t");
3069 $replace = array('\r', '\n', '\t');
3070 return str_replace($search, $replace, $text);
3071}
3072function ob_cleanup()
3073{
3074 while (ob_get_level()) {
3075 ob_end_clean();
3076 }
3077 if (headers_sent()) {
3078 return;
3079 }
3080 if (function_exists('headers_list')) {
3081 foreach (headers_list() as $header) {
3082 if (preg_match('/Content-Encoding:/i', $header)) {
3083 header('Content-encoding: none');
3084 break;
3085 }
3086 }
3087 } else {
3088 header('Content-encoding: none');
3089 }
3090}
3091function query_color($query)
3092{
3093 // @color
3094
3095 $color = 'red';
3096 $words = array('SELECT', 'UPDATE', 'DELETE', 'FROM', 'LIMIT', 'OFFSET', 'AND', 'LEFT JOIN', 'WHERE', 'SET',
3097 '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');
3098 $words = implode('|', $words);
3099
3100 $query = preg_replace("#^({$words})(\s)#i", '<font color="'.$color.'">$1</font>$2', $query);
3101 $query = preg_replace("#(\s)({$words})$#i", '$1<font color="'.$color.'">$2</font>', $query);
3102 // replace twice, some words when preceding other are not replaced
3103 $query = preg_replace("#([\s\(\),])({$words})([\s\(\),])#i", '$1<font color="'.$color.'">$2</font>$3', $query);
3104 $query = preg_replace("#([\s\(\),])({$words})([\s\(\),])#i", '$1<font color="'.$color.'">$2</font>$3', $query);
3105 $query = preg_replace("#^($words)$#i", '<font color="'.$color.'">$1</font>', $query);
3106
3107 preg_match_all('#<font[^>]+>('.$words.')</font>#i', $query, $matches);
3108 foreach ($matches[0] as $k => $font) {
3109 $font2 = str_replace($matches[1][$k], strtoupper($matches[1][$k]), $font);
3110 $query = str_replace($font, $font2, $query);
3111 }
3112
3113 return $query;
3114}
3115function query_upper($sql)
3116{
3117 // @color
3118
3119 return $sql;
3120 // todo: don't upper quoted ' and ' values
3121 $queries = preg_split("#;(\s*--[ \t\S]*)?(\r\n|\n|\r)#U", $sql);
3122 foreach ($queries as $k => $query) {
3123 $strip = query_strip($query);
3124 $color = query_color($strip);
3125 $sql = str_replace($strip, $color, $sql);
3126 }
3127 $sql = preg_replace('#<font color="\w+">([^>]+)</font>#iU', '$1', $sql);
3128 return $sql;
3129}
3130function query_cut($query)
3131{
3132 // @color
3133
3134 // removes sub-queries and string values from query
3135 $brace_start = '(';
3136 $brace_end = ')';
3137 $quote = "'";
3138 $inside_brace = false;
3139 $inside_quote = false;
3140 $depth = 0;
3141 $ret = '';
3142 $query = str_replace('\\\\', '', $query);
3143
3144 for ($i = 0; $i < strlen($query); $i++)
3145 {
3146 $prev_char = isset($query{$i-1}) ? $query{$i-1} : null;
3147 $char = $query{$i};
3148 if ($char == $brace_start) {
3149 if (!$inside_quote) {
3150 $depth++;
3151 }
3152 }
3153 if ($char == $brace_end) {
3154 if (!$inside_quote) {
3155 $depth--;
3156 if ($depth == 0) {
3157 $ret .= '(...)';
3158 }
3159 continue;
3160 }
3161 }
3162 if ($char == $quote) {
3163 if ($inside_quote) {
3164 if ($prev_char != '\\') {
3165 $inside_quote = false;
3166 if (!$depth) {
3167 $ret .= "'...'";
3168 }
3169 continue;
3170 }
3171 } else {
3172 $inside_quote = true;
3173 }
3174 }
3175 if (!$depth && !$inside_quote) {
3176 $ret .= $char;
3177 }
3178 }
3179 return $ret;
3180}
3181function table_from_query($query)
3182{
3183 // @query
3184
3185 if (preg_match('#\sFROM\s+["`]?(\w+)["`]?#i', $query, $match)) {
3186 $cut = query_cut($query);
3187 if (preg_match('#\sFROM\s+["`]?(\w+)["`]?#i', $cut, $match2)) {
3188 $table = $match2[1];
3189 } else {
3190 $table = $match[1];
3191 }
3192 } else if (preg_match('#UPDATE\s+"?(\w+)"?#i', $query, $match)) {
3193 $table = $match[1];
3194 } else if (preg_match('#INSERT\s+INTO\s+"?(\w+)"?#', $query, $match)) {
3195 $table = $match[1];
3196 } else {
3197 $table = false;
3198 }
3199 return $table;
3200}
3201function is_select($query)
3202{
3203 // @query
3204 return preg_match('#^\s*(SELECT)\s+#i', $query);
3205}
3206function is_show($query)
3207{
3208 // @query
3209
3210 // mysql only: SHOW CREATE TABLE, SHOW CREATE VIEW.
3211 // It is the same as SELECT, but cannot add LIMIT to such query.
3212
3213 // So that in SQL Editor popup we have SHOW statements available in "SELECT queries: <select>".
3214 // Also it allows us to click "Refetch" link.
3215
3216 return preg_match('#^\s*(SHOW)\s+#i', $query);
3217}
3218function query_strip($query)
3219{
3220 // @query
3221
3222 // strip comments and ';' from the end of query
3223 $query = trim($query);
3224 if (";" == substr($query, -1)) {
3225 $query = substr($query, 0, -1);
3226 }
3227 $lines = preg_split("#(\r\n|\n|\r)#", $query);
3228 foreach ($lines as $k => $line) {
3229 $line = trim($line);
3230 if (!$line || 0 === strpos($line, '--')) {
3231 unset($lines[$k]);
3232 }
3233 }
3234 $query = implode("\r\n", $lines);
3235 return $query;
3236}
3237function dump_table($table, $type)
3238{
3239 // @dump
3240 // @export
3241
3242 ob_cleanup();
3243 define('DEBUG_CONSOLE_HIDE', 1);
3244 set_time_limit(0);
3245 global $db_name;
3246 header("Cache-control: private");
3247 header("Content-type: application/octet-stream");
3248 header('Content-Disposition: attachment; filename='.$table.'.sql');
3249 // dump_table is called for both: tables and views.
3250 if ("table" == $type) {
3251 table_structure($table, $type);
3252 } else {
3253 // View > Export
3254 // We export only data for views.
3255 }
3256 table_data($table, $type);
3257 exit;
3258}
3259function dump_all($data = false)
3260{
3261 // @dump
3262 // @structure
3263 // @data
3264
3265 GET("table_filter", "string");
3266
3267 global $db_driver, $db_server, $db_name;
3268
3269 ob_cleanup();
3270 define('DEBUG_CONSOLE_HIDE', 1);
3271 set_time_limit(0);
3272
3273 $tables = list_tables();
3274 $table_filter = $_GET["table_filter"];
3275 $tables = table_filter($tables, $table_filter);
3276
3277 header("Cache-control: private");
3278 header("Content-type: application/octet-stream");
3279 header('Content-Disposition: attachment; filename='.$db_name.'.sql');
3280
3281 echo "--\n";
3282 if ($data) {
3283 echo "-- Dump type: DATA & STRUCTURE\n";
3284 } else {
3285 echo "-- Dump type: STRUCTURE ONLY\n";
3286 }
3287
3288 if ("sqlite" == $db_driver) {
3289 echo "-- Database file: $db_server\n";
3290 } else {
3291 echo "-- Database: $db_name\n";
3292 }
3293
3294 $date = date("Y-m-d");
3295 echo "-- Exported on: $date\n";
3296 $version = DBKISS_VERSION;
3297 echo "-- Powered by: DBKiss (http://www.gosu.pl/dbkiss/)\n";
3298 echo "--\n\n";
3299
3300 foreach ($tables as $key => $table)
3301 {
3302 echo "-- TABLE: \"$table\"\n\n";
3303 table_structure($table);
3304 if ($data) {
3305 echo "-- INSERTS for: \"$table\"\n\n";
3306 table_data($table);
3307 }
3308 flush();
3309 }
3310 unset($table);
3311
3312 $views = list_tables(true);
3313 foreach ($views as $key => $view)
3314 {
3315 echo "-- VIEW: \"$view\"\n\n";
3316 table_structure($view, "view");
3317 flush();
3318 }
3319
3320 echo "--\n";
3321 echo "-- END OF DUMP\n";
3322 echo "--\n";
3323
3324 exit;
3325}
3326function export_csv($query, $separator)
3327{
3328 // @csv
3329
3330 ob_cleanup();
3331 set_time_limit(0);
3332
3333 if (!is_select($query) && !is_show($query)) {
3334 trigger_error('export_csv() failed: not a SELECT or SHOW query: '.$query, E_USER_ERROR);
3335 }
3336
3337 $table = table_from_query($query);
3338 if (!$table) {
3339 $table = 'unknown';
3340 }
3341
3342 header("Cache-control: private");
3343 header("Content-type: application/octet-stream");
3344 header('Content-Disposition: attachment; filename='.$table.'_'.date('Ymd').'.csv');
3345
3346 $rs = db_query($query);
3347 $first = true;
3348
3349 while ($row = db_row($rs)) {
3350 if ($first) {
3351 echo csv_row(array_keys($row), $separator);
3352 $first = false;
3353 }
3354 echo csv_row($row, $separator);
3355 flush();
3356 }
3357
3358 exit();
3359}
3360function csv_row($row, $separator)
3361{
3362 // @csv
3363
3364 foreach ($row as $key => $val) {
3365 $enquote = false;
3366 if (false !== strpos($val, $separator)) {
3367 $enquote = true;
3368 }
3369 if (false !== strpos($val, "\"")) {
3370 $enquote = true;
3371 $val = str_replace("\"", "\"\"", $val);
3372 }
3373 if (false !== strpos($val, "\r") || false !== strpos($val, "\n")) {
3374 $enquote = true;
3375 $val = preg_replace('#(\r\n|\r|\n)#', "\n", $val); // excel needs \n instead of \r\n
3376 }
3377 if ($enquote) {
3378 $row[$key] = "\"".$val."\"";
3379 }
3380 }
3381 $out = implode($separator, $row);
3382 $out .= "\r\n";
3383 return $out;
3384}
3385function import($file, $ignore_errors = false, $transaction = false, $force_myisam = false, $query_start = false)
3386{
3387 // @import PHP
3388
3389 global $db_driver, $db_link, $db_charset;
3390 if ($ignore_errors && $transaction) {
3391 echo '<div>You cannot select both: ignoring errors and transaction</div>';
3392 exit;
3393 }
3394
3395 $count_errors = 0;
3396 set_time_limit(0);
3397 $fp = fopen($file, 'r');
3398 if (!$fp) { exit('fopen('.$file.') failed'); }
3399 flock($fp, 1);
3400 $text = trim(fread($fp, filesize($file)));
3401 flock($fp, 3);
3402 fclose($fp);
3403
3404 if ($force_myisam) {
3405 $text = preg_replace('#TYPE\s*=\s*InnoDB#i', 'TYPE=MyISAM', $text);
3406 }
3407 $text = preg_split("#;(\r\n|\n|\r)#", $text);
3408 $x = 0;
3409 echo '<div>Ignoring errors: <b>'.($ignore_errors?'Yes':'No').'</b></div>';
3410 echo '<div>Transaction: <b>'.($transaction?'Yes':'No').'</b></div>';
3411 echo '<div>Force MyIsam: <b>'.($force_myisam?'Yes':'No').'</b></div>';
3412 echo '<div>Query start: <b>#'.$query_start.'</b></div>';
3413 echo '<div>Queries found: <b>'.count($text).'</b></div>';
3414 echo '<div>Executing ...</div>';
3415 flush();
3416
3417 if ($transaction) {
3418 echo '<div>BEGIN;</div>';
3419 db_begin();
3420 }
3421
3422 $time = time_start();
3423 $query_start = (int) $query_start;
3424 if (!$query_start) {
3425 $query_start = 1;
3426 }
3427 $query_no = 0;
3428
3429 foreach($text as $key => $value)
3430 {
3431 $x++;
3432 $query_no++;
3433 if ($query_start > $query_no) {
3434 continue;
3435 }
3436
3437 if ('mysql' == $db_driver)
3438 {
3439 $result = @mysql_query($value.';', $db_link);
3440 }
3441 if ('pgsql' == $db_driver)
3442 {
3443 $result = @pg_query($db_link, $value.';');
3444 }
3445 if(!$result) {
3446 $x--;
3447 if (!$count_errors) {
3448 echo '<table class="ls" cellspacing="1"><tr><th width="25%">Error</th><th>Query</th></tr>';
3449 }
3450 $count_errors++;
3451 echo '<tr><td>#'.$query_no.' '.db_error() .')'.'</td><td>'.nl2br(html_once($value)).'</td></tr>';
3452 flush();
3453 if (!$ignore_errors) {
3454 echo '</table>';
3455 echo '<div><span style="color: red;"><b>Import failed.</b></span></div>';
3456 echo '<div>Queries executed: <b>'.($x-$query_start+1).'</b>.</div>';
3457 if ($transaction) {
3458 echo '<div>ROLLBACK;</div>';
3459 db_rollback();
3460 }
3461 echo '<br><div><a href="'.$_SERVER['PHP_SELF'].'?import=1"><< go back</a></div>';
3462 exit;
3463 }
3464 }
3465 }
3466 if ($count_errors) {
3467 echo '</table>';
3468 }
3469 if ($transaction) {
3470 echo '<div>COMMIT;</div>';
3471 db_end();
3472 }
3473 echo '<div><span style="color: green;"><b>Import finished.</b></span></div>';
3474 echo '<div>Queries executed: <b>'.($x-$query_start+1).'</b>.</div>';
3475 echo '<div>Time: <b>'.time_end($time).'</b> sec</div>';
3476 echo '<br><div><a href="'.$_SERVER['PHP_SELF'].'?import=1"><< go back</a></div>';
3477}
3478function layout()
3479{
3480 // @layout
3481
3482 global $sql_area;
3483 ?>
3484 <style type=text/css>
3485
3486 /* @styles */
3487 /* @css */
3488
3489 html, body { cursor: default; }
3490
3491 ::selection {
3492 background: #C1EBFA;
3493 }
3494
3495 body,table {
3496 font: 11px Tahoma;
3497 }
3498 body {
3499 line-height: 1.4em;
3500 }
3501 input,select,textarea {
3502 font: 11px Tahoma;
3503 }
3504
3505 input[type=text], input[type=search] {
3506 border: #b5b4bb 1px solid;
3507 border-radius: 3px;
3508 padding: 2px 3px;
3509 background: #f9f9f9;
3510 }
3511 input[type=text]:focus, input[type=search]:focus select:focus {
3512 background: #F2FBFE;
3513 border-color: #7FB2DA;
3514 /* #F0FAFE #F2FBFE #F6FCFE */
3515 }
3516 form .ls2 input[type=text] {
3517 background: #fff;
3518 }
3519 select {
3520 border: #b5b4bb 1px solid;
3521 border-radius: 3px;
3522 padding: 1px 3px;
3523 background: #f9f9f9;
3524 }
3525 input[type=button], input[type=submit] {
3526 border-width: 1px;
3527 border-radius: 3px;
3528 background: -webkit-linear-gradient(#fff, #ddd);
3529 background: -moz-linear-gradient(#fff, #ddd);
3530 background: -o-linear-gradient(#fff, #ddd);
3531 padding: 2px 12px;
3532 cursor: pointer;
3533 box-sizing: border-box;
3534 border-style: solid;
3535 border-color: #ddd #989699 #989699 #ddd;
3536 }
3537 input[type=button]:active, input[type=submit]:active {
3538 border-color: #989699 #ddd #ddd #989699 ;
3539 }
3540 input[type=button]:hover, input[type=submit]:hover, input[type=button]:focus, input[type=submit]:focus {
3541 background: -webkit-linear-gradient(#fff, #CDEFFB);
3542 background: -moz-linear-gradient(#fff, #CDEFFB);
3543 background: -o-linear-gradient(#fff, #CDEFFB);
3544 }
3545
3546 input:focus, select:focus, textarea:focus {
3547 outline: none;
3548 }
3549 body { padding: 0; margin: 1em 1.5em; }
3550
3551 h1, h2 { margin: 11px 0; }
3552 h1 { font: bold 15px Tahoma; }
3553 h2 { font: bold 13px Tahoma; }
3554
3555 a, a:visited { text-decoration: none; }
3556 a:hover { text-decoration: underline; }
3557 a, a:visited, a.blue, a.blue:visited { color: #0064ff; }
3558
3559 .special {
3560 font: 11px Tahoma;
3561 color: #000;
3562 padding: 2px 8px;
3563 border: #ccc 1px solid; border-radius: 5px;
3564 background: -webkit-linear-gradient(#fff, #eee);
3565 background: -moz-linear-gradient(#fff, #eee);
3566 background: -o-linear-gradient(#fff, #eee);
3567 filter: progid:dximagetransform.microsoft.gradient(startcolorstr=#ffffff, endcolorstr=#eeeeee);
3568 }
3569 .special:hover {
3570 border-color: #aaa;
3571 color: #000;
3572 text-decoration: none;
3573 background: -webkit-linear-gradient(#fff, #ddd);
3574 background: -moz-linear-gradient(#fff, #ddd);
3575 background: -o-linear-gradient(#fff, #ddd);
3576 filter: progid:dximagetransform.microsoft.gradient(startcolorstr=#ffffff, endcolorstr=#dddddd);
3577 }
3578
3579 p { margin: 0.75em 0; }
3580
3581 /* form */
3582
3583 form { margin: 0; padding: 0; }
3584 form th { text-align: left; }
3585
3586 form .none td, form .none th { background: none; padding: 0em 0.25em; }
3587 label { padding-left: 2px; padding-right: 4px; }
3588
3589 .checkbox { padding-left: 0; margin-left: 0; margin-top: 1px; }
3590
3591 /* messages */
3592
3593 .error { background: #ffffd7; padding: 0.5em; border: #ccc 1px solid; margin-bottom: 1em; margin-top: 1em; }
3594 .msg { background: #eee; padding: 0.5em; border: #ccc 1px solid; margin-bottom: 1em; margin-top: 1em; }
3595 .sql_area { <?php echo $sql_area;?> }
3596 .query { background: #eee; padding: 0.35em; border: #ccc 1px solid; margin-bottom: 1em; margin-top: 1em; }
3597
3598 /* @ls */
3599
3600 .ls {
3601 box-shadow: 1px 1px 8px #ddd;
3602 }
3603
3604 .ls > tbody > tr > th,
3605 .ls > tbody > tr > td { padding: 2px 10px; font: 11px Tahoma; }
3606
3607 .ls > tbody > tr > th {
3608 background: -webkit-linear-gradient(#fff, #ddd);
3609 background: -moz-linear-gradient(#fff, #ddd);
3610 background: -o-linear-gradient(#fff, #ddd);
3611 filter: progid:dximagetransform.microsoft.gradient(startcolorstr=#ffffff, endcolorstr=#dddddd);
3612 font-weight: bold;
3613 font-size: 11px;
3614 text-transform: none;
3615 border-top: #ccc 1px solid;
3616 border-bottom: #bbb 1px solid;
3617 padding: 3px 5px;
3618 }
3619 .ls > tbody > tr > th.camelcase {
3620 text-transform: none;
3621 }
3622
3623 .ls > tbody > tr > th.sortable {
3624 padding: 0px;
3625 }
3626 .ls > tbody > tr > th.sortable > a {
3627 display: block;
3628 color: #111;
3629 padding: 3px 14px;
3630 position: relative;
3631 }
3632 .ls > tbody > tr > th.sortable:hover {
3633 border-bottom: #999 1px solid;
3634 }
3635 .ls > tbody > tr > th.sortable > a:hover {
3636 text-decoration: none;
3637 background: -webkit-linear-gradient(#fff, #CDEFFB);
3638 background: -moz-linear-gradient(#fff, #bfbfbf);
3639 background: -o-linear-gradient(#fff, #bfbfbf);
3640 filter: progid:dximagetransform.microsoft.gradient(startcolorstr=#ffffff, endcolorstr=#bfbfbf);
3641 color: #000;
3642 }
3643 .ls > tbody > tr > th.sortable > a:active {
3644 text-decoration: none;
3645 background: -webkit-linear-gradient(#CDEFFB, #fff);
3646 background: -moz-linear-gradient(#eee, #fff);
3647 background: -o-linear-gradient(#eee, #fff);
3648 filter: progid:dximagetransform.microsoft.gradient(startcolorstr=#eeeeee, endcolorstr=#ffffff);
3649 color: #000;
3650 }
3651
3652
3653 .ls > tbody > tr > th.sortable > a > span.uparrow1 {
3654 position: absolute;
3655 width: 16px; height: 16px;
3656 top: 2px; left: -1px;
3657 background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPNJREFUeNpi/P//PwMlgImBQjDwBrCgCxj1XGfg4OZmYGNnj2FgZCxg+P9/wq+fP5f8+PqV4VyJJnEuAAZsDFBTQZS7mDGIBvGJ9gJI8c9v3wri/OWMX/1kYIjxkzMG8XEZgmEA0KkFceGaxvuP32d49p2B4eCJ+wwhIZrGIHGiwuD71y9n+yfsZXj79h2Dk4Ki8b7NZ86eOHaPgZGJ6SxRBvz/9y/9989fDJysrGfeAr0ApBmAfBNWdjbiYuHbp89AV3wFs3/9ZwCzQZgTGDNEGfDx7VtYaJ69uPesFMP372eB0cnw68cPrAYwjuYFBoAAAwCwH3kFP+QZjgAAAABJRU5ErkJggg==") no-repeat;
3658 }
3659 .ls > tbody > tr > th.sortable > a > span.downarrow1 {
3660 position: absolute;
3661 width: 16px; height: 16px;
3662 top: 2px; right: -2px;
3663 background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA40lEQVR42mNkoBAwDnMDWANmz2QwNPRlOH9+8+8NqekkG8AdueSMZna08fWpS89+XR5jQrIBIinrz6glBhjfmr/h7Js5gcQbIF+yb+b/f/+M3759x+CUG2q8b/Lqs8LCQgyMTExnH/Y4pRM0QKP+1JnYBFPji2fvMwhrKjK8vX6fwdJMkWHm3NNnbzSamRA0wKDragwjI2NBSqSm8btfQK+wMzDMWnb97P///ydcKNNeQlQYWEx9ADYkwV/OeMHGR2DNJ7IVlqCrwxuI9nNfxDAADWEAaj6YLLEEm5pBnhLpYgAAn+ZVERqSnwgAAAAASUVORK5CYII=") no-repeat;
3664 }
3665 .ls > tbody > tr > th.sortable > a > span.uparrow2 {
3666 position: absolute;
3667 width: 16px; height: 16px;
3668 top: 2px; left: -1px;
3669 background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAEdSURBVHjaYvz//z8DJQAggJgYKAQAAUSxAQABRLEBAAHEgi7Q0tLCwM3NzcDGxhbDyMhY8O/fvwm/fv1a8u3bN4aamhoMAwACCKsLgAEb8/PnzwInJydjoOYCEB+XCwACCJsBMUDbCry9vY2BhjB4eXkZ//jxowAkjs0AgADCMACkOTAw0PjkyZMgNgOI9vHxMQaJYzMAIIBYsBhwdubMmQzv379nkJaWNt6zZ89ZIGBgYmI6i80AgADCMAAYaOkgp7Oysp6B0gzAcDABBirWMAAIIAwDvnz5AnY6NDDB7O/fvzNwcnJiNQAggDAM+PDhA8wlZ48ePSoFDMCzQOczgFyDDQAEECOleQEggChOiQABRLEBAAFEsQEAAQYAUQR6EOOFIlQAAAAASUVORK5CYII=") no-repeat;
3670 }
3671 .ls > tbody > tr > th.sortable > a > span.downarrow2 {
3672 position: absolute;
3673 width: 16px; height: 16px;
3674 top: 2px; right: -2px;
3675 background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAETSURBVHjaYvz//z8DJQAggJgYKAQAAUSxAQABRLEBAAHEgk2QkZERTPv7+8/U0tLyvX79+uYNGzakg8TQwwwggPC6gIODw9ja2lqSnZ3dGJcagADCawAXFxfYNSAaFwAIIKxeyM/Pn/nv3z/jDx8+MLCxsTH8/v2bITc39wzQsLNA6XRktQABxILDZuOIiAjjCxcugG13dXU1BgKGpUuXYqgFCCCsXuDk5JywefPms6ampmADzMzMGNavX38WyJ6ArhYggBixpUSQv3t7e2OAzAJvb2/jrVu3gpw+obi4eAm6eoAAwmkACEyZMiUGyC4AqpmQk5OzBFs0AgQQI6V5ASCAKE6JAAFEsQEAAUSxAQABBgBLiE3/WjHs8wAAAABJRU5ErkJggg==") no-repeat;
3676 }
3677
3678
3679 .ls > tbody > tr > td {
3680 border-bottom: #e7e7e7 1px solid;
3681 background: #fff; /* has to be cause box-shadow might make it gray sometimes - bug */
3682 }
3683 .ls > tbody > tr:nth-of-type(odd) > td {
3684 background: -webkit-linear-gradient(#f9f9f9, #f0f0f0);
3685 background: -moz-linear-gradient(#f9f9f9, #f0f0f0);
3686 background: -o-linear-gradient(#f9f9f9, #f0f0f0);
3687 filter: progid:dximagetransform.microsoft.gradient(startcolorstr=#f9f9f9, endcolorstr=#f0f0f0);
3688 }
3689
3690 .ls > tbody > tr > th,
3691 .ls > tbody > tr > td { border-right: #fff 1px solid; }
3692 .ls > tbody > tr > th:last-child,
3693 .ls > tbody > tr > td:last-child { border-right: none; }
3694
3695 .ls > tbody > tr > th > a {
3696 display: block;
3697 }
3698
3699 .ls > tbody > tr > th {
3700 border-right: #ccc 1px solid;
3701 }
3702 .ls > tbody > tr > th:first-child {
3703 border-top-left-radius: 5px;
3704 border-left: #ccc 1px solid;
3705 }
3706 .ls > tbody > tr > th:last-child {
3707 border-top-right-radius: 5px;
3708 border-right: #ccc 1px solid;
3709 }
3710
3711
3712 .ls > tbody > tr > td:first-child {
3713 border-left: #ddd 1px solid;
3714 }
3715 .ls > tbody > tr > td:last-child {
3716 border-right: #ddd 1px solid;
3717 }
3718 .ls > tbody > tr:last-child > td {
3719 border-bottom: #ddd 1px solid;
3720 padding-bottom: 3px;
3721 }
3722
3723
3724 .ls > tbody > tr:last-child > td:first-child {
3725 border-bottom-left-radius: 5px;
3726 }
3727 .ls > tbody > tr:last-child > td:last-child {
3728 border-bottom-right-radius: 5px;
3729 }
3730
3731 .ls > tbody > tr > td.next_marked {
3732 border-bottom: #aaa 1px solid;
3733 }
3734 .ls > tbody > tr > td.marked {
3735 background: #ddd;
3736 border-bottom: #aaa 1px solid;
3737 background: -webkit-linear-gradient(#eee, #ddd);
3738 background: -moz-linear-gradient(#eee, #ddd);
3739 background: -o-linear-gradient(#eee, #ddd);
3740 filter: progid:dximagetransform.microsoft.gradient(startcolorstr=#eeeeee, endcolorstr=#dddddd);
3741 }
3742
3743 .tables > tbody > tr > td:first-child {
3744
3745 }
3746
3747
3748 /* @ls2 */
3749
3750 .ls2 th { background: #ccc; }
3751 .ls2 th th { background-color: none; }
3752 .ls2 td { background: #f5f5f5; }
3753 .ls2 td td { background-color: none; }
3754 .ls2 th, .ls2 td { padding: 0.1em 0.5em; }
3755 .ls2 th th, .ls2 td td { padding: 0; }
3756 .ls2 th { text-align: left; vertical-align: top; line-height: 1.7em; background: #e0e0e0; font-weight: normal; }
3757 .ls2 th th { line-height: normal; background-color: none; }
3758 .ls2 .none { background: none; padding-top: 0.4em; }
3759
3760 div.poweredby { }
3761
3762 /* @tooltip */
3763
3764 div.tooltip {
3765 background: #fff;
3766 padding: 0.75em 1em;
3767 font: 11px Tahoma; line-height: 1.4em;
3768 border: 1px solid #bbb;
3769 border-radius: 4px;
3770 box-shadow: 1px 1px 8px #ccc;
3771 opacity: 0;
3772 -webkit-transition: opacity 200ms ease-in;
3773 -moz-transition: opacity 200ms ease-in;
3774 -o-transition: opacity 200ms ease-in;
3775 -ms-transition: opacity 200ms ease-in;
3776 transition: opacity 200ms ease-in;
3777 }
3778
3779 /* @help */
3780
3781 .help {
3782 width: 15px; height: 15px;
3783 background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAbJJREFUKFNtk79rFEEUxz9zu1GjnAcWFv4GUxwWEkuVNJFoShs5ECKIKdJbBDlLBcFUFoY0KRSEgP+ACAch3VVphJNESUQNhCRmPXPr7uzMs1h2nL3Lt5mZN3y+82beG0WfRET6Y4WUUspfh/5CROTOoya3r11wsc1fGoDPG1uIiPgGDhYRmZqd49XLZ0RJvv9tXzMcVwCoA1ennpcMQh98OvuYxfYevhJtAEh1xuR0s2QQiojcaszwen6exfYeiTZcP3+UxmjNGSytRrTWUqLt70xONzk7dh8REZf2l50EAGMsjdEaS6sRy18PMMaycO8cHzr7DAUBAPUzJwGo4KlI0Qd9aWP4k/4vRum1jbEYa0snArxp76DTjCDMz+r8/D0Ipzpz85sXjznwYyfiMDm4ZwK0MQwF+dha75YgbcwA7O68HVfoxQnaGKy1jI9UefvgMhP1mgPj5G8JVpDXeezuQ27MzLG5tUuWaQ7T6UtXaC08ofP+BUopFULes75BNzhF76BbAo+fqDrQ2rwKpUYvDKLqCABpnBscGa6yu/GJHyvvsNYSBIEagAuD/lih/l/1D+7b7TstfO0wAAAAAElFTkSuQmCC") no-repeat;
3784 display: inline-block;
3785 margin-bottom: -3px;
3786 }
3787 .help:hover {
3788 background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAa5JREFUKFNtk71rFEEYxn+ztxya00AwQUGJhVhoGq0Ei1jYKFhGQUhxVUCIIBjBwr9AtFSEKwSTLqCFRSrRWCmICCLx64oLNibEYC57H3s781hsbp255Glm3nfm98zXO4YBSdJgri9jjPHj2A8k6fD9Ra5NDBe5j1ne//ntF5LkGxSwJJ1+9oa3s1P8zfLxRmI51duZe/Yc++8uBgaxD76YusCTlW18dTObtz3LzemroYEkjd57rK+J060PW7rxblPzjUS+5huJqstrqi6v6c5nyVy5LUkqtv29mQFgnZgeH2JhtcXr1TbOOZ5OjrFUb1IuRQAcOnMCgGivLfqgr9Q6kuz/YwS3bZ3IrAtWBKjVm7S7olzO5218qu+G015W9M8f3VeASz8S9lIBd1xEah3lUt6+aiQB1HIRpOExijOv9wwbbUNqHVbi4vEKzy8d4fLJSg4Cf7LgijCQv/PI3EOq12dY+d2mEy5QaOLYGLVajfTRDMYYE0Nes75BWjrAVtIKwOHKUAHanfIPCr1v0InHAbDNTQBKB0fofnmPe/kAKxFHkdkF9w0Gc30N/qp/BbAB6d6RyA0AAAAASUVORK5CYII=") no-repeat;
3789 }
3790
3791
3792 </style>
3793
3794 <script>
3795
3796 // @scripts
3797 // @js
3798
3799 function Element(id)
3800 {
3801 if (typeof id == "string") {
3802 return document.getElementById(id);
3803 } else {
3804 return id;
3805 }
3806 }
3807 function sprintf(text){
3808 var i=1, args=arguments;
3809 return text.replace(/%s/g, function(pattern){
3810 return (i < args.length) ? args[i++] : "";
3811 });
3812 }
3813
3814 // @popup
3815
3816 function popup(url, width, height, more)
3817 {
3818 if (!width) width = <?php echo SQL_POPUP_WIDTH; ?>;
3819 if (!height) height = <?php echo SQL_POPUP_HEIGHT; ?>;
3820 var x = (screen.width/2-width/2);
3821 var y = (screen.height/2-height/2);
3822 window.open(url, "", "scrollbars=yes,resizable=yes,width="+width+",height="+height+",screenX="+(x)+",screenY="+y+",left="+x+",top="+y+(more ? ","+more : ""));
3823 }
3824
3825 // @noreferer
3826
3827 function link_noreferer(link)
3828 {
3829 // Tested: Chrome, Firefox, Inetrnet Explorer, Opera.
3830 var w = window.open("about:blank", "_blank");
3831 w.document.open();
3832 w.document.write("<"+"!doctype html>");
3833 w.document.write("<"+"html><"+"head>");
3834 w.document.write("<"+"title>Secure redirect</title>");
3835 w.document.write("<"+"style>");
3836 w.document.write("body { font: 11px Tahoma; line-height: 1.4em; margin: 1em 1.5em; }");
3837 w.document.write("h1 { font: bold 15px Tahoma; color: #000; text-shadow: 1px 1px 1px #fff; }");
3838 w.document.write("h1 a { font: normal 13px Tahoma; } h1 small { font: normal 11px Tahoma; }");
3839 w.document.write("a, a:visited { color: rgb(0,110,255); display: inline-block; margin-top: 0.25em; }");
3840 w.document.write("<"+"/style>");
3841 w.document.write("<"+"meta http-equiv=refresh content='10;url="+link+"'>");
3842 // Meta.setAttribute() doesn't work on firefox.
3843 // Firefox: needs document.write('<meta>')
3844 // IE: the firefox workaround doesn't work on ie, but we can use a normal redirection
3845 // as IE is already not sending the referer because it does not do it when using
3846 // open.window, besides the blank url in address bar works fine (about:blank).
3847 // Opera: firefox fix works.
3848 w.document.write("<"+"script>var xcount=10; var xtimer=null; function counter(){ --xcount; if (xcount < 0) return; document.getElementById('xseconds').innerHTML = xcount; } xtimer = setInterval(counter, 1000);<"+"/script>");
3849 w.document.write("<"+"script>function redirect() { clearInterval(xtimer); document.getElementById('xseconds').innerHTML = '0'; if (navigator.userAgent.indexOf('MSIE') != -1) { location.replace('"+link+"'); } else { document.open(); document.write('<"+"meta http-equiv=refresh content=\"0;"+link+"\">'); document.close(); } }<"+"/script>");
3850 w.document.write("<"+"/head><"+"body>");
3851 w.document.write("<"+"h1>Secure redirect to:<br><a href=\"javascript:;\" onclick=\"redirect()\">"+link+"</a> <br><small>(safe to click)</small><"+"/h1>");
3852 w.document.write("<"+"p>This is a secure redirect that hides the HTTP REFERER header.");
3853 w.document.write("<br>The site you are being redirected won't know the location of the dbkiss script.");
3854 w.document.write("<br>In <b id=xseconds>10</b> seconds you will be redirected to that address. ");
3855 w.document.write("<"+"/body><"+"/html>");
3856 w.document.close();
3857 }
3858
3859 /* @tooltip */
3860
3861 var Tooltip_Div = null;
3862 var Tooltip_OverElem = null;
3863 if (document.addEventListener) {
3864 document.addEventListener('click', Tooltip_Hide, false);
3865 } else {
3866 document.attachEvent("onclick", Tooltip_Hide);
3867 }
3868
3869
3870 function Tooltip(overElem, textOrId, isPlaintext)
3871 {
3872 Tooltip_OverElem = overElem;
3873 Tooltip_Hide();
3874
3875 var text = textOrId;
3876
3877 if (text.length < 30 && document.getElementById(text)) {
3878 // Instead of text we can pass and id of the element that contains the text.
3879 text = document.getElementById(text).innerHTML;
3880 }
3881
3882 var div = document.createElement('DIV');
3883 div.className = 'tooltip';
3884
3885 if (isPlaintext) {
3886 div.innerHTML = text.replace(/\n/g, "<br>");
3887 } else {
3888 div.innerHTML = text;
3889 }
3890
3891 var top = 0;
3892 var left = 0;
3893
3894 var rects = overElem.getClientRects();
3895 if (rects.length) {
3896 top = rects[0].top + window.pageYOffset;
3897 left = rects[0].right + 10 + window.pageYOffset;
3898 }
3899
3900 div.style.position = 'absolute';
3901 div.style.top = top+'px';
3902 div.style.left = left+'px';
3903
3904 Tooltip_Div = div;
3905 document.body.appendChild(div);
3906
3907 window.setTimeout(function(){
3908 div.style.opacity = 1;
3909 }, 13);
3910 }
3911 function Tooltip_Hide(event)
3912 {
3913 if (event && event.target == Tooltip_OverElem) {
3914 return;
3915 }
3916 if (Tooltip_Div && Tooltip_Div.parentNode) {
3917 var div = Tooltip_Div;
3918 div.style.opacity = 0;
3919 window.setTimeout(function(){
3920 document.body.removeChild(div);
3921 }, 500);
3922 }
3923 Tooltip_Div = null;
3924 }
3925
3926 // @mark_row
3927
3928 function mark_row(tr, event)
3929 {
3930 // User might be selecting text, but onclick="" event will be also fired.
3931 // We detect whether user is selecting or unselecting, in that case we do not mark the row.
3932 var selection = window.getSelection();
3933 if (selection.rangeCount > 0) {
3934 // Range - making selection in row.
3935 // None - unselecting text.
3936 // Caret - normal click on a row.
3937 if (selection.type == "Range" || selection.type == "None") {
3938 return;
3939 }
3940 }
3941
3942 var event = event ? event : window.event;
3943 if (event && event.target && "TD" != event.target.tagName) {
3944 // So that clicking "Edit" or a parsed link does not mark the row.
3945 return 0;
3946 }
3947
3948 var els = tr.getElementsByTagName('td');
3949 if (tr.marked) {
3950 for (var i = 0; i < els.length; i++) {
3951 els[i].className = els[i].className.replace(/\bmarked\b/, "");
3952 }
3953 els = null;
3954 tr.marked = false;
3955
3956 var prev_td = tr.previousElementSibling.firstElementChild;
3957 if (prev_td.innerText != "#") {
3958 if (!/\bmarked\b/.test(prev_td)) {
3959 prev_els = tr.previousElementSibling.getElementsByTagName("td");
3960 for (var i = 0; i < prev_els.length; i++) {
3961 prev_els[i].className = prev_els[i].className.replace(/\bnext_marked\b/, "");
3962 }
3963 }
3964 }
3965 } else {
3966 for (var i = 0; i < els.length; i++) {
3967 els[i].className += " marked";
3968 }
3969 tr.marked = true;
3970 els = null;
3971
3972 var prev_td = tr.previousElementSibling.firstElementChild;
3973 if (prev_td.innerText != "#") {
3974 if (!/\bmarked\b/.test(prev_td)) {
3975 prev_els = tr.previousElementSibling.getElementsByTagName("td");
3976 for (var i = 0; i < prev_els.length; i++) {
3977 prev_els[i].className += " next_marked";
3978 }
3979 }
3980 }
3981 }
3982 }
3983
3984 var IS_CTRL = 0;
3985
3986 if (document.addEventListener) {
3987 document.addEventListener("keydown", function(event){
3988 if (17 == event.keyCode) {
3989 IS_CTRL = 1;
3990 }
3991 }, false);
3992 } else {
3993 document.attachEvent("onkeydown", function(event){
3994 event = event ? event : window.event;
3995 if (17 == event.keyCode) {
3996 IS_CTRL = 1;
3997 }
3998 });
3999 }
4000
4001 if (document.addEventListener) {
4002 document.addEventListener("keyup", function(event){
4003 if (17 == event.keyCode) {
4004 IS_CTRL = 0;
4005 }
4006 }, false);
4007 } else {
4008 document.attachEvent("onkeyup", function(event){
4009 event = event ? event : window.event;
4010 if (17 == event.keyCode) {
4011 IS_CTRL = 0;
4012 }
4013 });
4014 }
4015
4016 function ElementPosition(elem, event)
4017 {
4018 // You can pass any "event", it does not have to be related
4019 // with given element, it is only required because mouse position
4020 // can be fetched only from event object and firefox does not
4021 // support "window.event".
4022
4023 var rect = elem.getBoundingClientRect();
4024
4025 var pageX = rect.left + window.pageXOffset;
4026 var pageY = rect.top + window.pageYOffset;
4027
4028 var mouseX = -1;
4029 var mouseY = -1;
4030 if (event) {
4031 if (event.target === elem && "offsetX" in event) {
4032 // Firefox does not support "offsetX".
4033 mouseX = event.offsetX;
4034 mouseY = event.offsetY;
4035 } else {
4036 mouseX = event.pageX - pageX;
4037 mouseY = event.pageY - pageY;
4038 }
4039 }
4040
4041 var hasMouse = false;
4042 if (mouseX >= 0 && mouseX <= rect.width && mouseY >= 0 && mouseY <= rect.height) {
4043 hasMouse = true;
4044 }
4045
4046 var ret = {
4047 "screenX": rect.left, // x-coordinate relative to the top-left corner of the screen.
4048 "screenY": rect.top,
4049 "pageX": pageX, // x-coordinate relative to the top-left corner of the browser window's client area.
4050 "pageY": pageY,
4051 "width": rect.width,
4052 "height": rect.height,
4053 "mouseX": mouseX, // mouse X coordinate relative to current element, -1 when hasMouse=false and no event passed.
4054 "mouseY": mouseY,
4055 "hasMouse": hasMouse
4056 };
4057
4058 return ret;
4059 }
4060 function ElementSide(elem, event)
4061 {
4062 // Which side of element mouse points at? Left, Right, Up or Down?
4063 pos = ElementPosition(elem, event);
4064 halfWidth = Math.floor(pos.width / 2);
4065 halfHeight = Math.floor(pos.height / 2);
4066 var left = false;
4067 var right = false;
4068 if (pos.mouseX > halfWidth) { right = true; }
4069 else { left = true; }
4070 return {
4071 "left": left,
4072 "right": right
4073 };
4074 }
4075 function Sort_Mouseover(target, event)
4076 {
4077 var side = ElementSide(target, event);
4078 var match, arrow1;
4079 if (match = target.innerHTML.match(/class="?((up|down)arrow1)"?/i)) {
4080 arrow1 = match[1];
4081 }
4082 var className;
4083 if (arrow1) {
4084 className = (arrow1 == "uparrow1") ? "downarrow2" : "uparrow2";
4085 } else {
4086 className = side.left ? "uparrow2" : "downarrow2";
4087 }
4088 var className_existing = "";
4089 var match;
4090 if (match = target.innerHTML.match(/class="?((up|down)arrow2)"?/i)) {
4091 className_existing = match[1];
4092 }
4093 if (!className_existing || (className_existing && className_existing != className)) {
4094 if (className_existing && className_existing != className) {
4095 // Special case: always remove arrow2 (see 3rd param "forceRemove")
4096 Sort_Mouseout(target, event, true);
4097 }
4098 var span = document.createElement("span");
4099 span.className = className;
4100 var parent = target;
4101 span.onmouseover = function(event){ Sort_Mouseover(parent, event); };
4102 span.onmouseout = function(event){ Sort_Mouseout(parent, event); };
4103 span.onmousedown = function(event){ Sort_Click(parent, event); };
4104 target.appendChild(span);
4105 }
4106 }
4107 function Sort_Mouseout(target, event, forceRemove)
4108 {
4109 target.innerHTML = target.innerHTML.replace(/\s*<span[^<>]+class="?(up|down)arrow2"?[^<>]*><\/span>/i, "");
4110 }
4111 function Sort_Mousemove(target, event)
4112 {
4113 Sort_Mouseover(target, event);
4114 }
4115 function Sort_Click(target, event)
4116 {
4117 console.log("Sort_Click", target, event);
4118 var side = ElementSide(target, event);
4119 var link = target.getAttribute("mylink");
4120 if (!link) {
4121 console.log(link, target, event);
4122 }
4123 if (target.innerHTML.match(/class="?((up|down)arrow1)"?/i)) {
4124 link = link;
4125 } else {
4126 if (side.left) {
4127 link = link.replace(/(order_desc=)\d+/, function(m0,m1){ return m1+"0"; });
4128 } else {
4129 link = link.replace(/(order_desc=)\d+/, function(m0,m1){ return m1+"1"; });
4130 }
4131 }
4132 window.location.href = link;
4133 }
4134
4135 </script>
4136
4137 <!-- @keys. Keyboard shortcuts - not doing anything, just so that Chrome does not make that annoying Ding sound. -->
4138
4139 <a accesskey=q href="javascript:;"></a>
4140 <a accesskey=z href="javascript:;"></a>
4141 <a accesskey=s href="javascript:;"></a>
4142
4143 <?php
4144}
4145
4146// @rawlayout
4147function rawlayout_start($title='')
4148{
4149 // @layout
4150 // Used in: Edit row, SQL Editor, SQL Popup, Search.
4151
4152 global $page_charset;
4153 $flash = flash();
4154 ?>
4155
4156 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4157 <html>
4158 <head>
4159 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $page_charset;?>">
4160 <meta name="robots" content="noindex, nofollow">
4161 <title><?php echo $title;?></title>
4162 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
4163 </head>
4164 <body>
4165
4166 <?php layout(); ?>
4167
4168 <?php if ($flash) { echo $flash; } ?>
4169
4170 <?php
4171}
4172function rawlayout_end()
4173{
4174 // @layout
4175 // Used in: Edit row, SQL Editor, SQL Popup, Search.
4176
4177 ?>
4178 </body>
4179 </html>
4180 <?php
4181}
4182function conn_info()
4183{
4184 // @conn_info
4185 // @connection
4186 // @info
4187
4188 global $db_driver, $db_server, $db_name, $db_user, $db_charset, $page_charset, $charset1, $charset2;
4189 $dbs = list_dbs();
4190 $db_name = $db_name;
4191 ?>
4192 <p>
4193 <?php if (SQLITE_USED): ?>
4194
4195 <?php
4196 $db_file = realpath($db_server);
4197 $base = basename($db_file);
4198 $db_file = substr($db_file, 0, strlen($db_file) - strlen($base));
4199 $db_file = "<b style=\"cursor: help;\" title=\"Located in: $db_file\">$base</b>";
4200 ?>
4201
4202 Database: <?php echo $db_file; ?>
4203 -
4204
4205 <!--
4206 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?execute_sql=1">SQL Editor</a>
4207 -
4208 -->
4209
4210 <a class=blue href="javascript:void(0)" onclick="popup('<?php echo $_SERVER['PHP_SELF'];?>?execute_sql=1&popup=1')">SQL Editor</a>
4211 -
4212
4213 <!--
4214 Charset: <b>UTF8</b>
4215 -
4216 -->
4217
4218 <?php if (defined("SQLITE_INSECURE")): ?>
4219 User: <b>No authentication</b>
4220 <?php else: ?>
4221 User: <b><?php echo $db_user; ?></b>
4222 <?php endif; ?>
4223
4224
4225
4226 <?php if (!defined("SQLITE_INSECURE")): ?>
4227 -
4228 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?disconnect=1">Disconnect</a>
4229 <?php endif; ?>
4230
4231 <?php else: ?>
4232
4233 Driver: <b><?php echo $db_driver;?></b>
4234 -
4235
4236 Server: <b><?php echo $db_server;?></b>
4237 -
4238
4239 User: <b><?php echo $db_user;?></b>
4240 -
4241
4242 <!--
4243 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?execute_sql=1">SQL Editor</a>
4244 -
4245 -->
4246
4247 <a class=blue href="javascript:void(0)" onclick="popup('<?php echo $_SERVER['PHP_SELF'];?>?execute_sql=1&popup=1')">SQL Editor</a>
4248 -
4249
4250 Data<u>b</u>ase: <select accesskey=b id="db_name" name="db_name" onchange="location='<?php echo $_SERVER['PHP_SELF'];?>?db_name='+this.value"><?php echo options($dbs, $db_name);?></select>
4251 -
4252
4253 Db charset: <select name="db_charset" onchange="location='<?php echo $_SERVER['PHP_SELF'];?>?db_charset='+this.value+'&from=<?php echo urlencode($_SERVER['REQUEST_URI']);?>'">
4254 <option value=""></option><?php echo options($charset1, $db_charset);?></select>
4255 -
4256
4257 Page charset: <select name="page_charset" onchange="location='<?php echo $_SERVER['PHP_SELF'];?>?page_charset='+this.value+'&from=<?php echo urlencode($_SERVER['REQUEST_URI']);?>'">
4258 <option value=""></option><?php echo options($charset2, $page_charset);?></select>
4259 -
4260
4261 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?disconnect=1">Disconnect</a>
4262
4263 <?php endif; ?>
4264
4265 <!--
4266 <div style="position: absolute; top: 1em; right: 1.5em;">
4267 DBKiss version: <a title="Check for updates" href="javascript:void(0)" onclick="link_noreferer('http://www.gosu.pl/dbkiss/')"><?php echo DBKISS_VERSION; ?></a>
4268 </div>
4269 -->
4270
4271 <div style="position: absolute; top: 1em; right: 1.5em;">
4272 DBKiss version: <b><?php echo DBKISS_VERSION; ?></b>
4273
4274 <a class=special href="javascript:void(0)" onclick="link_noreferer('http://www.gosu.pl/dbkiss/')">Check for updates</a>
4275 </div>
4276
4277 </p>
4278 <?php
4279}
4280
4281// @files
4282
4283function size($bytes)
4284{
4285 return number_format(ceil($bytes / 1024),0,'',' ').' k';
4286}
4287function file_ext($name)
4288{
4289 $ext = null;
4290 if (($pos = strrpos($name, '.')) !== false) {
4291 $len = strlen($name) - ($pos+1);
4292 $ext = substr($name, -$len);
4293 if (!preg_match('#^[a-z0-9]+$#i', $ext)) {
4294 return null;
4295 }
4296 }
4297 return $ext;
4298}
4299function file_put($file, $s)
4300{
4301 // file_put_contents is not supported in 4.3
4302 $fp = fopen($file, 'wb') or trigger_error('fopen() failed: '.$file, E_USER_ERROR);
4303 if ($fp) {
4304 fwrite($fp, $s);
4305 fclose($fp);
4306 }
4307}
4308function file_date($file)
4309{
4310 return date('Y-m-d H:i:s', filemtime($file));
4311}
4312function dir_exists($dir)
4313{
4314 return file_exists($dir) && !is_file($dir);
4315}
4316function dir_read($dir, $ignore_ext = array(), $allow_ext = array(), $sort = null)
4317{
4318 if (is_null($ignore_ext)) $ignore_ext = array();
4319 if (is_null($allow_ext)) $allow_ext = array();
4320 foreach ($allow_ext as $k => $ext) {
4321 $allow_ext[$k] = str_replace('.', '', $ext);
4322 }
4323
4324 $ret = array();
4325 if ($handle = opendir($dir)) {
4326 while (($file = readdir($handle)) !== false) {
4327 if ($file != '.' && $file != '..') {
4328 $ignore = false;
4329 foreach ($ignore_ext as $ext) {
4330 if (file_ext_has($file, $ext)) {
4331 $ignore = true;
4332 }
4333 }
4334 if (is_array($allow_ext) && count($allow_ext) && !in_array(file_ext($file), $allow_ext)) {
4335 $ignore = true;
4336 }
4337 if (!$ignore) {
4338 $ret[] = array(
4339 'file' => $dir.'/'.$file,
4340 'time' => filemtime($dir.'/'.$file)
4341 );
4342 }
4343 }
4344 }
4345 closedir($handle);
4346 }
4347 if ('date_desc' == $sort) {
4348 $ret = array_sort_desc($ret, 'time');
4349 }
4350 return array_col($ret, 'file');
4351}
4352function sql_files()
4353{
4354 $files = dir_read('.', null, array('.sql'));
4355 $files2 = array();
4356 foreach ($files as $file) {
4357 $files2[md5($file)] = $file.sprintf(' (%s)', size(filesize($file)));
4358 }
4359 return $files2;
4360}
4361function sql_files_assoc()
4362{
4363 $files = dir_read('.', null, array('.sql'));
4364 $files2 = array();
4365 foreach ($files as $file) {
4366 $files2[md5($file)] = $file;
4367 }
4368 return $files2;
4369}
4370
4371// @array
4372
4373function array_assoc($a)
4374{
4375 $ret = array();
4376 foreach ($a as $v) {
4377 $ret[$v] = $v;
4378 }
4379 return $ret;
4380}
4381function array_col($arr, $col)
4382{
4383 $ret = array();
4384 foreach ($arr as $k => $row) {
4385 $ret[] = $row[$col];
4386 }
4387 return $ret;
4388}
4389function array_sort_desc($arr, $col_key)
4390{
4391 if (is_array($col_key)) {
4392 foreach ($arr as $k => $v) {
4393 $arr[$k]['__array_sort'] = '';
4394 foreach ($col_key as $col) {
4395 $arr[$k]['__array_sort'] .= $arr[$k][$col].'_';
4396 }
4397 }
4398 $col_key = '__array_sort';
4399 }
4400 uasort($arr, create_function('$a,$b', 'return strnatcasecmp($b["'.$col_key.'"], $a["'.$col_key.'"]);'));
4401 if ('__array_sort' == $col_key) {
4402 foreach ($arr as $k => $v) {
4403 unset($arr[$k]['__array_sort']);
4404 }
4405 }
4406 return $arr;
4407}
4408function array_first_key($arr)
4409{
4410 $arr2 = $arr;
4411 reset($arr);
4412 list($key, $val) = each($arr);
4413 return $key;
4414}
4415function array_first($arr)
4416{
4417 $arr2 = $arr;
4418 return array_shift($arr2);
4419}
4420function array_col_values($arr, $col)
4421{
4422 $ret = array();
4423 foreach ($arr as $k => $row) {
4424 $ret[] = $row[$col];
4425 }
4426 return $ret;
4427}
4428function array_col_values_unique($arr, $col)
4429{
4430 return array_unique(array_col_values($arr, $col));
4431}
4432function array_col_match($rows, $col, $pattern)
4433{
4434 if (!count($rows)) {
4435 trigger_error('array_col_match(): array is empty', E_USER_ERROR);
4436 }
4437 $ret = true;
4438 foreach ($rows as $row) {
4439 if (!preg_match($pattern, $row[$col])) {
4440 return false;
4441 }
4442 }
4443 return true;
4444}
4445function array_col_match_unique($rows, $col, $pattern)
4446{
4447 if (!array_col_match($rows, $col, $pattern)) {
4448 return false;
4449 }
4450 return count($rows) == count(array_col_values_unique($rows, $col));
4451}
4452
4453// @url
4454
4455function self($cut_query = false)
4456{
4457 $uri = $_SERVER['REQUEST_URI'];
4458 if ($cut_query) {
4459 $before = str_before($uri, '?');
4460 if ($before) {
4461 return $before;
4462 }
4463 }
4464 return $uri;
4465}
4466function url($script, $params = array())
4467{
4468 $query = '';
4469
4470 /* remove from script url, actual params if exist */
4471 foreach ($params as $k => $v) {
4472 $exp = sprintf('#(\?|&)%s=[^&]*#i', $k);
4473 if (preg_match($exp, $script)) {
4474 $script = preg_replace($exp, '', $script);
4475 }
4476 }
4477
4478 /* repair url like 'script.php&id=12&asd=133' */
4479 $exp = '#\?\w+=[^&]*#i';
4480 $exp2 = '#&(\w+=[^&]*)#i';
4481 if (!preg_match($exp, $script) && preg_match($exp2, $script)) {
4482 $script = preg_replace($exp2, '?$1', $script, 1);
4483 }
4484
4485 foreach ($params as $k => $v) {
4486 if (!strlen($v)) continue;
4487 if ($query) { $query .= '&'; }
4488 else {
4489 if (strpos($script, '?') === false) {
4490 $query .= '?';
4491 } else {
4492 $query .= '&';
4493 }
4494 }
4495 if ('%s' != $v) {
4496 $v = urlencode($v);
4497 }
4498 $v = preg_replace('#%25(\w+)%25#i', '%$1%', $v); // %id_news% etc. used in listing
4499 $query .= sprintf('%s=%s', $k, $v);
4500 }
4501 return $script.$query;
4502}
4503function url_offset($offset, $params = array())
4504{
4505 $url = $_SERVER['REQUEST_URI'];
4506 if (preg_match('#&offset=\d+#', $url)) {
4507 $url = preg_replace('#&offset=\d+#', '&offset='.$offset, $url);
4508 } else {
4509 $url .= '&offset='.$offset;
4510 }
4511 return $url;
4512}
4513
4514// @time
4515
4516function time_micro()
4517{
4518 list($usec, $sec) = explode(" ", microtime());
4519 return ((float)$usec + (float)$sec);
4520}
4521function time_start()
4522{
4523 return time_micro();
4524}
4525function time_end($start)
4526{
4527 $end = time_micro();
4528 $end = round($end - $start, 3);
4529 $end = pad_zeros($end, 3);
4530 return $end;
4531}
4532function pad_zeros($number, $zeros)
4533{
4534 if (strstr($number, '.')) {
4535 preg_match('#\.(\d+)$#', $number, $match);
4536 $number .= str_repeat('0', $zeros-strlen($match[1]));
4537 return $number;
4538 } else {
4539 return $number.'.'.str_repeat('0', $zeros);
4540 }
4541}
4542
4543// @string
4544
4545function str_has_any($str, $arr_needle, $ignore_case = false)
4546{
4547 if (is_string($arr_needle)) {
4548 $arr_needle = preg_replace('#\s+#', ' ', $arr_needle);
4549 $arr_needle = explode(' ', $arr_needle);
4550 }
4551 foreach ($arr_needle as $needle) {
4552 if (str_has($str, $needle, $ignore_case)) {
4553 return true;
4554 }
4555 }
4556 return false;
4557}
4558function str_before($str, $needle)
4559{
4560 $pos = strpos($str, $needle);
4561 if ($pos !== false) {
4562 $before = substr($str, 0, $pos);
4563 return strlen($before) ? $before : false;
4564 } else {
4565 return false;
4566 }
4567}
4568function ConvertPolishToUTF8($String)
4569{
4570 // @polish
4571
4572 // Converts "windows-1250" and "iso-8859-2" chars to UTF-8 equivalent.
4573 $ReplacePairs = array(
4574 "\xb9" => "\xc4\x85", "\xa5" => "\xc4\x84", "\xe6" => "\xc4\x87", "\xc6" => "\xc4\x86", "\xea" => "\xc4\x99", "\xca" => "\xc4\x98",
4575 "\xb3" => "\xc5\x82", "\xa3" => "\xc5\x81", "\xf1" => "\xc5\x84", "\xd1" => "\xc5\x83", "\xf3" => "\xc3\xb3", "\xd3" => "\xc3\x93",
4576 "\x9c" => "\xc5\x9b", "\x8c" => "\xc5\x9a", "\x9f" => "\xc5\xba", "\x8f" => "\xc5\xb9", "\xbf" => "\xc5\xbc", "\xaf" => "\xc5\xbb",
4577 "\xb1" => "\xc4\x85", "\xa1" => "\xc4\x84", "\xe6" => "\xc4\x87", "\xc6" => "\xc4\x86", "\xea" => "\xc4\x99", "\xca" => "\xc4\x98",
4578 "\xb3" => "\xc5\x82", "\xa3" => "\xc5\x81", "\xf1" => "\xc5\x84", "\xd1" => "\xc5\x83", "\xf3" => "\xc3\xb3", "\xd3" => "\xc3\x93",
4579 "\xb6" => "\xc5\x9b", "\xa6" => "\xc5\x9a", "\xbc" => "\xc5\xba", "\xac" => "\xc5\xb9", "\xbf" => "\xc5\xbc", "\xaf" => "\xc5\xbb"
4580 );
4581 // Cannot use str_replace() cause it replaces the replaced matches if the new string is longer, and UTF-8
4582 // consists of 2 chars so we must use strtr that does not replace stuff that it already has worked on.
4583 return strtr($String, $ReplacePairs);
4584}
4585
4586// @error
4587
4588global $_error, $_error_style;
4589$_error = array();
4590$_error_style = '';
4591
4592function error($msg = null)
4593{
4594 if (isset($msg) && func_num_args() > 1) {
4595 $args = func_get_args();
4596 $msg = call_user_func_array('sprintf', $args);
4597 }
4598 global $_error, $_error_style;
4599 if (isset($msg)) {
4600 $_error[] = $msg;
4601 }
4602 if (!count($_error)) {
4603 return null;
4604 }
4605 if (count($_error) == 1) {
4606 return sprintf('<div class="error" style="%s">%s</div>', $_error_style, $_error[0]);
4607 }
4608 $ret = '<div class="error" style="'.$_error_style.'">Following errors appeared:<ul>';
4609 foreach ($_error as $msg) {
4610 $ret .= sprintf('<li>%s</li>', $msg);
4611 }
4612 $ret .= '</ul></div>';
4613 return $ret;
4614}
4615
4616// @date
4617
4618function timestamp($time, $span = true)
4619{
4620 $time_base = $time;
4621 $time = substr($time, 0, 16);
4622 $time2 = substr($time, 0, 10);
4623 $today = date('Y-m-d');
4624 $yesterday = date('Y-m-d', time()-3600*24);
4625 if ($time2 == $today) {
4626 if (substr($time_base, -8) == '00:00:00') {
4627 $time = 'Today';
4628 } else {
4629 $time = 'Today'.substr($time, -6);
4630 }
4631 } else if ($time2 == $yesterday) {
4632 $time = 'Yesterday'.substr($time, -6);
4633 }
4634 return '<span style="white-space: nowrap;">'.$time.'</span>';
4635}
4636
4637// @redirect
4638
4639function redirect($url)
4640{
4641 $url = url($url);
4642 header("Location: $url");
4643 exit;
4644}
4645function redirect_notify($url, $msg)
4646{
4647 if (strpos($msg, '<') === false) {
4648 $msg = sprintf('<b>%s</b>', $msg);
4649 }
4650 cookie_set('flash_notify', $msg);
4651 redirect($url);
4652}
4653function redirect_ok($url, $msg)
4654{
4655 if (strpos($msg, '<') === false) {
4656 $msg = sprintf('<b>%s</b>', $msg);
4657 }
4658 cookie_set('flash_ok', $msg);
4659 redirect($url);
4660}
4661function redirect_error($url, $msg)
4662{
4663 if (strpos($msg, '<') === false) {
4664 $msg = sprintf('<b>%s</b>', $msg);
4665 }
4666 cookie_set('flash_error', $msg);
4667 redirect($url);
4668}
4669
4670// @flash
4671
4672function flash()
4673{
4674 static $is_style = false;
4675
4676 $flash_error = cookie_get('flash_error');
4677 $flash_ok = cookie_get('flash_ok');
4678 $flash_notify = cookie_get('flash_notify');
4679
4680 if (!($flash_error || $flash_ok || $flash_notify)) {
4681 return false;
4682 }
4683
4684 ob_start();
4685 ?>
4686
4687 <?php if (!$is_style): ?>
4688 <style type="text/css">
4689 #flash { background: #ffffd7; padding: 0.3em; padding-bottom: 0.15em; border: #ddd 1px solid; margin-bottom: 1em; }
4690 #flash div { padding: 0em 0em; }
4691 #flash table { font-weight: normal; }
4692 #flash td { text-align: left; }
4693 </style>
4694 <?php endif; ?>
4695
4696 <div id="flash" ondblclick="document.getElementById('flash').style.display='none';">
4697 <table width="100%" ondblclick="document.getElementById('flash').style.display='none';"><tr>
4698 <td style="line-height: 14px;"><?php echo $flash_error ? $flash_error : ($flash_ok ? $flash_ok : $flash_notify); ?></td></tr></table>
4699 </div>
4700
4701 <?php
4702 $cont = ob_get_contents();
4703 ob_end_clean();
4704
4705 if ($flash_error) cookie_del('flash_error');
4706 else if ($flash_ok) cookie_del('flash_ok');
4707 else if ($flash_notify) cookie_del('flash_notify');
4708
4709 $is_style = true;
4710
4711 return $cont;
4712}
4713
4714// @parsetime @naturaltime
4715function ParseTime($string, $now_unix=null)
4716{
4717 // ParseTime(): converts time in natural form to unix timestamp.
4718 // English and Polish words supported.
4719 // Author: Czarek Tomczak [czarek.tomczak@gosu.pl] (07-11-2011)
4720
4721 // + now, NOW, now(), NOW(), time, TIME, time(), TIME(), today, teraz, dzisiaj, dzis
4722 // + today 12:00 + current seconds
4723 // + today/now/dzisiaj 12:13:13
4724 // + yesterday, tomorrow (PL: wczoraj, jutro)
4725 // + tomorrow 12:30, dzis 12:13:13
4726
4727 static $static_now;
4728 if (!isset($static_now)) { $static_now = time(); }
4729
4730 if (isset($now_unix)) {
4731 $now = $now_unix;
4732 } else {
4733 $now = $static_now;
4734 }
4735
4736 static $static_hour;
4737 if (!isset($static_hour)) { $static_hour = (int) date("H", $static_now); }
4738 if (isset($now_unix)) { $now_hour = (int) date("H", $now_unix); }
4739 else { $now_hour = $static_hour; }
4740
4741 static $static_minute;
4742 if (!isset($static_minute)) { $static_minute = (int) date("i", $static_now);}
4743 if (isset($now_unix)) { $now_minute = (int) date("i", $now_unix); }
4744 else { $now_minute = $static_minute; }
4745
4746 static $static_second;
4747 if (!isset($static_second)) { $static_second = (int) date("s", $static_now); }
4748 if (isset($now_unix)) { $now_second = (int) date("s", $now_unix); }
4749 else { $now_second = $static_second; }
4750
4751 static $static_month;
4752 if (!isset($static_month)) { $static_month = (int) date("n", $static_now); }
4753 if (isset($now_unix)) { $now_month = (int) date("n", $now_unix); }
4754 else { $now_month = $static_month; }
4755
4756 static $static_day;
4757 if (!isset($static_day)) { $static_day = (int) date("j", $static_now); }
4758 if (isset($now_unix)) { $now_day = (int) date("j", $now_unix); }
4759 else { $now_day = $static_day; }
4760
4761 static $static_year;
4762 if (!isset($static_year)) { $static_year = (int) date("Y", $static_now); }
4763 if (isset($now_unix)) { $now_year = (int) date("Y", $now_unix); }
4764 else { $now_year = $static_year; }
4765
4766 static $static_dayofweek;
4767 if (!isset($static_dayofweek)) {
4768 $static_dayofweek = (int) date("w", $static_now);
4769 // 0 = sunday, make it 7
4770 if (0 == $static_dayofweek) {
4771 $static_dayofweek = 7;
4772 }
4773 }
4774 if (isset($now_unix)) {
4775 $now_dayofweek = (int) date("w", $now_unix);
4776 if (0 == $now_dayofweek) {
4777 $now_dayofweek = 7;
4778 }
4779 }
4780 else { $now_dayofweek = $static_dayofweek; }
4781
4782 // Removes polish chars "ą">"a", "ś">"s", so we can later detect "dzień" or "środa" by comparing
4783 // chars without tails "dzien", "sroda". Removing tails is supported for 3 charsets.
4784
4785 static $win_chars = "\xb9\xe6\xea\xb3\xf1\xf3\x9c\x9f\xbf\xa5\xc6\xca\xa3\xd1\xd3\x8c\x8f\xaf"; // windows-1250
4786 static $iso_chars = "\xb1\xe6\xea\xb3\xf1\xf3\xb6\xbc\xbf\xa1\xc6\xca\xa3\xd1\xd3\xa6\xac\xaf"; // iso-8859-2
4787 static $notail_chars = "acelnoszzACELNOSZZ";
4788 static $utf_map = array("\xc4\x85"=>"a", "\xc4\x84"=>"A", "\xc4\x87"=>"c", "\xc4\x86"=>"C", "\xc4\x99"=>"e", "\xc4\x98"=>"E", "\xc5\x82"=>"l", "\xc5\x81"=>"L", "\xc3\xb3"=>"o", "\xc3\x93"=>"O", "\xc5\x9b"=>"s", "\xc5\x9a"=>"S", "\xc5\xba"=>"z", "\xc5\xb9"=>"Z", "\xc5\xbc"=>"z", "\xc5\xbb"=>"Z", "\xc5\x84"=>"n", "\xc5\x83"=>"N");
4789
4790 $string = strtr($string, $win_chars, $notail_chars);
4791 $string = strtr($string, $iso_chars, $notail_chars);
4792 $string = strtr($string, $utf_map);
4793
4794 // To lower. "Dzień" > "Dzien" > "dzien"
4795
4796 $string = strtolower($string);
4797
4798 // en: "next Monday" = +1 Monday, "last"Monday" = -1 Monday, "prev Monday", "previous monday"
4799 // pl: "nastepny Poniedzialek", "poprzedni Poniedzialek", "ostatni poniedziałek"
4800
4801 // note: "prev" needs to be replaced after "previous", cause "ious" might come out of the replacement.
4802 static $replace_keys = array("next", "last", "previous", "prev", "nastepny", "poprzedni", "ostatni");
4803 static $replace_vals = array("+1", "-1", "-1", "-1", "+1", "-1", "-1");
4804 $string = str_replace($replace_keys, $replace_vals, $string);
4805
4806 // "in 2 days at 5:00" => remove "in", "at"
4807 // "in 2 days and 5 hours" => remove "and"
4808 // "za 2 dni o 5:00", "za 2 dni i 5 godzin oraz 5 minut i 6 sekund"
4809 $string = preg_replace("#(\b)(in|at|and|za|oraz|o|i)(\b)#", "\$1\$3", $string);
4810
4811 // Cut day endings.
4812
4813 // en:
4814 // "1st february" > "1 february"
4815 // "2nd Feb" > "2 Feb"
4816 // "3rd Feb" > "3 Feb",
4817 // "4th Feb 2013" > "4 Feb 2013"
4818
4819 $string = preg_replace("#(\d+)\-?(st|nd|rd|th)(\s)#i", "\$1\$3", $string);
4820
4821 // pl:
4822 // "1szy Lutego", "1-szy lutego" > "1 lutego"
4823 // "2gi Lutego", "2-gi lutego" > "2 lutego"
4824 // "3ci Lutego", "3-ci lutego"
4825 // "4ty Lutego", "4-ty lutego", "5ty", "6ty", "9ty", "10ty", "11ty
4826 // "7my lutego", "7-my lutego", "8my"
4827
4828 $string = preg_replace("#(\d+)\-?(szy|gi|ci|ty|my)(\s)#i", "\$1\$3", $string);
4829
4830 // Start mktime values.
4831 $start_year = $now_year;
4832 $start_month = $now_month;
4833 $start_day = $now_day;
4834 $start_hour = $now_hour;
4835 $start_minute = $now_minute;
4836 $start_second = $now_second;
4837
4838 // +11.05 = 2011-05-11 (current year) + current hour, minutes, seconds
4839 // +11.05.2011 (day.month.year)
4840 // +11.05.2011 15:30 + current seconds
4841 // +11.05.2011 15:30:13
4842 // +11.05 12:30
4843 // +11.05 12:30:13
4844 // + "11.05", "11.05 15:30", "11.05 15:30:13", "11.05.2011", "11.05.2011 15:30", "11.05.2011 15:30:13",
4845
4846 if (preg_match("#(\d\d)\.(\d\d)(\.(\d\d\d\d))?#", $string, $match))
4847 {
4848 $string = preg_replace("#".preg_quote($match[0], "#")."#", "", $string, 1);
4849
4850 $start_day = (int) $match[1];
4851 $start_month = (int) $match[2];
4852 if (isset($match[3])) {
4853 $start_year = (int) $match[4];
4854 } else {
4855 $start_year = $now_year;
4856 }
4857 }
4858
4859 // +"2011-05-11"
4860 // +"2011-05" = "2011-05-currentday"'
4861 // +"2011" = "2011-currmonth-currday"
4862 // +"2011 15:00"
4863
4864 // Daty typu "11.05.2011" muszą być wykonane przed tym regexpem bo
4865 // inaczej wyłapie rok z tej daty "2011".
4866
4867 if (preg_match("#(\d\d\d\d)(-(\d\d)(-(\d\d)))?#", $string, $match))
4868 {
4869 $string = preg_replace("#".preg_quote($match[0], "#")."#", "", $string, 1);
4870
4871 $start_year = (int) $match[1];
4872 if (isset($match[2])) {
4873 $start_month = (int) $match[3];
4874 if (isset($match[4])) {
4875 $start_day = (int) $match[5];
4876 } else {
4877 $start_day = 1;
4878 }
4879 } else {
4880 $start_month = 1;
4881 $start_day = 1;
4882 }
4883 }
4884
4885 $HoursFound = false;
4886
4887 // Hours: "15:30", "15:30:13",
4888 if (preg_match("#(\d\d):(\d\d)(:(\d\d))?#i", $string, $match))
4889 {
4890 $HoursFound = true;
4891 $string = preg_replace("#".preg_quote($match[0], "#")."#", "", $string, 1);
4892
4893 $start_hour = (int) $match[1];
4894 $start_minute = (int) $match[2];
4895 if (isset($match[3])) {
4896 // "15:30:13"
4897 $start_second = (int) $match[4];
4898 } else {
4899 $start_second = 0;
4900 }
4901 }
4902
4903 // + 12d, +12d, + 12d, +12 day, +12 days = time() + 12 days
4904 // + -5h = time() - 5 hours
4905 // + 1y - 5d + 5h = time() + 1year - 5 days + 5 hours
4906 // + -5d 15:55 = time() - 5 days
4907 // + -1week 12:00, -1 Week 12:00, - 1 week 12:00:53
4908 // + -1w
4909
4910 // + "now", " now", "now()", "time", "NOW()", "TIME()", "Today", "teraz", "dzisiaj", "dzis",
4911 // + "now 12:00", "now 12:50", "Today 12:50:50", "dzisiaj 12:51:51", "teraz 12:31", "dzis 12:31",
4912 // + "Tomorrow", "jutro",
4913 // + "Tomorrow 12:13", "tomorrow 12:13:13", "jutro 12:13",
4914 // + "pojutrze"
4915 // + "yesterday", "Wczoraj",
4916 // + "yesterday 12:13", "Yesterday 12:13:13", "Wczoraj 12:13",
4917 // + "przedwczoraj"
4918
4919 // + "tomorrow +2h", "tomorrow 15:00 +2h"
4920
4921 // "15 styczeń o 17:00", "21 styczen 2010", "15 stycznia", "15 sty"
4922
4923 // Day of week, the nearest one but not including the current one.
4924 // +"saturday 15:00" == on friday it means "+1day 15:00" or "tomorrow 15:00"
4925 // +"saturday 15:00" == on saturday it means next saturday
4926 // +"+1 saturday 15:00" == next saturday, on friday it means "+1 day"
4927 // +"+2 saturday" == saturday after next saturday, on friday it means ""
4928 // +"in 2days at 15:00", "za 2 dni o 15:00"
4929 // +"za 3 dni i 5 godzin" == "+3dni+5godz"
4930 // +"dzien i 2 godziny", "0dni 0godz 1 sekunda"
4931
4932 $start_time = mktime($start_hour, $start_minute, $start_second, $start_month, $start_day, $start_year);
4933
4934 preg_match_all("#([+-])?\s*(\d+)?\s*([a-z_]+(\(\))?)#i", $string, $matches);
4935
4936 foreach ($matches[0] as $k => $match0)
4937 {
4938 $match1 = $matches[1][$k];
4939 $match2 = $matches[2][$k];
4940 $match3 = $matches[3][$k];
4941
4942 $sign = "+";
4943 if ($match1) {
4944 $sign = $match1;
4945 }
4946
4947 if (strlen($match2)) { // could be "+0h"
4948 $number = (int) $match2;
4949 } else {
4950 $number = 1; // "dzien" == "1 dzien"
4951 }
4952
4953 $word = $match3;
4954
4955 // en: "now", "time", "now()", "time()",
4956 // pl: "teraz", "czas"
4957
4958 if ("unix_timestamp" == $word || "current_timestamp" == $word
4959 || "now" == $word || "time" == $word || "now()" == $word || "time()" == $word
4960 || "teraz" == $word || "czas" == $word)
4961 {
4962 $start_time = $now;
4963 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
4964 continue;
4965 }
4966
4967 // en: "today"
4968 // pl: "dzisiaj", "dzis"
4969 if ("today" == $word || "dzisiaj" == $word || "dzis" == $word)
4970 {
4971 if ($HoursFound) {
4972 $start_time = mktime($start_hour, $start_minute, $start_second, $now_month, $now_day, $now_year);
4973 } else {
4974 $start_time = mktime(0, 0, 0, $now_month, $now_day, $now_year);
4975 }
4976 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
4977 continue;
4978 }
4979
4980 // en: "tomorrow"
4981 // pl: "jutro"
4982
4983 if ("tomorrow" == $word || "jutro" == $word) {
4984 if ($HoursFound) {
4985 $start_time = mktime($start_hour, $start_minute, $start_second, $now_month, $now_day, $now_year);
4986 } else {
4987 $start_time = mktime(0, 0, 0, $now_month, $now_day, $now_year);
4988 }
4989 $start_time = $start_time + 3600*24;
4990 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
4991 continue;
4992 }
4993
4994 // pl: "pojutrze"
4995
4996 if ("pojutrze" == $word) {
4997 if ($HoursFound) {
4998 $start_time = mktime($start_hour, $start_minute, $start_second, $now_month, $now_day, $now_year);
4999 } else {
5000 $start_time = mktime(0, 0, 0, $now_month, $now_day, $now_year);
5001 }
5002 $start_time = $start_time + 3600*24*2;
5003 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5004 continue;
5005 }
5006
5007 // en: "yesterday"
5008 // pl: "wczoraj"
5009
5010 if ("yesterday" == $word || "wczoraj" == $word) {
5011 if ($HoursFound) {
5012 $start_time = mktime($start_hour, $start_minute, $start_second, $now_month, $now_day, $now_year);
5013 } else {
5014 $start_time = mktime(0, 0, 0, $now_month, $now_day, $now_year);
5015 }
5016 $start_time = $start_time - 3600*24;
5017 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5018 continue;
5019 }
5020
5021 // pl: "przedwczoraj"
5022
5023 if ("przedwczoraj" == $word) {
5024 $start_time = $start_time - 3600*24*2;
5025 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5026 continue;
5027 }
5028
5029 // en: "y", "year", "years"
5030 // pl: "r", "rok", "lata", "lat"
5031
5032 if ("y" == $word || "year" == $word || "years" == $word
5033 || "r" == $word || "rok" == $word || "lata" == $word || "lat" == $word)
5034 {
5035 // feb 2012 = 29 days
5036 // feb 2011 = 28 days
5037
5038 // 29 feb 2012 - 1 year == 28 feb 2011 and not 1 mar 2011
5039 // Adding years always keeps the month intact.
5040 // strototime() returns 1 mar 2011 in this case.
5041
5042 $temp_hour = (int) date("H", $start_time);
5043 $temp_minute = (int) date("i", $start_time);
5044 $temp_second = (int) date("s", $start_time);
5045 $temp_month = (int) date("n", $start_time);
5046 $temp_day = (int) date("j", $start_time);
5047 $temp_year = (int) date("Y", $start_time);
5048
5049 if ("+" == $sign) {
5050 $temp_year = $temp_year + $number;
5051 } else {
5052 $temp_year = $temp_year - $number;
5053 }
5054
5055 // Max 4 tries (should be probably 1 enought, but let's keep the code consistent with adding/subtracting months).
5056
5057 for ($i = 1; $i <= 5; ++$i)
5058 {
5059 if (5 == $i) {
5060 return 0; // Errpr.
5061 }
5062
5063 $test_time = mktime($temp_hour, $temp_minute, $temp_second, $temp_month, $temp_day, $temp_year);
5064 $new_month = (int) date("n", $test_time);
5065
5066 if ($new_month == $temp_month) {
5067 $start_time = $test_time;
5068 break;
5069 } else {
5070 --$temp_day;
5071 }
5072 }
5073
5074 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5075 continue;
5076 }
5077
5078 // en: "m", "month", "months"
5079 // pl: "mies", "miesiac", "miesiace", "miesiecy"
5080
5081 if ("m" == $word || "month" == $word || "months" == $word
5082 || "mies" == $word || "miesiac" == $word || "miesiace" == $word || "miesiecy" == $word)
5083 {
5084 // jan 2012 = 31 days
5085 // luty 2012 = 29 days
5086 // luty 2011 = 28 days
5087
5088 // 31 jan 2012 + 1 month == 29 feb 2011 and not 2 mar 2011 as in strtotime
5089 // 31 jan 2011 + 1 month == 28 feb 2011 and not 3 mar 2011 as in strtotime
5090 // Adding 1 month always returns the next month, and not +2 months as strtotime() does.
5091
5092 $temp_hour = (int) date("H", $start_time);
5093 $temp_minute = (int) date("i", $start_time);
5094 $temp_second = (int) date("s", $start_time);
5095 $temp_month = (int) date("n", $start_time);
5096 $temp_day = (int) date("j", $start_time);
5097 $temp_year = (int) date("Y", $start_time);
5098
5099 // We cannot simply add +number to month, cause months must be between 1..12.
5100 $temp_number = abs($number);
5101 while ($temp_number > 0)
5102 {
5103 if ("+" == $sign) {
5104 $temp_month = $temp_month + 1;
5105 } else {
5106 $temp_month = $temp_month - 1;
5107 }
5108
5109 if (13 == $temp_month) {
5110 $temp_month = 1;
5111 $temp_year = $temp_year + 1;
5112 } else if (0 == $temp_month) {
5113 $temp_month = 12;
5114 $temp_year = $temp_year - 1;
5115 }
5116
5117 $temp_number--;
5118 }
5119
5120 // Max 4 tries.
5121 // 31th day >> 28th day, 3 tries should be enough, allowing 4 just to be sure.
5122
5123 for ($i = 1; $i <= 5; ++$i)
5124 {
5125 if (5 == $i) {
5126 return 0; // Error.
5127 }
5128
5129 $test_time = mktime($temp_hour, $temp_minute, $temp_second, $temp_month, $temp_day, $temp_year);
5130 $new_day = (int) date("j", $test_time);
5131
5132 if ($temp_day >= 28 && in_array($new_day, array(1,2,3,4))) {
5133 // 31 Jan +1 month could be 03 Mar / 02 Mar / 01 Mar - bad.
5134 // Must be the last day of Feb.
5135 --$temp_day;
5136 } else {
5137 $start_time = $test_time;
5138 break;
5139 }
5140 }
5141
5142 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5143 continue;
5144 }
5145
5146 // en: "d", "day", "days"
5147 // pl: "dz", "dzien", "dni"
5148
5149 if ("d" == $word || "day" == $word || "days" == $word
5150 || "dz" == $word || "dzien" == $word || "dni" == $word)
5151 {
5152 $secs = 3600*24;
5153 if ("+" == $sign) {
5154 $start_time = $start_time + ($secs * $number);
5155 } else {
5156 $start_time = $start_time - ($secs * $number);
5157 }
5158
5159 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5160 continue;
5161 }
5162
5163 // en: "h", "hour", "hours"
5164 // pl: "g", "godz", "godzina", "godziny", "godzin"
5165
5166 if ("h" == $word || "hour" == $word || "hours" == $word
5167 || "g" == $word || "godz" == $word || "godzin" == $word || "godzina" == $word || "godziny" == $word)
5168 {
5169 if ("+" == $sign) {
5170 $start_time = $start_time + (3600 * $number);
5171 } else {
5172 $start_time = $start_time - (3600 * $number);
5173 }
5174
5175
5176 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5177 continue;
5178 }
5179
5180 // en: "i", "min", "minute", "minutes"
5181 // pl: "minuta", "minuty", "minut"
5182
5183 if ("i" == $word || "min" == $word || "minute" == $word || "minutes" == $word
5184 || "minuta" == $word || "minuty" == $word || "minut" == $word)
5185 {
5186 if ("+" == $sign) {
5187 $start_time = $start_time + (60 * $number);
5188 } else {
5189 $start_time = $start_time - (60 * $number);
5190 }
5191
5192 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5193 continue;
5194 }
5195
5196 // en: "s", "sec", "second", "seconds"
5197 // pl: "sek", "sekunda", "sekundy", "sekund"
5198
5199 if ("s" == $word || "sec" == $word || "second" == $word || "seconds" == $word
5200 || "sek" == $word || "sekunda" == $word || "sekundy" == $word || "sekund" == $word)
5201 {
5202 if ("+" == $sign) {
5203 $start_time = $start_time + (1 * $number);
5204 } else {
5205 $start_time = $start_time - (1 * $number);
5206 }
5207
5208 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5209 continue;
5210 }
5211
5212 // en: "w", "week", "weeks"
5213 // pl: "t", "tydz", "tydzien", "tyg", "tygodnie", "tygodni"
5214
5215 if ("w" == $word || "week" == $word || "weeks" == $word
5216 || "t" == $word || "tydz" == $word || "tydzien" == $word || "tyg" == $word || "tygodnie" == $word || "tygodni" == $word)
5217 {
5218 if ("+" == $sign) {
5219 $start_time = $start_time + ((3600*24*7)*$number);
5220 } else {
5221 $start_time = $start_time - ((3600*24*7)*$number);
5222 }
5223
5224 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5225 continue;
5226 }
5227
5228 // en: January, Jan, February, Feb, March, Mar, April, Apr, May, June, Jun, July, Jul, August, Aug, September, Sep, October, Oct, December, Dec.
5229 // examples: 1st February, 1 Feb, 4th Feb 2013 15:00
5230 // pl: Styczeń, Sty, Luty, Lut, Marzec, Mar, Kwiecień, Kwi, Maj, Czerwiec, Cze, Lipiec, Lip, Sierpień, Sie, Wrzesień, Wrz, Październik, Paź, Listopad, Lis, Grudzień, Gru.
5231 // examples: 12 lutego, 15 stycznia o 17:00, 15 styczeń, 15 sty.
5232
5233 static $months = array(
5234 "january" => 1, "jan" => 1,
5235 "february" => 2, "feb" => 2,
5236 "march" => 3, "mar" => 3,
5237 "april" => 4, "apr" => 4,
5238 "may" => 5,
5239 "june" => 6, "jun" => 6,
5240 "july" => 7, "jul" => 7,
5241 "august" => 8, "aug" => 8,
5242 "september" => 9, "sep" => 9,
5243 "october" => 10, "oct" => 10,
5244 "november" => 11, "nov" => 11,
5245 "december" => 12, "dev" => 12,
5246 "styczen" => 1, "stycznia" => 1, "sty" => 1,
5247 "luty" => 2, "lutego" => 2, "lut" => 2,
5248 "marzec" => 3, "marca" => 3, "mar" => 3,
5249 "kwiecien" => 4, "kwietnia" => 4, "kwi" => 4,
5250 "maja" => 5, "maj" => 5, // "maja" needs to be replaced before "maj", or "a" will stay in string.
5251 "czerwiec" => 6, "czerwca" => 6, "cze" => 6,
5252 "lipiec" => 7, "lipca" => 7, "lip" => 7,
5253 "sierpien" => 8, "sierpnia" => 8, "sie" => 8,
5254 "wrzesien" => 9, "wrzesnia" => 9, "wrz" => 9,
5255 "pazdziernika" => 10, "pazdziernik" => 10, "paz", // "pazdziernika" needs to be replaced before "pazdziernik".
5256 "listopada" => 11, "listopad" => 11, "lis" => 11, // "listopada" needs to be replaced before "listopad".
5257 "grudzień" => 12, "grudnia" => 12, "gru" => 12
5258 );
5259
5260 if (array_key_exists($word, $months))
5261 {
5262 if (!$number) {
5263 // when number is missing in string, it will be set to "1", so this line should never execute.
5264 return 0;
5265 }
5266
5267 $year = (int) date("Y", $start_time);
5268 $hour = (int) date("H", $start_time);
5269 $minute = (int) date("i", $start_time);
5270 $second = (int) date("s", $start_time);
5271
5272 $day = $number;
5273 $month = $months[$word];
5274
5275 $start_time = mktime($hour, $minute, $second, $month, $day, $year);
5276
5277 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5278 continue;
5279 }
5280
5281 // en: "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"
5282 // pl: "poniedzialek", "wtorek", "sroda", "czwartek", "piatek", "sobota", "niedziela"
5283 // +1 saturday - next saturday
5284
5285 if (in_array($word, array("monday", "mon", "tuesday", "tue", "wednesday", "wed", "thursday", "thu",
5286 "friday", "fri", "saturday", "sat", "sunday", "sun"))
5287 || in_array($word, array("poniedzialek", "pon", "wtorek", "wto", "sroda", "sro", "czwartek", "czw",
5288 "piatek", "pia", "sobota", "sob", "niedziela", "nie")))
5289 {
5290 $daynum = str_replace(
5291 array("monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday",
5292 "mon", "tue", "wed", "thu", "fri", "sat", "sun",
5293 "poniedzialek", "wtorek", "sroda", "czwartek", "piatek", "sobota", "niedziela",
5294 "pon", "wto", "sro", "czw", "pia", "sob", "nie"),
5295 array(1, 2, 3, 4, 5, 6, 7,
5296 1, 2, 3, 4, 5, 6, 7,
5297 1, 2, 3, 4, 5, 6, 7,
5298 1, 2, 3, 4, 5, 6, 7),
5299 $word
5300 );
5301
5302 if ("+" == $sign) {
5303 if ($daynum == $now_dayofweek) {
5304 $days = 7;
5305 } else if ($daynum > $now_dayofweek) {
5306 // string: 4 > today: 3
5307 $days = $daynum - $now_dayofweek;
5308 } else {
5309 // string: 3 < today: 4
5310 $days = (7 - $now_dayofweek) + ($daynum);
5311 }
5312 assert($days >= 1 && $days <= 7);
5313 // $days = difference in days only for 1st week
5314 if ($number >= 2) {
5315 $start_time = $start_time + (3600*24*$days) + (7 * ($number-1));
5316 } else {
5317 $start_time = $start_time + (3600*24*$days);
5318 }
5319 } else {
5320 if ($daynum == $now_dayofweek) {
5321 $days = 7;
5322 } else if ($daynum > $now_dayofweek) {
5323 // string: 4 > today: 3
5324 $days = 7 - ($daynum - $now_dayofweek);
5325 } else {
5326 // string: 3 < today: 4
5327 $days = $now_dayofweek - $daynum;
5328 }
5329 assert($days >= 1 && $days <= 7);
5330 // $days = difference in days only for 1st week
5331 if ($number >= 2) {
5332 $start_time = $start_time - (3600*24*$days) - (7 * ($number-1));
5333 } else {
5334 $start_time = $start_time - (3600*24*$days);
5335 }
5336 }
5337
5338 $string = preg_replace("#".preg_quote($match0, "#")."#", "", $string, 1);
5339 continue;
5340 }
5341
5342 // Unknown word - error.
5343 return 0;
5344 }
5345
5346 if (trim($string)) {
5347 // Some unknown identifier is still left in the string - error.
5348 return 0;
5349 } else {
5350 return $start_time;
5351 }
5352}
5353function ParseTime_Tests($now=null)
5354{
5355 while (ob_get_level()) { ob_end_clean(); }
5356 header("Content-Encoding: none");
5357 ob_start();
5358
5359 // + 12d, +12d, + 12d, +12 day, +12 days = time() + 12 days
5360 // + -5h = time() - 5 hours
5361 // + 1y - 5d + 5h = time() + 1year - 5 days + 5 hours
5362 // + -5d 15:55 = time() - 5 days
5363 // + -1week 12:00, -1 Week 12:00, - 1 week 12:00:53
5364 // + -1w
5365
5366 $tests = array(
5367 "now", " now", "now()", "time", "NOW()", "TIME()", "unix_timestamp", "current_timestamp", "Today", "teraz", "dzisiaj", "dzis",
5368 "now 13:00", "now 13:13", "Today 13:13:13", "dzisiaj 13:13:13", "teraz 13:13", "dzis 13:13",
5369 "yesterday", "Wczoraj",
5370 "Tomorrow", "jutro",
5371 "yesterday 13:13", "Yesterday 13:13:13", "Wczoraj 13:13",
5372 "Tomorrow 13:13", "tomorrow 13:13:13", "jutro 13:13",
5373 "pojutrze", "pojutrze 13:13", "przedwczoraj", "przedwczoraj 13:13",
5374 "2013-12-13", "2013-12-13 13:13", "2013-12-13 13:13:13",
5375 "2011-13-13", "2011-12-33",
5376 "13.12", "13.12 13:13", "13.12 13:13:13", "13.12.2013", "13.12.2013 13:13", "13.12.2013 13:13:13",
5377 "13:13",
5378 "12d", "12 dni", "+ 12 dni",
5379 "-1year", "teraz -1year", "dzisiaj 12:00 -1year", "-1month", "+1 month", "+2month", "+3month", "+4m", "+5m", "1d -5h", "1y - 5d + 5h", "1y -5 Dni", "-1 tydzien 13:13", "-1w",
5380 "wczoraj +1h", "wczoraj -1h", "jutro +1dzien",
5381 "+12m", "+13m", "+24m", "+25m", "+36m", "+37m", "+48m", "+49m",
5382 "1st february", "1 february", "2nd Feb", "3rd Feb", "4th Feb 2013",
5383 "15 stycznia", "stycznia", "styczeń 15:00", "15 styczeń", "15 sty", "12 lutego", "12 luty", "12 Lut", "15 styczeń o 17:00", "21 styczen 2010",
5384 "21szy stycznia", "21-szy stycznia", "21st January", "21 January",
5385 "monday 15:00", "tuesday 15:00", "poniedziałek 15:00", "wtorek 15:00",
5386 "+1 saturday 15:00", "+2 saturday", "in 2 days at 15:00", "za 2 dni o 15:00",
5387 "za 3 dni i 5 godzin", "in 2 days and 5 hours", "+2days +5hours",
5388 "+0h", "5 godzin", "5 minut", "5 sekund",
5389 "za tydzień", "za 2 tygodnie",
5390 "next monday", "prev monday", "previous monday", "last monday",
5391 "następny poniedziałek", "poprzedni poniedziałek", "ostatni poniedziałek",
5392 "+1mon", "+1 tue", "next wed", "next Wed 15:00",
5393 "+1pon", "+1 wto", "następny Pon"
5394 );
5395
5396 // "15 styczeń o 17:00", "21 styczen 2010", "15 stycznia"
5397 // Day of week, the nearest one but not including the current one.
5398 // "saturday 15:00" == on friday it means "+1day 15:00" or "tomorrow 15:00"
5399 // "saturday 15:00" == on saturday it means next saturday
5400 // "+1 saturday 15:00" == next saturday, on friday it means "+1 day"
5401 // "+2 saturday" == saturday after next saturday, on friday it means ""
5402 // "in 2days at 15:00", "za 2 dni o 15:00"
5403 // "za 3 dni i 5 godzin" == "+3dni+5godz"
5404 // "dzien i 2 godziny", "0dni 0godz 1 sekunda"
5405
5406 printf("<title>Natural time strings</title>");
5407 printf("<meta charset=utf-8>");
5408 printf("<style type=text/css>html, body { margin: 0; padding: 0; } body { margin: 1em 1.5em; padding: 0em; } body, table { font: 11px Tahoma; } body { line-height: 1.4em; } h1 { font: bold 15px Tahoma; }</style>");
5409 printf("<h1>Natural time strings</h1>");
5410 printf("<div>In fields of type <b>INT</b> you can use natural string times to generate <b>Unix Timestamps</b>.</div>");
5411 printf("<div>You can also use this strings in fields of type <b>DATETIME</b> and <b>TIMESTAMP</b>.</div>");
5412 printf("<div>Supported languages are: <b>English</b> and <b>Polish</b>.<div><br>");
5413
5414 printf("<style type=text/css>th { background: #ddd; padding: 2px 4px; } td { background: #f5f5f5; padding: 2px 4px; }</style>");
5415
5416 printf("<table cellspacing=1 cellpadding=0>");
5417 printf("<tr><th>String</th><th>Date</th></tr>");
5418
5419 $no = 0;
5420 foreach ($tests as $string) {
5421 ++$no;
5422 $result_time = ParseTime($string, $now);
5423 $result = date("Y-m-d H:i:s", $result_time);
5424 if ($result_time == 0) $result = 0;
5425 printf("<tr><td>%s</td><td>%s</td></tr>", $string, $result);
5426 }
5427
5428 printf("</table><br>");
5429
5430 exit();
5431}
5432
5433if (GET("action", "string") == "parsetime")
5434{
5435 // $now = strtotime("2012-02-29 01:01:01"); // Test -1year: 29 feb 2012 - 1 year == 28 feb 2011 and not 1 mar 2011
5436 // $now = strtotime("2012-01-31 01:01:01"); // Test +1month: 31 jan 2012 + 1 month == 29 feb 2011 and not 2 mar 2011
5437 $now = strtotime("2011-01-31 01:01:01"); // Test +1month: 31 jan 2011 + 1 month == 28 feb 2011 and not 3 mar 2011
5438 $now = time();
5439 ParseTime_Tests($now);
5440 exit();
5441}
5442
5443// ~~~~~~~~~ @funcsend
5444
5445?>
5446<?php if (GET("import", "bool")): ?>
5447
5448 <?php
5449
5450 // ----------------------------------------------------------------
5451 // @import HTML
5452 // ----------------------------------------------------------------
5453
5454 ?>
5455
5456 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
5457 <html>
5458 <head>
5459 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $page_charset;?>">
5460 <meta name="robots" content="noindex, nofollow">
5461 <title><?php echo $db_name_h1?$db_name_h1:$db_name;?> > Import</title>
5462 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
5463 </head>
5464 <body>
5465
5466 <?php layout(); ?>
5467 <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>
5468 <?php conn_info(); ?>
5469
5470 <?php $files = sql_files(); ?>
5471
5472 <?php if (count($files)): ?>
5473 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
5474 <table class="none" cellspacing="0" cellpadding="0">
5475 <tr>
5476 <td>SQL file:</th>
5477 <td><select name="sqlfile"><option value="" selected="selected"></option><?php echo options($files);?></select></td>
5478 <td><input type="checkbox" name="ignore_errors" id="ignore_errors" value="1"></td>
5479 <td><label for="ignore_errors">ignore errors</label></td>
5480 <td><input type="checkbox" name="transaction" id="transaction" value="1"></td>
5481 <td><label for="transaction">transaction</label></td>
5482 <td><input type="checkbox" name="force_myisam" id="force_myisam" value="1"></td>
5483 <td><label for="force_myisam">force myisam</label></td>
5484 <td><input type="text" size="5" name="query_start" value=""></td>
5485 <td>query start</td>
5486 <td><input type="submit" value="Import"></td>
5487 </tr>
5488 </table>
5489 </form>
5490 <br>
5491 <?php else: ?>
5492 No sql files found in current directory.
5493 <?php endif; ?>
5494
5495 </body></html>
5496
5497 <?php exit(); ?>
5498
5499<?php endif; ?>
5500
5501
5502<?php if ('editrow' == GET("action", "string")): ?>
5503<?php
5504
5505 // ----------------------------------------------------------------
5506 // @editrow PHP
5507 // ----------------------------------------------------------------
5508
5509 GET("id", "string");
5510 GET("pk", "string");
5511 GET("table", "string");
5512 POST("dbkiss_action", "string");
5513
5514 function dbkiss_filter_id($id)
5515 {
5516 # mysql allows table names of: `62-511`
5517 # also, columns might be numeric ex. `62`
5518 if (preg_match('#^[_a-z0-9][a-z0-9_\-]*$#i', $id)) {
5519 return $id;
5520 }
5521 return false;
5522 }
5523
5524 if (ctype_digit($_GET["id"])) {
5525 // sqlite:
5526 // 1 row: SELECT * FROM "sqlite_sequence" WHERE "seq" = 5
5527 // No rows found: SELECT * FROM "sqlite_sequence" WHERE "seq" = '5'
5528 // Solved by not querying sqlite_ special: AND name NOT LIKE 'sqlite_%'
5529 $_GET["id"] = (int) $_GET["id"];
5530 }
5531
5532 $_pk = $_GET["pk"];
5533 $_id = DecodeRowId($_GET["id"]);
5534
5535 if (strstr($_pk, ":")) {
5536 $_pkeys = explode(":", $_pk);
5537 $pvals_temp = $_id;
5538 $_where = array();
5539 foreach ($_pkeys as $arrKey => $key) {
5540 $_where[$key] = $pvals_temp[$arrKey];
5541 }
5542 } else {
5543 $_pkeys = false;
5544 $_where = array($_pk => $_id);
5545 }
5546
5547 $_GET['table'] = htmlspecialchars($_GET['table']);
5548 $_GET['pk'] = htmlspecialchars($_GET['pk']);
5549
5550 $title_edit = sprintf('Edit (%s=%s)', $_GET['pk'], $_GET['id']);
5551 $title = ' > '.$_GET['table'].' > '.$title_edit;
5552
5553 if (!dbkiss_filter_id($_GET['table'])) {
5554 error('Invalid table name');
5555 }
5556
5557 if ($_pkeys) {
5558 foreach ($_pkeys as $key) {
5559 if (!dbkiss_filter_id($key)) {
5560 error('Invalid pk');
5561 }
5562 }
5563 } else {
5564 if (!dbkiss_filter_id($_pk)) {
5565 error('Invalid pk');
5566 }
5567 }
5568
5569 $row = false;
5570
5571 if (!error())
5572 {
5573 $table_enq = quote_table($_GET['table']);
5574 $test = db_row("SELECT * FROM $table_enq");
5575
5576 if ($test) {
5577 if ($_pkeys) {
5578 foreach ($_pkeys as $key) {
5579 if (!array_key_exists($key, $test)) {
5580 error('Invalid pk');
5581 }
5582 }
5583 } else {
5584 if (!array_key_exists($_pk, $test)) {
5585 error('Invalid pk');
5586 }
5587 }
5588 }
5589
5590 if (!error())
5591 {
5592 $table_enq = quote_table($_GET['table']);
5593
5594 $where = db_where($_where);
5595 $query = "SELECT * FROM $table_enq $where";
5596 $query = db_limit($query, 0, 2);
5597 $rows = db_list($query);
5598
5599 if (count($rows) > 1) {
5600 error('Invalid pk: found more than one row with given id');
5601 } else if (count($rows) == 0) {
5602 error('Row not found');
5603 } else {
5604 $row = $rows[0];
5605 }
5606 }
5607 }
5608
5609 if ($row) {
5610 $types = table_columns($_GET['table']);
5611 }
5612
5613 $edit_actions_assoc = array(
5614 'update' => 'Update',
5615 'update_pk' => 'Overwrite pk',
5616 'insert' => 'Copy row (insert)',
5617 'delete' => 'Delete'
5618 );
5619
5620 // -----------------------------------------
5621
5622 $edit_action = $_POST['dbkiss_action'];
5623
5624 if ("GET" == $_SERVER["REQUEST_METHOD"])
5625 {
5626 $edit_action = array_first_key($edit_actions_assoc);
5627 $post = $row;
5628 }
5629
5630 if ("POST" == $_SERVER["REQUEST_METHOD"])
5631 {
5632 if (!array_key_exists($edit_action, $edit_actions_assoc)) {
5633 $edit_action = '';
5634 error('Invalid action');
5635 }
5636
5637 $post = array();
5638 foreach ($row as $k => $v) {
5639 if (array_key_exists($k, $_POST)) {
5640 $val = (string) $_POST[$k];
5641 if ('null' == $val || "NULL" == $val) {
5642 $val = null;
5643 }
5644 if ('int' == $types[$k]) {
5645 if (!strlen($val)) {
5646 $val = null;
5647 }
5648 if (!(preg_match('#^-?\d+$#', $val) || is_null($val))) {
5649 error('%s: invalid value', $k);
5650 }
5651 if (!ctype_digit($val)) {
5652 $val = ParseTime($val);
5653 }
5654 }
5655 if ('float' == $types[$k]) {
5656 if (!strlen($val)) {
5657 $val = null;
5658 }
5659 $val = str_replace(',', '.', $val);
5660 if (!(is_numeric($val) || is_null($val))) {
5661 error('%s: invalid value', $k);
5662 }
5663 }
5664 if ('datetime' == $types[$k] || 'timestamp' == $types[$k]) {
5665 if (!strlen($val)) {
5666 $val = null;
5667 }
5668 if (!ctype_digit($val)) {
5669 $parsetime = ParseTime($val);
5670 if ($parsetime) {
5671 $val = date("Y-m-d H:i:s", $parsetime);
5672 } else {
5673 $val = null;
5674 }
5675 }
5676 }
5677 $post[$k] = $val;
5678 } else {
5679 error('Missing key: %s in POST', $k);
5680 }
5681 }
5682
5683 if ('update' == $edit_action)
5684 {
5685 if ($post[$_GET['pk']] != $row[$_GET['pk']]) {
5686 if (count($row) != 1) { // Case: more than 1 column
5687 error('%s: cannot change pk on UPDATE', $_GET['pk']);
5688 }
5689 }
5690 }
5691 if ('update_pk' == $edit_action)
5692 {
5693 if ($post[$_GET['pk']] == $row[$_GET['pk']]) {
5694 error('%s: selected action Overwrite pk, but pk value has not changed', $_GET['pk']);
5695 }
5696 }
5697 if ('insert' == $edit_action)
5698 {
5699 if (strlen($post[$_GET['pk']])) {
5700 $table_enq = quote_table($_GET['table']);
5701 $pk_enq = quote_column($_GET["pk"]);
5702 $test = db_row("SELECT * FROM $table_enq WHERE $pk_enq = %0", array($post[$_GET['pk']]));
5703 if ($test) {
5704 error('%s: there is already a record with that id', $_GET['pk']);
5705 }
5706 }
5707 }
5708
5709 if (!error())
5710 {
5711 $post2 = $post;
5712 if ('update' == $edit_action)
5713 {
5714 if (count($row) != 1) { // Case: more than 1 column
5715 unset($post2[$_GET['pk']]);
5716 }
5717 db_update($_GET['table'], $post2, $_where);
5718 if (db_error()) {
5719 error('<font color="red"><b>DB error</b></font>: '.db_error());
5720 } else {
5721 if (count($row) == 1) { // Case: only 1 column
5722 redirect_ok(url(self(), array('id'=>$post[$_GET['pk']])), 'Row updated');
5723 } else {
5724 redirect_ok(self(), 'Row updated');
5725 }
5726 }
5727 }
5728 if ('update_pk' == $edit_action)
5729 {
5730 @db_update($_GET['table'], $post2, $_where);
5731 if (db_error()) {
5732 error('<font color="red"><b>DB error</b></font>: '.db_error());
5733 } else {
5734 $url = url(self(), array('id' => $post[$_GET['pk']]));
5735 redirect_ok($url, 'Row updated (pk overwritten)');
5736 }
5737 }
5738 if ('insert' == $edit_action)
5739 {
5740 $new_id = false;
5741 if (!strlen($post2[$_GET['pk']])) {
5742 unset($post2[$_GET['pk']]);
5743 } else {
5744 $new_id = $post2[$_GET['pk']];
5745 }
5746 @db_insert($_GET['table'], $post2);
5747 if (db_error()) {
5748 error('<font color="red"><b>DB error</b></font>: '.db_error());
5749 } else {
5750 if (!$new_id) {
5751 $new_id = db_insert_id($_GET['table'], $_GET['pk']);
5752 }
5753 $url = url(self(), array('id'=>$new_id));
5754 $msg = sprintf('Row inserted (%s=%s)', $_GET['pk'], $new_id);
5755 redirect_ok($url, $msg);
5756 }
5757 }
5758 if ('delete' == $edit_action)
5759 {
5760 $table_enq = quote_table($_GET['table']);
5761 $pk_enq = quote_column($_GET["pk"]);
5762 @db_exe("DELETE FROM $table_enq WHERE $pk_enq = %0", $_GET['id']);
5763 if (db_error()) {
5764 error('<font color="red"><b>DB error</b></font>: '.db_error());
5765 } else {
5766 redirect_ok(self(), 'Row deleted');
5767 }
5768 }
5769 }
5770 }
5771
5772 ?>
5773<?php rawlayout_start($_GET["table"]." > ".$title_edit); ?>
5774
5775 <?php
5776
5777 // ----------------------------------------------------------------
5778 // @editrow HTML
5779 // ----------------------------------------------------------------
5780
5781 ?>
5782
5783 <h1><span style="<?php echo $db_name_style;?>"><?php echo $db_name_h1?$db_name_h1:$db_name;?></span><?php echo $title;?></h1>
5784
5785 <?php echo error();?>
5786
5787 <?php if ($row): ?>
5788
5789 <form action="<?php echo self();?>" method="post">
5790
5791 <div id="Help_naturaltime" style="display: none;">
5792 You can use natural time strings in fields of type: int, datetime, timestamp.
5793 See <a href="javascript:popup('<?php echo $_SERVER['PHP_SELF']; ?>?action=parsetime', 550, 600)">examples</a>.
5794 </div>
5795
5796 <div style="float: left;">
5797 <?php echo radio_assoc($edit_action, $edit_actions_assoc, 'dbkiss_action');?>
5798 </div>
5799 <div style="float: left; margin-left: 0.5em;">
5800 <a class=help title="Help: natural time strings" href="javascript:void(0)" onclick="Tooltip(this, 'Help_naturaltime')"></a>
5801 </div>
5802
5803 <br style="clear: both;">
5804 <br>
5805
5806 <table cellspacing="1" class="ls2">
5807 <?php foreach ($post as $k => $v): if (is_null($v)) { $v = 'null'; } $v = htmlspecialchars($v); ?>
5808 <tr>
5809 <th><?php echo $k;?>:</th>
5810 <td>
5811 <?php if ('int' == $types[$k]): ?>
5812 <input type="text" name="<?php echo $k;?>" value="<?php echo html_once($v);?>" size="11">
5813 <?php elseif ('char' == $types[$k]): ?>
5814 <input type="text" name="<?php echo $k;?>" value="<?php echo html_once($v);?>" size="50">
5815 <?php elseif (in_array($types[$k], array('text', 'mediumtext', 'longtext')) || strstr($types[$k], 'blob')): ?>
5816 <textarea name="<?php echo $k;?>" cols="80" rows="<?php echo $k=='notes'?10:10;?>"><?php echo html_once($v);?></textarea>
5817 <?php else: ?>
5818 <input type="text" name="<?php echo $k;?>" value="<?php echo html_once($v);?>" size="30">
5819 <?php endif; ?>
5820 </td>
5821 <td valign="top"><?php echo $types[$k];?></td>
5822 </tr>
5823 <?php endforeach; ?>
5824 <tr>
5825 <td colspan="3" class="none">
5826 <input type="submit" wait="1" block="1" class="button" value="Edit">
5827 </td>
5828 </tr>
5829 </table>
5830
5831 </form>
5832
5833 <?php endif; ?>
5834
5835 <?php rawlayout_end(); ?>
5836
5837<?php exit(); endif; ?>
5838
5839
5840<?php if (GET("execute_sql", "bool")): ?>
5841
5842<?php
5843
5844 // ----------------------------------------------------------------
5845 // @sqleditor LISTING PHP
5846 // ----------------------------------------------------------------
5847
5848 function listing($base_query, $md5_get = false)
5849 {
5850 // @listing
5851
5852 GET("full_content", "bool");
5853 GET("only_select", "bool");
5854 GET("offset", "int");
5855
5856 POST("full_content", "bool");
5857 POST("only_select", "bool");
5858
5859 global $db_driver, $db_link;
5860
5861 $full_content = ($_GET["full_content"] || $_POST["full_content"]);
5862
5863 $md5_i = false;
5864 if ($md5_get) {
5865 preg_match('#_(\d+)$#', $md5_get, $match);
5866 $md5_i = $match[1];
5867 }
5868
5869 $base_query = trim($base_query);
5870
5871 if (";" == substr($base_query, -1)) {
5872 $base_query = substr($base_query, 0, -1);
5873 }
5874
5875 $query = $base_query;
5876 $ret = array('msg'=>'', 'error'=>'', 'data_html'=>false);
5877 $limit = 25;
5878 $offset = $_GET["offset"];
5879 $page = floor($offset / $limit + 1);
5880
5881 if ($query) {
5882 if (is_select($query) && !preg_match('#\s+LIMIT\s+\d+#i', $query) && !preg_match('#into\s+outfile\s+#', $query)) {
5883 $query = db_limit($query, $offset, $limit);
5884 } else {
5885 $limit = false;
5886 }
5887 $time = time_start();
5888 if (!db_is_safe($query, true)) {
5889 $ret['error'] = 'Detected UPDATE/DELETE without WHERE condition (put WHERE 1=1 if you want to execute this query)';
5890 return $ret;
5891 }
5892 $rs = @db_query($query);
5893 if ($rs) {
5894 if ($rs === true) {
5895 if ('mysql' == $db_driver)
5896 {
5897 $affected = mysql_affected_rows($db_link);
5898 $time = time_end($time);
5899 $ret['data_html'] = '<b>'.$affected.'</b> rows affected.<br>Time: <b>'.$time.'</b> sec';
5900 return $ret;
5901 }
5902 } else {
5903 if ('pgsql' == $db_driver)
5904 {
5905 $affected = @pg_affected_rows($rs);
5906 if ($affected || preg_match('#^\s*(DELETE|UPDATE)\s+#i', $query)) {
5907 $time = time_end($time);
5908 $ret['data_html'] = '<p><b>'.$affected.'</b> rows affected. Time: <b>'.$time.'</b> sec</p>';
5909 return $ret;
5910 }
5911 }
5912 }
5913
5914 $rows = array();
5915 while ($row = db_row($rs)) {
5916 $rows[] = $row;
5917 if ($limit) {
5918 if (count($rows) == $limit) { break; }
5919 }
5920 }
5921 db_free($rs);
5922
5923 if (is_select($base_query)) {
5924 $found = @db_one("SELECT COUNT(*) FROM ($base_query) AS sub");
5925 if (!is_numeric($found) || (count($rows) && !$found)) {
5926 global $COUNT_ERROR;
5927 $COUNT_ERROR = ' (COUNT ERROR) ';
5928 $found = count($rows);
5929 }
5930 } else {
5931 if (count($rows)) {
5932 $found = count($rows);
5933 } else {
5934 $found = false;
5935 }
5936 }
5937 if ($limit) {
5938 $pages = ceil($found / $limit);
5939 } else {
5940 $pages = 1;
5941 }
5942 $time = time_end($time);
5943
5944 } else {
5945 $ret['error'] = db_error();
5946 return $ret;
5947 }
5948 } else {
5949 $ret['error'] = 'No query found.';
5950 return $ret;
5951 }
5952
5953 ob_start();
5954
5955 // ----------------------------------------------------------------
5956 // @sqleditor LISTING HTML
5957 // ----------------------------------------------------------------
5958
5959 ?>
5960 <?php if (is_numeric($found)): ?>
5961 <p>
5962 Found: <b><?php echo $found;?></b><?php echo isset($GLOBALS['COUNT_ERROR'])?$GLOBALS['COUNT_ERROR']:'';?>.
5963 Time: <b><?php echo $time;?></b> sec.
5964 <?php
5965 $params = array('md5'=>$md5_get, 'offset'=>$_GET["offset"]);
5966 if ($_GET['only_select'] || $_POST['only_select']) { $params['only_select'] = 1; }
5967 if ($_GET['full_content'] || $_POST['full_content']) { $params['full_content'] = 1; }
5968 ?>
5969 / <a href="<?php echo url(self(), $params);?>">Refetch</a>
5970 / Export to CSV:
5971
5972 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode('|');?>&query=<?php echo base64_encode($base_query); ?>">pipe</a>
5973 -
5974 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode("\t");?>&query=<?php echo base64_encode($base_query); ?>">tab</a>
5975 -
5976 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode(',');?>&query=<?php echo base64_encode($base_query); ?>">comma</a>
5977 -
5978 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode(';');?>&query=<?php echo base64_encode($base_query); ?>">semicolon</a>
5979 </p>
5980 <?php else: ?>
5981 <p>Result: <b>OK</b>. Time: <b><?php echo $time;?></b> sec</p>
5982 <?php endif; ?>
5983
5984 <?php if (is_numeric($found)): ?>
5985
5986 <?php if ($pages > 1): ?>
5987 <p>
5988 <?php if ($page > 1): ?>
5989 <?php $ofs = ($page-1)*$limit-$limit; ?>
5990 <?php
5991 $params = array('md5'=>$md5_get, 'offset'=>$ofs);
5992 if ($_GET['only_select'] || $_POST['only_select']) { $params['only_select'] = 1; }
5993 ?>
5994 <a href="<?php echo url(self(), $params);?>"><< Prev</a>
5995 <?php endif; ?>
5996 Page <b><?php echo $page;?></b> of <b><?php echo $pages;?></b>
5997 <?php if ($pages > $page): ?>
5998 <?php $ofs = $page*$limit; ?>
5999 <?php
6000 $params = array('md5'=>$md5_get, 'offset'=>$ofs);
6001 if ($_GET['only_select'] || $_POST['only_select']) { $params['only_select'] = 1; }
6002 ?>
6003 <a href="<?php echo url(self(), $params);?>">Next >></a>
6004 <?php endif; ?>
6005 </p>
6006 <?php endif; ?>
6007
6008 <?php if ($found): ?>
6009
6010 <?php
6011 $edit_table = table_from_query($base_query);
6012 if ($edit_table) {
6013 $edit_pk = array_first_key($rows[0]);
6014 if (is_numeric($edit_pk)) { $edit_table = false; }
6015 }
6016 if ($edit_table) {
6017 $types = table_columns($edit_table);
6018 if ($types && count($types)) {
6019 if (in_array($edit_pk, array_keys($types))) {
6020 if (!array_col_match_unique($rows, $edit_pk, '#^\d+$#')) {
6021 $edit_pk = guess_pk($rows);
6022 if (!$edit_pk) {
6023 $edit_table = false;
6024 }
6025 }
6026 } else {
6027 $edit_table = false;
6028 }
6029 } else {
6030 $edit_table = false;
6031 }
6032 }
6033 $edit_url = '';
6034 if ($edit_table) {
6035 $edit_url = url(self(true), array('action'=>'editrow', 'table'=>$edit_table, 'pk'=>$edit_pk, 'id'=>'%s'));
6036 }
6037 ?>
6038
6039 <table class="ls" cellspacing="1">
6040 <tr>
6041 <?php if ($edit_url): ?><th>#</th><?php endif; ?>
6042 <?php foreach ($rows[0] as $col => $v): ?>
6043 <th><?php echo $col;?></th>
6044 <?php endforeach; ?>
6045 </tr>
6046 <?php foreach ($rows as $row): ?>
6047 <tr onclick="mark_row(this, event)">
6048 <?php if ($edit_url): ?>
6049 <td valign=top><a href="javascript:void(0)" onclick="popup('<?php echo sprintf($edit_url, $row[$edit_pk]);?>', <?php echo EDITROW_POPUP_WIDTH; ?>, <?php echo EDITROW_POPUP_HEIGHT; ?>)">Edit</a> </td>
6050 <?php endif; ?>
6051 <?php
6052 $count_cols = 0;
6053 foreach ($row as $v) { $count_cols++; }
6054 ?>
6055 <?php foreach ($row as $k => $v): ?>
6056 <?php
6057 if (preg_match('#^\s*<a[^>]+>[^<]+</a>\s*$#iU', $v) && strlen(strip_tags($v)) < 50) {
6058 $v = strip_tags($v, '<a>');
6059 $v = create_links($v);
6060 } else {
6061 $v = strip_tags($v);
6062 $v = str_replace(' ', ' ', $v);
6063 $v = preg_replace('#[ ]+#', ' ', $v);
6064 $v = create_links($v);
6065 if (!$full_content && strlen($v) > 50) {
6066 if (1 == $count_cols) {
6067 $v = truncate_html($v, 255);
6068 } else {
6069 $v = truncate_html($v, 50);
6070 }
6071 }
6072 // $v = html_once($v); - create_links() disabling
6073 }
6074 if ($full_content) {
6075 $v = str_wrap($v, 80, '<br>', true);
6076 }
6077 if ($full_content) {
6078 $v = nl2br($v);
6079 }
6080 //$v = stripslashes(stripslashes($v));
6081 if (isset($types[$k]) && $types && $types[$k] == 'int' && IsTimestampColumn($k, $v))
6082 {
6083 // 100 000 000 == 1973-03-03 10:46:40
6084 // Only big integers change to dates, so a low one like "1054"
6085 // does not get changed into a date, cause that would probably be wrong.
6086
6087 $tmp = date('Y-m-d H:i', $v);
6088 if ($tmp) {
6089 $v = $tmp;
6090 }
6091 }
6092 ?>
6093 <td <?php echo $full_content ? 'valign="top"':'';?> nowrap><?php echo is_null($row[$k])?'-':$v;?></td>
6094 <?php endforeach; ?>
6095 </tr>
6096 <?php endforeach; ?>
6097 </table>
6098
6099 <?php endif; ?>
6100
6101 <?php if ($pages > 1): ?>
6102 <p>
6103 <?php if ($page > 1): ?>
6104 <?php $ofs = ($page-1)*$limit-$limit; ?>
6105 <?php
6106 $params = array('md5'=>$md5_get, 'offset'=>$ofs);
6107 if ($_GET['only_select'] || $_POST['only_select']) { $params['only_select'] = 1; }
6108 ?>
6109 <a href="<?php echo url(self(), $params);?>"><< Prev</a>
6110 <?php endif; ?>
6111 Page <b><?php echo $page;?></b> of <b><?php echo $pages;?></b>
6112 <?php if ($pages > $page): ?>
6113 <?php $ofs = $page*$limit; ?>
6114 <?php
6115 $params = array('md5'=>$md5_get, 'offset'=>$ofs);
6116 if ($_GET['only_select'] || $_POST['only_select']) { $params['only_select'] = 1; }
6117 ?>
6118 <a href="<?php echo url(self(), $params);?>">Next >></a>
6119 <?php endif; ?>
6120 </p>
6121 <?php endif; ?>
6122
6123 <?php endif; ?>
6124
6125 <?php
6126 $cont = ob_get_contents();
6127 ob_end_clean();
6128 $ret['data_html'] = $cont;
6129 return $ret;
6130 }
6131
6132?>
6133<?php
6134
6135 // ----------------------------------------------------------------
6136 // @sqleditor PHP
6137 // ----------------------------------------------------------------
6138
6139 set_time_limit(0);
6140
6141 $msg = '';
6142 $error = '';
6143 $top_html = '';
6144 $data_html = '';
6145
6146 $template = GET("template", "string");
6147 GET("popup", "bool");
6148 GET("md5", "string");
6149 GET("full_content", "bool");
6150 GET("only_select", "bool");
6151
6152 POST("sql", "string");
6153 POST("perform", "string");
6154 POST("only_select", "bool");
6155 POST("full_content", "bool");
6156 POST("save_as", "string");
6157 POST("load_from", "string");
6158
6159 if ($_GET['md5']) {
6160 $_GET['only_select'] = true;
6161 $_GET['only_select'] = true;
6162 }
6163
6164 if ($_GET['only_select']) { $_POST['only_select'] = 1; }
6165
6166 $sql_dir = false;
6167 if (defined('DBKISS_SQL_DIR')) {
6168 $sql_dir = DBKISS_SQL_DIR;
6169 }
6170
6171 if ($sql_dir) {
6172 if (!(dir_exists($sql_dir) && is_writable($sql_dir))) {
6173 if (!dir_exists($sql_dir) && is_writable('.')) {
6174 mkdir($sql_dir);
6175 } else {
6176 exit('You must create "'.$sql_dir.'" directory with write permission.');
6177 }
6178 }
6179 if (!file_exists($sql_dir.'/.htaccess')) {
6180 file_put($sql_dir.'/.htaccess', 'deny from all');
6181 }
6182 if (!file_exists($sql_dir.'/index.html')) {
6183 file_put($sql_dir.'/index.html', '');
6184 }
6185 }
6186
6187 if ('GET' == $_SERVER['REQUEST_METHOD']) {
6188 if ($sql_dir)
6189 {
6190 if ($_GET['md5'] && preg_match('#^(\w{32,32})_(\d+)$#', $_GET['md5'], $match)) {
6191 $md5_i = $match[2];
6192 $md5_tmp = sprintf($sql_dir.'/zzz_%s.dat', $match[1]);
6193 $_POST['sql'] = file_get_contents($md5_tmp);
6194 $_SERVER['REQUEST_METHOD'] = 'POST';
6195 $_POST['perform'] = 'execute';
6196 } else if ($_GET['md5'] && preg_match('#^(\w{32,32})$#', $_GET['md5'], $match)) {
6197 $md5_tmp = sprintf($sql_dir.'/zzz_%s.dat', $match[1]);
6198 $_POST['sql'] = file_get_contents($md5_tmp);
6199 $_GET['md5'] = '';
6200 } else {
6201 if ($_GET['md5']) {
6202 trigger_error('invalid md5', E_USER_ERROR);
6203 }
6204 }
6205 }
6206 } else {
6207 $_GET['md5'] = '';
6208 }
6209
6210 $_POST['sql'] = trim($_POST['sql']);
6211 $md5 = md5($_POST['sql']);
6212 $md5_file = sprintf($sql_dir.'/zzz_%s.dat', $md5);
6213 if ($sql_dir && $_POST['sql']) {
6214 file_put($md5_file, $_POST['sql']);
6215 }
6216
6217 if ($sql_dir && 'save' == $_POST['perform'] && $_POST['save_as'] && $_POST['sql'])
6218 {
6219 $_POSAT['save_as'] = str_replace('.sql', '', $_POST['save_as']);
6220 if (preg_match('#^[\w ]+$#', $_POST['save_as'])) {
6221 $file = $sql_dir.'/'.$_POST['save_as'].'.sql';
6222 $overwrite = '';
6223 if (file_exists($file)) {
6224 $overwrite = ' - <b>overwritten</b>';
6225 $bak = $sql_dir.'/zzz_'.$_POST['save_as'].'_'.md5(file_get_contents($file)).'.dat';
6226 copy($file, $bak);
6227 }
6228 $msg .= sprintf('<div>Sql saved: %s %s</div>', basename($file), $overwrite);
6229 file_put($file, $_POST['sql']);
6230 } else {
6231 error('Saving sql failed: only alphanumeric chars are allowed');
6232 }
6233 }
6234
6235 if ($sql_dir) {
6236 $load_files = dir_read($sql_dir, null, array('.sql'), 'date_desc');
6237 }
6238 $load_assoc = array();
6239 if ($sql_dir) {
6240 foreach ($load_files as $file) {
6241 $file_path = $file;
6242 $file = basename($file);
6243 $load_assoc[$file] = '('.substr(file_date($file_path), 0, 10).')'.' ' .$file;
6244 }
6245 }
6246
6247 if ($sql_dir && 'load' == $_POST['perform'])
6248 {
6249 $file = $sql_dir.'/'.$_POST['load_from'];
6250 if (array_key_exists($_POST['load_from'], $load_assoc) && file_exists($file)) {
6251 $msg .= sprintf('<div>Sql loaded: %s (%s)</div>', basename($file), timestamp(file_date($file)));
6252 $_POST['sql'] = file_get_contents($file);
6253 $_POST['save_as'] = basename($file);
6254 $_POST['save_as'] = str_replace('.sql', '', $_POST['save_as']);
6255 } else {
6256 error('<div>File not found: %s</div>', $file);
6257 }
6258 }
6259
6260 // after load - md5 may change
6261 $md5 = md5($_POST['sql']);
6262
6263 if ($sql_dir && 'load' == $_POST['perform'] && !error()) {
6264 $md5_tmp = sprintf($sql_dir.'/zzz_%s.dat', $md5);
6265 file_put($md5_tmp, $_POST['sql']);
6266 }
6267
6268 $is_sel = false;
6269
6270 $queries = preg_split("#;(\s*--[ \t\S]*)?(\r\n|\n|\r)#U", $_POST['sql']);
6271 foreach ($queries as $k => $query) {
6272 $query = query_strip($query);
6273 if (0 === strpos($query, '@')) {
6274 $is_sel = true;
6275 }
6276 $queries[$k] = $query;
6277 if (!trim($query)) { unset($queries[$k]); }
6278 }
6279
6280 $sql_assoc = array();
6281 $sql_selected = false;
6282 $i = 0;
6283
6284 $params = array(
6285 'md5' => $md5,
6286 'only_select' => $_GET["only_select"] || $_POST['only_select'],
6287 'full_content' => $_GET["full_content"] || $_POST['full_content'],
6288 'offset' => ''
6289 );
6290 $sql_main_url = url(self(), $params);
6291
6292 foreach ($queries as $query) {
6293 $i++;
6294 $query = preg_replace("#^@#", "", $query);
6295 if (!is_select($query) && !is_show($query)) {
6296 continue;
6297 }
6298 $query = preg_replace('#\s+#', ' ', $query);
6299 $params = array(
6300 'md5' => $md5.'_'.$i,
6301 'only_select' => $_GET["only_select"] || $_POST['only_select'],
6302 'full_content' => $_GET["full_content"] || $_POST['full_content'],
6303 'offset' => ''
6304 );
6305 $url = url(self(), $params);
6306 if ($_GET['md5'] && $_GET['md5'] == $params['md5']) {
6307 $sql_selected = $url;
6308 }
6309 $sql_assoc[$url] = str_truncate(strip_tags($query), 80);
6310 }
6311
6312 if ('POST' == $_SERVER['REQUEST_METHOD'])
6313 {
6314 if (!$_POST['perform']) {
6315 $error = 'No action selected.';
6316 }
6317 if (!$error)
6318 {
6319 $time = time_start();
6320 switch ($_POST['perform']) {
6321 case 'execute':
6322 $i = 0;
6323 db_begin();
6324 $commit = true;
6325 foreach ($queries as $query)
6326 {
6327 $i++;
6328 if ($is_sel) {
6329 if (0 === strpos($query, '@')) {
6330 $query = substr($query, 1);
6331 } else {
6332 if (!$_GET['md5']) { continue; }
6333 }
6334 }
6335 if ($_POST['only_select'] && !is_select($query) && !is_show($query)) {
6336 continue;
6337 }
6338 if ($_GET['md5'] && $i != $md5_i) {
6339 continue;
6340 }
6341 if ($_GET['md5'] && $i == $md5_i) {
6342 if (!is_select($query) && !is_show($query)) {
6343 trigger_error('not select query', E_USER_ERROR);
6344 }
6345 }
6346
6347 $exec = listing($query, $md5.'_'.$i);
6348 $query_trunc = str_truncate(html_once($query), 1000);
6349 $query_trunc = query_color($query_trunc);
6350 $query_trunc = nl2br($query_trunc);
6351 $query_trunc = html_spaces($query_trunc);
6352 if ($exec['error']) {
6353 $exec['error'] = preg_replace('#error:#i', '', $exec['error']);
6354 $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);
6355 $commit = false;
6356 break;
6357 } else {
6358 $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);
6359 $data_html .= $query_html;
6360 $data_html .= $exec['data_html'];
6361 }
6362 }
6363 if ($commit) {
6364 db_end();
6365 } else {
6366 db_rollback();
6367 }
6368 break;
6369 }
6370 $time = time_end($time);
6371 }
6372 }
6373
6374?>
6375<?php rawlayout_start('SQL Editor ' . ("[".($db_name_h1?$db_name_h1:$db_name))."]"); ?>
6376
6377 <?php
6378
6379 // ----------------------------------------------------------------
6380 // @sqleditor HTML
6381 // ----------------------------------------------------------------
6382
6383 ?>
6384
6385 <?php if ($_GET['popup']): ?>
6386 <h1>SQL Editor [<span style="<?php echo $db_name_style;?>"><?php echo $db_name_h1?$db_name_h1:$db_name;?></span>]</h1>
6387 <?php else: ?>
6388 <h1><a class=blue style="<?php echo $db_name_style;?>" href="<?php echo $_SERVER['PHP_SELF'];?>">
6389 <?php echo $db_name_h1?$db_name_h1:$db_name;?></a> > SQL Editor</h1>
6390 <?php endif; ?>
6391
6392 <?php echo error();?>
6393
6394 <script>
6395 function sql_submit(form)
6396 {
6397 if (form.perform.value.length) {
6398 return true;
6399 }
6400 return false;
6401 }
6402 function sql_execute(form)
6403 {
6404 form.perform.value='execute';
6405 form.submit();
6406 }
6407 function sql_preview(form)
6408 {
6409 form.perform.value='preview';
6410 form.submit();
6411 }
6412 function sql_save(form)
6413 {
6414 form.perform.value='save';
6415 form.submit();
6416 }
6417 function sql_load(form)
6418 {
6419 if (form.load_from.selectedIndex)
6420 {
6421 form.perform.value='load';
6422 form.submit();
6423 return true;
6424 }
6425 button_clear(form);
6426 return false;
6427 }
6428 </script>
6429
6430 <?php if ($msg): ?>
6431 <div class="msg"><?php echo $msg;?></div>
6432 <?php endif; ?>
6433
6434 <?php echo $top_html;?>
6435
6436 <?php if (count($sql_assoc)): ?>
6437 <p>
6438 SELECT queries:
6439 <select name="sql_assoc" onchange="if (this.value.length) location=this.value">
6440 <option value="<?php echo html_once($sql_main_url);?>"></option>
6441 <?php echo options($sql_assoc, $sql_selected);?>
6442 </select>
6443 </p>
6444 <?php endif; ?>
6445
6446 <?php if ($_GET['md5']): ?>
6447 <?php echo $data_html;?>
6448 <?php endif; ?>
6449
6450 <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;">
6451 <input type="hidden" name="perform" value="">
6452 <div style="margin-bottom: 0.25em;">
6453 <textarea accesskey=s id="sql_area" name="sql" class="sql_area"><?php echo htmlspecialchars(query_upper($_POST['sql']));?></textarea>
6454 </div>
6455 <table cellspacing="0" cellpadding="0"><tr>
6456 <td nowrap>
6457 <input type="button" wait="1" class="button" value="Execute" onclick="sql_execute(this.form); ">
6458 </td>
6459 <td nowrap>
6460
6461 <input type="button" wait="1" class="button" value="Preview" onclick="sql_preview(this.form); ">
6462 </td>
6463 <td nowrap>
6464
6465 <input type="checkbox" name="only_select" id="only_select" value="1" <?php echo checked($_POST['only_select'] || $_GET['only_select']);?>>
6466 </td>
6467 <td nowrap>
6468 <label for="only_select">Only SELECT queries</label>
6469 </td>
6470 <td nowrap>
6471
6472 <input type="checkbox" name="full_content" id="full_content" value="1" <?php echo checked($_POST['full_content'] || $_GET['full_content']);?>>
6473 </td>
6474 <td nowrap>
6475 <label for="full_content">Full content</label>
6476
6477 </td>
6478
6479
6480
6481 <td nowrap>
6482 <input type="text" name="save_as" value="<?php echo html_once($_POST['save_as']);?>">
6483
6484 </td>
6485 <td nowrap>
6486 <input type="button" wait="1" class="button" value="Save" onclick="sql_save(this.form); ">
6487
6488 </td>
6489 <td nowrap>
6490 <select name="load_from" style="width: 140px;"><option value=""></option><?php echo options($load_assoc);?></select>
6491
6492 </td>
6493 <td nowrap>
6494 <input type="button" wait="1" class="button" value="Load" onclick="return sql_load(this.form);">
6495 </td>
6496 </tr></table>
6497 </form>
6498
6499 <?php
6500
6501 if ('preview' == $_POST['perform'])
6502 {
6503 echo '<h2>Preview</h2>';
6504 $i = 0;
6505 foreach ($queries as $query)
6506 {
6507 $i++;
6508 $query = preg_replace("#^@#", "", $query);
6509 $query = html_once($query);
6510 $query = query_color($query);
6511 $query = nl2br($query);
6512 $query = html_spaces($query);
6513 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);
6514 }
6515 }
6516
6517 ?>
6518
6519 <?php if (!$_GET['md5']): ?>
6520 <script>Element('sql_area').focus();</script>
6521 <?php echo $data_html;?>
6522 <?php endif; ?>
6523
6524 <?php rawlayout_end(); ?>
6525
6526<?php exit(); endif; ?>
6527
6528<?php if (GET("viewtable", "string")): ?>
6529<?php
6530
6531 // ----------------------------------------------------------------
6532 // @viewtable
6533 // ----------------------------------------------------------------
6534
6535 GET("viewtable", "string");
6536 GET("full_content", "bool");
6537 GET("search", "string");
6538 GET("column", "string");
6539 GET("column_type", "string");
6540 GET("offset", "int");
6541 GET("order_by", "string");
6542 GET("order_desc", "bool");
6543 POST("full_content", "bool");
6544
6545 set_time_limit(0);
6546
6547 $full_content = ($_GET["full_content"] || $_POST["full_content"]);
6548
6549 $table = $_GET['viewtable'];
6550 $table_enq = quote_table($table);
6551 $count = db_one("SELECT COUNT(*) FROM $table_enq");
6552
6553 $types = table_columns($table);
6554 $columns = array_assoc(array_keys($types));
6555 $columns2 = $columns;
6556
6557 foreach ($columns2 as $k => $v) {
6558 $columns2[$k] = $v.' ('.$types[$k].')';
6559 }
6560 $types_group = table_columns_group($types);
6561
6562 $where = '';
6563 $found = $count;
6564 if ($_GET['search']) {
6565 $search = $_GET['search'];
6566 $cols2 = array();
6567
6568 if ($_GET['column']) {
6569 $cols2[] = $_GET['column'];
6570 } else {
6571 $cols2 = $columns;
6572 }
6573 $where = '';
6574 $search = db_escape($search);
6575 $search = str_replace(array("%", "_"), array("\%", "\_"), $search);
6576
6577 $column_type = '';
6578 if (!$_GET['column']) {
6579 $column_type = $_GET['column_type'];
6580 } else {
6581 $_GET['column_type'] = '';
6582 }
6583
6584 $ignore_int = false;
6585 $ignore_time = false;
6586
6587 foreach ($columns as $col)
6588 {
6589 if (!$_GET['column'] && $column_type) {
6590 if ($types[$col] != $column_type) {
6591 continue;
6592 }
6593 }
6594 if (!$column_type && !is_numeric($search) && strstr($types[$col], 'int')) {
6595 $ignore_int = true;
6596 continue;
6597 }
6598 if (!$column_type && is_numeric($search) && ( strstr($types[$col], 'time') || strstr($types[$col], 'date') )) {
6599 $ignore_time = true;
6600 continue;
6601 }
6602 if ($_GET['column'] && $col != $_GET['column']) {
6603 continue;
6604 }
6605 if ($where) { $where .= ' OR '; }
6606 if (is_numeric($search)) {
6607 if ("mysql" == $db_driver) {
6608 $where .= "`$col` = '$search' ";
6609 } else {
6610 // pgsql, sqlite
6611 $where .= "\"$col\" = '$search' ";
6612 }
6613 } else {
6614 if ('mysql' == $db_driver) {
6615 $where .= "`$col` LIKE '%$search%' ";
6616 } else if ('pgsql' == $db_driver) {
6617 $where .= "\"$col\" ILIKE '%$search%' ";
6618 } else if ("sqlite" == $db_driver) {
6619 $where .= "\"$col\" LIKE '%$search%' ";
6620 } else {
6621 trigger_error('db_driver not implemented');
6622 }
6623 }
6624 }
6625 if (($ignore_int || $ignore_time) && !$where) {
6626 $where .= ' 1=2 ';
6627 }
6628 $where = 'WHERE '.$where;
6629 }
6630
6631 if ($where) {
6632 $table_enq = quote_table($table);
6633 $found = db_one("SELECT COUNT(*) FROM $table_enq $where");
6634 }
6635
6636 $limit = 50;
6637 $offset = $_GET["offset"];
6638 $page = floor($offset / $limit + 1);
6639 $pages = ceil($found / $limit);
6640
6641
6642 $pk = table_pk($table);
6643
6644 // Pkeys needed for "Edit" row link parameter.
6645
6646 if (strstr($pk, ":")) {
6647 $pkeys = $pk;
6648 $pkeys_enq = QuotePkeys($pkeys);
6649 } else {
6650 $pk_enq = quote_column($pk);
6651 $pkeys = false;
6652 }
6653
6654 $order = "ORDER BY";
6655 if ($_GET['order_by']) {
6656 $order_by_enq = quote_column($_GET['order_by']);
6657 if ("char" == $types[$_GET["order_by"]] || "text" == $types[$_GET["order_by"]]) {
6658 $order .= " LOWER($order_by_enq)";
6659 } else {
6660 $order .= " $order_by_enq";
6661 }
6662 } else {
6663 if ($pk) {
6664 if ($pkeys) {
6665 $order .= " $pkeys_enq";
6666 $_GET["order_by"] = FirstFromPkeys($pk); // So that when clicking on first column to sort it will be sorted Descendant.
6667 } else {
6668 $order .= " $pk_enq";
6669 $_GET["order_by"] = $pk; // So that when clicking on first column to sort it will be sorted Descendant.
6670 }
6671 } else {
6672 $order = '';
6673 }
6674 }
6675
6676 if ($_GET['order_desc']) { $order .= ' DESC'; }
6677
6678 $table_enq = quote_table($table);
6679 $base_query = "SELECT * FROM $table_enq $where $order";
6680 $rs = db_query(db_limit($base_query, $offset, $limit));
6681
6682 if ($count && $rs) {
6683 $rows = array();
6684 while ($row = db_row($rs)) {
6685 $rows[] = $row;
6686 }
6687 db_free($rs);
6688 // If there are multiple pkeys then that is 100% sure and we do not have to check it later.
6689 if (!$pkeys) {
6690 if (count($rows) && !array_col_match_unique($rows, $pk, '#^\d+$#')) {
6691 $pk = guess_pk($rows);
6692 }
6693 }
6694 }
6695
6696 function indenthead($str)
6697 {
6698 if (is_array($str)) {
6699 $str2 = '';
6700 foreach ($str as $k => $v) {
6701 $str2 .= sprintf('%s: %s'."\r\n", $k, $v);
6702 }
6703 $str = $str2;
6704 }
6705 $lines = explode("\n", $str);
6706 $max_len = 0;
6707 foreach ($lines as $k => $line) {
6708 $lines[$k] = trim($line);
6709 if (preg_match('#^[^:]+:#', $line, $match)) {
6710 if ($max_len < strlen($match[0])) {
6711 $max_len = strlen($match[0]);
6712 }
6713 }
6714 }
6715 foreach ($lines as $k => $line) {
6716 if (preg_match('#^[^:]+:#', $line, $match)) {
6717 $lines[$k] = str_replace($match[0], $match[0].str_repeat(' ', $max_len - strlen($match[0])), $line);
6718 }
6719 }
6720 return implode("\r\n", $lines);
6721 }
6722
6723 ?>
6724
6725 <?php
6726
6727 // ----------------------------------------------------------------
6728 // @viewtable HTML
6729 // ----------------------------------------------------------------
6730
6731 ?>
6732
6733 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
6734 <html>
6735 <head>
6736 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $page_charset;?>">
6737 <meta name="robots" content="noindex, nofollow">
6738 <title><?php echo $db_name_h1?$db_name_h1:$db_name;?> > <?php echo $table;?></title>
6739 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
6740 </head>
6741 <body>
6742
6743 <?php layout(); ?>
6744
6745 <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> > <?php echo $table;?></h1>
6746
6747 <?php conn_info(); ?>
6748
6749 <p>
6750 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>">All tables</a>
6751 >
6752 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $table;?>"><?php echo $table;?></a> (<?php echo $count;?>)
6753 /
6754
6755 Export to CSV:
6756
6757 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode('|');?>&query=<?php echo base64_encode($base_query); ?>">pipe</a>
6758 -
6759 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode("\t");?>&query=<?php echo base64_encode($base_query); ?>">tab</a>
6760 -
6761 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode(',');?>&query=<?php echo base64_encode($base_query); ?>">comma</a>
6762 -
6763 <a href="<?php echo $_SERVER['PHP_SELF']; ?>?export=csv&separator=<?php echo urlencode(';');?>&query=<?php echo base64_encode($base_query); ?>">semicolon</a>
6764
6765 <?php AutoFocus_HelpLink(); ?>
6766
6767
6768 <!--
6769 <a title="Click to see some help for this page." class="help" style="margin-bottom: -4px;" href="javascript:;" onclick="Tooltip(this, 'Help_MarkRows')"></a>
6770
6771 <div id="Help_MarkRows" style="display: none;">
6772 You can <b>mark</b> rows on the listing by clicking on the row while <b>holding CTRL</b>.<br>
6773 Row's background will change to <b>darker gray</b> when you do this.<br>
6774 This can be helpful in a few cases, one of them is to be able to <b>compare visually</b> some of the records on current page.<br>
6775 Unfortunately, that marking won't be <b>preserved</b> when you go to the Next or Previous page.<br>
6776 <br>
6777 But such a feature could be implemented in the future, some kind of <b>virtual table</b> to which the marked records<br>
6778 will be put, so you would be able to come back later and list them in an easy manner. If you would like such a feature <br>
6779 then <b>Vote for it</b> by contacting the author of this project.
6780 </div>
6781 -->
6782
6783 <!--
6784 /
6785 Functions:
6786 <a href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $table;?>&indenthead=1">indenthead()</a>
6787 -->
6788 </p>
6789
6790 <?php AutoFocus_Script(); ?>
6791
6792 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="get" style="margin-bottom: 1em;" name=AutoFocus_Form onsubmit="document.getElementById('AutoFocus_Submit').focus()">
6793 <input type="hidden" name="viewtable" value="<?php echo $table;?>">
6794
6795 <div>
6796 <u>S</u>earch: <input size=30 type="text" name="search" value="<?php echo html_once($_GET['search']);?>" id=AutoFocus_Input onfocus="this.setAttribute('isfocused', '1');" onblur="this.setAttribute('isfocused', '');" autocomplete=off></td>
6797 <input type="submit" value="Search" id=AutoFocus_Submit>
6798
6799 <!--
6800 <input type="checkbox" name="full_content" id="full_content" <?php echo checked($full_content);?>>
6801 <label for="full_content">Full content</label>
6802 -->
6803
6804 <select><option>Truncate content</option><option>Full content</option></select>
6805
6806 <a class=help href="javascript:;" title="Help: searching" onclick="Tooltip(this, 'Help_TableSearch')"></a>
6807 </div>
6808
6809 <div>
6810 Column: <select name="column"><option value=""></option><?php echo options($columns2, $_GET['column']);?></select>
6811
6812 Type: <select name="column_type"><option value=""></option><?php echo options($types_group, $_GET['column_type']);?></select>
6813
6814 S<u>o</u>rt:
6815 <select accesskey=o id="order_by" name="order_by"><option value=""></option>
6816 <?php echo options($columns, $_GET['order_by']);?></select>
6817
6818 <!--
6819 <input type="checkbox" name="order_desc" id="order_desc" value="1" <?php echo checked($_GET['order_desc']);?>>
6820 <label for="order_desc">Descending order</label>
6821 -->
6822
6823 Sort type:
6824 <select><option>Sort up</option><option>Sort down</option></select>
6825
6826 Export query:
6827 <a href="">View in SQL Editor</a>
6828
6829
6830
6831 </div>
6832
6833 </form>
6834
6835 <div id=Help_TableSearch style="display: none;">
6836 Wyszukiwanie: id=nick, gdy INT to dokladnie sprawdza, gdy char lub text to uzywa LIKE.<br>
6837 Wystarczy wpisac czesc nazwy kolumny, nie trzeba calej, wtedy znajdzie 1 kolumne ktora zawiera to slowo i w niej bedzie wyszukiwał.<br>
6838 Sort: w liscie dodac sortowanie desc, czyli: id, id DESC, name, name DESC - w &lgt;options><br>
6839 Type: dac jako checkboxy? Zrobic to jakos wygodniej zeby nie bylo rozdzielenia na Column i Type jak jest teraz.
6840 </div>
6841
6842 <?php if ($count): ?>
6843
6844 <?php if ($count && $count != $found): ?>
6845 <p>Found: <b><?php echo $found;?></b></p>
6846 <?php endif; ?>
6847
6848 <?php if ($found): ?>
6849
6850 <?php if ($pages > 1): ?>
6851 <p>
6852
6853 <?php if ($page > 1): ?>
6854 <a href="<?php echo url_offset(($page-1)*$limit-$limit);?>"><< Prev</a>
6855 <?php endif; ?>
6856 Page <b><?php echo $page;?></b> of <b><?php echo $pages;?></b>
6857 <?php if ($pages > $page): ?>
6858 <a href="<?php echo url_offset($page*$limit);?>">Next >></a>
6859 <?php endif; ?>
6860
6861 </p>
6862 <?php endif; ?>
6863
6864 <table class="ls" cellspacing="0">
6865 <tr>
6866 <?php if ($pk || $pkeys): ?><th>#</th><?php endif; ?>
6867 <?php foreach ($columns as $col): ?>
6868 <?php
6869 $params = array('order_by'=>$col);
6870 $params['order_desc'] = 0;
6871 $params["offset"] = 0;
6872 $col2 = $col;
6873 if ($_GET['order_by'] == $col) {
6874 if ($_GET["order_desc"]) {
6875 $col2 = "$col2 <span class=downarrow1 onmousedown=\"Sort_Click(document.getElementById('current_order_arrow'), event);\"></span>";
6876 } else {
6877 $col2 = "$col2 <span class=uparrow1 onmousedown=\"Sort_Click(document.getElementById('current_order_arrow'), event);\"></span>";
6878 }
6879 $params['order_desc'] = $_GET['order_desc'] ? 0 : 1;
6880 }
6881 $camelcase = (strtolower($col) != $col);
6882 ?>
6883 <th class="sortable <?php echo $camelcase; ?>">
6884 <a href="javascript:void(0)"
6885 <?php if ($_GET["order_by"] == $col): ?>id="current_order_arrow"<?php endif; ?>
6886 onmouseover="Sort_Mouseover(this, event)"
6887 onmouseout="Sort_Mouseout(this, event)"
6888 onmousemove="Sort_Mousemove(this, event)"
6889 onmousedown="Sort_Click(this, event)"
6890 mylink="<?php echo url(self(), $params);?>">
6891 <?php echo $col2;?></a></th>
6892 <?php endforeach; ?>
6893 </tr>
6894 <?php
6895 $get_search = $_GET['search'];
6896 ?>
6897 <?php
6898 $edit_url_tpl = url(self(true), array('action'=>'editrow', 'table'=>$table, 'pk'=>$pkeys ? $pkeys : $pk, 'id'=>'EDIT_URL_TPL_ID'));
6899 ?>
6900 <?php foreach ($rows as $row): ?>
6901 <tr onclick="mark_row(this, event)">
6902 <?php if ($pk || $pkeys): ?>
6903 <?php $edit_url = str_replace("EDIT_URL_TPL_ID", EncodeRowId($row, $pk, $pkeys), $edit_url_tpl); ?>
6904 <td valign=top><a href="javascript:void(0)" onclick="popup('<?php echo $edit_url;?>', <?php echo EDITROW_POPUP_WIDTH; ?>, <?php echo EDITROW_POPUP_HEIGHT; ?>)">Edit</a> </td>
6905 <?php endif; ?>
6906 <?php foreach ($row as $k => $v): ?>
6907 <?php
6908 $v = strip_tags($v);
6909 $v = create_links($v);
6910 if (!$full_content) {
6911 $v = truncate_html($v, 50);
6912 }
6913 //$v = html_once($v);
6914 //$v = htmlspecialchars($v); -- create_links() disabling
6915 if ($full_content) {
6916 $v = str_wrap($v, 80, '<br>', true);
6917 }
6918 if ($full_content) {
6919 $v = nl2br($v);
6920 }
6921 //$v = stripslashes(stripslashes($v));
6922 if ($get_search) {
6923 $search = $_GET['search'];
6924 if (isset($_GET["column"]) && $_GET["column"]) {
6925 // When search specific columns highlight the search phrase only for that column.
6926 if ($k == $_GET["column"]) {
6927 $v = ColorSearchPhrase($v, $search);
6928 }
6929 } else {
6930 $v = ColorSearchPhrase($v, $search);
6931 }
6932 }
6933 if ($types[$k] == 'int' && IsTimestampColumn($k, $v))
6934 {
6935 $tmp = date('Y-m-d H:i', $v);
6936 if ($tmp) {
6937 $v = $tmp;
6938 }
6939 }
6940 ?>
6941 <td <?php echo $full_content ? 'valign="top"':'';?> nowrap><?php echo is_null($row[$k])?'-':$v;?></td>
6942 <?php endforeach; ?>
6943 </tr>
6944 <?php endforeach; ?>
6945 </table>
6946
6947 <?php if ($pages > 1): ?>
6948 <p>
6949 <?php if ($page > 1): ?>
6950 <a href="<?php echo url_offset(($page-1)*$limit-$limit);?>"><< Prev</a>
6951 <?php endif; ?>
6952 Page <b><?php echo $page;?></b> of <b><?php echo $pages;?></b>
6953 <?php if ($pages > $page): ?>
6954 <a href="<?php echo url_offset($page*$limit);?>">Next >></a>
6955 <?php endif; ?>
6956 </p>
6957 <?php endif; ?>
6958
6959 <?php endif; ?>
6960
6961 <?php endif; ?>
6962
6963</body>
6964</html>
6965<?php exit(); endif; ?>
6966
6967
6968<?php if (GET("searchdb", "bool")): ?>
6969<?php
6970
6971 // ----------------------------------------------------------------
6972 // @searchdb PHP
6973 // ----------------------------------------------------------------
6974
6975 GET("types", "array");
6976 GET("search", "string");
6977 GET("md5", "bool");
6978 GET("table_filter", "string");
6979
6980 $_GET['search'] = trim($_GET['search']);
6981
6982 $tables = list_tables();
6983
6984 if ($_GET['table_filter']) {
6985 foreach ($tables as $k => $table) {
6986 if (!str_has_any($table, $_GET['table_filter'], $ignore_case = true)) {
6987 unset($tables[$k]);
6988 }
6989 }
6990 }
6991
6992 $all_types = array();
6993 $columns = array();
6994 foreach ($tables as $table) {
6995 $types = table_columns($table);
6996 $columns[$table] = $types;
6997 $types = array_values($types);
6998 $all_types = array_merge($all_types, $types);
6999 }
7000 $all_types = array_unique($all_types);
7001
7002 if ($_GET['search'] && $_GET['md5']) {
7003 $_GET['search'] = md5($_GET['search']);
7004 }
7005
7006?>
7007<?php rawlayout_start(sprintf('%s > Search', $db_name)); ?>
7008
7009 <?php
7010 // ----------------------------------------------------------------
7011 // @searchdb HTML
7012 // ----------------------------------------------------------------
7013 ?>
7014
7015 <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>
7016 <?php conn_info(); ?>
7017
7018 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="get">
7019 <input type="hidden" name="searchdb" value="1">
7020 <table class="ls2" cellspacing="1">
7021 <tr>
7022 <th>Search:</th>
7023 <td>
7024 <input type="text" name="search" value="<?php echo html_once($_GET['search']);?>" size="40">
7025 <?php if ($_GET['search'] && $_GET['md5']): ?>
7026 md5(<?php echo html_once($_GET['search']);?>)
7027 <?php endif; ?>
7028 <input type="checkbox" name="md5" id="md5_label" value="1">
7029 <label for="md5_label">md5</label>
7030 </td>
7031 </tr>
7032 <tr>
7033 <th>Table filter:</th>
7034 <td><input type="text" name="table_filter" value="<?php echo html_once($_GET['table_filter']);?>">
7035 </tr>
7036 <tr>
7037 <th>Columns:</th>
7038 <td>
7039 <?php foreach ($all_types as $type): ?>
7040 <input type="checkbox" id="type_<?php echo $type;?>" name="types[<?php echo $type;?>]" value="1" <?php echo checked(isset($_GET['types'][$type]));?>>
7041 <label for="type_<?php echo $type;?>"><?php echo $type;?></label>
7042 <?php endforeach; ?>
7043 </td>
7044 </tr>
7045 <tr>
7046 <td colspan="2" class="none">
7047 <input type="submit" value="Search">
7048 </td>
7049 </tr>
7050 </table>
7051 </form>
7052
7053 <?php if ($_GET['search'] && !count($_GET['types'])): ?>
7054 <p>No columns selected.</p>
7055 <?php endif; ?>
7056
7057 <?php if ($_GET['search'] && count($_GET['types'])): ?>
7058
7059 <p>Searching <b><?php echo count($tables);?></b> tables for: <b><?php echo htmlspecialchars($_GET['search']);?></b></p>
7060
7061 <?php $found_any = false; ?>
7062
7063 <?php set_time_limit(0); ?>
7064
7065 <?php foreach ($tables as $table): ?>
7066 <?php
7067
7068 $where = '';
7069 $cols2 = array();
7070
7071 $where = '';
7072 $search = db_escape($_GET['search']);
7073 $search = str_replace(array("%", "_"), array("\%", "\_"), $search);
7074
7075 foreach ($columns[$table] as $col => $type)
7076 {
7077 if (!in_array($type, array_keys($_GET['types']))) {
7078 continue;
7079 }
7080 if ($where) {
7081 $where .= ' OR ';
7082 }
7083 if (is_numeric($search)) {
7084 if ("mysql" == $db_driver) {
7085 $where .= "`$col` = '$search' ";
7086 } else {
7087 // pgsql, sqlite
7088 $where .= "\"$col\" = '$search' ";
7089 }
7090 } else {
7091 if ('mysql' == $db_driver) {
7092 $where .= "`$col` LIKE '%$search%' ";
7093 } else if ('pgsql' == $db_driver) {
7094 $where .= "\"$col\" ILIKE '%$search%' ";
7095 } else if ("sqlite" == $db_driver) {
7096 $where .= "\"$col\" LIKE '%$search%' ";
7097 } else {
7098 trigger_error('db_driver not implemented');
7099 }
7100 }
7101 }
7102
7103 $found = false;
7104
7105 if ($where) {
7106 $where = 'WHERE '.$where;
7107 $table_enq = quote_table($table);
7108 $found = db_one("SELECT COUNT(*) FROM $table_enq $where");
7109 }
7110
7111 if ($found) {
7112 $found_any = true;
7113 }
7114
7115 ?>
7116
7117 <?php
7118 if ($where && $found) {
7119 $limit = 10;
7120 $offset = 0;
7121
7122 $pk = table_pk($table);
7123
7124 if (strstr($pk, ":")) {
7125 $pkeys = $pk;
7126 $pkeys_enq = QuotePkeys($pkeys);
7127 } else {
7128 $pkeys = false;
7129 $pk_enq = quote_column($pk);
7130 }
7131
7132 if ($pkeys) {
7133 $order = "ORDER BY $pkeys_enq";
7134 } else {
7135 $order = "ORDER BY $pk_enq";
7136 }
7137
7138 $table_enq = quote_table($table);
7139 $rs = db_query(db_limit("SELECT * FROM $table_enq $where $order", $offset, $limit));
7140
7141 $rows = array();
7142 while ($row = db_row($rs)) {
7143 $rows[] = $row;
7144 }
7145 db_free($rs);
7146
7147 if (!$pkeys) {
7148 // If there are multiple primary keys then this pkeys are 100% sure, we do not have to guess.
7149 if (count($rows) && !array_col_match_unique($rows, $pk, '#^\d+$#')) {
7150 $pk = guess_pk($rows);
7151 }
7152 }
7153 }
7154 ?>
7155
7156 <?php if ($where && $found): ?>
7157
7158 <p>
7159 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>
7160 Found: <b><?php echo $found;?></b>
7161 <?php if ($found > $limit): ?>
7162 <a href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $table;?>&search=<?php echo urlencode($_GET['search']);?>">show all >></a>
7163 <?php endif; ?>
7164 </p>
7165
7166 <table class="ls" cellspacing="1">
7167 <tr>
7168 <?php if ($pk || $pkeys): ?><th>#</th><?php endif; ?>
7169 <?php foreach ($columns[$table] as $col => $type): ?>
7170 <th><?php echo $col;?></th>
7171 <?php endforeach; ?>
7172 </tr>
7173 <?php foreach ($rows as $row): ?>
7174 <tr>
7175 <?php if ($pk || $pkeys): ?>
7176 <?php $edit_url = url(self(true), array('action'=>'editrow', 'table'=>$table, 'pk'=>$pkeys ? $pkeys : $pk, 'id'=>EncodeRowId($row, $pk, $pkeys))); ?>
7177 <td valign=top><a href="javascript:void(0)" onclick="popup('<?php echo $edit_url;?>', <?php echo EDITROW_POPUP_WIDTH; ?>, <?php echo EDITROW_POPUP_HEIGHT; ?>)">Edit</a> </td>
7178 <?php endif; ?>
7179 <?php foreach ($row as $k => $v): ?>
7180 <?php
7181 $v = str_truncate($v, 50);
7182 $v = html_once($v);
7183 //$v = stripslashes(stripslashes($v));
7184 $search = $_GET['search'];
7185 if ($columns[$table][$k] == 'int' && IsTimestampColumn($k, $v)) {
7186 $tmp = date('Y-m-d H:i', $v);
7187 if ($tmp) {
7188 $v = $tmp;
7189 }
7190 }
7191 $v = ColorSearchPhrase($v, $search);
7192 ?>
7193 <td nowrap><?php echo $v;?></td>
7194 <?php endforeach; ?>
7195 </tr>
7196 <?php endforeach; ?>
7197 </table>
7198
7199 <?php endif; ?>
7200
7201 <?php endforeach; ?>
7202
7203 <?php if (!$found_any): ?>
7204 <p>No rows found.</p>
7205 <?php endif; ?>
7206
7207 <?php endif; ?>
7208
7209 <?php rawlayout_end(); ?>
7210<?php exit; endif; ?>
7211
7212<?php
7213
7214 // ----------------------------------------------------------------
7215 // @mainscreen PHP
7216 // ----------------------------------------------------------------
7217
7218 GET("table_filter", "string");
7219 GET("views_count", "bool");
7220 GET("precise_count", "bool");
7221
7222 $tables = list_tables();
7223 $status = table_status();
7224 $views = list_tables(true);
7225
7226?>
7227
7228<?php
7229
7230 // ----------------------------------------------------------------
7231 // @mainscreen HTML
7232 // ----------------------------------------------------------------
7233
7234?>
7235
7236 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
7237 <html>
7238 <head>
7239 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $page_charset;?>">
7240 <meta name="robots" content="noindex, nofollow">
7241 <title><?php echo $db_name_h1?$db_name_h1:$db_name;?></title>
7242 <link rel="shortcut icon" href="<?php echo $_SERVER['PHP_SELF']; ?>?dbkiss_favicon=1">
7243 </head>
7244 <body>
7245
7246 <?php layout(); ?>
7247
7248 <?php if (stristr($_SERVER["HTTP_USER_AGENT"], "MSIE") && stristr($_SERVER["HTTP_USER_AGENT"], "Trident")): ?>
7249 <div style="background: rgb(255, 255, 225); padding: 0.5em 1em; border: #ddd 1px solid; display: inline-block;">
7250 Internet Explorer is not supported. You may see interface glitches and javascript features broken.<br>
7251 Try using some decent browser like: Chrome, Firefox, Opera, Safari.
7252 </div>
7253 <?php endif; ?>
7254
7255 <h1 style="<?php echo $db_name_style;?>"><?php echo $db_name_h1?$db_name_h1:$db_name;?></h1>
7256
7257 <?php conn_info(); ?>
7258
7259 <p>
7260 Tables: <b><?php echo count($tables);?></b>
7261 -
7262 Total size: <b><?php echo number_format(ceil($status['total_size']/1024),0,'',' ').' k';?></b>
7263 -
7264 Views: <b><?php echo count($views);?></b>
7265 -
7266
7267 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?searchdb=1&table_filter=<?php echo html_once($_GET['table_filter']);?>">Search</a>
7268 -
7269 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?import=1">Import SQL</a>
7270 -
7271 D<u>u</u>mp database:
7272
7273 <?php
7274 $export_structure = $_SERVER['PHP_SELF'] . "?dump_all=1&table_filter=" . urlencode(html_once($_GET['table_filter'])); // Structure only.
7275 $export_data = $_SERVER['PHP_SELF'] . "?dump_all=2&table_filter=" . urlencode(html_once($_GET['table_filter'])); // Data and structure.
7276 ?>
7277
7278 <?php if ('pgsql' == $db_driver): ?>
7279 <select accesskey=u id=dump_database onchange="if (this.value) { window.location.href=this.value; }">
7280 <option value=""></option>
7281 <option value="<?php echo $export_data; ?>">Data only</option>
7282 </select>
7283 <?php else: ?>
7284 <select accesskey=u id=dump_database onchange="if (this.value) { window.location.href=this.value; }">
7285 <option value=""></option>
7286 <option value="<?php echo $export_structure; ?>">Structure only</option>
7287 <option value="<?php echo $export_data; ?>">Data and structure</option>
7288 </select>
7289 <?php endif; ?>
7290
7291 <a title="Help: dumping database" class=help href="javascript:;" onclick="Tooltip(this, 'Help_DumpDatabase')"></a>
7292
7293 <div id=Help_DumpDatabase style="display: none;">
7294 Dumping database takes into account the <b>table search</b> on the main page.<br>It allows
7295 you to dump only the <b>found tables</b>.<br>
7296 <div style="margin-top: 0.5em;">Do not make mistake by thinking that you are making a dump of the <b>whole database</b>,<br>
7297 when in fact you are dumping only <b>some of the tables</b>.</div>
7298 </div>
7299
7300 </p>
7301
7302 <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="get" name=AutoFocus_Form style="margin-bottom: 0.5em;" onsubmit="document.getElementById('AutoFocus_Submit').focus()">
7303 <table cellspacing="0" cellpadding="0"><tr>
7304 <td style="padding-right: 3px;">Table:</td>
7305 <td style="padding-right: 3px;">
7306 <input type="text" name="table_filter" value="<?php echo html_once($_GET['table_filter']);?>" id=AutoFocus_Input onfocus="this.setAttribute('isfocused', '1');" onblur="this.setAttribute('isfocused', '');" autocomplete=off>
7307 </td>
7308 <td style="padding-right: 3px;"><input id=AutoFocus_Submit type="submit" class="button" wait="1" value="Filter"> <?php AutoFocus_HelpLink(); ?></td>
7309 </tr></table>
7310 </form>
7311
7312 <?php AutoFocus_Script(); ?>
7313
7314 <div style="float: left;">
7315
7316 <!------------------>
7317 <!-- @listtables -->
7318 <!------------------>
7319
7320 <?php
7321 $tables = table_filter($tables, $_GET['table_filter']);
7322 ?>
7323
7324 <?php if ($_GET['table_filter']): ?>
7325 <p>Tables found: <b><?php echo count($tables);?></b></p>
7326 <?php endif; ?>
7327
7328 <table class="ls tables" cellspacing="0" style="margin-top: 1em;">
7329 <tr>
7330 <th style="min-width: 70px;">Table</th>
7331
7332 <?php if ("sqlite" == $db_driver && $status["total_size"] > SQLITE_ESTIMATE_COUNT): ?>
7333 <?php $title = $_GET["precise_count"] ? "Click to Disable precise counting" : "Click to Enable precise counting"; ?>
7334 <th><a class=blue href="<?php echo $_SERVER['PHP_SELF']; ?>?table_filter=<?php echo urlencode($_GET['table_filter']);?>&precise_count=<?php echo $_GET['precise_count'] ? 0 : 1; ?>" style="color: #000; text-decoration: underline;" title="<?php echo $title; ?>"><?php echo $_GET["precise_count"] ? "*" : "~"; ?>Count</a></th>
7335 <?php else: ?>
7336 <th>Count</th>
7337 <?php endif; ?>
7338
7339 <?php if (!SQLITE_USED): ?>
7340 <th>Size</th>
7341 <?php endif; ?>
7342
7343 <th style="min-width: 65px;">Options</th>
7344 </tr>
7345
7346 <?php if (!count($tables)): ?>
7347 <tr>
7348 <td align="" colspan=4 style="padding: 0.25em 0.5em;">No tables found.</td>
7349 </tr>
7350 <?php endif; ?>
7351
7352 <?php foreach ($tables as $table): ?>
7353 <tr>
7354 <?php
7355 if ('mysql' == $db_driver) {
7356
7357 // COUNT(*) would be slower!
7358 // We already have this info from table's status.
7359
7360 $count = $status[$table]['count'];
7361
7362 // $table_enq = quote_table($table);
7363 // $count = db_one("SELECT COUNT(*) FROM $table_enq");
7364
7365 }
7366 else if ('pgsql' == $db_driver) {
7367
7368 $count = $status[$table]['count'];
7369
7370 if (!$count) {
7371
7372 // Some tables might have missing "reltuples"? This has not been
7373 // documented and now I have no idea what is this chunk of code
7374 // doing here, really.
7375
7376 $table_enq = quote_table($table);
7377 $count = db_one("SELECT COUNT(*) FROM $table_enq");
7378 }
7379 }
7380 else if ("sqlite" == $db_driver) {
7381
7382 $table_enq = quote_table($table);
7383
7384 // COUNT(*) might be very slow in SQLite!
7385 // Do some tests and maybe use MAX(rowid) as count.
7386 // A faser count but not too precise when some records has been deleted
7387 // from the table: SELECT MAX(rowid) FROM sometable;
7388
7389 // COUNT(*) in sqlite requires reading all the data, so it might be slow
7390 // for a large database like 400 MB file. The solution is to count precisely
7391 // only if the database is small for example < 25 MB. When it's larger then
7392 // use MAX(rowid) instead of counting.
7393
7394 // SQLITE_ESTIMATE_COUNT
7395
7396 $precise_count = true;
7397 if ($status["total_size"] > SQLITE_ESTIMATE_COUNT) {
7398 $precise_count = false;
7399 if ($_GET["precise_count"]) {
7400 $precise_count = true;
7401 }
7402 }
7403
7404 if ($precise_count) {
7405 $count = db_one("SELECT COUNT(*) FROM $table_enq");
7406 } else {
7407 $count = db_one("SELECT MAX(rowid) FROM $table_enq");
7408 }
7409 }
7410 ?>
7411 <td>
7412 <a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $table;?>"><?php echo $table;?></a>
7413 </td>
7414 <td align=right style="color: #333;"><?php echo number_format($count,0,'',' ');?></td>
7415
7416 <?php if (!SQLITE_USED): ?>
7417 <td align=right style="color: #666;"><?php echo isset($status[$table]) ? number_format(ceil($status[$table]['size']/1024),0,'',',').' k' : "-";?></td>
7418 <?php endif; ?>
7419
7420 <td>
7421 <a href="<?php echo $_SERVER['PHP_SELF'];?>?dump_table=<?php echo $table;?>">Export</a>
7422 -
7423 <?php $table_enq = quote_table($table); ?>
7424 <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>
7425 <a href="javascript:void(0)" onclick="if (confirm('DROP TABLE <?php echo AttributeValue($table_enq);?> ?')) document.forms['drop_<?php echo $table;?>'].submit();">Drop</a>
7426 </td>
7427
7428
7429
7430 </tr>
7431 <?php endforeach; ?>
7432 </table>
7433 <?php unset($table); ?>
7434
7435 </div>
7436
7437 <?php if (views_supported()): ?>
7438 <div style="float: left; margin-left: 3em;">
7439
7440 <!------------------>
7441 <!-- @listviews -->
7442 <!------------------>
7443
7444 <?php
7445 $views = table_filter($views, $_GET['table_filter']);
7446 ?>
7447
7448 <?php if ($_GET['table_filter']): ?>
7449 <p>Views found: <b><?php echo count($views);?></b></p>
7450 <?php endif; ?>
7451
7452 <table class="ls tables" cellspacing="0" style="margin-top: 1em;">
7453 <tr>
7454 <th style="min-width: 70px;">View</th>
7455 <th><a class=blue href="<?php echo $_SERVER['PHP_SELF']; ?>?table_filter=<?php echo urlencode($_GET['table_filter']);?>&views_count=<?php echo $_GET['views_count'] ? 0 : 1; ?>" style="color: #000; text-decoration: underline;" title="Click to enable/disable counting in Views">Count</a></th>
7456 <th style="min-width: 65px;">Options</th>
7457 </tr>
7458 <?php if (!count($views)): ?>
7459 <tr>
7460 <td align="" colspan=3 style="padding: 0.25em 0.5em;">No views found.</td>
7461 </tr>
7462 <?php endif; ?>
7463
7464 <?php foreach ($views as $view): ?>
7465 <?php $view_enq = quote_table($view); ?>
7466 <tr>
7467 <td><a class=blue href="<?php echo $_SERVER['PHP_SELF'];?>?viewtable=<?php echo $view;?>"><?php echo $view;?></a></td>
7468 <?php
7469 if ($_GET['views_count']) {
7470 $count = db_one("SELECT COUNT(*) FROM $view_enq");
7471 } else {
7472 $count = null;
7473 }
7474 ?>
7475 <td align=right><?php echo isset($count) ? number_format($count,0,'',' ') : "-"; ?></td>
7476 <td>
7477 <a href="<?php echo $_SERVER['PHP_SELF'];?>?dump_table=<?php echo $view;?>&type=view">Export</a>
7478 -
7479 <form action="<?php echo $_SERVER['PHP_SELF'];?>" name="drop_<?php echo $view;?>" method="post" style="display: inline;">
7480 <input type="hidden" name="drop_view" value="<?php echo $view;?>"></form>
7481 <a href="javascript:void(0)" onclick="if (confirm('DROP VIEW <?php echo AttributeValue($view_enq);?> ?')) document.forms['drop_<?php echo $view;?>'].submit();">Drop</a>
7482 </td>
7483 </tr>
7484 <?php endforeach; ?>
7485 </table>
7486
7487 </div>
7488 <?php endif; ?>
7489
7490 <div style="clear: both;"></div>
7491
7492 </body>
7493 </html>
7494
7495<?php
7496
7497// ----------------------------------------------------------------
7498// @autofocus JAVASCRIPT
7499// ----------------------------------------------------------------
7500
7501function AutoFocus_Script()
7502{
7503?>
7504
7505 <script>
7506
7507 // @autofocus
7508
7509 if (document.addEventListener) {
7510 document.addEventListener("keydown", AutoFocus_OnKeyDown, false);
7511 } else {
7512 document.attachEvent("onkeydown", AutoFocus_OnKeyDown);
7513 }
7514
7515 function AutoFocus_Help(elem)
7516 {
7517 if (!elem) {
7518 elem = document.getElementById("AutoFocus_HelpLink");
7519 }
7520 var msg = "";
7521 msg += "You can just <b>start typing</b> on this page and the search input will be <b>focused automatically</b>.<br>";
7522 msg += "Click <b>Alt + S</b> to focus the search input and not delete the text.<br>";
7523 msg += "Press <b>Alt + Z</b> to reset the input and resubmit the form.<br>";
7524 msg += "Press <b>Alt + R</b> to reset the search filters.<br>";
7525 msg += "<br>";
7526 msg += "Most <b>form controls</b> have keyboard shortcuts associated, press ALT + underlined letter.<br>";
7527 msg += "After you choose an option from <b><select></b> element, press Enter to submit the form.<br>";
7528 msg += "<br>";
7529 msg += "You can navigate through a listing by using <b>arrows</b> on your keyboard.<br>";
7530 msg += "Use <b>Up</b> or <b>Down</b> to move to the next or previous record.<br>";
7531 msg += "Use <b>Left</b> or <b>Right</b> to move to the next page or previous page on table view screen<br>or switch between tables and views on the main page.<br>";
7532 msg += "Use <b>Page Up</b> or <b>Page Down</b> to jump up or down by one page screen.<br>";
7533 msg += "Use <b>Home</b> or <b>End</b> to jump to the first or to the last record.<br>";
7534 msg += "<br>";
7535 msg += "Use <b>Enter</b> to view the table or edit the row.<br>";
7536 msg += "Use <b>Delete</b> to drop the table or delete the row.<br>";
7537 msg += "Use <b>Shift</b> to select multiple rows.";
7538 Tooltip(elem, msg);
7539 }
7540
7541 // @expandselect
7542 function ExpandSelect(select, maxOptionsVisible)
7543 {
7544 // Downloaded from:
7545 // http://www.gosu.pl/expand-html-select-element-in-javascript.html
7546
7547 if (typeof maxOptionsVisible == "undefined") {
7548 maxOptionsVisible = 20;
7549 }
7550 if (typeof select == "string") {
7551 select = document.getElementById(select);
7552 }
7553 if (typeof window["ExpandSelect_tempID"] == "undefined") {
7554 window["ExpandSelect_tempID"] = 0;
7555 }
7556 window["ExpandSelect_tempID"]++;
7557
7558 var rects = select.getClientRects();
7559
7560 // ie: cannot populate options using innerHTML.
7561 function PopulateOptions(select, select2)
7562 {
7563 select2.options.length = 0; // clear out existing items
7564 for (var i = 0; i < select.options.length; i++) {
7565 var d = select.options[i];
7566 select2.options.add(new Option(d.text, i))
7567 }
7568 }
7569
7570 var select2 = document.createElement("SELECT");
7571 //select2.innerHTML = select.innerHTML;
7572 PopulateOptions(select, select2);
7573 select2.style.cssText = "visibility: hidden;";
7574 if (select.style.width) {
7575 select2.style.width = select.style.width;
7576 }
7577 if (select.style.height) {
7578 select2.style.height = select.style.height;
7579 }
7580 select2.id = "ExpandSelect_" + window.ExpandSelect_tempID;
7581
7582 select.parentNode.insertBefore(select2, select.nextSibling);
7583 select = select.parentNode.removeChild(select);
7584
7585 if (select.length > maxOptionsVisible) {
7586 select.size = maxOptionsVisible;
7587 } else {
7588 select.size = select.length;
7589 }
7590
7591 if ("pageXOffset" in window) {
7592 var scrollLeft = window.pageXOffset;
7593 var scrollTop = window.pageYOffset;
7594 } else {
7595 // ie <= 8
7596 // Function taken from here: http://help.dottoro.com/ljafodvj.php
7597 function GetZoomFactor()
7598 {
7599 var factor = 1;
7600 if (document.body.getBoundingClientRect) {
7601 var rect = document.body.getBoundingClientRect ();
7602 var physicalW = rect.right - rect.left;
7603 var logicalW = document.body.offsetWidth;
7604 factor = Math.round ((physicalW / logicalW) * 100) / 100;
7605 }
7606 return factor;
7607 }
7608 var zoomFactor = GetZoomFactor();
7609 var scrollLeft = Math.round(document.documentElement.scrollLeft / zoomFactor);
7610 var scrollTop = Math.round(document.documentElement.scrollTop / zoomFactor);
7611 }
7612
7613 select.style.position = "absolute";
7614 select.style.left = (rects[0].left + scrollLeft) + "px";
7615 select.style.top = (rects[0].top + scrollTop) + "px";
7616 select.style.zIndex = "1000000";
7617 select.setAttribute("_ExpandSelect", "1"); // So that Enter in AutoFocus_OnKeyDown does not submit form when expanded.
7618
7619 var old_onchange = select.onchange;
7620 select.onchange = null;
7621
7622 var tempID = window["ExpandSelect_tempID"];
7623
7624 var collapseFunc;
7625
7626 var blurFunc = function(){
7627 collapseFunc();
7628 };
7629
7630 var clickFunc = function(e){
7631 e = e ? e : window.event;
7632 if (e.target) {
7633 if (e.target.tagName == "OPTION") {
7634 e.preventDefault();
7635 collapseFunc();
7636 return 0;
7637 }
7638 } else {
7639 // IE case.
7640 if (e.srcElement.tagName == "SELECT" || e.srcElement.tagName == "OPTION") {
7641 e.preventDefault();
7642 collapseFunc();
7643 return 0;
7644 }
7645 }
7646 return 1;
7647 };
7648
7649 var keydownFunc = function(e){
7650 e = e ? e : window.event;
7651 // Need to implement hiding select on "Escape" and "Enter".
7652 if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
7653 return 1;
7654 }
7655 // Escape, Enter.
7656 if (27 == e.keyCode || 13 == e.keyCode) {
7657 e.preventDefault();
7658 collapseFunc();
7659 return 0;
7660 }
7661
7662 return 1;
7663 };
7664
7665 collapseFunc = function(){
7666 if (select.removeEventListener) {
7667 select.removeEventListener("blur", blurFunc, false);
7668 select.removeEventListener("click", clickFunc, false);
7669 select.removeEventListener("keydown", keydownFunc, false);
7670 } else {
7671 select.detachEvent("onblur", blurFunc);
7672 select.detachEvent("onclick", clickFunc);
7673 select.detachEvent("onkeydown", keydownFunc);
7674 }
7675 select.size = 1;
7676 select.style.position = "static";
7677 select = select.parentNode.removeChild(select);
7678 var select2 = document.getElementById("ExpandSelect_"+tempID);
7679 select2.parentNode.insertBefore(select, select2);
7680 select2.parentNode.removeChild(select2);
7681 select.focus();
7682 window.setTimeout(function(){
7683 // Enter on select should submit the form only when collapsed, in AutoFocus_OnKeyDown.
7684 select.setAttribute("_ExpandSelect", "");
7685 select.onchange = old_onchange;
7686 }, 20);
7687 };
7688
7689 if (select.addEventListener)
7690 select.addEventListener("keydown", keydownFunc, false);
7691 else select.attachEvent("onkeydown", keydownFunc);
7692
7693 if (select.addEventListener)
7694 select.addEventListener("click", clickFunc, false);
7695 else select.attachEvent("onclick", clickFunc);
7696
7697 if (select.addEventListener)
7698 select.addEventListener("blur", blurFunc, false);
7699 else select.attachEvent("onblur", blurFunc);
7700
7701 document.body.appendChild(select);
7702 select.focus();
7703 }
7704
7705 // @autofocus @keyboard @keys
7706
7707 function AutoFocus_OnKeyDown(event)
7708 {
7709 // Add this code to form:
7710 // name=AutoFocus_Form onsubmit="document.getElementById('AutoFocus_Submit').focus()"
7711
7712 // Add this code to input:
7713 // id=AutoFocus_Input onfocus="this.setAttribute('isfocused', '1');" onblur="this.setAttribute('isfocused', '');" autocomplete=off
7714
7715 // ALSO EDIT <a accesskey=> in Layout().
7716
7717 if (!event)
7718 event = window.event;
7719
7720 var form = document.forms["AutoFocus_Form"];
7721 var input = document.getElementById("AutoFocus_Input");
7722 var submit = document.getElementById("AutoFocus_Submit");
7723 //var search_focused = input.getAttribute("isfocused"); // Need to set that attribute on input's events: "onfocus" and "onblur".
7724
7725 // If other element in the form of type: input[text], select - is focused, then do not focus the search text input.
7726
7727 // F1 help.
7728 if (112 == event.keyCode) {
7729 event.preventDefault();
7730 if (Tooltip_Div && Tooltip_Div.parentNode) {
7731 document.body.removeChild(Tooltip_Div);
7732 } else {
7733 AutoFocus_Help();
7734 }
7735 return 0;
7736 }
7737
7738 // Alt + S (search - focus)
7739 if (event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey && 83 == event.keyCode) {
7740 event.preventDefault();
7741 if (document.activeElement.id == "AutoFocus_Input") {
7742 input.blur();
7743 } else {
7744 input.focus();
7745 input.select();
7746 }
7747 return 0;
7748 }
7749
7750 // Alt + R (Reset - go to main page)
7751 // Must be called before 0-9 or A-Z detections.
7752 if (event.altKey && 82 == event.keyCode) {
7753 event.preventDefault();
7754 if (window.location.href.match(/viewtable=([^&]+)/) != -1) {
7755 window.location.href = "<?php echo $_SERVER['PHP_SELF']; ?>?viewtable=".RegExp.$1;
7756 } else {
7757 window.location.href = "<?php echo $_SERVER['PHP_SELF'];?>";
7758 }
7759 return 0;
7760 }
7761
7762 // Alt + Z (reset)
7763 // Must be called before 0-9 or A-Z detections.
7764 if (event.altKey && 90 == event.keyCode) {
7765 event.preventDefault();
7766 input.value = "";
7767 submit ? submit.focus() : void(0);
7768 form.submit();
7769 return 0;
7770 }
7771
7772 // 0-9, shiftKey allowed
7773 // A-Z, a-z, shiftKey allowed
7774 if ( (!event.altKey && !event.ctrlKey && !event.metaKey && event.keyCode >= 48 && event.keyCode <= 57)
7775 || (!event.altKey && !event.ctrlKey && !event.metaKey && event.keyCode >= 65 && event.keyCode <= 90)
7776 ) {
7777 if (document.activeElement.id != "AutoFocus_Input") {
7778 var focusedElem = document.activeElement;
7779 if (focusedElem.tagName == "SELECT"
7780 || (focusedElem.tagName == "INPUT" && focusedElem.type == "text")
7781 ) {
7782 event.preventDefault();
7783 return 0;
7784 }
7785 input.value = "";
7786 input.focus();
7787 }
7788 return 1;
7789 }
7790
7791 // @accesskeys
7792
7793 // Keyboard shortcuts for <select> elements.
7794 var select_shortcuts = [ // can have multiple shortcuts for the same letter, but on different pages, so must use array.
7795 [79, "order_by"], // "o" - Sort.
7796 [66, "db_name"], // "D" - Database.
7797 [85, "dump_database"] // "u" - Dump database.
7798 ];
7799 for (var i = 0; i < select_shortcuts.length; ++i) {
7800 var keyCode = select_shortcuts[i][0];
7801 var elemID = select_shortcuts[i][1];
7802 if (event.keyCode == keyCode && Element(elemID)) {
7803 event.preventDefault();
7804 ExpandSelect(elemID);
7805 return 0;
7806 }
7807 }
7808
7809 // No alt, no ctrl, no shift, no meta - from now on...
7810 if (event.altKey || event.ctrlKey || event.shiftKey || event.metaKey) {
7811 return 1;
7812 }
7813
7814 // 27 Escape - hide tooltip
7815 if (27 == event.keyCode && typeof Tooltip_Div != "undefined" && Tooltip_Div) {
7816 // Escape also hides tooltip if shown.
7817 Tooltip_Hide();
7818 return 0;
7819 }
7820
7821 // 27 Escape - undo focus of search input
7822 if (27 == event.keyCode && (document.activeElement.tagName == "INPUT" || document.activeElement.tagName == "SELECT")) {
7823 // Escape also hides tooltip if shown.
7824 document.activeElement.blur();
7825 return 0;
7826 }
7827
7828 // 13 Enter - after choosing option from <select> submit the form when typing "enter".
7829 if (13 == event.keyCode && document.activeElement.tagName == "SELECT") {
7830 if (!document.activeElement.getAttribute("_ExpandSelect")) {
7831 if (document.activeElement.form) {
7832 event.preventDefault();
7833 var form = document.activeElement.form;
7834 document.activeElement.blur();
7835 form.submit();
7836 return 0;
7837 }
7838 else if (document.activeElement.onchange) {
7839 event.preventDefault();
7840 document.activeElement.onchange();
7841 document.activeElement.blur();
7842 return 0;
7843 }
7844 }
7845 }
7846
7847 // return value:
7848 // 1 - do propagate further events.
7849 // 0 - do not propagate any events for this key, we have taken of all that should be donevent.
7850
7851 return 1;
7852 }
7853 </script>
7854<?php
7855}
7856function AutoFocus_HelpLink()
7857{
7858?>
7859 <a class="help" id="AutoFocus_HelpLink" href="javascript:void(0)" onclick="AutoFocus_Help(this)" title="Help: keyboard shortcuts F1"></a>
7860<?php
7861}
7862?>