PageRenderTime 112ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 1ms

/phpliteadmin.php

https://github.com/Thann/tascal
PHP | 4524 lines | 4302 code | 86 blank | 136 comment | 280 complexity | 2f7f54d41f0c585cde6abdaa3a08e0aa MD5 | raw file
Possible License(s): LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. //
  3. // Project: phpLiteAdmin (http://phpliteadmin.googlecode.com)
  4. // Version: 1.9.2
  5. // Summary: PHP-based admin tool to manage SQLite2 and SQLite3 databases on the web
  6. // Last updated: 5/30/12
  7. // Developers:
  8. // Dane Iracleous (daneiracleous@gmail.com)
  9. // Ian Aldrighetti (ian.aldrighetti@gmail.com)
  10. // George Flanagin & Digital Gaslight, Inc (george@digitalgaslight.com)
  11. // Christopher Kramer (crazy4chrissi@gmail.com)
  12. //
  13. //
  14. // Copyright (C) 2011 phpLiteAdmin
  15. //
  16. // This program is free software: you can redistribute it and/or modify
  17. // it under the terms of the GNU General Public License as published by
  18. // the Free Software Foundation, either version 3 of the License, or
  19. // (at your option) any later version.
  20. //
  21. // This program is distributed in the hope that it will be useful,
  22. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. // GNU General Public License for more details.
  25. //
  26. // You should have received a copy of the GNU General Public License
  27. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  28. //
  29. ///////////////////////////////////////////////////////////////////////////
  30. //please report any bugs you encounter to http://code.google.com/p/phpliteadmin/issues/list
  31. //BEGIN USER-DEFINED VARIABLES
  32. //////////////////////////////
  33. //password to gain access
  34. $password = "admin";
  35. //directory relative to this file to search for databases (if false, manually list databases in the $databases variable)
  36. $directory = "application/db";
  37. //whether or not to scan the subdirectories of the above directory infinitely deep
  38. $subdirectories = false;
  39. //if the above $directory variable is set to false, you must specify the databases manually in an array as the next variable
  40. //if any of the databases do not exist as they are referenced by their path, they will be created automatically
  41. $databases = array
  42. (
  43. array
  44. (
  45. "path"=> "database1.sqlite",
  46. "name"=> "Database 1"
  47. ),
  48. array
  49. (
  50. "path"=> "database2.sqlite",
  51. "name"=> "Database 2"
  52. )
  53. );
  54. //a list of custom functions that can be applied to columns in the databases
  55. //make sure to define every function below if it is not a core PHP function
  56. $custom_functions = array('md5', 'md5rev', 'sha1', 'sha1rev', 'time', 'mydate', 'strtotime', 'myreplace');
  57. //define all the non-core custom functions
  58. function md5rev($value)
  59. {
  60. return strrev(md5($value));
  61. }
  62. function sha1rev($value)
  63. {
  64. return strrev(sha1($value));
  65. }
  66. function mydate($value)
  67. {
  68. return date("g:ia n/j/y", intval($value));
  69. }
  70. function myreplace($value)
  71. {
  72. return ereg_replace("[^A-Za-z0-9]", "", strval($value));
  73. }
  74. //changing the following variable allows multiple phpLiteAdmin installs to work under the same domain.
  75. $cookie_name = 'pla3412';
  76. //whether or not to put the app in debug mode where errors are outputted
  77. $debug = false;
  78. ////////////////////////////
  79. //END USER-DEFINED VARIABLES
  80. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  81. //there is no reason for the average user to edit anything below this comment
  82. //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  83. session_start(); //don't mess with this - required for the login session
  84. date_default_timezone_set(date_default_timezone_get()); //needed to fix STRICT warnings about timezone issues
  85. if($debug==true)
  86. {
  87. ini_set("display_errors", 1);
  88. error_reporting(E_STRICT | E_ALL);
  89. }
  90. $startTimeTot = microtime(true); //start the timer to record page load time
  91. //the salt and password encrypting is probably unnecessary protection but is done just for the sake of being very secure
  92. //create a random salt for this session if a cookie doesn't already exist for it
  93. if(!isset($_SESSION[$cookie_name.'_salt']) && !isset($_COOKIE[$cookie_name.'_salt']))
  94. {
  95. $n = rand(10e16, 10e20);
  96. $_SESSION[$cookie_name.'_salt'] = base_convert($n, 10, 36);
  97. }
  98. else if(!isset($_SESSION[$cookie_name.'_salt']) && isset($_COOKIE[$cookie_name.'_salt'])) //session doesn't exist, but cookie does so grab it
  99. {
  100. $_SESSION[$cookie_name.'_salt'] = $_COOKIE[$cookie_name.'_salt'];
  101. }
  102. //build the basename of this file for later reference
  103. $info = pathinfo($_SERVER['PHP_SELF']);
  104. $thisName = $info['basename'];
  105. //constants
  106. define("PROJECT", "phpLiteAdmin");
  107. define("VERSION", "1.9.2");
  108. define("PAGE", $thisName);
  109. define("COOKIENAME", $cookie_name);
  110. define("SYSTEMPASSWORD", $password); // Makes things easier.
  111. define("SYSTEMPASSWORDENCRYPTED", md5($password."_".$_SESSION[$cookie_name.'_salt'])); //extra security - salted and encrypted password used for checking
  112. define("FORCETYPE", false); //force the extension that will be used (set to false in almost all circumstances except debugging)
  113. //data types array
  114. $types = array("INTEGER", "REAL", "TEXT", "BLOB");
  115. define("DATATYPES", serialize($types));
  116. //accepted db extensions
  117. $exts = array("sqlite", "sqlite3", "db", "db3");
  118. define("EXTENSIONS", serialize($exts));
  119. //available SQLite functions array (don't add anything here or there will be problems)
  120. $functions = array("abs", "hex", "length", "lower", "ltrim", "random", "round", "rtrim", "trim", "typeof", "upper");
  121. define("FUNCTIONS", serialize($functions));
  122. define("CUSTOM_FUNCTIONS", serialize($custom_functions));
  123. //function that allows SQL delimiter to be ignored inside comments or strings
  124. function explode_sql($delimiter, $sql)
  125. {
  126. $ign = array('"' => '"', "'" => "'", "/*" => "*/", "--" => "\n"); // Ignore sequences.
  127. $out = array();
  128. $last = 0;
  129. $slen = strlen($sql);
  130. $dlen = strlen($delimiter);
  131. $i = 0;
  132. while($i < $slen)
  133. {
  134. // Split on delimiter
  135. if($slen - $i >= $dlen && substr($sql, $i, $dlen) == $delimiter)
  136. {
  137. array_push($out, substr($sql, $last, $i - $last));
  138. $last = $i + $dlen;
  139. $i += $dlen;
  140. continue;
  141. }
  142. // Eat comments and string literals
  143. foreach($ign as $start => $end)
  144. {
  145. $ilen = strlen($start);
  146. if($slen - $i >= $ilen && substr($sql, $i, $ilen) == $start)
  147. {
  148. $i+=strlen($start);
  149. $elen = strlen($end);
  150. while($i < $slen)
  151. {
  152. if($slen - $i >= $elen && substr($sql, $i, $elen) == $end)
  153. {
  154. // SQL comment characters can be escaped by doubling the character. This recognizes and skips those.
  155. if($start == $end && $slen - $i >= $elen*2 && substr($sql, $i, $elen*2) == $end.$end)
  156. {
  157. $i += $elen * 2;
  158. continue;
  159. }
  160. else
  161. {
  162. $i += $elen;
  163. continue 3;
  164. }
  165. }
  166. $i++;
  167. }
  168. continue 2;
  169. }
  170. }
  171. $i++;
  172. }
  173. if($last < $slen)
  174. array_push($out, substr($sql, $last, $slen - $last));
  175. return $out;
  176. }
  177. //function to scan entire directory tree and subdirectories
  178. function dir_tree($dir)
  179. {
  180. $path = '';
  181. $stack[] = $dir;
  182. while($stack)
  183. {
  184. $thisdir = array_pop($stack);
  185. if($dircont = scandir($thisdir))
  186. {
  187. $i=0;
  188. while(isset($dircont[$i]))
  189. {
  190. if($dircont[$i] !== '.' && $dircont[$i] !== '..')
  191. {
  192. $current_file = "{$thisdir}/{$dircont[$i]}";
  193. if(is_file($current_file))
  194. {
  195. $path[] = "{$thisdir}/{$dircont[$i]}";
  196. }
  197. elseif (is_dir($current_file))
  198. {
  199. $path[] = "{$thisdir}/{$dircont[$i]}";
  200. $stack[] = $current_file;
  201. }
  202. }
  203. $i++;
  204. }
  205. }
  206. }
  207. return $path;
  208. }
  209. //the function echo the help [?] links to the documentation
  210. function helpLink($name)
  211. {
  212. return "<a href='javascript:openHelp(\"".$name."\");' class='helpq' title='Help: ".$name."'>[?]</a>";
  213. }
  214. //user is deleting a database
  215. if(isset($_GET['database_delete']))
  216. {
  217. $dbpath = $_POST['database_delete'];
  218. unlink($dbpath);
  219. $_SESSION[COOKIENAME.'currentDB'] = 0;
  220. }
  221. //user is renaming a database
  222. if(isset($_GET['database_rename']))
  223. {
  224. $oldpath = $_POST['oldname'];
  225. $newpath = $_POST['newname'];
  226. if(!file_exists($newpath))
  227. {
  228. copy($oldpath, $newpath);
  229. unlink($oldpath);
  230. $justrenamed = true;
  231. }
  232. else
  233. {
  234. $dbexists = true;
  235. }
  236. }
  237. //user is creating a new Database
  238. if(isset($_POST['new_dbname']))
  239. {
  240. $str = preg_replace('@[^\w-.]@','', $_POST['new_dbname']);
  241. $dbname = $str;
  242. $dbpath = $str;
  243. $info = pathinfo($dbpath);
  244. if(!isset($info['extension']))
  245. $dbpath = $dbpath.".".$exts[0];
  246. else
  247. {
  248. if(!in_array(strtolower($info['extension']), $exts))
  249. {
  250. $dbpath = $dbpath.".".$exts[0];
  251. }
  252. }
  253. $tdata = array();
  254. $tdata['name'] = $dbname;
  255. $tdata['path'] = $directory."/".$dbpath;
  256. $td = new Database($tdata);
  257. }
  258. //if the user wants to scan a directory for databases, do so
  259. if($directory!==false)
  260. {
  261. if($directory[strlen($directory)-1]=="/") //if user has a trailing slash in the directory, remove it
  262. $directory = substr($directory, 0, strlen($directory)-1);
  263. if(is_dir($directory)) //make sure the directory is valid
  264. {
  265. if($subdirectories===true)
  266. $arr = dir_tree($directory);
  267. else
  268. $arr = scandir($directory);
  269. $databases = array();
  270. $j = 0;
  271. for($i=0; $i<sizeof($arr); $i++) //iterate through all the files in the databases
  272. {
  273. $file = pathinfo($arr[$i]);
  274. if(isset($file['extension']))
  275. {
  276. $ext = strtolower($file['extension']);
  277. if(in_array(strtolower($ext), $exts)) //make sure the file is a valid SQLite database by checking its extension
  278. {
  279. if($subdirectories===true)
  280. $databases[$j]['path'] = $arr[$i];
  281. else
  282. $databases[$j]['path'] = $directory."/".$arr[$i];
  283. $databases[$j]['name'] = $arr[$i];
  284. // 22 August 2011: gkf fixed bug 49.
  285. $perms = 0;
  286. $perms += is_readable($databases[$j]['path']) ? 4 : 0;
  287. $perms += is_writeable($databases[$j]['path']) ? 2 : 0;
  288. switch($perms)
  289. {
  290. case 6: $perms = "[rw] "; break;
  291. case 4: $perms = "[r ] "; break;
  292. case 2: $perms = "[ w] "; break; // God forbid, but it might happen.
  293. default: $perms = "[ ] "; break;
  294. }
  295. $databases[$j]['perms'] = $perms;
  296. $j++;
  297. }
  298. }
  299. }
  300. // 22 August 2011: gkf fixed bug #50.
  301. sort($databases);
  302. if(isset($tdata))
  303. {
  304. for($i=0; $i<sizeof($databases); $i++)
  305. {
  306. if($tdata['path'] == $databases[$i]['path'])
  307. {
  308. $_SESSION[COOKIENAME.'currentDB'] = $i;
  309. break;
  310. }
  311. }
  312. }
  313. if(isset($justrenamed))
  314. {
  315. for($i=0; $i<sizeof($databases); $i++)
  316. {
  317. if($newpath == $databases[$i]['path'])
  318. {
  319. $_SESSION[COOKIENAME.'currentDB'] = $i;
  320. break;
  321. }
  322. }
  323. }
  324. }
  325. else //the directory is not valid - display error and exit
  326. {
  327. echo "<div class='confirm' style='margin:20px;'>";
  328. echo "The directory you specified to scan for databases does not exist or is not a directory.";
  329. echo "</div>";
  330. exit();
  331. }
  332. }
  333. // 22 August 2011: gkf added this function to support display of
  334. // default values in the form used to INSERT new data.
  335. function deQuoteSQL($s)
  336. {
  337. return trim(trim($s), "'");
  338. }
  339. //
  340. // Authorization class
  341. // Maintains user's logged-in state and security of application
  342. //
  343. class Authorization
  344. {
  345. public function grant($remember)
  346. {
  347. if($remember) //user wants to be remembered, so set a cookie
  348. {
  349. $expire = time()+60*60*24*30; //set expiration to 1 month from now
  350. setcookie(COOKIENAME, SYSTEMPASSWORD, $expire);
  351. setcookie(COOKIENAME."_salt", $_SESSION[COOKIENAME.'_salt'], $expire);
  352. }
  353. else
  354. {
  355. //user does not want to be remembered, so destroy any potential cookies
  356. setcookie(COOKIENAME, "", time()-86400);
  357. setcookie(COOKIENAME."_salt", "", time()-86400);
  358. unset($_COOKIE[COOKIENAME]);
  359. unset($_COOKIE[COOKIENAME.'_salt']);
  360. }
  361. $_SESSION[COOKIENAME.'password'] = SYSTEMPASSWORDENCRYPTED;
  362. }
  363. public function revoke()
  364. {
  365. //destroy everything - cookies and session vars
  366. setcookie(COOKIENAME, "", time()-86400);
  367. setcookie(COOKIENAME."_salt", "", time()-86400);
  368. unset($_COOKIE[COOKIENAME]);
  369. unset($_COOKIE[COOKIENAME.'_salt']);
  370. session_unset();
  371. session_destroy();
  372. }
  373. public function isAuthorized()
  374. {
  375. // Is this just session long? (What!?? -DI)
  376. if((isset($_SESSION[COOKIENAME.'password']) && $_SESSION[COOKIENAME.'password'] == SYSTEMPASSWORDENCRYPTED) || (isset($_COOKIE[COOKIENAME]) && isset($_COOKIE[COOKIENAME.'_salt']) && md5($_COOKIE[COOKIENAME]."_".$_COOKIE[COOKIENAME.'_salt']) == SYSTEMPASSWORDENCRYPTED))
  377. return true;
  378. else
  379. {
  380. return false;
  381. }
  382. }
  383. }
  384. //
  385. // Database class
  386. // Generic database abstraction class to manage interaction with database without worrying about SQLite vs. PHP versions
  387. //
  388. class Database
  389. {
  390. protected $db; //reference to the DB object
  391. protected $type; //the extension for PHP that handles SQLite
  392. protected $data;
  393. protected $lastResult;
  394. protected $fns;
  395. public function __construct($data)
  396. {
  397. $this->data = $data;
  398. $this->fns = array();
  399. try
  400. {
  401. if(!file_exists($this->data["path"]) && !is_writable(dirname($this->data["path"]))) //make sure the containing directory is writable if the database does not exist
  402. {
  403. echo "<div class='confirm' style='margin:20px;'>";
  404. echo "The database, '".$this->data["path"]."', does not exist and cannot be created because the containing directory, '".dirname($this->data["path"])."', is not writable. The application is unusable until you make it writable.";
  405. echo "<form action='".PAGE."' method='post'/>";
  406. echo "<input type='submit' value='Log Out' name='logout' class='btn'/>";
  407. echo "</form>";
  408. echo "</div><br/>";
  409. exit();
  410. }
  411. $ver = $this->getVersion();
  412. switch(true)
  413. {
  414. case (FORCETYPE=="PDO" || ((FORCETYPE==false || $ver!=-1) && class_exists("PDO") && ($ver==-1 || $ver==3))):
  415. $this->db = new PDO("sqlite:".$this->data['path']);
  416. if($this->db!=NULL)
  417. {
  418. $this->type = "PDO";
  419. $cfns = unserialize(CUSTOM_FUNCTIONS);
  420. for($i=0; $i<sizeof($cfns); $i++)
  421. {
  422. $this->db->sqliteCreateFunction($cfns[$i], $cfns[$i], 1);
  423. $this->addUserFunction($cfns[$i]);
  424. }
  425. break;
  426. }
  427. case (FORCETYPE=="SQLite3" || ((FORCETYPE==false || $ver!=-1) && class_exists("SQLite3") && ($ver==-1 || $ver==3))):
  428. $this->db = new SQLite3($this->data['path']);
  429. if($this->db!=NULL)
  430. {
  431. $cfns = unserialize(CUSTOM_FUNCTIONS);
  432. for($i=0; $i<sizeof($cfns); $i++)
  433. {
  434. $this->db->createFunction($cfns[$i], $cfns[$i], 1);
  435. $this->addUserFunction($cfns[$i]);
  436. }
  437. $this->type = "SQLite3";
  438. break;
  439. }
  440. case (FORCETYPE=="SQLiteDatabase" || ((FORCETYPE==false || $ver!=-1) && class_exists("SQLiteDatabase") && ($ver==-1 || $ver==2))):
  441. $this->db = new SQLiteDatabase($this->data['path']);
  442. if($this->db!=NULL)
  443. {
  444. $cfns = unserialize(CUSTOM_FUNCTIONS);
  445. for($i=0; $i<sizeof($cfns); $i++)
  446. {
  447. $this->db->createFunction($cfns[$i], $cfns[$i], 1);
  448. $this->addUserFunction($cfns[$i]);
  449. }
  450. $this->type = "SQLiteDatabase";
  451. break;
  452. }
  453. default:
  454. $this->showError();
  455. exit();
  456. }
  457. }
  458. catch(Exception $e)
  459. {
  460. $this->showError();
  461. exit();
  462. }
  463. }
  464. public function getUserFunctions()
  465. {
  466. return $this->fns;
  467. }
  468. public function addUserFunction($name)
  469. {
  470. array_push($this->fns, $name);
  471. }
  472. public function getError()
  473. {
  474. if($this->type=="PDO")
  475. {
  476. $e = $this->db->errorInfo();
  477. return $e[2];
  478. }
  479. else if($this->type=="SQLite3")
  480. {
  481. return $this->db->lastErrorMsg();
  482. }
  483. else
  484. {
  485. return sqlite_error_string($this->db->lastError());
  486. }
  487. }
  488. public function showError()
  489. {
  490. $classPDO = class_exists("PDO");
  491. $classSQLite3 = class_exists("SQLite3");
  492. $classSQLiteDatabase = class_exists("SQLiteDatabase");
  493. if($classPDO)
  494. $strPDO = "installed";
  495. else
  496. $strPDO = "not installed";
  497. if($classSQLite3)
  498. $strSQLite3 = "installed";
  499. else
  500. $strSQLite3 = "not installed";
  501. if($classSQLiteDatabase)
  502. $strSQLiteDatabase = "installed";
  503. else
  504. $strSQLiteDatabase = "not installed";
  505. echo "<div class='confirm' style='margin:20px;'>";
  506. echo "There was a problem setting up your database, ".$this->getPath().". An attempt will be made to find out what's going on so you can fix the problem more easily.<br/><br/>";
  507. echo "<i>Checking supported SQLite PHP extensions...<br/><br/>";
  508. echo "<b>PDO</b>: ".$strPDO."<br/>";
  509. echo "<b>SQLite3</b>: ".$strSQLite3."<br/>";
  510. echo "<b>SQLiteDatabase</b>: ".$strSQLiteDatabase."<br/><br/>...done.</i><br/><br/>";
  511. if(!$classPDO && !$classSQLite3 && !$classSQLiteDatabase)
  512. echo "It appears that none of the supported SQLite library extensions are available in your installation of PHP. You may not use ".PROJECT." until you install at least one of them.";
  513. else
  514. {
  515. if(!$classPDO && !$classSQLite3 && $this->getVersion()==3)
  516. echo "It appears that your database is of SQLite version 3 but your installation of PHP does not contain the necessary extensions to handle this version. To fix the problem, either delete the database and allow ".PROJECT." to create it automatically or recreate it manually as SQLite version 2.";
  517. else if(!$classSQLiteDatabase && $this->getVersion()==2)
  518. echo "It appears that your database is of SQLite version 2 but your installation of PHP does not contain the necessary extensions to handle this version. To fix the problem, either delete the database and allow ".PROJECT." to create it automatically or recreate it manually as SQLite version 3.";
  519. else
  520. echo "The problem cannot be diagnosed properly. Please email me at daneiracleous@gmail.com with your database as an attachment and the contents of this error message. It may be that your database is simply not a valid SQLite database, but this is not certain.";
  521. }
  522. echo "</div><br/>";
  523. }
  524. public function __destruct()
  525. {
  526. if($this->db)
  527. $this->close();
  528. }
  529. //get the exact PHP extension being used for SQLite
  530. public function getType()
  531. {
  532. return $this->type;
  533. }
  534. //get the name of the database
  535. public function getName()
  536. {
  537. return $this->data["name"];
  538. }
  539. //get the filename of the database
  540. public function getPath()
  541. {
  542. return $this->data["path"];
  543. }
  544. //get the version of the database
  545. public function getVersion()
  546. {
  547. if(file_exists($this->data['path'])) //make sure file exists before getting its contents
  548. {
  549. $content = strtolower(file_get_contents($this->data['path'], NULL, NULL, 0, 40)); //get the first 40 characters of the database file
  550. $p = strpos($content, "** this file contains an sqlite 2"); //this text is at the beginning of every SQLite2 database
  551. if($p!==false) //the text is found - this is version 2
  552. return 2;
  553. else
  554. return 3;
  555. }
  556. else //return -1 to indicate that it does not exist and needs to be created
  557. {
  558. return -1;
  559. }
  560. }
  561. //get the size of the database
  562. public function getSize()
  563. {
  564. return round(filesize($this->data["path"])*0.0009765625, 1)." Kb";
  565. }
  566. //get the last modified time of database
  567. public function getDate()
  568. {
  569. return date("g:ia \o\\n F j, Y", filemtime($this->data["path"]));
  570. }
  571. //get number of affected rows from last query
  572. public function getAffectedRows()
  573. {
  574. if($this->type=="PDO")
  575. return $this->lastResult->rowCount();
  576. else if($this->type=="SQLite3")
  577. return $this->db->changes();
  578. else if($this->type=="SQLiteDatabase")
  579. return $this->db->changes();
  580. }
  581. public function close()
  582. {
  583. if($this->type=="PDO")
  584. $this->db = NULL;
  585. else if($this->type=="SQLite3")
  586. $this->db->close();
  587. else if($this->type=="SQLiteDatabase")
  588. $this->db = NULL;
  589. }
  590. public function beginTransaction()
  591. {
  592. $this->query("BEGIN");
  593. }
  594. public function commitTransaction()
  595. {
  596. $this->query("COMMIT");
  597. }
  598. public function rollbackTransaction()
  599. {
  600. $this->query("ROLLBACK");
  601. }
  602. //generic query wrapper
  603. public function query($query, $ignoreAlterCase=false)
  604. {
  605. if(strtolower(substr(ltrim($query),0,5))=='alter' && $ignoreAlterCase==false) //this query is an ALTER query - call the necessary function
  606. {
  607. $queryparts = preg_split("/[\s]+/", $query, 4, PREG_SPLIT_NO_EMPTY);
  608. $tablename = $queryparts[2];
  609. $alterdefs = $queryparts[3];
  610. //echo $query;
  611. $result = $this->alterTable($tablename, $alterdefs);
  612. }
  613. else //this query is normal - proceed as normal
  614. $result = $this->db->query($query);
  615. if(!$result)
  616. return NULL;
  617. $this->lastResult = $result;
  618. return $result;
  619. }
  620. //wrapper for an INSERT and returns the ID of the inserted row
  621. public function insert($query)
  622. {
  623. $result = $this->query($query);
  624. if($this->type=="PDO")
  625. return $this->db->lastInsertId();
  626. else if($this->type=="SQLite3")
  627. return $this->db->lastInsertRowID();
  628. else if($this->type=="SQLiteDatabase")
  629. return $this->db->lastInsertRowid();
  630. }
  631. //returns an array for SELECT
  632. public function select($query, $mode="both")
  633. {
  634. $result = $this->query($query);
  635. if(!$result) //make sure the result is valid
  636. return NULL;
  637. if($this->type=="PDO")
  638. {
  639. if($mode=="assoc")
  640. $mode = PDO::FETCH_ASSOC;
  641. else if($mode=="num")
  642. $mode = PDO::FETCH_NUM;
  643. else
  644. $mode = PDO::FETCH_BOTH;
  645. return $result->fetch($mode);
  646. }
  647. else if($this->type=="SQLite3")
  648. {
  649. if($mode=="assoc")
  650. $mode = SQLITE3_ASSOC;
  651. else if($mode=="num")
  652. $mode = SQLITE3_NUM;
  653. else
  654. $mode = SQLITE3_BOTH;
  655. return $result->fetchArray($mode);
  656. }
  657. else if($this->type=="SQLiteDatabase")
  658. {
  659. if($mode=="assoc")
  660. $mode = SQLITE_ASSOC;
  661. else if($mode=="num")
  662. $mode = SQLITE_NUM;
  663. else
  664. $mode = SQLITE_BOTH;
  665. return $result->fetch($mode);
  666. }
  667. }
  668. //returns an array of arrays after doing a SELECT
  669. public function selectArray($query, $mode="both")
  670. {
  671. $result = $this->query($query);
  672. if(!$result) //make sure the result is valid
  673. return NULL;
  674. if($this->type=="PDO")
  675. {
  676. if($mode=="assoc")
  677. $mode = PDO::FETCH_ASSOC;
  678. else if($mode=="num")
  679. $mode = PDO::FETCH_NUM;
  680. else
  681. $mode = PDO::FETCH_BOTH;
  682. return $result->fetchAll($mode);
  683. }
  684. else if($this->type=="SQLite3")
  685. {
  686. if($mode=="assoc")
  687. $mode = SQLITE3_ASSOC;
  688. else if($mode=="num")
  689. $mode = SQLITE3_NUM;
  690. else
  691. $mode = SQLITE3_BOTH;
  692. $arr = array();
  693. $i = 0;
  694. while($res = $result->fetchArray($mode))
  695. {
  696. $arr[$i] = $res;
  697. $i++;
  698. }
  699. return $arr;
  700. }
  701. else if($this->type=="SQLiteDatabase")
  702. {
  703. if($mode=="assoc")
  704. $mode = SQLITE_ASSOC;
  705. else if($mode=="num")
  706. $mode = SQLITE_NUM;
  707. else
  708. $mode = SQLITE_BOTH;
  709. return $result->fetchAll($mode);
  710. }
  711. }
  712. //function that is called for an alter table statement in a query
  713. //code borrowed with permission from http://code.jenseng.com/db/
  714. public function alterTable($table, $alterdefs)
  715. {
  716. if($alterdefs != '')
  717. {
  718. $tempQuery = "SELECT sql,name,type FROM sqlite_master WHERE tbl_name = '".$table."' ORDER BY type DESC";
  719. $result = $this->query($tempQuery);
  720. $resultArr = $this->selectArray($tempQuery);
  721. if(sizeof($resultArr)>0)
  722. {
  723. $row = $this->select($tempQuery); //table sql
  724. $tmpname = 't'.time();
  725. $origsql = trim(preg_replace("/[\s]+/", " ", str_replace(",", ", ",preg_replace("/[\(]/", "( ", $row['sql'], 1))));
  726. $createtemptableSQL = 'CREATE TEMPORARY '.substr(trim(preg_replace("'".$table."'", $tmpname, $origsql, 1)), 6);
  727. $createindexsql = array();
  728. $i = 0;
  729. $defs = preg_split("/[,]+/",$alterdefs, -1, PREG_SPLIT_NO_EMPTY);
  730. $prevword = $table;
  731. $oldcols = preg_split("/[,]+/", substr(trim($createtemptableSQL), strpos(trim($createtemptableSQL), '(')+1), -1, PREG_SPLIT_NO_EMPTY);
  732. $newcols = array();
  733. for($i=0; $i<sizeof($oldcols); $i++)
  734. {
  735. $colparts = preg_split("/[\s]+/", $oldcols[$i], -1, PREG_SPLIT_NO_EMPTY);
  736. $oldcols[$i] = $colparts[0];
  737. $newcols[$colparts[0]] = $colparts[0];
  738. }
  739. $newcolumns = '';
  740. $oldcolumns = '';
  741. reset($newcols);
  742. while(list($key, $val) = each($newcols))
  743. {
  744. $newcolumns .= ($newcolumns?', ':'').$val;
  745. $oldcolumns .= ($oldcolumns?', ':'').$key;
  746. }
  747. $copytotempsql = 'INSERT INTO '.$tmpname.'('.$newcolumns.') SELECT '.$oldcolumns.' FROM '.$table;
  748. $dropoldsql = 'DROP TABLE '.$table;
  749. $createtesttableSQL = $createtemptableSQL;
  750. foreach($defs as $def)
  751. {
  752. $defparts = preg_split("/[\s]+/", $def,-1, PREG_SPLIT_NO_EMPTY);
  753. $action = strtolower($defparts[0]);
  754. switch($action)
  755. {
  756. case 'add':
  757. if(sizeof($defparts) <= 2)
  758. return false;
  759. $createtesttableSQL = substr($createtesttableSQL, 0, strlen($createtesttableSQL)-1).',';
  760. for($i=1;$i<sizeof($defparts);$i++)
  761. $createtesttableSQL.=' '.$defparts[$i];
  762. $createtesttableSQL.=')';
  763. break;
  764. case 'change':
  765. if(sizeof($defparts) <= 3)
  766. {
  767. return false;
  768. }
  769. if($severpos = strpos($createtesttableSQL,' '.$defparts[1].' '))
  770. {
  771. if($newcols[$defparts[1]] != $defparts[1])
  772. return false;
  773. $newcols[$defparts[1]] = $defparts[2];
  774. $nextcommapos = strpos($createtesttableSQL,',',$severpos);
  775. $insertval = '';
  776. for($i=2;$i<sizeof($defparts);$i++)
  777. $insertval.=' '.$defparts[$i];
  778. if($nextcommapos)
  779. $createtesttableSQL = substr($createtesttableSQL,0,$severpos).$insertval.substr($createtesttableSQL,$nextcommapos);
  780. else
  781. $createtesttableSQL = substr($createtesttableSQL,0,$severpos-(strpos($createtesttableSQL,',')?0:1)).$insertval.')';
  782. }
  783. else
  784. return false;
  785. break;
  786. case 'drop':
  787. if(sizeof($defparts) < 2)
  788. return false;
  789. if($severpos = strpos($createtesttableSQL,' '.$defparts[1].' '))
  790. {
  791. $nextcommapos = strpos($createtesttableSQL,',',$severpos);
  792. if($nextcommapos)
  793. $createtesttableSQL = substr($createtesttableSQL,0,$severpos).substr($createtesttableSQL,$nextcommapos + 1);
  794. else
  795. $createtesttableSQL = substr($createtesttableSQL,0,$severpos-(strpos($createtesttableSQL,',')?0:1) - 1).')';
  796. unset($newcols[$defparts[1]]);
  797. }
  798. else
  799. return false;
  800. break;
  801. default:
  802. return false;
  803. }
  804. $prevword = $defparts[sizeof($defparts)-1];
  805. }
  806. //this block of code generates a test table simply to verify that the columns specifed are valid in an sql statement
  807. //this ensures that no reserved words are used as columns, for example
  808. $tempResult = $this->query($createtesttableSQL);
  809. if(!$tempResult)
  810. return false;
  811. $droptempsql = 'DROP TABLE '.$tmpname;
  812. $tempResult = $this->query($droptempsql);
  813. //end block
  814. $createnewtableSQL = 'CREATE '.substr(trim(preg_replace("'".$tmpname."'", $table, $createtesttableSQL, 1)), 17);
  815. $newcolumns = '';
  816. $oldcolumns = '';
  817. reset($newcols);
  818. while(list($key,$val) = each($newcols))
  819. {
  820. $newcolumns .= ($newcolumns?', ':'').$val;
  821. $oldcolumns .= ($oldcolumns?', ':'').$key;
  822. }
  823. $copytonewsql = 'INSERT INTO '.$table.'('.$newcolumns.') SELECT '.$oldcolumns.' FROM '.$tmpname;
  824. $this->query($createtemptableSQL); //create temp table
  825. $this->query($copytotempsql); //copy to table
  826. $this->query($dropoldsql); //drop old table
  827. $this->query($createnewtableSQL); //recreate original table
  828. $this->query($copytonewsql); //copy back to original table
  829. $this->query($droptempsql); //drop temp table
  830. }
  831. else
  832. {
  833. return false;
  834. }
  835. return true;
  836. }
  837. }
  838. //multiple query execution
  839. public function multiQuery($query)
  840. {
  841. $error = "Unknown error.";
  842. if($this->type=="PDO")
  843. {
  844. $success = $this->db->exec($query);
  845. }
  846. else if($this->type=="SQLite3")
  847. {
  848. $success = $this->db->exec($query, $error);
  849. }
  850. else
  851. {
  852. $success = $this->db->queryExec($query, $error);
  853. }
  854. if(!$success)
  855. {
  856. return "Error in query: '".$error."'";
  857. }
  858. else
  859. {
  860. return true;
  861. }
  862. }
  863. //get number of rows in table
  864. public function numRows($table)
  865. {
  866. $result = $this->select("SELECT Count(*) FROM ".$table);
  867. return $result[0];
  868. }
  869. //correctly escape a string to be injected into an SQL query
  870. public function quote($value)
  871. {
  872. if($this->type=="PDO")
  873. {
  874. // PDO quote() escapes and adds quotes
  875. return $this->db->quote($value);
  876. }
  877. else if($this->type=="SQLite3")
  878. {
  879. return "'".$this->db->escapeString($value)."'";
  880. }
  881. else
  882. {
  883. return "'".sqlite_escape_string($value)."'";
  884. }
  885. }
  886. //correctly format a string value from a table before showing it
  887. public function formatString($value)
  888. {
  889. return htmlspecialchars(stripslashes($value));
  890. }
  891. //import sql
  892. public function import_sql($query)
  893. {
  894. return $this->multiQuery($query);
  895. }
  896. //import csv
  897. public function import_csv($filename, $table, $field_terminate, $field_enclosed, $field_escaped, $null, $fields_in_first_row)
  898. {
  899. // CSV import implemented by Christopher Kramer - http://www.christosoft.de
  900. $csv_handle = fopen($filename,'r');
  901. $csv_insert = "BEGIN;\n";
  902. $csv_number_of_rows = 0;
  903. // PHP requires enclosure defined, but has no problem if it was not used
  904. if($field_enclosed=="") $field_enclosed='"';
  905. // PHP requires escaper defined
  906. if($field_escaped=="") $field_escaped='\\';
  907. while(!feof($csv_handle))
  908. {
  909. $csv_data = fgetcsv($csv_handle, 0, $field_terminate, $field_enclosed, $field_escaped);
  910. if($csv_data[0] != NULL || count($csv_data)>1)
  911. {
  912. $csv_number_of_rows++;
  913. if($fields_in_first_row && $csv_number_of_rows==1) continue;
  914. $csv_col_number = count($csv_data);
  915. $csv_insert .= "INSERT INTO $table VALUES (";
  916. foreach($csv_data as $csv_col => $csv_cell)
  917. {
  918. if($csv_cell == $null) $csv_insert .= "NULL";
  919. else
  920. {
  921. $csv_insert.= $this->quote($csv_cell);
  922. }
  923. if($csv_col == $csv_col_number-2 && $csv_data[$csv_col+1]=='')
  924. {
  925. // the CSV row ends with the separator (like old phpliteadmin exported)
  926. break;
  927. }
  928. if($csv_col < $csv_col_number-1) $csv_insert .= ",";
  929. }
  930. $csv_insert .= ");\n";
  931. if($csv_number_of_rows > 5000)
  932. {
  933. $csv_insert .= "COMMIT;\nBEGIN;\n";
  934. $csv_number_of_rows = 0;
  935. }
  936. }
  937. }
  938. $csv_insert .= "COMMIT;";
  939. fclose($csv_handle);
  940. return $this->multiQuery($csv_insert);
  941. }
  942. //export csv
  943. public function export_csv($tables, $field_terminate, $field_enclosed, $field_escaped, $null, $crlf, $fields_in_first_row)
  944. {
  945. $field_enclosed = stripslashes($field_enclosed);
  946. $query = "SELECT * FROM sqlite_master WHERE type='table' ORDER BY type DESC";
  947. $result = $this->selectArray($query);
  948. for($i=0; $i<sizeof($result); $i++)
  949. {
  950. $valid = false;
  951. for($j=0; $j<sizeof($tables); $j++)
  952. {
  953. if($result[$i]['tbl_name']==$tables[$j])
  954. $valid = true;
  955. }
  956. if($valid)
  957. {
  958. $query = "PRAGMA table_info('".$result[$i]['tbl_name']."')";
  959. $temp = $this->selectArray($query);
  960. $cols = array();
  961. for($z=0; $z<sizeof($temp); $z++)
  962. $cols[$z] = $temp[$z][1];
  963. if($fields_in_first_row)
  964. {
  965. for($z=0; $z<sizeof($cols); $z++)
  966. {
  967. echo $field_enclosed.$cols[$z].$field_enclosed;
  968. // do not terminate the last column!
  969. if($z < sizeof($cols)-1)
  970. echo $field_terminate;
  971. }
  972. echo "\r\n";
  973. }
  974. $query = "SELECT * FROM ".$result[$i]['tbl_name'];
  975. $arr = $this->selectArray($query, "assoc");
  976. for($z=0; $z<sizeof($arr); $z++)
  977. {
  978. for($y=0; $y<sizeof($cols); $y++)
  979. {
  980. $cell = $arr[$z][$cols[$y]];
  981. if($crlf)
  982. {
  983. $cell = str_replace("\n","", $cell);
  984. $cell = str_replace("\r","", $cell);
  985. }
  986. $cell = str_replace($field_terminate,$field_escaped.$field_terminate,$cell);
  987. $cell = str_replace($field_enclosed,$field_escaped.$field_enclosed,$cell);
  988. // do not enclose NULLs
  989. if($cell == NULL)
  990. echo $null;
  991. else
  992. echo $field_enclosed.$cell.$field_enclosed;
  993. // do not terminate the last column!
  994. if($y < sizeof($cols)-1)
  995. echo $field_terminate;
  996. }
  997. if($z<sizeof($arr)-1)
  998. echo "\r\n";
  999. }
  1000. if($i<sizeof($result)-1)
  1001. echo "\r\n";
  1002. }
  1003. }
  1004. }
  1005. //export sql
  1006. public function export_sql($tables, $drop, $structure, $data, $transaction, $comments)
  1007. {
  1008. if($comments)
  1009. {
  1010. echo "----\r\n";
  1011. echo "-- phpLiteAdmin database dump (http://phpliteadmin.googlecode.com)\r\n";
  1012. echo "-- phpLiteAdmin version: ".VERSION."\r\n";
  1013. echo "-- Exported on ".date('M jS, Y, h:i:sA')."\r\n";
  1014. echo "-- Database file: ".$this->getPath()."\r\n";
  1015. echo "----\r\n";
  1016. }
  1017. $query = "SELECT * FROM sqlite_master WHERE type='table' OR type='index' ORDER BY type DESC";
  1018. $result = $this->selectArray($query);
  1019. //iterate through each table
  1020. for($i=0; $i<sizeof($result); $i++)
  1021. {
  1022. $valid = false;
  1023. for($j=0; $j<sizeof($tables); $j++)
  1024. {
  1025. if($result[$i]['tbl_name']==$tables[$j])
  1026. $valid = true;
  1027. }
  1028. if($valid)
  1029. {
  1030. if($drop)
  1031. {
  1032. if($comments)
  1033. {
  1034. echo "\r\n----\r\n";
  1035. if($result[$i]['type']=="table")
  1036. echo "-- Drop table for ".$result[$i]['tbl_name']."\r\n";
  1037. else
  1038. echo "-- Drop index for ".$result[$i]['name']."\r\n";
  1039. echo "----\r\n";
  1040. }
  1041. if($result[$i]['type']=="table")
  1042. echo "DROP TABLE '".$result[$i]['tbl_name']."';\r\n";
  1043. else
  1044. echo "DROP INDEX '".$result[$i]['name']."';\r\n";
  1045. }
  1046. if($structure)
  1047. {
  1048. if($comments)
  1049. {
  1050. echo "\r\n----\r\n";
  1051. if($result[$i]['type']=="table")
  1052. echo "-- Table structure for ".$result[$i]['tbl_name']."\r\n";
  1053. else
  1054. echo "-- Structure for index ".$result[$i]['name']." on table ".$result[$i]['tbl_name']."\r\n";
  1055. echo "----\r\n";
  1056. }
  1057. echo $result[$i]['sql'].";\r\n";
  1058. }
  1059. if($data && $result[$i]['type']=="table")
  1060. {
  1061. $query = "SELECT * FROM ".$result[$i]['tbl_name'];
  1062. $arr = $this->selectArray($query, "assoc");
  1063. if($comments)
  1064. {
  1065. echo "\r\n----\r\n";
  1066. echo "-- Data dump for ".$result[$i]['tbl_name'].", a total of ".sizeof($arr)." rows\r\n";
  1067. echo "----\r\n";
  1068. }
  1069. $query = "PRAGMA table_info('".$result[$i]['tbl_name']."')";
  1070. $temp = $this->selectArray($query);
  1071. $cols = array();
  1072. $vals = array();
  1073. for($z=0; $z<sizeof($temp); $z++)
  1074. $cols[$z] = $temp[$z][1];
  1075. for($z=0; $z<sizeof($arr); $z++)
  1076. {
  1077. for($y=0; $y<sizeof($cols); $y++)
  1078. {
  1079. if(!isset($vals[$z]))
  1080. $vals[$z] = array();
  1081. $vals[$z][$cols[$y]] = $this->quote($arr[$z][$cols[$y]]);
  1082. }
  1083. }
  1084. if($transaction)
  1085. echo "BEGIN TRANSACTION;\r\n";
  1086. for($j=0; $j<sizeof($vals); $j++)
  1087. echo "INSERT INTO ".$result[$i]['tbl_name']." (".implode(",", $cols).") VALUES (".implode(",", $vals[$j]).");\r\n";
  1088. if($transaction)
  1089. echo "COMMIT;\r\n";
  1090. }
  1091. }
  1092. }
  1093. }
  1094. }
  1095. $auth = new Authorization(); //create authorization object
  1096. if(isset($_POST['logout'])) //user has attempted to log out
  1097. $auth->revoke();
  1098. else if(isset($_POST['login']) || isset($_POST['proc_login'])) //user has attempted to log in
  1099. {
  1100. $_POST['login'] = true;
  1101. if($_POST['password']==SYSTEMPASSWORD) //make sure passwords match before granting authorization
  1102. {
  1103. if(isset($_POST['remember']))
  1104. $auth->grant(true);
  1105. else
  1106. $auth->grant(false);
  1107. }
  1108. }
  1109. //user is downloading the exported database file
  1110. if(isset($_POST['export']))
  1111. {
  1112. if($_POST['export_type']=="sql")
  1113. {
  1114. header('Content-Type: text/sql');
  1115. header('Content-Disposition: attachment; filename="'.$_POST['filename'].'.'.$_POST['export_type'].'";');
  1116. if(isset($_POST['tables']))
  1117. $tables = $_POST['tables'];
  1118. else
  1119. {
  1120. $tables = array();
  1121. $tables[0] = $_POST['single_table'];
  1122. }
  1123. $drop = isset($_POST['drop']);
  1124. $structure = isset($_POST['structure']);
  1125. $data = isset($_POST['data']);
  1126. $transaction = isset($_POST['transaction']);
  1127. $comments = isset($_POST['comments']);
  1128. $db = new Database($databases[$_SESSION[COOKIENAME.'currentDB']]);
  1129. echo $db->export_sql($tables, $drop, $structure, $data, $transaction, $comments);
  1130. }
  1131. else if($_POST['export_type']=="csv")
  1132. {
  1133. header("Content-type: application/csv");
  1134. header('Content-Disposition: attachment; filename="'.$_POST['filename'].'.'.$_POST['export_type'].'";');
  1135. header("Pragma: no-cache");
  1136. header("Expires: 0");
  1137. if(isset($_POST['tables']))
  1138. $tables = $_POST['tables'];
  1139. else
  1140. {
  1141. $tables = array();
  1142. $tables[0] = $_POST['single_table'];
  1143. }
  1144. $field_terminate = $_POST['export_csv_fieldsterminated'];
  1145. $field_enclosed = $_POST['export_csv_fieldsenclosed'];
  1146. $field_escaped = $_POST['export_csv_fieldsescaped'];
  1147. $null = $_POST['export_csv_replacenull'];
  1148. $crlf = isset($_POST['export_csv_crlf']);
  1149. $fields_in_first_row = isset($_POST['export_csv_fieldnames']);
  1150. $db = new Database($databases[$_SESSION[COOKIENAME.'currentDB']]);
  1151. echo $db->export_csv($tables, $field_terminate, $field_enclosed, $field_escaped, $null, $crlf, $fields_in_first_row);
  1152. }
  1153. exit();
  1154. }
  1155. //user is importing a file
  1156. if(isset($_POST['import']))
  1157. {
  1158. $db = new Database($databases[$_SESSION[COOKIENAME.'currentDB']]);
  1159. if($_POST['import_type']=="sql")
  1160. {
  1161. $data = file_get_contents($_FILES["file"]["tmp_name"]);
  1162. $importSuccess = $db->import_sql($data);
  1163. }
  1164. else
  1165. {
  1166. $field_terminate = $_POST['import_csv_fieldsterminated'];
  1167. $field_enclosed = $_POST['import_csv_fieldsenclosed'];
  1168. $field_escaped = $_POST['import_csv_fieldsescaped'];
  1169. $null = $_POST['import_csv_replacenull'];
  1170. $fields_in_first_row = isset($_POST['import_csv_fieldnames']);
  1171. $importSuccess = $db->import_csv($_FILES["file"]["tmp_name"], $_POST['single_table'], $field_terminate, $field_enclosed, $field_escaped, $null, $fields_in_first_row);
  1172. }
  1173. }
  1174. // here begins the HTML.
  1175. ?>
  1176. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  1177. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  1178. <head>
  1179. <!-- Copyright 2011 phpLiteAdmin (http://phpliteadmin.googlecode.com) -->
  1180. <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
  1181. <title><?php echo PROJECT ?></title>
  1182. <?php
  1183. if(!file_exists("phpliteadmin.css")) //only use the inline stylesheet if an external one does not exist
  1184. {
  1185. ?>
  1186. <!-- begin the customizable stylesheet/theme -->
  1187. <style type="text/css">
  1188. /* overall styles for entire page */
  1189. body
  1190. {
  1191. margin: 0px;
  1192. padding: 0px;
  1193. font-family: Arial, Helvetica, sans-serif;
  1194. font-size: 14px;
  1195. color: #000000;
  1196. background-color: #e0ebf6;
  1197. }
  1198. /* general styles for hyperlink */
  1199. a
  1200. {
  1201. color: #03F;
  1202. text-decoration: none;
  1203. cursor :pointer;
  1204. }
  1205. hr
  1206. {
  1207. height: 1px;
  1208. border: 0;
  1209. color: #bbb;
  1210. background-color: #bbb;
  1211. width: 100%;
  1212. }
  1213. a:hover
  1214. {
  1215. color: #06F;
  1216. }
  1217. /* logo text containing name of project */
  1218. h1
  1219. {
  1220. margin: 0px;
  1221. padding: 5px;
  1222. font-size: 24px;
  1223. background-color: #f3cece;
  1224. text-align: center;
  1225. color: #000;
  1226. border-top-left-radius:5px;
  1227. border-top-right-radius:5px;
  1228. -moz-border-radius-topleft:5px;
  1229. -moz-border-radius-topright:5px;
  1230. }
  1231. /* the div container for the links */
  1232. #headerlinks
  1233. {
  1234. text-align:center;
  1235. margin-bottom:10px;
  1236. padding:5px;
  1237. border-color:#03F;
  1238. border-width:1px;
  1239. border-style:solid;
  1240. border-left-style:none;
  1241. border-right-style:none;
  1242. font-size:12px;
  1243. background-color:#e0ebf6;
  1244. font-weight:bold;
  1245. }
  1246. /* version text within the logo */
  1247. h1 #version
  1248. {
  1249. color: #000000;
  1250. font-size: 16px;
  1251. }
  1252. /* logo text within logo */
  1253. h1 #logo
  1254. {
  1255. color:#000;
  1256. }
  1257. /* general header for various views */
  1258. h2
  1259. {
  1260. margin:0px;
  1261. padding:0px;
  1262. font-size:14px;
  1263. margin-bottom:20px;
  1264. }
  1265. /* input buttons and areas for entering text */
  1266. input, select, textarea
  1267. {
  1268. font-family:Arial, Helvetica, sans-serif;
  1269. background-color:#eaeaea;
  1270. color:#03F;
  1271. border-color:#03F;
  1272. border-style:solid;
  1273. border-width:1px;
  1274. margin:5px;
  1275. border-radius:5px;
  1276. -moz-border-radius:5px;
  1277. padding:3px;
  1278. }
  1279. /* just input buttons */
  1280. input.btn
  1281. {
  1282. cursor:pointer;
  1283. }
  1284. input.btn:hover
  1285. {
  1286. background-color:#ccc;
  1287. }
  1288. /* general styles for hyperlink */
  1289. fieldset
  1290. {
  1291. padding:15px;
  1292. border-color:#03F;
  1293. border-width:1px;
  1294. border-style:solid;
  1295. border-radius:5px;
  1296. -moz-border-radius:5px;
  1297. background-color:#f9f9f9;
  1298. }
  1299. /* outer div that holds everything */
  1300. #container
  1301. {
  1302. padding:10px;
  1303. }
  1304. /* div of left box with log, list of databases, etc. */
  1305. #leftNav
  1306. {
  1307. float:left;
  1308. min-width:250px;
  1309. padding:0px;
  1310. border-color:#03F;
  1311. border-width:1px;
  1312. border-style:solid;
  1313. background-color:#FFF;
  1314. padding-bottom:15px;
  1315. border-radius:5px;
  1316. -moz-border-radius:5px;
  1317. }
  1318. /* div holding the content to the right of the leftNav */
  1319. #content
  1320. {
  1321. overflow:hidden;
  1322. padding-left:10px;
  1323. }
  1324. /* div holding the login fields */
  1325. #loginBox
  1326. {
  1327. width:500px;
  1328. margin-left:auto;
  1329. margin-right:auto;
  1330. margin-top:50px;
  1331. border-color:#03F;
  1332. border-width:1px;
  1333. border-style:solid;
  1334. background-color:#FFF;
  1335. border-radius:5px;
  1336. -moz-border-radius:5px;
  1337. }
  1338. /* div under tabs with tab-specific content */
  1339. #main
  1340. {
  1341. border-color:#03F;
  1342. border-width:1px;
  1343. border-style:solid;
  1344. padding:15px;
  1345. overflow:auto;
  1346. background-color:#FFF;
  1347. border-bottom-left-radius:5px;
  1348. border-bottom-right-radius:5px;
  1349. border-top-right-radius:5px;
  1350. -moz-border-radius-bottomleft:5px;
  1351. -moz-border-radius-bottomright:5px;
  1352. -moz-border-radius-topright:5px;
  1353. }
  1354. /* odd-numbered table rows */
  1355. .td1
  1356. {
  1357. background-color:#f9e3e3;
  1358. text-align:right;
  1359. font-size:12px;
  1360. padding-left:10px;
  1361. padding-right:10px;
  1362. }
  1363. /* even-numbered table rows */
  1364. .td2
  1365. {
  1366. background-color:#f3cece;
  1367. text-align:right;
  1368. font-size:12px;
  1369. padding-left:10px;
  1370. padding-right:10px;
  1371. }
  1372. /* table column headers */
  1373. .tdheader
  1374. {
  1375. border-color:#03F;
  1376. border-width:1px;
  1377. border-style:solid;
  1378. font-weight:bold;
  1379. font-size:12px;
  1380. padding-left:10px;
  1381. padding-right:10px;
  1382. background-color:#e0ebf6;
  1383. border-radius:5px;
  1384. -moz-border-radius:5px;
  1385. }
  1386. /* div holding the confirmation text of certain actions */
  1387. .confirm
  1388. {
  1389. border-color:#03F;
  1390. border-width:1px;
  1391. border-style:dashed;
  1392. padding:15px;
  1393. background-color:#e0ebf6;
  1394. }
  1395. /* tab navigation for each table */
  1396. .tab
  1397. {
  1398. display:block;
  1399. padding:5px;
  1400. padding-right:8px;
  1401. padding-left:8px;
  1402. border-color:#03F;
  1403. border-width:1px;
  1404. border-style:solid;
  1405. margin-right:5px;
  1406. float:left;
  1407. border-bottom-style:none;
  1408. position:relative;
  1409. top:1px;
  1410. padding-bottom:4px;
  1411. background-color:#eaeaea;
  1412. border-top-left-radius:5px;
  1413. border-top-right-radius:5px;
  1414. -moz-border-radius-topleft:5px;
  1415. -moz-border-radius-topright:5px;
  1416. }
  1417. /* pressed state of tab */
  1418. .tab_pressed
  1419. {
  1420. display:block;
  1421. padding:5px;
  1422. padding-right:8px;
  1423. padding-left:8px;
  1424. border-color:#03F;
  1425. border-width:1px;
  1426. border-style:solid;
  1427. margin-right:5px;
  1428. float:left;
  1429. border-bottom-style:none;
  1430. position:relative;
  1431. top:1px;
  1432. background-color:#FFF;
  1433. cursor:default;
  1434. border-top-left-radius:5px;
  1435. border-top-right-radius:5px;
  1436. -moz-border-radius-topleft:5px;
  1437. -moz-border-radius-topright:5px;
  1438. }
  1439. /* help section */
  1440. .helpq
  1441. {
  1442. font-size:11px;
  1443. font-weight:normal;
  1444. }
  1445. #help_container
  1446. {
  1447. padding:0px;
  1448. font-size:12px;
  1449. margin-left:auto;
  1450. margin-right:auto;
  1451. background-color:#ffffff;
  1452. }
  1453. .help_outer
  1454. {
  1455. background-color:#FFF;
  1456. padding:0px;
  1457. height:300px;
  1458. overflow:hidden;
  1459. position:relative;
  1460. }
  1461. .help_list
  1462. {
  1463. padding:10px;
  1464. height:auto;
  1465. }
  1466. .headd
  1467. {
  1468. font-size:14px;
  1469. font-weight:bold;
  1470. display:block;
  1471. padding:10px;
  1472. background-color:#e0ebf6;
  1473. border-color:#03F;
  1474. border-width:1px;
  1475. border-style:solid;
  1476. border-left-style:none;
  1477. border-right-style:none;
  1478. }
  1479. .help_inner
  1480. {
  1481. padding:10px;
  1482. }
  1483. .help_top
  1484. {
  1485. display:block;
  1486. position:absolute;
  1487. right:10px;
  1488. bottom:10px;
  1489. }
  1490. </style>
  1491. <!-- end the customizable stylesheet/theme -->
  1492. <?php
  1493. }
  1494. else //an external stylesheet exists - import it
  1495. {
  1496. echo "<link href='phpliteadmin.css' rel='stylesheet' type='text/css' />";
  1497. }
  1498. if(isset($_GET['help'])) //this page is used as the popup help section
  1499. {
  1500. //help section array
  1501. $help = array
  1502. (
  1503. 'SQLite Library Extensions' =>
  1504. 'phpLiteAdmin uses PHP library extensions that allow interaction with SQLite databases. Currently, phpLiteAdmin supports PDO, SQLite3, and SQLiteDatabase. Both PDO and SQLite3 deal with version 3 of SQLite, while SQLiteDatabase deals with version 2. So, if your PHP installation includes more than one SQLite library extension, PDO and SQLite3 will take precedence to make use of the better technology. However, if you have existing databases that are of version 2 of SQLite, phpLiteAdmin will be forced to use SQLiteDatabase for only those databases. Not all databases need to be of the same version. During the database creation, however, the most advanced extension will be used.',
  1505. 'Creating a New Database' =>
  1506. 'When you create a new database, the name you entered will be appended with the appropriate file extension (.db, .db3, .sqlite, etc.) if you do not include it yourself. The database will be created in the directory you specified as the $directory variable.',
  1507. 'Tables vs. Views' =>
  1508. 'On the main database page, there is a list of tables and views. Since views are read-only, certain operations will be disabled. These disabled operations will be apparent by their omission in the location where they should appear on the row for a view. If you want to change the data for a view, you need to drop that view and create a new view with the appropriate SELECT statement that queries other existing tables. For more information, see <a href="http://en.wikipedia.org/wiki/View_(database)" target="_blank">http://en.wikipedia.org/wiki/View_(database)</a>',
  1509. 'Writing a Select Statement for a New View' =>
  1510. 'When you create a new view, you must write an SQL SELECT statement that it will use as its data. A view is simply a read-only table that can be accessed and queried like a regular table, except it cannot be modified through insertion, column editing, or row editing. It is only used for conveniently fetching data.',
  1511. 'Export Structure to SQL File' =>
  1512. 'During the process for exporting to an SQL file, you may choose to include the queries that create the table and columns.',
  1513. 'Export Data to SQL File' =>
  1514. 'During the process for exporting to an SQL file, you may choose to include the queries that populate the table(s) with the current records of the table(s).',
  1515. 'Add Drop Table to Exported SQL File' =>
  1516. 'During the process for exporting to an SQL file, you may choose to include queries to DROP the existing tables before adding them so that problems do not occur when trying to create tables that already exist.',
  1517. 'Add Transaction to Exported SQL File' =>
  1518. 'During the process for exporting to an SQL file, you may choose to wrap the queries around a TRANSACTION so that if an error occurs at any time during the importation process using the exported file, the database can be reverted to its previous state, preventing partially updated data from populating the database.',
  1519. 'Add Comments to Exported SQL File' =>
  1520. 'During the process for exporting to an SQL file, you may choose to include comments that explain each step of the process so that a human can better understand what is happening.',
  1521. );
  1522. ?>
  1523. </head>
  1524. <body>
  1525. <div id='help_container'>
  1526. <?php
  1527. echo "<div class='help_list'>";
  1528. echo "<span style='font-size:18px;'>".PROJECT." v".VERSION." Help Documentation</span><br/><br/>";
  1529. foreach((array)$help as $key => $val)
  1530. {
  1531. echo "<a href='#".$key."'>".$key."</a><br/>";
  1532. }
  1533. echo "</div>";
  1534. echo "<br/><br/>";
  1535. foreach((array)$help as $key => $val)
  1536. {
  1537. echo "<div class='help_outer'>";
  1538. echo "<a class='headd' name='".$key."'>".$key."</a>";
  1539. echo "<div class='help_inner'>";
  1540. echo $val;
  1541. echo "</div>";
  1542. echo "<a class='help_top' href='#top'>Back to Top</a>";
  1543. echo "</div>";
  1544. }
  1545. ?>
  1546. </div>
  1547. </body>
  1548. </html>
  1549. <?php
  1550. exit();
  1551. }
  1552. ?>
  1553. <!-- JavaScript Support -->
  1554. <script type="text/javascript">
  1555. //makes sure autoincrement can only be selected when integer type is selected
  1556. function toggleAutoincrement(i)
  1557. {
  1558. var type = document.getElementById(i+'_type');
  1559. var autoincrement = document.getElementById(i+'_autoincrement');
  1560. if(type.value=="INTEGER")
  1561. autoincrement.disabled = false;
  1562. else
  1563. {
  1564. autoincrement.disabled = true;
  1565. autoincrement.checked = false;
  1566. }
  1567. }
  1568. function toggleNull(i)
  1569. {
  1570. var pk = document.getElementById(i+'_primarykey');
  1571. var notnull = document.getElementById(i+'_notnull');
  1572. if(pk.checked)
  1573. {
  1574. notnull.disabled = true;
  1575. notnull.checked = true;
  1576. }
  1577. else
  1578. {
  1579. notnull.disabled = false;
  1580. }
  1581. }
  1582. //finds and checks all checkboxes for all rows on the Browse or Structure tab for a table
  1583. function checkAll(field)
  1584. {
  1585. var i=0;
  1586. while(document.getElementById('check_'+i)!=undefined)
  1587. {
  1588. document.getElementById('check_'+i).checked = true;
  1589. i++;
  1590. }
  1591. }
  1592. //finds and unchecks all checkboxes for all rows on the Browse or Structure tab for a table
  1593. function uncheckAll(field)
  1594. {
  1595. var i=0;
  1596. while(document.getElementById('check_'+i)!=undefined)
  1597. {
  1598. document.getElementById('check_'+i).checked = false;
  1599. i++;
  1600. }
  1601. }
  1602. //unchecks the ignore checkbox if user has typed something into one of the fields for adding new rows
  1603. function changeIgnore(area, e, u)
  1604. {
  1605. if(area.value!="")
  1606. {
  1607. if(document.getElementById(e)!=

Large files files are truncated, but you can click here to view the full file