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