mirror of
https://github.com/maxpozdeev/mytinytodo.git
synced 2026-03-11 08:55:27 +00:00
convert indention to spaces in php files
This commit is contained in:
parent
69f3702a2e
commit
acfb316e9a
21 changed files with 2787 additions and 2785 deletions
|
|
@ -11,8 +11,13 @@ tab_width = 4
|
|||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.php]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = false
|
||||
|
||||
# temporary. spaces will be used later.
|
||||
[*.{php,js}]
|
||||
[*.js]
|
||||
indent_style = tab
|
||||
tab_width = 4
|
||||
|
||||
|
|
@ -20,9 +25,6 @@ tab_width = 4
|
|||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.php]
|
||||
insert_final_newline = false
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = false
|
||||
|
|
|
|||
64
buildzip.php
64
buildzip.php
|
|
@ -4,7 +4,7 @@
|
|||
// PHP 5.4 is required
|
||||
|
||||
if ( !isset($argv) || !isset($argv[1]) ) {
|
||||
die("Usage: buildzip.php <path_to_repo> [-o source.zip] [-v VERSION]\n");
|
||||
die("Usage: buildzip.php <path_to_repo> [-o source.zip] [-v VERSION]\n");
|
||||
}
|
||||
|
||||
$repo = $argv[1];
|
||||
|
|
@ -15,28 +15,28 @@ $ver = 0;
|
|||
|
||||
while ($arg = next($argv))
|
||||
{
|
||||
if ($arg == '-o') {
|
||||
$zipfile = next($argv);
|
||||
}
|
||||
elseif ($arg == '-v') {
|
||||
$ver = next($argv);
|
||||
}
|
||||
if ($arg == '-o') {
|
||||
$zipfile = next($argv);
|
||||
}
|
||||
elseif ($arg == '-v') {
|
||||
$ver = next($argv);
|
||||
}
|
||||
}
|
||||
|
||||
deleteTreeIfDir($dir);
|
||||
$out = `git clone $repo $dir 2>&1`;
|
||||
if (!is_dir($dir)) {
|
||||
die("Error while clone: $out\n");
|
||||
die("Error while clone: $out\n");
|
||||
}
|
||||
print "> Repository was cloned to temp dir: $dir\n";
|
||||
|
||||
#get current version number if not specified
|
||||
if (!$ver)
|
||||
{
|
||||
chdir($dir);
|
||||
$fh = fopen('version.txt', 'r') or die("Cant open version.txt\n");
|
||||
$ver = trim(fgets($fh, 100));
|
||||
fclose($fh);
|
||||
chdir($dir);
|
||||
$fh = fopen('version.txt', 'r') or die("Cant open version.txt\n");
|
||||
$ver = trim(fgets($fh, 100));
|
||||
fclose($fh);
|
||||
}
|
||||
chdir($dir. DIRECTORY_SEPARATOR. 'src');
|
||||
$rev = trim(`git show --format=format:%H --summary`);
|
||||
|
|
@ -62,9 +62,9 @@ unlink('./content/lang/en-rtl.json');
|
|||
# save only 2 languages
|
||||
$dh = opendir('./content/lang/') or die("Cant opendir lang\n");
|
||||
while (false !== ($f = readdir($dh))) {
|
||||
if (!in_array($f, ['.', '..', '.htaccess', 'en.json', 'ru.json'])) {
|
||||
unlink('./content/lang/'. $f);
|
||||
}
|
||||
if (!in_array($f, ['.', '..', '.htaccess', 'en.json', 'ru.json'])) {
|
||||
unlink('./content/lang/'. $f);
|
||||
}
|
||||
}
|
||||
closedir($dh);
|
||||
*/
|
||||
|
|
@ -75,7 +75,7 @@ rename('src', 'mytinytodo') or die("Cant rename 'src'\n");
|
|||
|
||||
`zip -9 -r mytinytodo.zip mytinytodo`; #OS dep.!!!
|
||||
if (!file_exists('mytinytodo.zip')) {
|
||||
die("Failed to pack files (no output zip file)\n");
|
||||
die("Failed to pack files (no output zip file)\n");
|
||||
}
|
||||
|
||||
$zipfile = str_replace('@VERSION', $ver, $zipfile);
|
||||
|
|
@ -83,7 +83,7 @@ $zipfile = str_replace('@REV', $rev, $zipfile);
|
|||
|
||||
chdir($curdir);
|
||||
if ( ! rename("$dir/mytinytodo.zip", $zipfile) ) {
|
||||
die("Failed to move mytinytodo.zip to $zipfile");
|
||||
die("Failed to move mytinytodo.zip to $zipfile");
|
||||
}
|
||||
|
||||
deleteTreeIfDir($dir);
|
||||
|
|
@ -98,23 +98,23 @@ echo("> Build is stored in $zipfile\n");
|
|||
|
||||
function deleteTreeIfDir($dir)
|
||||
{
|
||||
if ( is_dir($dir) ) {
|
||||
switch (PHP_OS) {
|
||||
case 'Darwin':
|
||||
system("rm -rf $dir");
|
||||
break;
|
||||
case 'Windows':
|
||||
system("rmdir /s /q $dir");
|
||||
break;
|
||||
default:
|
||||
die("Unknown system ". PHP_OS. "\n");
|
||||
}
|
||||
}
|
||||
if ( is_dir($dir) ) {
|
||||
switch (PHP_OS) {
|
||||
case 'Darwin':
|
||||
system("rm -rf $dir");
|
||||
break;
|
||||
case 'Windows':
|
||||
system("rmdir /s /q $dir");
|
||||
break;
|
||||
default:
|
||||
die("Unknown system ". PHP_OS. "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replaceVer($filename, $ver)
|
||||
{
|
||||
$s = @file_get_contents($filename) or die("Cant open $filename\n");
|
||||
$s = str_replace('@VERSION', $ver, $s);
|
||||
@file_put_contents($filename, $s) or die("Cant write $filename\n");
|
||||
$s = @file_get_contents($filename) or die("Cant open $filename\n");
|
||||
$s = str_replace('@VERSION', $ver, $s);
|
||||
@file_put_contents($filename, $s) or die("Cant write $filename\n");
|
||||
}
|
||||
1470
src/ajax.php
1470
src/ajax.php
File diff suppressed because it is too large
Load diff
|
|
@ -3,17 +3,17 @@
|
|||
// Rename it to config.php before using in docker.
|
||||
|
||||
if (getenv('MTT_DB_TYPE') == 'mysql') {
|
||||
define("MTT_DB_TYPE", "mysql");
|
||||
define("MTT_DB_HOST", getenv('MTT_DB_HOST'));
|
||||
define("MTT_DB_NAME", getenv('MTT_DB'));
|
||||
define("MTT_DB_USER", getenv('MTT_DB_USER'));
|
||||
define("MTT_DB_PASSWORD", getenv('MTT_DB_PASSWORD'));
|
||||
define("MTT_DB_PREFIX", getenv('MTT_DB_PREFIX'));
|
||||
define("MTT_DB_DRIVER", getenv('MTT_DB_DRIVER'));
|
||||
define("MTT_DB_TYPE", "mysql");
|
||||
define("MTT_DB_HOST", getenv('MTT_DB_HOST'));
|
||||
define("MTT_DB_NAME", getenv('MTT_DB'));
|
||||
define("MTT_DB_USER", getenv('MTT_DB_USER'));
|
||||
define("MTT_DB_PASSWORD", getenv('MTT_DB_PASSWORD'));
|
||||
define("MTT_DB_PREFIX", getenv('MTT_DB_PREFIX'));
|
||||
define("MTT_DB_DRIVER", getenv('MTT_DB_DRIVER'));
|
||||
}
|
||||
else if (getenv('MTT_DB_TYPE') == 'sqlite') {
|
||||
define("MTT_DB_TYPE", "sqlite");
|
||||
define("MTT_DB_PREFIX", "");
|
||||
define("MTT_DB_TYPE", "sqlite");
|
||||
define("MTT_DB_PREFIX", "");
|
||||
}
|
||||
|
||||
define("MTT_SALT", "Random text");
|
||||
198
src/export.php
198
src/export.php
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2010-2011,2019-2021 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2010-2011,2019-2021 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
//$dontStartSession = 1;
|
||||
|
|
@ -15,7 +15,7 @@ if(!have_write_access()) $onlyPublishedList = true;
|
|||
$listId = (int)_get('list');
|
||||
$listData = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$listId ". ($onlyPublishedList ? "AND published=1" : "") );
|
||||
if(!$listData) {
|
||||
die("No such list or access denied");
|
||||
die("No such list or access denied");
|
||||
}
|
||||
|
||||
$sqlSort = "ORDER BY compl ASC, ";
|
||||
|
|
@ -27,7 +27,7 @@ $data = array();
|
|||
$q = $db->dq("SELECT *, duedate IS NULL AS ddn FROM {$db->prefix}todolist WHERE list_id=$listId $sqlSort");
|
||||
while($r = $q->fetchAssoc())
|
||||
{
|
||||
$data[] = $r;
|
||||
$data[] = $r;
|
||||
}
|
||||
|
||||
$format = _get('format');
|
||||
|
|
@ -38,124 +38,124 @@ else printCSV($listData, $data);
|
|||
|
||||
function have_write_access()
|
||||
{
|
||||
if(is_logged()) return true;
|
||||
return false;
|
||||
if(is_logged()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function printCSV($listData, $data)
|
||||
{
|
||||
$s = "\xEF\xBB\xBF". "Completed;Priority;Task;Notes;Tags;Due;DateCreated;DateCompleted\n";
|
||||
foreach($data as $r)
|
||||
{
|
||||
$s .= ($r['compl']?'1':'0'). ';'.
|
||||
$r['prio']. ';'. escape_csv($r['title']). ';'.
|
||||
escape_csv($r['note']). ';'.
|
||||
escape_csv($r['tags']). ';'.
|
||||
$r['duedate']. ';'.
|
||||
date('Y-m-d H:i:s O',$r['d_created']). ';'.
|
||||
($r['d_completed'] ? date('Y-m-d H:i:s O',$r['d_completed']) :''). "\n";
|
||||
}
|
||||
header('Content-type: text/csv; charset=utf-8');
|
||||
header('Content-disposition: attachment; filename=list_'.(int)$listData['id'].'.csv');
|
||||
print $s;
|
||||
$s = "\xEF\xBB\xBF". "Completed;Priority;Task;Notes;Tags;Due;DateCreated;DateCompleted\n";
|
||||
foreach($data as $r)
|
||||
{
|
||||
$s .= ($r['compl']?'1':'0'). ';'.
|
||||
$r['prio']. ';'. escape_csv($r['title']). ';'.
|
||||
escape_csv($r['note']). ';'.
|
||||
escape_csv($r['tags']). ';'.
|
||||
$r['duedate']. ';'.
|
||||
date('Y-m-d H:i:s O',$r['d_created']). ';'.
|
||||
($r['d_completed'] ? date('Y-m-d H:i:s O',$r['d_completed']) :''). "\n";
|
||||
}
|
||||
header('Content-type: text/csv; charset=utf-8');
|
||||
header('Content-disposition: attachment; filename=list_'.(int)$listData['id'].'.csv');
|
||||
print $s;
|
||||
}
|
||||
|
||||
function escape_csv($v)
|
||||
{
|
||||
//escape formulas
|
||||
$nf = '';
|
||||
$trimmed = ltrim($v);
|
||||
$trimmed = ltrim($v);
|
||||
if (strlen($trimmed) > 0 && in_array(substr($trimmed, 0, 1), array('=', '+', '-', '@'))) {
|
||||
$nf = "'";
|
||||
}
|
||||
return '"'. $nf. str_replace('"', '""', $v). '"';
|
||||
return '"'. $nf. str_replace('"', '""', $v). '"';
|
||||
}
|
||||
|
||||
function printICal($listData, $data)
|
||||
{
|
||||
$mttToIcalPrio = array("1" => 5, "2" => 1);
|
||||
$s = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nMETHOD:PUBLISH\r\nCALSCALE:GREGORIAN\r\nPRODID:-//myTinyTodo//iCalendar Export v1.4//EN\r\n".
|
||||
"X-WR-CALNAME:". $listData['name']. "\r\nX-MTT-TIMEZONE:".Config::get('timezone')."\r\n";
|
||||
# to-do
|
||||
foreach($data as $r)
|
||||
{
|
||||
$a = array();
|
||||
$a[] = "BEGIN:VTODO";
|
||||
$a[] = "UID:". $r['uuid'];
|
||||
$a[] = "CREATED:". gmdate('Ymd\THis\Z', $r['d_created']);
|
||||
$a[] = "DTSTAMP:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
||||
$a[] = "LAST-MODIFIED:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
||||
$a[] = utf8chunks("SUMMARY:". $r['title']);
|
||||
if($r['duedate']) {
|
||||
$dda = explode('-', $r['duedate']);
|
||||
$a[] = "DUE;VALUE=DATE:".sprintf("%u%02u%02u", $dda[0], $dda[1], $dda[2]);
|
||||
}
|
||||
# Apple's iCal priorities: low-9, medium-5, high-1
|
||||
if($r['prio'] > 0 && isset($mttToIcalPrio[$r['prio']])) $a[] = "PRIORITY:". $mttToIcalPrio[$r['prio']];
|
||||
$a[] = "X-MTT-PRIORITY:". $r['prio'];
|
||||
$mttToIcalPrio = array("1" => 5, "2" => 1);
|
||||
$s = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nMETHOD:PUBLISH\r\nCALSCALE:GREGORIAN\r\nPRODID:-//myTinyTodo//iCalendar Export v1.4//EN\r\n".
|
||||
"X-WR-CALNAME:". $listData['name']. "\r\nX-MTT-TIMEZONE:".Config::get('timezone')."\r\n";
|
||||
# to-do
|
||||
foreach($data as $r)
|
||||
{
|
||||
$a = array();
|
||||
$a[] = "BEGIN:VTODO";
|
||||
$a[] = "UID:". $r['uuid'];
|
||||
$a[] = "CREATED:". gmdate('Ymd\THis\Z', $r['d_created']);
|
||||
$a[] = "DTSTAMP:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
||||
$a[] = "LAST-MODIFIED:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
||||
$a[] = utf8chunks("SUMMARY:". $r['title']);
|
||||
if($r['duedate']) {
|
||||
$dda = explode('-', $r['duedate']);
|
||||
$a[] = "DUE;VALUE=DATE:".sprintf("%u%02u%02u", $dda[0], $dda[1], $dda[2]);
|
||||
}
|
||||
# Apple's iCal priorities: low-9, medium-5, high-1
|
||||
if($r['prio'] > 0 && isset($mttToIcalPrio[$r['prio']])) $a[] = "PRIORITY:". $mttToIcalPrio[$r['prio']];
|
||||
$a[] = "X-MTT-PRIORITY:". $r['prio'];
|
||||
|
||||
$descr = array();
|
||||
if($r['tags'] != '') $descr[] = Lang::instance()->get('tags'). ": ". str_replace(',', ', ', $r['tags']);
|
||||
if($r['note'] != '') $descr[] = Lang::instance()->get('note'). ": ". $r['note'];
|
||||
if($descr) $a[] = utf8chunks("DESCRIPTION:". str_replace("\n", '\\n', implode("\n",$descr)));
|
||||
$descr = array();
|
||||
if($r['tags'] != '') $descr[] = Lang::instance()->get('tags'). ": ". str_replace(',', ', ', $r['tags']);
|
||||
if($r['note'] != '') $descr[] = Lang::instance()->get('note'). ": ". $r['note'];
|
||||
if($descr) $a[] = utf8chunks("DESCRIPTION:". str_replace("\n", '\\n', implode("\n",$descr)));
|
||||
|
||||
if($r['compl']) {
|
||||
$a[] = "STATUS:COMPLETED"; #used in Sunbird
|
||||
$a[] = "COMPLETED:". gmdate('Ymd\THis\Z', $r['d_completed']);
|
||||
#$a[] = "PERCENT-COMPLETE:100"; #used in Sunbird
|
||||
}
|
||||
if($r['tags'] != '') $a[] = utf8chunks("X-MTT-TAGS:". $r['tags']);
|
||||
$a[] = "END:VTODO\r\n";
|
||||
$s .= implode("\r\n", $a);
|
||||
}
|
||||
# events
|
||||
foreach($data as $r)
|
||||
{
|
||||
if(!$r['duedate'] || $r['compl']) continue; # skip tasks completed and without duedate
|
||||
$a = array();
|
||||
$a[] = "BEGIN:VEVENT";
|
||||
$a[] = "UID:_". $r['uuid']; # do not duplicate VTODO UID
|
||||
$a[] = "CREATED:". gmdate('Ymd\THis\Z', $r['d_created']);
|
||||
$a[] = "DTSTAMP:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
||||
$a[] = "LAST-MODIFIED:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
||||
$a[] = utf8chunks("SUMMARY:". $r['title']);
|
||||
if($r['prio'] > 0 && isset($mttToIcalPrio[$r['prio']])) $a[] = "PRIORITY:". $mttToIcalPrio[$r['prio']];
|
||||
$dda = explode('-', $r['duedate']);
|
||||
$a[] = "DTSTART;VALUE=DATE:".sprintf("%u%02u%02u", $dda[0], $dda[1], $dda[2]);
|
||||
$a[] = "DTEND;VALUE=DATE:".date('Ymd', mktime(1,1,1,$dda[1],$dda[2],$dda[0]) + 86400);
|
||||
$descr = array();
|
||||
if($r['tags'] != '') $descr[] = Lang::instance()->get('tags'). ": ". str_replace(',', ', ', $r['tags']);
|
||||
if($r['note'] != '') $descr[] = Lang::instance()->get('note'). ": ". $r['note'];
|
||||
if($descr) $a[] = utf8chunks("DESCRIPTION:". str_replace("\n", '\\n', implode("\n",$descr)));
|
||||
$a[] = "END:VEVENT\r\n";
|
||||
$s .= implode("\r\n", $a);
|
||||
}
|
||||
$s .= "END:VCALENDAR\r\n";
|
||||
header('Content-type: text/calendar; charset=utf-8');
|
||||
header('Content-disposition: attachment; filename=list_'.(int)$listData['id'].'.ics');
|
||||
print $s;
|
||||
if($r['compl']) {
|
||||
$a[] = "STATUS:COMPLETED"; #used in Sunbird
|
||||
$a[] = "COMPLETED:". gmdate('Ymd\THis\Z', $r['d_completed']);
|
||||
#$a[] = "PERCENT-COMPLETE:100"; #used in Sunbird
|
||||
}
|
||||
if($r['tags'] != '') $a[] = utf8chunks("X-MTT-TAGS:". $r['tags']);
|
||||
$a[] = "END:VTODO\r\n";
|
||||
$s .= implode("\r\n", $a);
|
||||
}
|
||||
# events
|
||||
foreach($data as $r)
|
||||
{
|
||||
if(!$r['duedate'] || $r['compl']) continue; # skip tasks completed and without duedate
|
||||
$a = array();
|
||||
$a[] = "BEGIN:VEVENT";
|
||||
$a[] = "UID:_". $r['uuid']; # do not duplicate VTODO UID
|
||||
$a[] = "CREATED:". gmdate('Ymd\THis\Z', $r['d_created']);
|
||||
$a[] = "DTSTAMP:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
||||
$a[] = "LAST-MODIFIED:". gmdate('Ymd\THis\Z', $r['d_edited']);
|
||||
$a[] = utf8chunks("SUMMARY:". $r['title']);
|
||||
if($r['prio'] > 0 && isset($mttToIcalPrio[$r['prio']])) $a[] = "PRIORITY:". $mttToIcalPrio[$r['prio']];
|
||||
$dda = explode('-', $r['duedate']);
|
||||
$a[] = "DTSTART;VALUE=DATE:".sprintf("%u%02u%02u", $dda[0], $dda[1], $dda[2]);
|
||||
$a[] = "DTEND;VALUE=DATE:".date('Ymd', mktime(1,1,1,$dda[1],$dda[2],$dda[0]) + 86400);
|
||||
$descr = array();
|
||||
if($r['tags'] != '') $descr[] = Lang::instance()->get('tags'). ": ". str_replace(',', ', ', $r['tags']);
|
||||
if($r['note'] != '') $descr[] = Lang::instance()->get('note'). ": ". $r['note'];
|
||||
if($descr) $a[] = utf8chunks("DESCRIPTION:". str_replace("\n", '\\n', implode("\n",$descr)));
|
||||
$a[] = "END:VEVENT\r\n";
|
||||
$s .= implode("\r\n", $a);
|
||||
}
|
||||
$s .= "END:VCALENDAR\r\n";
|
||||
header('Content-type: text/calendar; charset=utf-8');
|
||||
header('Content-disposition: attachment; filename=list_'.(int)$listData['id'].'.ics');
|
||||
print $s;
|
||||
}
|
||||
|
||||
function utf8chunks($text, $chunklen=75, $delimiter="\r\n\t")
|
||||
{
|
||||
if($text == '') return '';
|
||||
preg_match_all('/./u', $text, $m);
|
||||
$chars = $m[0];
|
||||
$a = array();
|
||||
$s = '';
|
||||
$max = count($chars);
|
||||
for($i=0; $i<$max; $i++)
|
||||
{
|
||||
$ch = $chars[$i];
|
||||
if(strlen($s) + strlen($ch) > $chunklen) { # line should be not more than $chunklen bytes
|
||||
$a[] = $s;
|
||||
$s = $ch;
|
||||
}
|
||||
else $s .= $ch;
|
||||
}
|
||||
if($s != '') $a[] = $s;
|
||||
return implode($delimiter, $a);
|
||||
if($text == '') return '';
|
||||
preg_match_all('/./u', $text, $m);
|
||||
$chars = $m[0];
|
||||
$a = array();
|
||||
$s = '';
|
||||
$max = count($chars);
|
||||
for($i=0; $i<$max; $i++)
|
||||
{
|
||||
$ch = $chars[$i];
|
||||
if(strlen($s) + strlen($ch) > $chunklen) { # line should be not more than $chunklen bytes
|
||||
$a[] = $s;
|
||||
$s = $ch;
|
||||
}
|
||||
else $s .= $ch;
|
||||
}
|
||||
if($s != '') $a[] = $s;
|
||||
return implode($delimiter, $a);
|
||||
}
|
||||
|
||||
?>
|
||||
174
src/feed.php
174
src/feed.php
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2011,2020-2021 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2011,2020-2021 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
$dontStartSession = 1;
|
||||
|
|
@ -16,10 +16,10 @@ $listId = (int)_get('list');
|
|||
|
||||
$listData = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$listId");
|
||||
if (need_auth() && (!$listData || !$listData['published'])) {
|
||||
die("Access denied!<br> List is not published.");
|
||||
die("Access denied!<br> List is not published.");
|
||||
}
|
||||
if(!$listData) {
|
||||
die("No list found");
|
||||
die("No list found");
|
||||
}
|
||||
|
||||
$data = array();
|
||||
|
|
@ -27,26 +27,26 @@ $feedType = _get('feed');
|
|||
|
||||
if($feedType == 'completed') {
|
||||
$listData['_feed_descr'] = $lang->get('feed_completed_tasks');
|
||||
fillData( $data, $listId, 'd_completed', 'AND compl=1' );
|
||||
fillData( $data, $listId, 'd_completed', 'AND compl=1' );
|
||||
}
|
||||
elseif($feedType == 'modified') {
|
||||
$listData['_feed_descr'] = $lang->get('feed_modified_tasks');
|
||||
fillData( $data, $listId, 'd_edited', '' );
|
||||
$listData['_feed_descr'] = $lang->get('feed_modified_tasks');
|
||||
fillData( $data, $listId, 'd_edited', '' );
|
||||
}
|
||||
elseif($feedType == 'current') {
|
||||
$listData['_feed_descr'] = $lang->get('feed_new_tasks');
|
||||
fillData( $data, $listId, 'd_created', 'AND compl=0' );
|
||||
$listData['_feed_descr'] = $lang->get('feed_new_tasks');
|
||||
fillData( $data, $listId, 'd_created', 'AND compl=0' );
|
||||
}
|
||||
elseif($feedType == 'status') {
|
||||
$listData['_feed_descr'] = $lang->get('feed_tasks');
|
||||
fillData( $data, $listId, 'd_created', '' );
|
||||
fillData( $data, $listId, 'd_edited', 'AND compl=0 AND d_edited > d_created' );
|
||||
fillData( $data, $listId, 'd_completed', 'AND compl=1' );
|
||||
$listData['_feed_descr'] = $lang->get('feed_tasks');
|
||||
fillData( $data, $listId, 'd_created', '' );
|
||||
fillData( $data, $listId, 'd_edited', 'AND compl=0 AND d_edited > d_created' );
|
||||
fillData( $data, $listId, 'd_completed', 'AND compl=1' );
|
||||
}
|
||||
else {
|
||||
$listData['_feed_descr'] = $lang->get('feed_new_tasks');
|
||||
$feedType = 'tasks';
|
||||
fillData( $data, $listId, 'd_created', '' );
|
||||
$listData['_feed_descr'] = $lang->get('feed_new_tasks');
|
||||
$feedType = 'tasks';
|
||||
fillData( $data, $listId, 'd_created', '' );
|
||||
}
|
||||
|
||||
$listData['_feed_title'] = sprintf($lang->get('feed_title'), $listData['name']) . ' - '. $listData['_feed_descr'];
|
||||
|
|
@ -59,86 +59,86 @@ printRss($data, $listData);
|
|||
|
||||
function fillData(&$data, $listId, $field, $sqlWhere )
|
||||
{
|
||||
$lang = Lang::instance();
|
||||
$db = DBConnection::instance();
|
||||
$q = $db->dq("SELECT * FROM {$db->prefix}todolist WHERE list_id=$listId $sqlWhere ORDER BY $field DESC LIMIT 100");
|
||||
while ($r = $q->fetchAssoc())
|
||||
{
|
||||
if ($r['prio'] > 0) {
|
||||
$r['prio'] = '+'.$r['prio'];
|
||||
}
|
||||
$a = array();
|
||||
$a[] = $lang->get('task'). ": ". $r['title'];
|
||||
if ($r['prio']) {
|
||||
$a[] = $lang->get('priority'). ": $r[prio]";
|
||||
}
|
||||
if ($r['duedate'] != '') {
|
||||
$ad = explode('-', $r['duedate']);
|
||||
$a[] = $lang->get('due'). ": ".formatDate3(Config::get('dateformat'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang);
|
||||
}
|
||||
if ($r['tags'] != '') {
|
||||
$a[] = $lang->get('tags'). ": ". str_replace(',', ', ', $r['tags']);
|
||||
}
|
||||
if ($r['compl']) {
|
||||
$a[] = $lang->get('taskdate_completed'). ": ". timestampToDatetime($r['d_completed']);
|
||||
}
|
||||
$r['title'] = htmlspecialchars( $r['title'] );
|
||||
$r['note'] = noteMarkup($r['note'], true);
|
||||
$r['_descr'] = implode("<br/>", htmlarray($a)). "<br/><br/>". $r['note'];
|
||||
$r['_title'] = "#". (int)$r['id']. ": ". $r['title'];
|
||||
$r['_d'] = gmdate('r', $r[$field]);
|
||||
$r['_field'] = $field;
|
||||
$data[] = $r;
|
||||
}
|
||||
$lang = Lang::instance();
|
||||
$db = DBConnection::instance();
|
||||
$q = $db->dq("SELECT * FROM {$db->prefix}todolist WHERE list_id=$listId $sqlWhere ORDER BY $field DESC LIMIT 100");
|
||||
while ($r = $q->fetchAssoc())
|
||||
{
|
||||
if ($r['prio'] > 0) {
|
||||
$r['prio'] = '+'.$r['prio'];
|
||||
}
|
||||
$a = array();
|
||||
$a[] = $lang->get('task'). ": ". $r['title'];
|
||||
if ($r['prio']) {
|
||||
$a[] = $lang->get('priority'). ": $r[prio]";
|
||||
}
|
||||
if ($r['duedate'] != '') {
|
||||
$ad = explode('-', $r['duedate']);
|
||||
$a[] = $lang->get('due'). ": ".formatDate3(Config::get('dateformat'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang);
|
||||
}
|
||||
if ($r['tags'] != '') {
|
||||
$a[] = $lang->get('tags'). ": ". str_replace(',', ', ', $r['tags']);
|
||||
}
|
||||
if ($r['compl']) {
|
||||
$a[] = $lang->get('taskdate_completed'). ": ". timestampToDatetime($r['d_completed']);
|
||||
}
|
||||
$r['title'] = htmlspecialchars( $r['title'] );
|
||||
$r['note'] = noteMarkup($r['note'], true);
|
||||
$r['_descr'] = implode("<br/>", htmlarray($a)). "<br/><br/>". $r['note'];
|
||||
$r['_title'] = "#". (int)$r['id']. ": ". $r['title'];
|
||||
$r['_d'] = gmdate('r', $r[$field]);
|
||||
$r['_field'] = $field;
|
||||
$data[] = $r;
|
||||
}
|
||||
}
|
||||
|
||||
function printRss($data, $listData)
|
||||
{
|
||||
$lang = Lang::instance();
|
||||
$link = get_mttinfo('url'). "?list=". (int)$listData['id'];
|
||||
$buildDate = gmdate('r');
|
||||
$lang = Lang::instance();
|
||||
$link = get_mttinfo('url'). "?list=". (int)$listData['id'];
|
||||
$buildDate = gmdate('r');
|
||||
|
||||
$s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".
|
||||
"<rss version=\"2.0\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n".
|
||||
"<channel>\n".
|
||||
"<title>$listData[_feed_title]</title>\n".
|
||||
"<link>$link</link>\n".
|
||||
"<atom:link href=\"${listData['_feed_link']}\" rel=\"self\" type=\"application/rss+xml\"/>\n".
|
||||
"<description>$listData[_feed_descr]</description>\n".
|
||||
"<lastBuildDate>$buildDate</lastBuildDate>\n\n";
|
||||
$s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".
|
||||
"<rss version=\"2.0\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n".
|
||||
"<channel>\n".
|
||||
"<title>$listData[_feed_title]</title>\n".
|
||||
"<link>$link</link>\n".
|
||||
"<atom:link href=\"${listData['_feed_link']}\" rel=\"self\" type=\"application/rss+xml\"/>\n".
|
||||
"<description>$listData[_feed_descr]</description>\n".
|
||||
"<lastBuildDate>$buildDate</lastBuildDate>\n\n";
|
||||
|
||||
foreach($data as $v)
|
||||
{
|
||||
$guid = $listData['_feed_type']. '-'. $listData['id']. '-'. $v['id']. '-'. $v[$v['_field']];
|
||||
$itemLink = $link. "&task=". (int)$v['id'];
|
||||
foreach($data as $v)
|
||||
{
|
||||
$guid = $listData['_feed_type']. '-'. $listData['id']. '-'. $v['id']. '-'. $v[$v['_field']];
|
||||
$itemLink = $link. "&task=". (int)$v['id'];
|
||||
|
||||
$status = '';
|
||||
if ( $listData['_feed_type'] == 'status' ) {
|
||||
if ( $v['_field'] == 'd_created' ) {
|
||||
$status = $lang->get('feed_status_new');
|
||||
}
|
||||
elseif ( $v['_field'] == 'd_edited' ) {
|
||||
$status = $lang->get('feed_status_updated');
|
||||
}
|
||||
elseif ( $v['_field'] == 'd_completed' ) {
|
||||
$status = $lang->get('feed_status_completed');
|
||||
}
|
||||
}
|
||||
if ( $status !='' ) $status = "[$status] ";
|
||||
$status = '';
|
||||
if ( $listData['_feed_type'] == 'status' ) {
|
||||
if ( $v['_field'] == 'd_created' ) {
|
||||
$status = $lang->get('feed_status_new');
|
||||
}
|
||||
elseif ( $v['_field'] == 'd_edited' ) {
|
||||
$status = $lang->get('feed_status_updated');
|
||||
}
|
||||
elseif ( $v['_field'] == 'd_completed' ) {
|
||||
$status = $lang->get('feed_status_completed');
|
||||
}
|
||||
}
|
||||
if ( $status !='' ) $status = "[$status] ";
|
||||
|
||||
$s .= "<item>\n".
|
||||
"<title>". $status. $v['title']. "</title>\n".
|
||||
"<link>". $itemLink. "</link>\n".
|
||||
"<pubDate>". $v['_d']. "</pubDate>\n".
|
||||
"<description><![CDATA[". $v['_descr']. "]]></description>\n".
|
||||
"<guid isPermaLink=\"false\">$guid</guid>\n".
|
||||
"</item>\n\n";
|
||||
}
|
||||
$s .= "<item>\n".
|
||||
"<title>". $status. $v['title']. "</title>\n".
|
||||
"<link>". $itemLink. "</link>\n".
|
||||
"<pubDate>". $v['_d']. "</pubDate>\n".
|
||||
"<description><![CDATA[". $v['_descr']. "]]></description>\n".
|
||||
"<guid isPermaLink=\"false\">$guid</guid>\n".
|
||||
"</item>\n\n";
|
||||
}
|
||||
|
||||
$s .= "</channel>\n</rss>";
|
||||
$s .= "</channel>\n</rss>";
|
||||
|
||||
header("Content-type: text/xml; charset=utf-8");
|
||||
print $s;
|
||||
header("Content-type: text/xml; charset=utf-8");
|
||||
print $s;
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -1,309 +1,309 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2021-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2021-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
class Config
|
||||
{
|
||||
/** @var bool */
|
||||
public static $noDatabase = false;
|
||||
/** @var bool */
|
||||
public static $noDatabase = false;
|
||||
|
||||
/** @var array[] */
|
||||
private static $dbparams = array(
|
||||
# Database type: sqlite or mysql
|
||||
'db.type' => array('default'=>'sqlite', 'type'=>'s'),
|
||||
/** @var array[] */
|
||||
private static $dbparams = array(
|
||||
# Database type: sqlite or mysql
|
||||
'db.type' => array('default'=>'sqlite', 'type'=>'s'),
|
||||
|
||||
# Specific database api
|
||||
'db.driver' => array('default'=>'', 'type'=>'s'),
|
||||
# Specific database api
|
||||
'db.driver' => array('default'=>'', 'type'=>'s'),
|
||||
|
||||
# Mysql connection settings
|
||||
'db.host' => array('default'=>'localhost', 'type'=>'s'),
|
||||
'db.user' => array('default'=>'mtt', 'type'=>'s'),
|
||||
'db.password' => array('default'=>'mtt', 'type'=>'s'),
|
||||
'db.name' => array('default'=>'mytinytodo', 'type'=>'s'),
|
||||
# Mysql connection settings
|
||||
'db.host' => array('default'=>'localhost', 'type'=>'s'),
|
||||
'db.user' => array('default'=>'mtt', 'type'=>'s'),
|
||||
'db.password' => array('default'=>'mtt', 'type'=>'s'),
|
||||
'db.name' => array('default'=>'mytinytodo', 'type'=>'s'),
|
||||
|
||||
# Prefix for table names
|
||||
'db.prefix' => array('default'=>'', 'type'=>'s')
|
||||
);
|
||||
# Prefix for table names
|
||||
'db.prefix' => array('default'=>'', 'type'=>'s')
|
||||
);
|
||||
|
||||
/** @var array[] */
|
||||
private static $convert = array(
|
||||
'mysql.host' => 'db.host',
|
||||
'mysql.user' => 'db.user',
|
||||
'mysql.password' => 'db.password',
|
||||
'mysql.db' => 'db.name',
|
||||
'db' => 'db.type',
|
||||
'prefix' => 'db.prefix'
|
||||
);
|
||||
/** @var array[] */
|
||||
private static $convert = array(
|
||||
'mysql.host' => 'db.host',
|
||||
'mysql.user' => 'db.user',
|
||||
'mysql.password' => 'db.password',
|
||||
'mysql.db' => 'db.name',
|
||||
'db' => 'db.type',
|
||||
'prefix' => 'db.prefix'
|
||||
);
|
||||
|
||||
/** @var array[] */
|
||||
public static $params = array(
|
||||
# These two parameters are used when mytinytodo index.php called not from installation directory
|
||||
# 'url' - URL where index.php is called from (ex.: http://site.com/todo.php)
|
||||
# 'mtt_url' - directory URL where mytinytodo is installed (with trailing slash) (ex.: http://site.com/lib/mytinytodo/)
|
||||
'url' => array('default'=>'', 'type'=>'s'),
|
||||
'mtt_url' => array('default'=>'', 'type'=>'s'),
|
||||
/** @var array[] */
|
||||
public static $params = array(
|
||||
# These two parameters are used when mytinytodo index.php called not from installation directory
|
||||
# 'url' - URL where index.php is called from (ex.: http://site.com/todo.php)
|
||||
# 'mtt_url' - directory URL where mytinytodo is installed (with trailing slash) (ex.: http://site.com/lib/mytinytodo/)
|
||||
'url' => array('default'=>'', 'type'=>'s'),
|
||||
'mtt_url' => array('default'=>'', 'type'=>'s'),
|
||||
|
||||
# Top title
|
||||
'title' => array('default'=>'', 'type'=>'s'),
|
||||
# Top title
|
||||
'title' => array('default'=>'', 'type'=>'s'),
|
||||
|
||||
# Language pack
|
||||
'lang' => array('default'=>'en', 'type'=>'s'),
|
||||
# Language pack
|
||||
'lang' => array('default'=>'en', 'type'=>'s'),
|
||||
|
||||
# Password to protect your tasks from modification,
|
||||
# leave empty that everyone could read/write todolist
|
||||
'password' => array('default'=>'', 'type'=>'s'),
|
||||
# Password to protect your tasks from modification,
|
||||
# leave empty that everyone could read/write todolist
|
||||
'password' => array('default'=>'', 'type'=>'s'),
|
||||
|
||||
# Smart Syntax enabled flag
|
||||
'smartsyntax' => array('default'=>1, 'type'=>'i'),
|
||||
# Smart Syntax enabled flag
|
||||
'smartsyntax' => array('default'=>1, 'type'=>'i'),
|
||||
|
||||
# Default Time zone
|
||||
'timezone' => array('default'=>'UTC', 'type'=>'s'),
|
||||
# Default Time zone
|
||||
'timezone' => array('default'=>'UTC', 'type'=>'s'),
|
||||
|
||||
# To disable auto adding selected tag set value to 0
|
||||
'autotag' => array('default'=>1, 'type'=>'i'),
|
||||
# To disable auto adding selected tag set value to 0
|
||||
'autotag' => array('default'=>1, 'type'=>'i'),
|
||||
|
||||
# duedate calendar format: 1 => y-m-d (default), 2 => m/d/y, 3 => d.m.y
|
||||
'duedateformat' => array('default'=>1, 'type'=>'i'),
|
||||
# duedate calendar format: 1 => y-m-d (default), 2 => m/d/y, 3 => d.m.y
|
||||
'duedateformat' => array('default'=>1, 'type'=>'i'),
|
||||
|
||||
# First day of week: 0-Sunday, 1-Monday, 2-Tuesday, .. 6-Saturday
|
||||
'firstdayofweek' => array('default'=>1, 'type'=>'i', 'options'=>array(0,1,2,3,4,5,6)),
|
||||
# First day of week: 0-Sunday, 1-Monday, 2-Tuesday, .. 6-Saturday
|
||||
'firstdayofweek' => array('default'=>1, 'type'=>'i', 'options'=>array(0,1,2,3,4,5,6)),
|
||||
|
||||
# Date/time formats
|
||||
'clock' => array('default'=>24, 'type'=>'i', 'options'=>array(12,24)),
|
||||
'dateformat' => array('default'=>'j M Y', 'type'=>'s'),
|
||||
'dateformat2' => array('default'=>'n/j/y', 'type'=>'s'),
|
||||
'dateformatshort' => array('default'=>'j M', 'type'=>'s'),
|
||||
'template' => array('default'=>'default', 'type'=>'s'),
|
||||
# Date/time formats
|
||||
'clock' => array('default'=>24, 'type'=>'i', 'options'=>array(12,24)),
|
||||
'dateformat' => array('default'=>'j M Y', 'type'=>'s'),
|
||||
'dateformat2' => array('default'=>'n/j/y', 'type'=>'s'),
|
||||
'dateformatshort' => array('default'=>'j M', 'type'=>'s'),
|
||||
'template' => array('default'=>'default', 'type'=>'s'),
|
||||
|
||||
# Show task date in list
|
||||
'showdate' => array('default'=>0, 'type'=>'i'),
|
||||
# Show task date in list
|
||||
'showdate' => array('default'=>0, 'type'=>'i'),
|
||||
|
||||
# Use Markdown syntax for notes. Set to 'v1' to use old v1.6 syntax.
|
||||
'markup' => array('default'=>'markdown', 'type'=>'s'),
|
||||
);
|
||||
# Use Markdown syntax for notes. Set to 'v1' to use old v1.6 syntax.
|
||||
'markup' => array('default'=>'markdown', 'type'=>'s'),
|
||||
);
|
||||
|
||||
/** @var mixed[] */
|
||||
private static $config = array();
|
||||
/** @var mixed[] */
|
||||
private static $config = array();
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed[] $config
|
||||
* @return void
|
||||
*/
|
||||
public static function loadConfigV14(array $config)
|
||||
{
|
||||
foreach ($config as $key => $val) {
|
||||
if (isset(self::$convert[$key])) {
|
||||
$key = self::$convert[$key];
|
||||
}
|
||||
elseif ($key == 'mysqli' && (int)$val != 0) {
|
||||
$key = 'db.driver';
|
||||
$val = 'mysqli';
|
||||
}
|
||||
elseif ($key == 'password' && $val != '') {
|
||||
$val = passwordHash($val); // in v1.7 password is hashed
|
||||
}
|
||||
// if (!isset(self::$dbparams[$key])) {
|
||||
// throw new Exception("Unknown key: $key");
|
||||
// }
|
||||
self::$config[$key] = $val;
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param mixed[] $config
|
||||
* @return void
|
||||
*/
|
||||
public static function loadConfigV14(array $config)
|
||||
{
|
||||
foreach ($config as $key => $val) {
|
||||
if (isset(self::$convert[$key])) {
|
||||
$key = self::$convert[$key];
|
||||
}
|
||||
elseif ($key == 'mysqli' && (int)$val != 0) {
|
||||
$key = 'db.driver';
|
||||
$val = 'mysqli';
|
||||
}
|
||||
elseif ($key == 'password' && $val != '') {
|
||||
$val = passwordHash($val); // in v1.7 password is hashed
|
||||
}
|
||||
// if (!isset(self::$dbparams[$key])) {
|
||||
// throw new Exception("Unknown key: $key");
|
||||
// }
|
||||
self::$config[$key] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function load()
|
||||
{
|
||||
if (self::$noDatabase) {
|
||||
return;
|
||||
}
|
||||
$j = self::requestDefaultDomain();
|
||||
foreach ($j as $key=>$val) {
|
||||
// Ignore params for database config
|
||||
if ( !isset(self::$dbparams[$key]) ) {
|
||||
self::$config[$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function load()
|
||||
{
|
||||
if (self::$noDatabase) {
|
||||
return;
|
||||
}
|
||||
$j = self::requestDefaultDomain();
|
||||
foreach ($j as $key=>$val) {
|
||||
// Ignore params for database config
|
||||
if ( !isset(self::$dbparams[$key]) ) {
|
||||
self::$config[$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get($key)
|
||||
{
|
||||
if (isset(self::$config[$key])) return self::$config[$key];
|
||||
elseif (isset(self::$params[$key])) return self::$params[$key]['default'];
|
||||
elseif (isset(self::$dbparams[$key])) return self::$dbparams[$key]['default'];
|
||||
else return null;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get($key)
|
||||
{
|
||||
if (isset(self::$config[$key])) return self::$config[$key];
|
||||
elseif (isset(self::$params[$key])) return self::$params[$key]['default'];
|
||||
elseif (isset(self::$dbparams[$key])) return self::$dbparams[$key]['default'];
|
||||
else return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getUrl($key)
|
||||
{
|
||||
$url = '';
|
||||
if ( isset(self::$config[$key]) ) $url = self::$config[$key];
|
||||
else if( isset(self::$params[$key]) ) $url = self::$params[$key]['default'];
|
||||
else return null;
|
||||
return str_replace( ["\r","\n"], '', $url );
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getUrl($key)
|
||||
{
|
||||
$url = '';
|
||||
if ( isset(self::$config[$key]) ) $url = self::$config[$key];
|
||||
else if( isset(self::$params[$key]) ) $url = self::$params[$key]['default'];
|
||||
else return null;
|
||||
return str_replace( ["\r","\n"], '', $url );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function set($key, $value)
|
||||
{
|
||||
if ($key == "db.prefix" && $value != "" && !preg_match("/^[a-zA-Z0-9_]+$/", $value)) {
|
||||
throw new Exception("Incorrect table prefix. Can contain only latin letters, digits and underscore character.");
|
||||
}
|
||||
self::$config[$key] = $value;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function set($key, $value)
|
||||
{
|
||||
if ($key == "db.prefix" && $value != "" && !preg_match("/^[a-zA-Z0-9_]+$/", $value)) {
|
||||
throw new Exception("Incorrect table prefix. Can contain only latin letters, digits and underscore character.");
|
||||
}
|
||||
self::$config[$key] = $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function save()
|
||||
{
|
||||
$j = array();
|
||||
foreach (self::$params as $param => $v)
|
||||
{
|
||||
if ( !isset(self::$config[$param]) ) $val = $v['default'];
|
||||
elseif ( isset($v['options']) && !in_array(self::$config[$param], $v['options'])) $val = $v['default'];
|
||||
else $val = self::$config[$param];
|
||||
/**
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function save()
|
||||
{
|
||||
$j = array();
|
||||
foreach (self::$params as $param => $v)
|
||||
{
|
||||
if ( !isset(self::$config[$param]) ) $val = $v['default'];
|
||||
elseif ( isset($v['options']) && !in_array(self::$config[$param], $v['options'])) $val = $v['default'];
|
||||
else $val = self::$config[$param];
|
||||
|
||||
if ($v['type']=='i') $val = (int)$val;
|
||||
else $val = strval($val);
|
||||
if ($v['type']=='i') $val = (int)$val;
|
||||
else $val = strval($val);
|
||||
|
||||
$j[$param] = $val;
|
||||
}
|
||||
self::saveDomain('config.json', $j);
|
||||
}
|
||||
$j[$param] = $val;
|
||||
}
|
||||
self::saveDomain('config.json', $j);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function requestDomain(string $key)
|
||||
{
|
||||
$db = DBConnection::instance();
|
||||
$json = $db->sq("SELECT param_value FROM {$db->prefix}settings WHERE param_key = ?", array($key));
|
||||
if (!$json) return array();
|
||||
$j = json_decode($json, true);
|
||||
return $j;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function requestDomain(string $key)
|
||||
{
|
||||
$db = DBConnection::instance();
|
||||
$json = $db->sq("SELECT param_value FROM {$db->prefix}settings WHERE param_key = ?", array($key));
|
||||
if (!$json) return array();
|
||||
$j = json_decode($json, true);
|
||||
return $j;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function requestDefaultDomain()
|
||||
{
|
||||
return self::requestDomain('config.json');
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function requestDefaultDomain()
|
||||
{
|
||||
return self::requestDomain('config.json');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $array
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function saveDomain($key, $array)
|
||||
{
|
||||
$json = json_encode($array, JSON_PRETTY_PRINT);
|
||||
$db = DBConnection::instance();
|
||||
$keyExists = $db->sq("SELECT COUNT(param_key) FROM {$db->prefix}settings WHERE param_key = ?", array($key) );
|
||||
if ($keyExists) {
|
||||
$db->ex("UPDATE {$db->prefix}settings SET param_value = ? WHERE param_key = ?", array($json,$key) );
|
||||
}
|
||||
else {
|
||||
$db->ex("INSERT INTO {$db->prefix}settings (param_key,param_value) VALUES (?,?)", array($key,$json) );
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $array
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function saveDomain($key, $array)
|
||||
{
|
||||
$json = json_encode($array, JSON_PRETTY_PRINT);
|
||||
$db = DBConnection::instance();
|
||||
$keyExists = $db->sq("SELECT COUNT(param_key) FROM {$db->prefix}settings WHERE param_key = ?", array($key) );
|
||||
if ($keyExists) {
|
||||
$db->ex("UPDATE {$db->prefix}settings SET param_value = ? WHERE param_key = ?", array($json,$key) );
|
||||
}
|
||||
else {
|
||||
$db->ex("INSERT INTO {$db->prefix}settings (param_key,param_value) VALUES (?,?)", array($key,$json) );
|
||||
}
|
||||
}
|
||||
|
||||
public static function defineDbConstants()
|
||||
{
|
||||
define("MTT_DB_TYPE", self::get('db.type'));
|
||||
define("MTT_DB_HOST", self::get('db.host'));
|
||||
define("MTT_DB_USER", self::get('db.user'));
|
||||
define("MTT_DB_PASSWORD", self::get('db.password'));
|
||||
define("MTT_DB_NAME", self::get('db.name'));
|
||||
define("MTT_DB_PREFIX", self::get('db.prefix'));
|
||||
if ( self::get('db.driver') != '' ) {
|
||||
define("MTT_DB_DRIVER", self::get('db.driver'));
|
||||
}
|
||||
}
|
||||
public static function defineDbConstants()
|
||||
{
|
||||
define("MTT_DB_TYPE", self::get('db.type'));
|
||||
define("MTT_DB_HOST", self::get('db.host'));
|
||||
define("MTT_DB_USER", self::get('db.user'));
|
||||
define("MTT_DB_PASSWORD", self::get('db.password'));
|
||||
define("MTT_DB_NAME", self::get('db.name'));
|
||||
define("MTT_DB_PREFIX", self::get('db.prefix'));
|
||||
if ( self::get('db.driver') != '' ) {
|
||||
define("MTT_DB_DRIVER", self::get('db.driver'));
|
||||
}
|
||||
}
|
||||
|
||||
public static function dbConfigAsFileContents(): string
|
||||
{
|
||||
$a = array();
|
||||
$a[] = "<?php\n";
|
||||
$a[] = "// myTinyTodo Database connection configuration\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_TYPE", self::get('db.type')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_HOST", self::get('db.host')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_USER", self::get('db.user')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_PASSWORD", self::get('db.password')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_NAME", self::get('db.name')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_PREFIX", self::get('db.prefix')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_DRIVER", self::get('db.driver')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_SALT", defined('MTT_SALT') ? MTT_SALT : generateUUID()) . "\n";
|
||||
return implode("\n", $a);
|
||||
}
|
||||
public static function dbConfigAsFileContents(): string
|
||||
{
|
||||
$a = array();
|
||||
$a[] = "<?php\n";
|
||||
$a[] = "// myTinyTodo Database connection configuration\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_TYPE", self::get('db.type')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_HOST", self::get('db.host')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_USER", self::get('db.user')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_PASSWORD", self::get('db.password')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_NAME", self::get('db.name')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_PREFIX", self::get('db.prefix')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_DB_DRIVER", self::get('db.driver')) . "\n";
|
||||
$a[] = self::prepareDbDefine("MTT_SALT", defined('MTT_SALT') ? MTT_SALT : generateUUID()) . "\n";
|
||||
return implode("\n", $a);
|
||||
}
|
||||
|
||||
private static function prepareDbDefine(string $key, string $value): string
|
||||
{
|
||||
if (!preg_match("/^[a-zA-Z0-9_]+$/", $key)) {
|
||||
throw new Exception("Unexpected constant name: ". $key);
|
||||
}
|
||||
if (preg_match('~\R~', $value)) {
|
||||
throw new Exception("Unexpected constant value: ". $value);
|
||||
}
|
||||
return "define(\"$key\", \"". str_replace(
|
||||
array("\\", "'", "\""),
|
||||
array("\\\\", "\\'", "\\\""),
|
||||
$value )
|
||||
. "\");";
|
||||
}
|
||||
private static function prepareDbDefine(string $key, string $value): string
|
||||
{
|
||||
if (!preg_match("/^[a-zA-Z0-9_]+$/", $key)) {
|
||||
throw new Exception("Unexpected constant name: ". $key);
|
||||
}
|
||||
if (preg_match('~\R~', $value)) {
|
||||
throw new Exception("Unexpected constant value: ". $value);
|
||||
}
|
||||
return "define(\"$key\", \"". str_replace(
|
||||
array("\\", "'", "\""),
|
||||
array("\\\\", "\\'", "\\\""),
|
||||
$value )
|
||||
. "\");";
|
||||
}
|
||||
|
||||
public static function saveDbConfig()
|
||||
{
|
||||
$contents = self::dbConfigAsFileContents();
|
||||
$f = fopen(MTTPATH. 'config.php', 'w');
|
||||
if ($f === false) throw new Exception("Error while saving config file");
|
||||
fwrite($f, $contents);
|
||||
fclose($f);
|
||||
public static function saveDbConfig()
|
||||
{
|
||||
$contents = self::dbConfigAsFileContents();
|
||||
$f = fopen(MTTPATH. 'config.php', 'w');
|
||||
if ($f === false) throw new Exception("Error while saving config file");
|
||||
fwrite($f, $contents);
|
||||
fclose($f);
|
||||
|
||||
//Reset Zend OPcache
|
||||
//opcache_get_status() sometimes crashes
|
||||
if (function_exists("opcache_invalidate") && 0 != (int)opcache_get_configuration()["directives"]["opcache.enable"]) {
|
||||
opcache_invalidate(MTTPATH. 'config.php', true);
|
||||
}
|
||||
}
|
||||
//Reset Zend OPcache
|
||||
//opcache_get_status() sometimes crashes
|
||||
if (function_exists("opcache_invalidate") && 0 != (int)opcache_get_configuration()["directives"]["opcache.enable"]) {
|
||||
opcache_invalidate(MTTPATH. 'config.php', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -1,192 +1,192 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------- //
|
||||
class DatabaseResult_Mysql extends DatabaseResult_Abstract
|
||||
{
|
||||
/** @var PDOStatement */
|
||||
private $q;
|
||||
/** @var PDOStatement */
|
||||
private $q;
|
||||
|
||||
private $affected;
|
||||
private $affected;
|
||||
|
||||
function __construct($dbh, $query, $resultless = 0)
|
||||
{
|
||||
// use with DELETE, INSERT, UPDATE
|
||||
if ($resultless)
|
||||
{
|
||||
$this->affected = $dbh->exec($query); //throws PDOException
|
||||
}
|
||||
// SELECT
|
||||
else
|
||||
{
|
||||
$this->q = $dbh->query($query); //throws PDOException
|
||||
$this->affected = $this->q->rowCount();
|
||||
}
|
||||
}
|
||||
function __construct($dbh, $query, $resultless = 0)
|
||||
{
|
||||
// use with DELETE, INSERT, UPDATE
|
||||
if ($resultless)
|
||||
{
|
||||
$this->affected = $dbh->exec($query); //throws PDOException
|
||||
}
|
||||
// SELECT
|
||||
else
|
||||
{
|
||||
$this->q = $dbh->query($query); //throws PDOException
|
||||
$this->affected = $this->q->rowCount();
|
||||
}
|
||||
}
|
||||
|
||||
function fetchRow()
|
||||
{
|
||||
return $this->q->fetch(PDO::FETCH_NUM);
|
||||
}
|
||||
function fetchRow()
|
||||
{
|
||||
return $this->q->fetch(PDO::FETCH_NUM);
|
||||
}
|
||||
|
||||
function fetchAssoc()
|
||||
{
|
||||
return $this->q->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
function fetchAssoc()
|
||||
{
|
||||
return $this->q->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
function rowsAffected()
|
||||
{
|
||||
return $this->affected;
|
||||
}
|
||||
function rowsAffected()
|
||||
{
|
||||
return $this->affected;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------- //
|
||||
class Database_Mysql extends Database_Abstract
|
||||
{
|
||||
/** @var PDO */
|
||||
private $dbh;
|
||||
/** @var PDO */
|
||||
private $dbh;
|
||||
|
||||
private $affected = null;
|
||||
var $lastQuery;
|
||||
private $dbname;
|
||||
var $prefix = '';
|
||||
private $affected = null;
|
||||
var $lastQuery;
|
||||
private $dbname;
|
||||
var $prefix = '';
|
||||
|
||||
function __construct()
|
||||
{
|
||||
}
|
||||
function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
function connect($params)
|
||||
{
|
||||
$host = $params['host'];
|
||||
$user = $params['user'];
|
||||
$pass = $params['password'];
|
||||
$db = $params['db'];
|
||||
$options = array(
|
||||
PDO::MYSQL_ATTR_FOUND_ROWS => true,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
);
|
||||
$this->dbname = $db;
|
||||
function connect($params)
|
||||
{
|
||||
$host = $params['host'];
|
||||
$user = $params['user'];
|
||||
$pass = $params['password'];
|
||||
$db = $params['db'];
|
||||
$options = array(
|
||||
PDO::MYSQL_ATTR_FOUND_ROWS => true,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
);
|
||||
$this->dbname = $db;
|
||||
|
||||
$this->dbh = new PDO("mysql:host=$host;dbname=$db", $user, $pass, $options);
|
||||
return true;
|
||||
}
|
||||
$this->dbh = new PDO("mysql:host=$host;dbname=$db", $user, $pass, $options);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Returns single row of SELECT query as indexed array (FETCH_NUM).
|
||||
Returns single field value if resulting array has only one field.
|
||||
*/
|
||||
function sq($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
/*
|
||||
Returns single row of SELECT query as indexed array (FETCH_NUM).
|
||||
Returns single field value if resulting array has only one field.
|
||||
*/
|
||||
function sq($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
|
||||
$res = $q->fetchRow();
|
||||
if ($res === false) return NULL;
|
||||
$res = $q->fetchRow();
|
||||
if ($res === false) return NULL;
|
||||
|
||||
if (sizeof($res) > 1) return $res;
|
||||
else return $res[0];
|
||||
}
|
||||
if (sizeof($res) > 1) return $res;
|
||||
else return $res[0];
|
||||
}
|
||||
|
||||
/*
|
||||
Returns single row of SELECT query as dictionary array (FETCH_ASSOC).
|
||||
Returns single field value if resulting array has only one field.
|
||||
*/
|
||||
function sqa($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
/*
|
||||
Returns single row of SELECT query as dictionary array (FETCH_ASSOC).
|
||||
Returns single field value if resulting array has only one field.
|
||||
*/
|
||||
function sqa($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
|
||||
$res = $q->fetchAssoc();
|
||||
if ($res === false) return NULL;
|
||||
$res = $q->fetchAssoc();
|
||||
if ($res === false) return NULL;
|
||||
|
||||
if (sizeof($res) > 1) return $res;
|
||||
else return $res[0];
|
||||
}
|
||||
if (sizeof($res) > 1) return $res;
|
||||
else return $res[0];
|
||||
}
|
||||
|
||||
function dq($query, $p = NULL) : DatabaseResult_Abstract
|
||||
{
|
||||
return $this->_dq($query, $p);
|
||||
}
|
||||
function dq($query, $p = NULL) : DatabaseResult_Abstract
|
||||
{
|
||||
return $this->_dq($query, $p);
|
||||
}
|
||||
|
||||
/*
|
||||
for resultless queries like INSERT,UPDATE,DELETE
|
||||
*/
|
||||
function ex($query, $p = NULL)
|
||||
{
|
||||
$dbr = $this->_dq($query, $p, true);
|
||||
return $this->affected();
|
||||
}
|
||||
/*
|
||||
for resultless queries like INSERT,UPDATE,DELETE
|
||||
*/
|
||||
function ex($query, $p = NULL)
|
||||
{
|
||||
$dbr = $this->_dq($query, $p, true);
|
||||
return $this->affected();
|
||||
}
|
||||
|
||||
private function _dq($query, $p = NULL, $resultless = 0) : DatabaseResult_Abstract
|
||||
{
|
||||
if (!isset($p)) $p = array();
|
||||
elseif (!is_array($p)) $p = array($p);
|
||||
private function _dq($query, $p = NULL, $resultless = 0) : DatabaseResult_Abstract
|
||||
{
|
||||
if (!isset($p)) $p = array();
|
||||
elseif (!is_array($p)) $p = array($p);
|
||||
|
||||
$m = explode('?', $query);
|
||||
$m = explode('?', $query);
|
||||
|
||||
if (sizeof($p) > 0)
|
||||
{
|
||||
if (sizeof($m) < sizeof($p)+1) {
|
||||
throw new Exception("params to set MORE than query params");
|
||||
}
|
||||
if (sizeof($m) > sizeof($p)+1) {
|
||||
throw new Exception("params to set LESS than query params");
|
||||
}
|
||||
$query = "";
|
||||
for ($i=0; $i<sizeof($m)-1; $i++) {
|
||||
$query .= $m[$i]. (is_null($p[$i]) ? 'NULL' : $this->quote($p[$i]));
|
||||
}
|
||||
$query .= $m[$i];
|
||||
}
|
||||
$this->lastQuery = $query;
|
||||
$dbr = new DatabaseResult_Mysql($this->dbh, $query, $resultless);
|
||||
$this->affected = $dbr->rowsAffected();
|
||||
return $dbr;
|
||||
}
|
||||
if (sizeof($p) > 0)
|
||||
{
|
||||
if (sizeof($m) < sizeof($p)+1) {
|
||||
throw new Exception("params to set MORE than query params");
|
||||
}
|
||||
if (sizeof($m) > sizeof($p)+1) {
|
||||
throw new Exception("params to set LESS than query params");
|
||||
}
|
||||
$query = "";
|
||||
for ($i=0; $i<sizeof($m)-1; $i++) {
|
||||
$query .= $m[$i]. (is_null($p[$i]) ? 'NULL' : $this->quote($p[$i]));
|
||||
}
|
||||
$query .= $m[$i];
|
||||
}
|
||||
$this->lastQuery = $query;
|
||||
$dbr = new DatabaseResult_Mysql($this->dbh, $query, $resultless);
|
||||
$this->affected = $dbr->rowsAffected();
|
||||
return $dbr;
|
||||
}
|
||||
|
||||
function affected()
|
||||
{
|
||||
return $this->affected;
|
||||
}
|
||||
function affected()
|
||||
{
|
||||
return $this->affected;
|
||||
}
|
||||
|
||||
function quote($s)
|
||||
{
|
||||
return '\''. addslashes($s). '\'';
|
||||
}
|
||||
function quote($s)
|
||||
{
|
||||
return '\''. addslashes($s). '\'';
|
||||
}
|
||||
|
||||
function quoteForLike($format, $s)
|
||||
{
|
||||
$s = str_replace(array('%','_'), array('\%','\_'), addslashes($s));
|
||||
return '\''. sprintf($format, $s). '\'';
|
||||
}
|
||||
function quoteForLike($format, $s)
|
||||
{
|
||||
$s = str_replace(array('%','_'), array('\%','\_'), addslashes($s));
|
||||
return '\''. sprintf($format, $s). '\'';
|
||||
}
|
||||
|
||||
function lastInsertId($name = null)
|
||||
{
|
||||
return $this->dbh->lastInsertId();
|
||||
}
|
||||
function lastInsertId($name = null)
|
||||
{
|
||||
return $this->dbh->lastInsertId();
|
||||
}
|
||||
|
||||
function tableExists($table)
|
||||
{
|
||||
$r = $this->sq("SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?",
|
||||
array($this->dbname, $table) );
|
||||
if ($r === false || $r === null) return false;
|
||||
return true;
|
||||
}
|
||||
function tableExists($table)
|
||||
{
|
||||
$r = $this->sq("SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?",
|
||||
array($this->dbname, $table) );
|
||||
if ($r === false || $r === null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function tableFieldExists($table, $field): bool
|
||||
{
|
||||
$table = str_replace('`', '\\`', addslashes($table));
|
||||
$q = $this->dq("DESCRIBE `$table`");
|
||||
while ($r = $q->fetchRow()) {
|
||||
if ($r[0] == $field) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function tableFieldExists($table, $field): bool
|
||||
{
|
||||
$table = str_replace('`', '\\`', addslashes($table));
|
||||
$q = $this->dq("DESCRIBE `$table`");
|
||||
while ($r = $q->fetchRow()) {
|
||||
if ($r[0] == $field) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -1,157 +1,157 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2019-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2019-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------- //
|
||||
class DatabaseResult_Mysql extends DatabaseResult_Abstract
|
||||
{
|
||||
/** @var mysqli_result */
|
||||
private $q;
|
||||
/** @var mysqli_result */
|
||||
private $q;
|
||||
|
||||
function __construct(mysqli $dbh, $query, $resultless = 0)
|
||||
{
|
||||
$this->q = $dbh->query($query); //throws mysqli_sql_exception
|
||||
}
|
||||
function __construct(mysqli $dbh, $query, $resultless = 0)
|
||||
{
|
||||
$this->q = $dbh->query($query); //throws mysqli_sql_exception
|
||||
}
|
||||
|
||||
function fetchRow()
|
||||
{
|
||||
return $this->q->fetch_row();
|
||||
}
|
||||
function fetchRow()
|
||||
{
|
||||
return $this->q->fetch_row();
|
||||
}
|
||||
|
||||
function fetchAssoc()
|
||||
{
|
||||
return $this->q->fetch_assoc();
|
||||
}
|
||||
function fetchAssoc()
|
||||
{
|
||||
return $this->q->fetch_assoc();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------- //
|
||||
class Database_Mysql extends Database_Abstract
|
||||
{
|
||||
/** @var mysqli */
|
||||
private $dbh;
|
||||
/** @var mysqli */
|
||||
private $dbh;
|
||||
|
||||
private $dbname;
|
||||
var $prefix = '';
|
||||
private $dbname;
|
||||
var $prefix = '';
|
||||
|
||||
function __construct()
|
||||
{
|
||||
// enable throwing exceptions
|
||||
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
|
||||
}
|
||||
function __construct()
|
||||
{
|
||||
// enable throwing exceptions
|
||||
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
|
||||
}
|
||||
|
||||
function connect($params)
|
||||
{
|
||||
$host = $params['host'];
|
||||
$user = $params['user'];
|
||||
$pass = $params['password'];
|
||||
$db = $params['db'];
|
||||
$this->dbname = $db;
|
||||
$this->dbh = new mysqli($host, $user, $pass, $db); //throws mysqli_sql_exception
|
||||
return true;
|
||||
}
|
||||
function connect($params)
|
||||
{
|
||||
$host = $params['host'];
|
||||
$user = $params['user'];
|
||||
$pass = $params['password'];
|
||||
$db = $params['db'];
|
||||
$this->dbname = $db;
|
||||
$this->dbh = new mysqli($host, $user, $pass, $db); //throws mysqli_sql_exception
|
||||
return true;
|
||||
}
|
||||
|
||||
function lastInsertId($name = null)
|
||||
{
|
||||
return $this->dbh->insert_id;
|
||||
}
|
||||
function lastInsertId($name = null)
|
||||
{
|
||||
return $this->dbh->insert_id;
|
||||
}
|
||||
|
||||
function sq($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
function sq($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
|
||||
$res = $q->fetchRow();
|
||||
if ($res === false || $res === null) return NULL;
|
||||
$res = $q->fetchRow();
|
||||
if ($res === false || $res === null) return NULL;
|
||||
|
||||
if (sizeof($res) > 1) return $res;
|
||||
else return $res[0];
|
||||
}
|
||||
if (sizeof($res) > 1) return $res;
|
||||
else return $res[0];
|
||||
}
|
||||
|
||||
function sqa($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
function sqa($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
|
||||
$res = $q->fetchAssoc();
|
||||
if ($res === false || $res === null) return NULL;
|
||||
$res = $q->fetchAssoc();
|
||||
if ($res === false || $res === null) return NULL;
|
||||
|
||||
return $res;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
function dq($query, $p = NULL) : DatabaseResult_Abstract
|
||||
{
|
||||
return $this->_dq($query, $p);
|
||||
}
|
||||
function dq($query, $p = NULL) : DatabaseResult_Abstract
|
||||
{
|
||||
return $this->_dq($query, $p);
|
||||
}
|
||||
|
||||
/*
|
||||
for resultless queries like INSERT,UPDATE,DELETE
|
||||
*/
|
||||
function ex($query, $p = NULL)
|
||||
{
|
||||
$dbr = $this->_dq($query, $p, 1);
|
||||
return $this->affected();
|
||||
}
|
||||
/*
|
||||
for resultless queries like INSERT,UPDATE,DELETE
|
||||
*/
|
||||
function ex($query, $p = NULL)
|
||||
{
|
||||
$dbr = $this->_dq($query, $p, 1);
|
||||
return $this->affected();
|
||||
}
|
||||
|
||||
private function _dq($query, $p = NULL, $resultless = 0) : DatabaseResult_Abstract
|
||||
{
|
||||
if (!isset($p)) $p = array();
|
||||
elseif (!is_array($p)) $p = array($p);
|
||||
private function _dq($query, $p = NULL, $resultless = 0) : DatabaseResult_Abstract
|
||||
{
|
||||
if (!isset($p)) $p = array();
|
||||
elseif (!is_array($p)) $p = array($p);
|
||||
|
||||
$m = explode('?', $query);
|
||||
$m = explode('?', $query);
|
||||
|
||||
if (sizeof($p) > 0)
|
||||
{
|
||||
if (sizeof($m) < sizeof($p)+1) {
|
||||
throw new Exception("params to set MORE than query params");
|
||||
}
|
||||
if (sizeof($m) > sizeof($p)+1) {
|
||||
throw new Exception("params to set LESS than query params");
|
||||
}
|
||||
$query = "";
|
||||
for ($i=0; $i < sizeof($m)-1; $i++) {
|
||||
$query .= $m[$i]. (is_null($p[$i]) ? 'NULL' : $this->quote($p[$i]));
|
||||
}
|
||||
$query .= $m[$i];
|
||||
}
|
||||
$this->lastQuery = $query;
|
||||
return new DatabaseResult_Mysql($this->dbh, $query, $resultless);
|
||||
}
|
||||
if (sizeof($p) > 0)
|
||||
{
|
||||
if (sizeof($m) < sizeof($p)+1) {
|
||||
throw new Exception("params to set MORE than query params");
|
||||
}
|
||||
if (sizeof($m) > sizeof($p)+1) {
|
||||
throw new Exception("params to set LESS than query params");
|
||||
}
|
||||
$query = "";
|
||||
for ($i=0; $i < sizeof($m)-1; $i++) {
|
||||
$query .= $m[$i]. (is_null($p[$i]) ? 'NULL' : $this->quote($p[$i]));
|
||||
}
|
||||
$query .= $m[$i];
|
||||
}
|
||||
$this->lastQuery = $query;
|
||||
return new DatabaseResult_Mysql($this->dbh, $query, $resultless);
|
||||
}
|
||||
|
||||
function affected()
|
||||
{
|
||||
return $this->dbh->affected_rows;
|
||||
}
|
||||
function affected()
|
||||
{
|
||||
return $this->dbh->affected_rows;
|
||||
}
|
||||
|
||||
function quote($s)
|
||||
{
|
||||
return '\''. addslashes($s). '\'';
|
||||
}
|
||||
function quote($s)
|
||||
{
|
||||
return '\''. addslashes($s). '\'';
|
||||
}
|
||||
|
||||
function quoteForLike($format, $s)
|
||||
{
|
||||
$s = str_replace(array('%','_'), array('\%','\_'), addslashes($s));
|
||||
return '\''. sprintf($format, $s). '\'';
|
||||
}
|
||||
function quoteForLike($format, $s)
|
||||
{
|
||||
$s = str_replace(array('%','_'), array('\%','\_'), addslashes($s));
|
||||
return '\''. sprintf($format, $s). '\'';
|
||||
}
|
||||
|
||||
function tableExists($table)
|
||||
{
|
||||
$r = $this->sq("SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?",
|
||||
array($this->dbname, $table) );
|
||||
if ($r === false || $r === null) return false;
|
||||
return true;
|
||||
}
|
||||
function tableExists($table)
|
||||
{
|
||||
$r = $this->sq("SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?",
|
||||
array($this->dbname, $table) );
|
||||
if ($r === false || $r === null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function tableFieldExists($table, $field): bool
|
||||
{
|
||||
$table = str_replace('`', '\\`', addslashes($table));
|
||||
$q = $this->dq("DESCRIBE `$table`");
|
||||
while ($r = $q->fetchRow()) {
|
||||
if ($r[0] == $field) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function tableFieldExists($table, $field): bool
|
||||
{
|
||||
$table = str_replace('`', '\\`', addslashes($table));
|
||||
$q = $this->dq("DESCRIBE `$table`");
|
||||
while ($r = $q->fetchRow()) {
|
||||
if ($r[0] == $field) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -1,185 +1,185 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009,2019-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009,2019-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
class DatabaseResult_Sqlite3 extends DatabaseResult_Abstract
|
||||
{
|
||||
/** @var PDOStatement */
|
||||
private $q;
|
||||
/** @var PDOStatement */
|
||||
private $q;
|
||||
|
||||
private $affected;
|
||||
private $affected;
|
||||
|
||||
function __construct($dbh, $query, $resultless = 0)
|
||||
{
|
||||
// use with DELETE, INSERT, UPDATE
|
||||
if ($resultless)
|
||||
{
|
||||
$this->affected = $dbh->exec($query); //throws PDOException
|
||||
}
|
||||
// SELECT
|
||||
else
|
||||
{
|
||||
$this->q = $dbh->query($query); //throws PDOException
|
||||
$this->affected = $this->q->rowCount();
|
||||
}
|
||||
}
|
||||
function __construct($dbh, $query, $resultless = 0)
|
||||
{
|
||||
// use with DELETE, INSERT, UPDATE
|
||||
if ($resultless)
|
||||
{
|
||||
$this->affected = $dbh->exec($query); //throws PDOException
|
||||
}
|
||||
// SELECT
|
||||
else
|
||||
{
|
||||
$this->q = $dbh->query($query); //throws PDOException
|
||||
$this->affected = $this->q->rowCount();
|
||||
}
|
||||
}
|
||||
|
||||
function fetchRow()
|
||||
{
|
||||
return $this->q->fetch(PDO::FETCH_NUM);
|
||||
}
|
||||
function fetchRow()
|
||||
{
|
||||
return $this->q->fetch(PDO::FETCH_NUM);
|
||||
}
|
||||
|
||||
function fetchAssoc()
|
||||
{
|
||||
return $this->q->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
function fetchAssoc()
|
||||
{
|
||||
return $this->q->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
function rowsAffected()
|
||||
{
|
||||
return $this->affected;
|
||||
}
|
||||
function rowsAffected()
|
||||
{
|
||||
return $this->affected;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Database_Sqlite3 extends Database_Abstract
|
||||
{
|
||||
/** @var PDO */
|
||||
private $dbh;
|
||||
/** @var PDO */
|
||||
private $dbh;
|
||||
|
||||
private $affected = null;
|
||||
var $lastQuery;
|
||||
var $prefix = '';
|
||||
private $affected = null;
|
||||
var $lastQuery;
|
||||
var $prefix = '';
|
||||
|
||||
function __construct()
|
||||
{
|
||||
}
|
||||
function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
function connect($params)
|
||||
{
|
||||
$filename = $params['filename'];
|
||||
$options = array(
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
);
|
||||
$this->dbh = new PDO("sqlite:$filename", null, null, $options); //throws PDOException
|
||||
return true;
|
||||
}
|
||||
function connect($params)
|
||||
{
|
||||
$filename = $params['filename'];
|
||||
$options = array(
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
);
|
||||
$this->dbh = new PDO("sqlite:$filename", null, null, $options); //throws PDOException
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
SELECT queries for single row
|
||||
*/
|
||||
function sq($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
/*
|
||||
SELECT queries for single row
|
||||
*/
|
||||
function sq($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
|
||||
$res = $q->fetchRow();
|
||||
if ($res === false) return NULL;
|
||||
$res = $q->fetchRow();
|
||||
if ($res === false) return NULL;
|
||||
|
||||
if (sizeof($res) > 1) return $res;
|
||||
else return $res[0];
|
||||
}
|
||||
if (sizeof($res) > 1) return $res;
|
||||
else return $res[0];
|
||||
}
|
||||
|
||||
/*
|
||||
SELECT queries for single row
|
||||
*/
|
||||
function sqa($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
/*
|
||||
SELECT queries for single row
|
||||
*/
|
||||
function sqa($query, $p = NULL)
|
||||
{
|
||||
$q = $this->_dq($query, $p);
|
||||
|
||||
$res = $q->fetchAssoc();
|
||||
if ($res === false) return NULL;
|
||||
return $res;
|
||||
}
|
||||
$res = $q->fetchAssoc();
|
||||
if ($res === false) return NULL;
|
||||
return $res;
|
||||
}
|
||||
|
||||
/*
|
||||
SELECT queries for multiple rows
|
||||
*/
|
||||
function dq($query, $p = NULL) : DatabaseResult_Abstract
|
||||
{
|
||||
return $this->_dq($query, $p);
|
||||
}
|
||||
/*
|
||||
SELECT queries for multiple rows
|
||||
*/
|
||||
function dq($query, $p = NULL) : DatabaseResult_Abstract
|
||||
{
|
||||
return $this->_dq($query, $p);
|
||||
}
|
||||
|
||||
/*
|
||||
for resultless queries like INSERT,UPDATE,DELETE
|
||||
*/
|
||||
function ex($query, $p = NULL)
|
||||
{
|
||||
$dbr = $this->_dq($query, $p, 1);
|
||||
return $this->affected();
|
||||
}
|
||||
/*
|
||||
for resultless queries like INSERT,UPDATE,DELETE
|
||||
*/
|
||||
function ex($query, $p = NULL)
|
||||
{
|
||||
$dbr = $this->_dq($query, $p, 1);
|
||||
return $this->affected();
|
||||
}
|
||||
|
||||
private function _dq($query, $p = NULL, $resultless = 0) : DatabaseResult_Abstract
|
||||
{
|
||||
if (!isset($p)) $p = array();
|
||||
elseif (!is_array($p)) $p = array($p);
|
||||
private function _dq($query, $p = NULL, $resultless = 0) : DatabaseResult_Abstract
|
||||
{
|
||||
if (!isset($p)) $p = array();
|
||||
elseif (!is_array($p)) $p = array($p);
|
||||
|
||||
$m = explode('?', $query);
|
||||
$m = explode('?', $query);
|
||||
|
||||
if (sizeof($p) > 0)
|
||||
{
|
||||
if (sizeof($m) < sizeof($p)+1) {
|
||||
throw new Exception("params to set MORE than query params");
|
||||
}
|
||||
if (sizeof($m) > sizeof($p)+1) {
|
||||
throw new Exception("params to set LESS than query params");
|
||||
}
|
||||
$query = "";
|
||||
for ($i=0; $i<sizeof($m)-1; $i++) {
|
||||
$query .= $m[$i]. (is_null($p[$i]) ? 'NULL' : $this->quote($p[$i]));
|
||||
}
|
||||
$query .= $m[$i];
|
||||
}
|
||||
$this->lastQuery = $query;
|
||||
$dbr = new DatabaseResult_Sqlite3($this->dbh, $query, $resultless);
|
||||
$this->affected = $dbr->rowsAffected();
|
||||
return $dbr;
|
||||
}
|
||||
if (sizeof($p) > 0)
|
||||
{
|
||||
if (sizeof($m) < sizeof($p)+1) {
|
||||
throw new Exception("params to set MORE than query params");
|
||||
}
|
||||
if (sizeof($m) > sizeof($p)+1) {
|
||||
throw new Exception("params to set LESS than query params");
|
||||
}
|
||||
$query = "";
|
||||
for ($i=0; $i<sizeof($m)-1; $i++) {
|
||||
$query .= $m[$i]. (is_null($p[$i]) ? 'NULL' : $this->quote($p[$i]));
|
||||
}
|
||||
$query .= $m[$i];
|
||||
}
|
||||
$this->lastQuery = $query;
|
||||
$dbr = new DatabaseResult_Sqlite3($this->dbh, $query, $resultless);
|
||||
$this->affected = $dbr->rowsAffected();
|
||||
return $dbr;
|
||||
}
|
||||
|
||||
function affected()
|
||||
{
|
||||
return $this->affected;
|
||||
}
|
||||
function affected()
|
||||
{
|
||||
return $this->affected;
|
||||
}
|
||||
|
||||
function quote($s)
|
||||
{
|
||||
return $this->dbh->quote($s);
|
||||
}
|
||||
function quote($s)
|
||||
{
|
||||
return $this->dbh->quote($s);
|
||||
}
|
||||
|
||||
function quoteForLike($format, $s)
|
||||
{
|
||||
$s = str_replace(array('\\','%','_'), array('\\\\','\%','\_'), $s);
|
||||
return $this->dbh->quote(sprintf($format, $s)). " ESCAPE '\'";
|
||||
}
|
||||
function quoteForLike($format, $s)
|
||||
{
|
||||
$s = str_replace(array('\\','%','_'), array('\\\\','\%','\_'), $s);
|
||||
return $this->dbh->quote(sprintf($format, $s)). " ESCAPE '\'";
|
||||
}
|
||||
|
||||
function lastInsertId($name = null)
|
||||
{
|
||||
return $this->dbh->lastInsertId();
|
||||
}
|
||||
function lastInsertId($name = null)
|
||||
{
|
||||
return $this->dbh->lastInsertId();
|
||||
}
|
||||
|
||||
function tableExists($table)
|
||||
{
|
||||
$exists = $this->sq("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?", $table);
|
||||
if ($exists == "1") {
|
||||
return true;
|
||||
}
|
||||
$exists = $this->sq("SELECT 1 FROM sqlite_temp_master WHERE type='table' AND name=?", $table);
|
||||
if ($exists == "1") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function tableExists($table)
|
||||
{
|
||||
$exists = $this->sq("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?", $table);
|
||||
if ($exists == "1") {
|
||||
return true;
|
||||
}
|
||||
$exists = $this->sq("SELECT 1 FROM sqlite_temp_master WHERE type='table' AND name=?", $table);
|
||||
if ($exists == "1") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function tableFieldExists($table, $field): bool
|
||||
{
|
||||
$q = $this->dq("PRAGMA table_info(". $this->quote($table). ")");
|
||||
while ($r = $q->fetchRow()) {
|
||||
if ($r[1] == $field) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function tableFieldExists($table, $field): bool
|
||||
{
|
||||
$q = $this->dq("PRAGMA table_info(". $this->quote($table). ")");
|
||||
while ($r = $q->fetchRow()) {
|
||||
if ($r[1] == $field) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -1,67 +1,67 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2021,2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2021,2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
class DBConnection
|
||||
{
|
||||
protected static $instance;
|
||||
protected static $instance;
|
||||
|
||||
public static function init(Database_Abstract $instance) : Database_Abstract
|
||||
{
|
||||
self::$instance = $instance;
|
||||
return $instance;
|
||||
}
|
||||
public static function init(Database_Abstract $instance) : Database_Abstract
|
||||
{
|
||||
self::$instance = $instance;
|
||||
return $instance;
|
||||
}
|
||||
|
||||
public static function instance() : Database_Abstract
|
||||
{
|
||||
public static function instance() : Database_Abstract
|
||||
{
|
||||
if (!isset(self::$instance)) {
|
||||
throw new Exception("DBConnection is not initialized");
|
||||
throw new Exception("DBConnection is not initialized");
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public static function setPrefix($prefix)
|
||||
{
|
||||
$db = self::instance();
|
||||
$db->setPrefix($prefix);
|
||||
}
|
||||
public static function setPrefix($prefix)
|
||||
{
|
||||
$db = self::instance();
|
||||
$db->setPrefix($prefix);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Database_Abstract
|
||||
{
|
||||
var $lastQuery = null;
|
||||
var $prefix = ''; //TODO: make private
|
||||
abstract function connect($params);
|
||||
abstract function sq($query, $p = NULL);
|
||||
abstract function sqa($query, $p = NULL);
|
||||
abstract function dq($query, $p = NULL) : DatabaseResult_Abstract;
|
||||
abstract function ex($query, $p = NULL);
|
||||
abstract function affected();
|
||||
abstract function quote($s);
|
||||
abstract function quoteForLike($format, $s);
|
||||
abstract function lastInsertId($name = null);
|
||||
abstract function tableExists($table);
|
||||
abstract function tableFieldExists($table, $field): bool;
|
||||
var $lastQuery = null;
|
||||
var $prefix = ''; //TODO: make private
|
||||
abstract function connect($params);
|
||||
abstract function sq($query, $p = NULL);
|
||||
abstract function sqa($query, $p = NULL);
|
||||
abstract function dq($query, $p = NULL) : DatabaseResult_Abstract;
|
||||
abstract function ex($query, $p = NULL);
|
||||
abstract function affected();
|
||||
abstract function quote($s);
|
||||
abstract function quoteForLike($format, $s);
|
||||
abstract function lastInsertId($name = null);
|
||||
abstract function tableExists($table);
|
||||
abstract function tableFieldExists($table, $field): bool;
|
||||
|
||||
function prefix(): string {
|
||||
return $this->prefix;
|
||||
}
|
||||
function prefix(): string {
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
function setPrefix(string $prefix) {
|
||||
if ($prefix != '' && !preg_match("/^[a-zA-Z0-9_]+$/", $prefix)) {
|
||||
throw new Exception("Incorrect table prefix");
|
||||
}
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
function setPrefix(string $prefix) {
|
||||
if ($prefix != '' && !preg_match("/^[a-zA-Z0-9_]+$/", $prefix)) {
|
||||
throw new Exception("Incorrect table prefix");
|
||||
}
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DatabaseResult_Abstract
|
||||
{
|
||||
abstract function fetchRow();
|
||||
abstract function fetchAssoc();
|
||||
abstract function fetchRow();
|
||||
abstract function fetchAssoc();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -11,68 +11,68 @@
|
|||
|
||||
class DBCore
|
||||
{
|
||||
/** @var Database_Abstract $db */
|
||||
protected $db;
|
||||
/** @var Database_Abstract $db */
|
||||
protected $db;
|
||||
|
||||
/** @var DBCore $defaultdb */
|
||||
protected static $defaultInstance;
|
||||
/** @var DBCore $defaultdb */
|
||||
protected static $defaultInstance;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Database_Abstract $db Value of DBConnection::instance() or similar
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Database_Abstract $db) {
|
||||
$this->db = $db;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param Database_Abstract $db Value of DBConnection::instance() or similar
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Database_Abstract $db) {
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Database_Abstract
|
||||
* @throws Exception
|
||||
*/
|
||||
public function connection()
|
||||
{
|
||||
if (!isset($this->db)) {
|
||||
throw new Exception("DBConnection is not set");
|
||||
}
|
||||
return $this->db;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return DBCore
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function defaultInstance() : DBCore
|
||||
{
|
||||
if (!isset(self::$defaultInstance)) {
|
||||
throw new Exception("DBCore defaultInstance is not initialized");
|
||||
/**
|
||||
*
|
||||
* @return Database_Abstract
|
||||
* @throws Exception
|
||||
*/
|
||||
public function connection()
|
||||
{
|
||||
if (!isset($this->db)) {
|
||||
throw new Exception("DBConnection is not set");
|
||||
}
|
||||
return self::$defaultInstance;
|
||||
}
|
||||
return $this->db;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param DBCore $instance
|
||||
* @return void
|
||||
*/
|
||||
public static function setDefaultInstance(DBCore $instance)
|
||||
{
|
||||
self::$defaultInstance = $instance;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return DBCore
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function defaultInstance() : DBCore
|
||||
{
|
||||
if (!isset(self::$defaultInstance)) {
|
||||
throw new Exception("DBCore defaultInstance is not initialized");
|
||||
}
|
||||
return self::$defaultInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $id
|
||||
* @return int
|
||||
*/
|
||||
public function getListIdByTaskId(int $id): int
|
||||
{
|
||||
$db = $this->db;
|
||||
$listId = (int)$db->sq("SELECT list_id FROM {$db->prefix}todolist WHERE id=". (int)$id);
|
||||
return $listId;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param DBCore $instance
|
||||
* @return void
|
||||
*/
|
||||
public static function setDefaultInstance(DBCore $instance)
|
||||
{
|
||||
self::$defaultInstance = $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $id
|
||||
* @return int
|
||||
*/
|
||||
public function getListIdByTaskId(int $id): int
|
||||
{
|
||||
$db = $this->db;
|
||||
$listId = (int)$db->sq("SELECT list_id FROM {$db->prefix}todolist WHERE id=". (int)$id);
|
||||
return $listId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,165 +1,165 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
/*
|
||||
myTinyTodo language class
|
||||
myTinyTodo language class
|
||||
*/
|
||||
|
||||
class Lang
|
||||
{
|
||||
protected static $instance;
|
||||
protected static $langDir = MTTLANG;
|
||||
protected $code = 'en';
|
||||
protected $default = 'en';
|
||||
protected $strings;
|
||||
protected static $instance;
|
||||
protected static $langDir = MTTLANG;
|
||||
protected $code = 'en';
|
||||
protected $default = 'en';
|
||||
protected $strings;
|
||||
|
||||
public static function instance()
|
||||
{
|
||||
public static function instance()
|
||||
{
|
||||
if (!isset(self::$instance)) {
|
||||
$c = __CLASS__;
|
||||
self::$instance = new $c;
|
||||
$c = __CLASS__;
|
||||
self::$instance = new $c;
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public static function loadLangOrDie($code, $die = 1)
|
||||
{
|
||||
$lang = self::instance();
|
||||
public static function loadLangOrDie($code, $die = 1)
|
||||
{
|
||||
$lang = self::instance();
|
||||
|
||||
//check if json file exists
|
||||
if ( self::langExists($code) ) {
|
||||
$jsonString = file_get_contents( self::$langDir. "{$code}.json" );
|
||||
$lang->loadJsonString($code, $jsonString);
|
||||
}
|
||||
else if ( $die == 0 ) {
|
||||
//notice?
|
||||
$lang->code = $lang->default; //sure?
|
||||
$lang->loadDefaultStrings();
|
||||
}
|
||||
else if ( $die == 1 ) {
|
||||
die("Language file not found (". htmlspecialchars($code). ".json)");
|
||||
}
|
||||
}
|
||||
//check if json file exists
|
||||
if ( self::langExists($code) ) {
|
||||
$jsonString = file_get_contents( self::$langDir. "{$code}.json" );
|
||||
$lang->loadJsonString($code, $jsonString);
|
||||
}
|
||||
else if ( $die == 0 ) {
|
||||
//notice?
|
||||
$lang->code = $lang->default; //sure?
|
||||
$lang->loadDefaultStrings();
|
||||
}
|
||||
else if ( $die == 1 ) {
|
||||
die("Language file not found (". htmlspecialchars($code). ".json)");
|
||||
}
|
||||
}
|
||||
|
||||
public static function loadLang($code)
|
||||
{
|
||||
self::loadLangOrDie($code, 0);
|
||||
}
|
||||
public static function loadLang($code)
|
||||
{
|
||||
self::loadLangOrDie($code, 0);
|
||||
}
|
||||
|
||||
public static function langExists($code)
|
||||
{
|
||||
return file_exists(self::$langDir. $code. '.json');
|
||||
}
|
||||
public static function langExists($code)
|
||||
{
|
||||
return file_exists(self::$langDir. $code. '.json');
|
||||
}
|
||||
|
||||
function loadJsonString($code, $jsonString)
|
||||
{
|
||||
$this->code = $code;
|
||||
$json = json_decode($jsonString, true);
|
||||
function loadJsonString($code, $jsonString)
|
||||
{
|
||||
$this->code = $code;
|
||||
$json = json_decode($jsonString, true);
|
||||
|
||||
//load default language
|
||||
if ( $code != $this->default ) {
|
||||
$this->loadDefaultStrings();
|
||||
$this->strings = array_replace($this->strings, $json);
|
||||
}
|
||||
else {
|
||||
$this->strings = $json;
|
||||
}
|
||||
}
|
||||
//load default language
|
||||
if ( $code != $this->default ) {
|
||||
$this->loadDefaultStrings();
|
||||
$this->strings = array_replace($this->strings, $json);
|
||||
}
|
||||
else {
|
||||
$this->strings = $json;
|
||||
}
|
||||
}
|
||||
|
||||
function loadDefaultStrings()
|
||||
{
|
||||
if ( ! self::langExists($this->default) ) {
|
||||
die("Default language file not found (". htmlspecialchars($this->default). ".json)");
|
||||
}
|
||||
$defStr = file_get_contents($this->langDir(). "{$this->default}.json");
|
||||
$this->strings = json_decode($defStr, true);
|
||||
}
|
||||
function loadDefaultStrings()
|
||||
{
|
||||
if ( ! self::langExists($this->default) ) {
|
||||
die("Default language file not found (". htmlspecialchars($this->default). ".json)");
|
||||
}
|
||||
$defStr = file_get_contents($this->langDir(). "{$this->default}.json");
|
||||
$this->strings = json_decode($defStr, true);
|
||||
}
|
||||
|
||||
function get($key)
|
||||
{
|
||||
if ( isset($this->strings[$key]) ) {
|
||||
return $this->strings[$key];
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
function get($key)
|
||||
{
|
||||
if ( isset($this->strings[$key]) ) {
|
||||
return $this->strings[$key];
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
function rtl()
|
||||
{
|
||||
if ( isset($this->strings['_rtl']) ) {
|
||||
return intval($this->strings['_rtl']);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
function rtl()
|
||||
{
|
||||
if ( isset($this->strings['_rtl']) ) {
|
||||
return intval($this->strings['_rtl']);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* minimal number of translated strings to use in js front-end */
|
||||
function jsStrings()
|
||||
{
|
||||
$a = array();
|
||||
$a['daysMin'] = $this->get('days_min');
|
||||
$a['daysLong'] = $this->get('days_long');
|
||||
$a['monthsShort'] = $this->get('months_short');
|
||||
$a['monthsLong'] = $this->get('months_long');
|
||||
/* minimal number of translated strings to use in js front-end */
|
||||
function jsStrings()
|
||||
{
|
||||
$a = array();
|
||||
$a['daysMin'] = $this->get('days_min');
|
||||
$a['daysLong'] = $this->get('days_long');
|
||||
$a['monthsShort'] = $this->get('months_short');
|
||||
$a['monthsLong'] = $this->get('months_long');
|
||||
|
||||
$this->fillWithValues($a, [
|
||||
'confirmDelete',
|
||||
'confirmLeave',
|
||||
'actionNoteSave',
|
||||
'actionNoteCancel',
|
||||
'error',
|
||||
'denied',
|
||||
'listNotFound',
|
||||
'noPublicLists',
|
||||
'invalidpass',
|
||||
'addList',
|
||||
'addListDefault',
|
||||
'renameList',
|
||||
'deleteList',
|
||||
'clearCompleted',
|
||||
'settingsSaved',
|
||||
'tags',
|
||||
'tasks',
|
||||
'f_past',
|
||||
'f_today',
|
||||
'f_soon',
|
||||
'alltasks',
|
||||
'set_header'
|
||||
]);
|
||||
$a['_rtl'] = $this->rtl() ? 1 : 0;
|
||||
$this->fillWithValues($a, [
|
||||
'confirmDelete',
|
||||
'confirmLeave',
|
||||
'actionNoteSave',
|
||||
'actionNoteCancel',
|
||||
'error',
|
||||
'denied',
|
||||
'listNotFound',
|
||||
'noPublicLists',
|
||||
'invalidpass',
|
||||
'addList',
|
||||
'addListDefault',
|
||||
'renameList',
|
||||
'deleteList',
|
||||
'clearCompleted',
|
||||
'settingsSaved',
|
||||
'tags',
|
||||
'tasks',
|
||||
'f_past',
|
||||
'f_today',
|
||||
'f_soon',
|
||||
'alltasks',
|
||||
'set_header'
|
||||
]);
|
||||
$a['_rtl'] = $this->rtl() ? 1 : 0;
|
||||
|
||||
return $a;
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
|
||||
function makeJS($pretty = 0)
|
||||
{
|
||||
$a = $this->jsStrings();
|
||||
$opts = JSON_UNESCAPED_UNICODE;
|
||||
if ($pretty) {
|
||||
$opts |= JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES;
|
||||
}
|
||||
return json_encode($a, $opts);
|
||||
}
|
||||
function makeJS($pretty = 0)
|
||||
{
|
||||
$a = $this->jsStrings();
|
||||
$opts = JSON_UNESCAPED_UNICODE;
|
||||
if ($pretty) {
|
||||
$opts |= JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES;
|
||||
}
|
||||
return json_encode($a, $opts);
|
||||
}
|
||||
|
||||
protected function fillWithValues(array &$a, array $keys)
|
||||
{
|
||||
foreach ( $keys as $key ) {
|
||||
$a[$key] = $this->get($key);
|
||||
}
|
||||
}
|
||||
protected function fillWithValues(array &$a, array $keys)
|
||||
{
|
||||
foreach ( $keys as $key ) {
|
||||
$a[$key] = $this->get($key);
|
||||
}
|
||||
}
|
||||
|
||||
function langDir()
|
||||
{
|
||||
return self::$langDir;
|
||||
}
|
||||
function langDir()
|
||||
{
|
||||
return self::$langDir;
|
||||
}
|
||||
|
||||
function langCode()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
function langCode()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,105 +1,105 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2021-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2021-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
class MTTSessionHandler implements SessionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @var Database_Abstract
|
||||
*/
|
||||
private $db;
|
||||
/**
|
||||
* @var Database_Abstract
|
||||
*/
|
||||
private $db;
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function open($path, $name): bool
|
||||
{
|
||||
$this->db = DBConnection::instance();
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string $name
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function open($path, $name): bool
|
||||
{
|
||||
$this->db = DBConnection::instance();
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @return bool */
|
||||
public function close(): bool
|
||||
/** @return bool */
|
||||
public function close(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function read($id)
|
||||
{
|
||||
// read session data if not expired
|
||||
$time = time();
|
||||
$expire = $time;
|
||||
$r = $this->db->sq("SELECT data,last_access FROM {$this->db->prefix}sessions WHERE id = ? AND expires >= $expire", $id);
|
||||
if ( is_null($r) ) return '';
|
||||
/**
|
||||
* @param string $id
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function read($id)
|
||||
{
|
||||
// read session data if not expired
|
||||
$time = time();
|
||||
$expire = $time;
|
||||
$r = $this->db->sq("SELECT data,last_access FROM {$this->db->prefix}sessions WHERE id = ? AND expires >= $expire", $id);
|
||||
if ( is_null($r) ) return '';
|
||||
|
||||
// update last access time and set expires in 14 days
|
||||
// refresh once in a second
|
||||
if ( $r[1] < $time ) {
|
||||
$expire = $time + 14 * 86400;
|
||||
$this->db->ex("UPDATE {$this->db->prefix}sessions SET last_access=?,expires=? WHERE id = ?",
|
||||
array($time, $expire, $id) );
|
||||
}
|
||||
return $r[0];
|
||||
}
|
||||
// update last access time and set expires in 14 days
|
||||
// refresh once in a second
|
||||
if ( $r[1] < $time ) {
|
||||
$expire = $time + 14 * 86400;
|
||||
$this->db->ex("UPDATE {$this->db->prefix}sessions SET last_access=?,expires=? WHERE id = ?",
|
||||
array($time, $expire, $id) );
|
||||
}
|
||||
return $r[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @param string $data
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function write($id, $data): bool
|
||||
{
|
||||
$exists = $this->db->sq("SELECT COUNT(*) FROM {$this->db->prefix}sessions WHERE id = ?", $id);
|
||||
if (!$exists) {
|
||||
// Create new session with 14 days lifetime
|
||||
$expire = time() + 14 * 86400;
|
||||
$this->db->ex("INSERT INTO {$this->db->prefix}sessions (id,data,expires) VALUES (?,?,?)",
|
||||
array($id, $data, $expire) );
|
||||
}
|
||||
else {
|
||||
// Update existing session
|
||||
$this->db->ex("UPDATE {$this->db->prefix}sessions SET data = ? WHERE id = ?",
|
||||
array($data, $id) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @param string $id
|
||||
* @param string $data
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function write($id, $data): bool
|
||||
{
|
||||
$exists = $this->db->sq("SELECT COUNT(*) FROM {$this->db->prefix}sessions WHERE id = ?", $id);
|
||||
if (!$exists) {
|
||||
// Create new session with 14 days lifetime
|
||||
$expire = time() + 14 * 86400;
|
||||
$this->db->ex("INSERT INTO {$this->db->prefix}sessions (id,data,expires) VALUES (?,?,?)",
|
||||
array($id, $data, $expire) );
|
||||
}
|
||||
else {
|
||||
// Update existing session
|
||||
$this->db->ex("UPDATE {$this->db->prefix}sessions SET data = ? WHERE id = ?",
|
||||
array($data, $id) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function destroy($id): bool
|
||||
{
|
||||
$this->db->ex("DELETE FROM {$this->db->prefix}sessions WHERE id = ?", $id);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* @param string $id
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function destroy($id): bool
|
||||
{
|
||||
$this->db->ex("DELETE FROM {$this->db->prefix}sessions WHERE id = ?", $id);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $max_lifetime
|
||||
* @return int|false
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function gc($max_lifetime)
|
||||
{
|
||||
// We ignore php runtime 'session.gc_maxlifetime'
|
||||
$expire = time();
|
||||
$affected = $this->db->ex("DELETE FROM {$this->db->prefix}sessions WHERE expires < $expire");
|
||||
return $affected;
|
||||
}
|
||||
/**
|
||||
* @param int $max_lifetime
|
||||
* @return int|false
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function gc($max_lifetime)
|
||||
{
|
||||
// We ignore php runtime 'session.gc_maxlifetime'
|
||||
$expire = time();
|
||||
$affected = $this->db->ex("DELETE FROM {$this->db->prefix}sessions WHERE expires < $expire");
|
||||
return $affected;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,123 +1,123 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2010,2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2010,2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
function htmlarray($a, $exclude=null)
|
||||
{
|
||||
htmlarray_ref($a, $exclude);
|
||||
return $a;
|
||||
htmlarray_ref($a, $exclude);
|
||||
return $a;
|
||||
}
|
||||
|
||||
function htmlarray_ref(&$a, $exclude=null)
|
||||
{
|
||||
if(!$a) return;
|
||||
if(!is_array($a)) {
|
||||
$a = htmlspecialchars($a);
|
||||
return;
|
||||
}
|
||||
reset($a);
|
||||
if($exclude && !is_array($exclude)) $exclude = array($exclude);
|
||||
foreach($a as $k=>$v)
|
||||
{
|
||||
if(is_array($v)) $a[$k] = htmlarray($v, $exclude);
|
||||
elseif(!$exclude) $a[$k] = htmlspecialchars($v);
|
||||
elseif(!in_array($k, $exclude)) $a[$k] = htmlspecialchars($v);
|
||||
}
|
||||
return;
|
||||
if(!$a) return;
|
||||
if(!is_array($a)) {
|
||||
$a = htmlspecialchars($a);
|
||||
return;
|
||||
}
|
||||
reset($a);
|
||||
if($exclude && !is_array($exclude)) $exclude = array($exclude);
|
||||
foreach($a as $k=>$v)
|
||||
{
|
||||
if(is_array($v)) $a[$k] = htmlarray($v, $exclude);
|
||||
elseif(!$exclude) $a[$k] = htmlspecialchars($v);
|
||||
elseif(!in_array($k, $exclude)) $a[$k] = htmlspecialchars($v);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function _post($param,$defvalue = '')
|
||||
{
|
||||
if(!isset($_POST[$param])) {
|
||||
return $defvalue;
|
||||
}
|
||||
else {
|
||||
return $_POST[$param];
|
||||
}
|
||||
if(!isset($_POST[$param])) {
|
||||
return $defvalue;
|
||||
}
|
||||
else {
|
||||
return $_POST[$param];
|
||||
}
|
||||
}
|
||||
|
||||
function _get($param,$defvalue = '')
|
||||
{
|
||||
if(!isset($_GET[$param])) {
|
||||
return $defvalue;
|
||||
}
|
||||
else {
|
||||
return $_GET[$param];
|
||||
}
|
||||
if(!isset($_GET[$param])) {
|
||||
return $defvalue;
|
||||
}
|
||||
else {
|
||||
return $_GET[$param];
|
||||
}
|
||||
}
|
||||
|
||||
function _server($param, $defvalue = '')
|
||||
{
|
||||
if ( !isset($_SERVER[$param]) ) {
|
||||
return $defvalue;
|
||||
}
|
||||
else {
|
||||
return $_SERVER[$param];
|
||||
}
|
||||
if ( !isset($_SERVER[$param]) ) {
|
||||
return $defvalue;
|
||||
}
|
||||
else {
|
||||
return $_SERVER[$param];
|
||||
}
|
||||
}
|
||||
|
||||
function formatDate3($format, $ay, $am, $ad, $lang)
|
||||
{
|
||||
# F - month long, M - month short
|
||||
# m - month 2-digit, n - month 1-digit
|
||||
# d - day 2-digit, j - day 1-digit
|
||||
$ml = $lang->get('months_long');
|
||||
$ms = $lang->get('months_short');
|
||||
$Y = $ay;
|
||||
$YC = 100 * floor($Y/100); //...1900,2000,2100...
|
||||
if ($YC == 2000) $y = $Y < $YC+10 ? '0'.($Y-$YC) : $Y-$YC;
|
||||
else $y = $Y;
|
||||
$n = $am;
|
||||
$m = $n < 10 ? '0'.$n : $n;
|
||||
$F = $ml[$am-1];
|
||||
$M = $ms[$am-1];
|
||||
$j = $ad;
|
||||
$d = $j < 10 ? '0'.$j : $j;
|
||||
return strtr($format, array('Y'=>$Y, 'y'=>$y, 'F'=>$F, 'M'=>$M, 'n'=>$n, 'm'=>$m, 'd'=>$d, 'j'=>$j));
|
||||
# F - month long, M - month short
|
||||
# m - month 2-digit, n - month 1-digit
|
||||
# d - day 2-digit, j - day 1-digit
|
||||
$ml = $lang->get('months_long');
|
||||
$ms = $lang->get('months_short');
|
||||
$Y = $ay;
|
||||
$YC = 100 * floor($Y/100); //...1900,2000,2100...
|
||||
if ($YC == 2000) $y = $Y < $YC+10 ? '0'.($Y-$YC) : $Y-$YC;
|
||||
else $y = $Y;
|
||||
$n = $am;
|
||||
$m = $n < 10 ? '0'.$n : $n;
|
||||
$F = $ml[$am-1];
|
||||
$M = $ms[$am-1];
|
||||
$j = $ad;
|
||||
$d = $j < 10 ? '0'.$j : $j;
|
||||
return strtr($format, array('Y'=>$Y, 'y'=>$y, 'F'=>$F, 'M'=>$M, 'n'=>$n, 'm'=>$m, 'd'=>$d, 'j'=>$j));
|
||||
}
|
||||
|
||||
function getRequestUri()
|
||||
{
|
||||
// Do not use HTTP_X_REWRITE_URL due to CVE-2018-14773
|
||||
// SCRIPT_NAME or PATH_INFO ?
|
||||
if (isset($_SERVER['REQUEST_URI'])) {
|
||||
return $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
else if (isset($_SERVER['ORIG_PATH_INFO'])) // IIS 5.0 CGI
|
||||
{
|
||||
$uri = $_SERVER['ORIG_PATH_INFO']; //has no query
|
||||
if (!empty($_SERVER['QUERY_STRING'])) $uri .= '?'. $_SERVER['QUERY_STRING'];
|
||||
return $uri;
|
||||
}
|
||||
// Do not use HTTP_X_REWRITE_URL due to CVE-2018-14773
|
||||
// SCRIPT_NAME or PATH_INFO ?
|
||||
if (isset($_SERVER['REQUEST_URI'])) {
|
||||
return $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
else if (isset($_SERVER['ORIG_PATH_INFO'])) // IIS 5.0 CGI
|
||||
{
|
||||
$uri = $_SERVER['ORIG_PATH_INFO']; //has no query
|
||||
if (!empty($_SERVER['QUERY_STRING'])) $uri .= '?'. $_SERVER['QUERY_STRING'];
|
||||
return $uri;
|
||||
}
|
||||
}
|
||||
|
||||
function url_dir($url, $onlyPath = 1)
|
||||
{
|
||||
if (false !== $p = strpos($url, '?')) {
|
||||
$url = substr($url, 0, $p); # to avoid parse errors on strange query strings
|
||||
}
|
||||
if ($onlyPath) {
|
||||
$url = parse_url($url, PHP_URL_PATH);
|
||||
}
|
||||
if ($url == '') {
|
||||
return '/';
|
||||
}
|
||||
if (substr($url, -1) == '/') {
|
||||
return $url;
|
||||
}
|
||||
if (false !== $p = strrpos($url, '/')) {
|
||||
return substr($url, 0, $p+1);
|
||||
}
|
||||
return '/';
|
||||
if (false !== $p = strpos($url, '?')) {
|
||||
$url = substr($url, 0, $p); # to avoid parse errors on strange query strings
|
||||
}
|
||||
if ($onlyPath) {
|
||||
$url = parse_url($url, PHP_URL_PATH);
|
||||
}
|
||||
if ($url == '') {
|
||||
return '/';
|
||||
}
|
||||
if (substr($url, -1) == '/') {
|
||||
return $url;
|
||||
}
|
||||
if (false !== $p = strrpos($url, '/')) {
|
||||
return substr($url, 0, $p+1);
|
||||
}
|
||||
return '/';
|
||||
}
|
||||
|
||||
function removeNewLines($s)
|
||||
{
|
||||
return str_replace( ["\r","\n"], '', $s );
|
||||
return str_replace( ["\r","\n"], '', $s );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -126,21 +126,21 @@ function removeNewLines($s)
|
|||
*/
|
||||
function generateUUID(): string
|
||||
{
|
||||
$uuid = bin2hex(random_bytes(16));
|
||||
return sprintf('%08s-%04s-4%03s-%04x-%012s',
|
||||
substr($uuid, 0, 8),
|
||||
substr($uuid, 8, 4),
|
||||
// $uuid[14] = 4
|
||||
substr($uuid, 13, 3),
|
||||
hexdec(substr($uuid, 16, 4)) & 0x3fff | 0x8000,
|
||||
substr($uuid, 20, 12)
|
||||
$uuid = bin2hex(random_bytes(16));
|
||||
return sprintf('%08s-%04s-4%03s-%04x-%012s',
|
||||
substr($uuid, 0, 8),
|
||||
substr($uuid, 8, 4),
|
||||
// $uuid[14] = 4
|
||||
substr($uuid, 13, 3),
|
||||
hexdec(substr($uuid, 16, 4)) & 0x3fff | 0x8000,
|
||||
substr($uuid, 20, 12)
|
||||
);
|
||||
}
|
||||
|
||||
function passwordHash(string $p): string
|
||||
{
|
||||
if ($p == '') return '';
|
||||
return 'sha256:'. hash('sha256', $p);
|
||||
if ($p == '') return '';
|
||||
return 'sha256:'. hash('sha256', $p);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -151,26 +151,26 @@ function passwordHash(string $p): string
|
|||
*/
|
||||
function isPasswordEqualsToHash(string $p, string $hash): bool
|
||||
{
|
||||
if ($hash == '' && $p == '') return true;
|
||||
if ($hash == '' || $p == '') return false;
|
||||
if ( false !== $pos = strpos($hash, ':') ) {
|
||||
$algo = substr($hash, 0, $pos);
|
||||
if ($algo != 'sha256') throw new Exception("Unsupported algo of password hash");
|
||||
if ( hash_equals($hash, passwordHash($p)) ) return true;
|
||||
}
|
||||
return false;
|
||||
if ($hash == '' && $p == '') return true;
|
||||
if ($hash == '' || $p == '') return false;
|
||||
if ( false !== $pos = strpos($hash, ':') ) {
|
||||
$algo = substr($hash, 0, $pos);
|
||||
if ($algo != 'sha256') throw new Exception("Unsupported algo of password hash");
|
||||
if ( hash_equals($hash, passwordHash($p)) ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function idSignature(string $id, string $key, string $salt): string
|
||||
{
|
||||
$secret = $key.$salt;
|
||||
return hash_hmac('sha256', $id, $secret);
|
||||
$secret = $key.$salt;
|
||||
return hash_hmac('sha256', $id, $secret);
|
||||
}
|
||||
|
||||
function isSignatureOk(string $signature, string $id, string $key, string $salt): bool
|
||||
{
|
||||
if ( hash_equals($signature, idSignature($id, $key, $salt)) ) return true;
|
||||
return false;
|
||||
if ( hash_equals($signature, idSignature($id, $key, $salt)) ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2021-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2021-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
require_once(MTTINC. 'parsedown/Parsedown.php');
|
||||
|
|
@ -12,76 +12,76 @@ require_once(MTTINC. 'parsedown/MTTParsedown.php');
|
|||
|
||||
function noteMarkup($note, $toExternal = false)
|
||||
{
|
||||
if ($note === null) {
|
||||
$note = '';
|
||||
}
|
||||
if (Config::get('markup') == 'v1') {
|
||||
return mttMarkup_v1($note);
|
||||
}
|
||||
return markdownToHtml($note, $toExternal);
|
||||
if ($note === null) {
|
||||
$note = '';
|
||||
}
|
||||
if (Config::get('markup') == 'v1') {
|
||||
return mttMarkup_v1($note);
|
||||
}
|
||||
return markdownToHtml($note, $toExternal);
|
||||
}
|
||||
|
||||
// Markdown converter (Parsedown)
|
||||
function markdownToHtml($s, $toExternal = false)
|
||||
{
|
||||
$parser = MTTParsedown::instance();
|
||||
$parser->setToExternal($toExternal);
|
||||
$parser->setSafeMode(true);
|
||||
//$parser->setBreaksEnabled(true);
|
||||
return $parser->text($s);
|
||||
$parser = MTTParsedown::instance();
|
||||
$parser->setToExternal($toExternal);
|
||||
$parser->setSafeMode(true);
|
||||
//$parser->setBreaksEnabled(true);
|
||||
return $parser->text($s);
|
||||
}
|
||||
|
||||
|
||||
// Convert note's raw text to html with allowed elements (b,i,u,s and raw urls)
|
||||
function mttMarkup_v1($s)
|
||||
{
|
||||
//hide allowed elements from escaping
|
||||
$c1 = chr(1);
|
||||
$c2 = chr(2);
|
||||
$s = preg_replace("~<b>([\s\S]*?)</b>~i", "${c1}b${c2}\$1${c1}/b${c2}", $s);
|
||||
$s = preg_replace("~<i>([\s\S]*?)</i>~i", "${c1}i${c2}\$1${c1}/i${c2}", $s);
|
||||
$s = preg_replace("~<u>([\s\S]*?)</u>~i", "${c1}u${c2}\$1${c1}/u${c2}", $s);
|
||||
$s = preg_replace("~<s>([\s\S]*?)</s>~i", "${c1}s${c2}\$1${c1}/s${c2}", $s);
|
||||
$s = htmlspecialchars($s, ENT_QUOTES); //escape all elements, except above
|
||||
$s = str_replace( [$c1, $c2], ['<','>'], $s ); //unhide
|
||||
$s = nl2br($s);
|
||||
//hide allowed elements from escaping
|
||||
$c1 = chr(1);
|
||||
$c2 = chr(2);
|
||||
$s = preg_replace("~<b>([\s\S]*?)</b>~i", "${c1}b${c2}\$1${c1}/b${c2}", $s);
|
||||
$s = preg_replace("~<i>([\s\S]*?)</i>~i", "${c1}i${c2}\$1${c1}/i${c2}", $s);
|
||||
$s = preg_replace("~<u>([\s\S]*?)</u>~i", "${c1}u${c2}\$1${c1}/u${c2}", $s);
|
||||
$s = preg_replace("~<s>([\s\S]*?)</s>~i", "${c1}s${c2}\$1${c1}/s${c2}", $s);
|
||||
$s = htmlspecialchars($s, ENT_QUOTES); //escape all elements, except above
|
||||
$s = str_replace( [$c1, $c2], ['<','>'], $s ); //unhide
|
||||
$s = nl2br($s);
|
||||
|
||||
// make links from text starting with 'www.'
|
||||
$s = preg_replace(
|
||||
"/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" ,
|
||||
'$1<a href="http://$2" target="_blank">$2</a>$4' ,
|
||||
$s
|
||||
);
|
||||
// make links from text starting with 'www.'
|
||||
$s = preg_replace(
|
||||
"/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" ,
|
||||
'$1<a href="http://$2" target="_blank">$2</a>$4' ,
|
||||
$s
|
||||
);
|
||||
|
||||
// make link from text starting with protocol like 'http://'
|
||||
$s = preg_replace(
|
||||
"/(^|\s|>)([a-z]+:\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" ,
|
||||
'$1<a href="$2" target="_blank">$2</a>$4' ,
|
||||
$s
|
||||
);
|
||||
// make link from text starting with protocol like 'http://'
|
||||
$s = preg_replace(
|
||||
"/(^|\s|>)([a-z]+:\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" ,
|
||||
'$1<a href="$2" target="_blank">$2</a>$4' ,
|
||||
$s
|
||||
);
|
||||
|
||||
return $s;
|
||||
return $s;
|
||||
}
|
||||
|
||||
// Convert raw title to html with allowed urls
|
||||
function titleMarkup($title)
|
||||
{
|
||||
//escape all unsafe
|
||||
$title = htmlspecialchars($title, ENT_QUOTES);
|
||||
//escape all unsafe
|
||||
$title = htmlspecialchars($title, ENT_QUOTES);
|
||||
|
||||
// make links from text starting with 'www.'
|
||||
$title = preg_replace(
|
||||
"/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" ,
|
||||
'$1<a href="http://$2" target="_blank">$2</a>$4' ,
|
||||
$title
|
||||
);
|
||||
// make links from text starting with 'www.'
|
||||
$title = preg_replace(
|
||||
"/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" ,
|
||||
'$1<a href="http://$2" target="_blank">$2</a>$4' ,
|
||||
$title
|
||||
);
|
||||
|
||||
// make link from text starting with protocol like 'http://'
|
||||
$title = preg_replace(
|
||||
"/(^|\s|>)([a-z]+:\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" ,
|
||||
'$1<a href="$2" target="_blank">$2</a>$4' ,
|
||||
$title
|
||||
);
|
||||
return $title;
|
||||
// make link from text starting with protocol like 'http://'
|
||||
$title = preg_replace(
|
||||
"/(^|\s|>)([a-z]+:\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" ,
|
||||
'$1<a href="$2" target="_blank">$2</a>$4' ,
|
||||
$title
|
||||
);
|
||||
return $title;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,41 +1,41 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
class MTTParsedown extends Parsedown
|
||||
{
|
||||
|
||||
protected $toExternal;
|
||||
protected $toExternal;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->toExternal = false;
|
||||
$this->toExternal = false;
|
||||
|
||||
$this->InlineTypes['#'][]= 'TaskId';
|
||||
$this->inlineMarkerList .= '#';
|
||||
}
|
||||
|
||||
public function setToExternal(bool $v)
|
||||
{
|
||||
$this->toExternal = $v;
|
||||
}
|
||||
public function setToExternal(bool $v)
|
||||
{
|
||||
$this->toExternal = $v;
|
||||
}
|
||||
|
||||
protected function inlineTaskId($excerpt)
|
||||
{
|
||||
if (preg_match('/^#(\d+)/', $excerpt['text'], $matches))
|
||||
{
|
||||
$attrs = array(
|
||||
'href' => get_mttinfo('url'). '?task='. $matches[1],
|
||||
'target' => '_blank',
|
||||
);
|
||||
if (!$this->toExternal) {
|
||||
$attrs['class'] = 'mtt-link-to-task';
|
||||
$attrs['target-id'] = $matches[1];
|
||||
}
|
||||
$attrs = array(
|
||||
'href' => get_mttinfo('url'). '?task='. $matches[1],
|
||||
'target' => '_blank',
|
||||
);
|
||||
if (!$this->toExternal) {
|
||||
$attrs['class'] = 'mtt-link-to-task';
|
||||
$attrs['target-id'] = $matches[1];
|
||||
}
|
||||
return array(
|
||||
|
||||
// How many characters to advance the Parsedown's
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
<?php
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2010,2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2010,2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
require_once('./init.php');
|
||||
|
||||
//Parse query string
|
||||
if ( isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != '' ) {
|
||||
parseRoute($_SERVER['QUERY_STRING']);
|
||||
parseRoute($_SERVER['QUERY_STRING']);
|
||||
}
|
||||
|
||||
|
||||
$lang = Lang::instance();
|
||||
|
||||
if ($lang->rtl()) {
|
||||
Config::set('rtl', 1);
|
||||
Config::set('rtl', 1);
|
||||
}
|
||||
|
||||
if (!is_int(Config::get('firstdayofweek')) || Config::get('firstdayofweek')<0 || Config::get('firstdayofweek')>6) {
|
||||
Config::set('firstdayofweek', 1);
|
||||
Config::set('firstdayofweek', 1);
|
||||
}
|
||||
|
||||
define('TEMPLATEPATH', MTTTHEMES. Config::get('template'). '/');
|
||||
|
|
@ -32,51 +32,51 @@ require(TEMPLATEPATH. 'index.php');
|
|||
|
||||
function parseRoute($queryString)
|
||||
{
|
||||
parse_str($queryString, $q);
|
||||
if (isset($q['list'])) {
|
||||
$hash = ($q['list'] == 'alltasks') ? ['alltasks'] : ['list', (int)$q['list']];
|
||||
unset($q['list']);
|
||||
redirectWithHashRoute($hash, $q);
|
||||
}
|
||||
else if (isset($q['task'])) {
|
||||
$listId = (int)DBCore::defaultInstance()->getListIdByTaskId((int)$q['task']);
|
||||
if ($listId > 0) {
|
||||
$h = [ 'list', $listId, 'search', '#'. (int)$q['task']];
|
||||
redirectWithHashRoute($h);
|
||||
}
|
||||
// TODO: not found
|
||||
}
|
||||
parse_str($queryString, $q);
|
||||
if (isset($q['list'])) {
|
||||
$hash = ($q['list'] == 'alltasks') ? ['alltasks'] : ['list', (int)$q['list']];
|
||||
unset($q['list']);
|
||||
redirectWithHashRoute($hash, $q);
|
||||
}
|
||||
else if (isset($q['task'])) {
|
||||
$listId = (int)DBCore::defaultInstance()->getListIdByTaskId((int)$q['task']);
|
||||
if ($listId > 0) {
|
||||
$h = [ 'list', $listId, 'search', '#'. (int)$q['task']];
|
||||
redirectWithHashRoute($h);
|
||||
}
|
||||
// TODO: not found
|
||||
}
|
||||
}
|
||||
|
||||
function redirectWithHashRoute(array $hash, array $q = [])
|
||||
{
|
||||
$url = get_unsafe_mttinfo('url');
|
||||
$query = http_build_query($q);
|
||||
if ($query != '') $url .= "?$query";
|
||||
if (count($hash) > 0) {
|
||||
$encodedHash = implode("/", array_map("rawurlencode", $hash));
|
||||
$url .= "#$encodedHash";
|
||||
}
|
||||
header("Location: ". $url);
|
||||
exit;
|
||||
$url = get_unsafe_mttinfo('url');
|
||||
$query = http_build_query($q);
|
||||
if ($query != '') $url .= "?$query";
|
||||
if (count($hash) > 0) {
|
||||
$encodedHash = implode("/", array_map("rawurlencode", $hash));
|
||||
$url .= "#$encodedHash";
|
||||
}
|
||||
header("Location: ". $url);
|
||||
exit;
|
||||
}
|
||||
|
||||
function js_options()
|
||||
{
|
||||
$a = array(
|
||||
"token" => htmlspecialchars(access_token()),
|
||||
"title" => get_unsafe_mttinfo('title'),
|
||||
"lang" => Lang::instance()->jsStrings(),
|
||||
"mttUrl" => get_mttinfo('mtt_url'),
|
||||
"homeUrl" => get_mttinfo('url'),
|
||||
"needAuth" => need_auth() ? true : false,
|
||||
"isLogged" => is_logged() ? true : false,
|
||||
"showdate" => Config::get('showdate') ? true : false,
|
||||
"duedatepickerformat" => htmlspecialchars(Config::get('dateformat2')),
|
||||
"firstdayofweek" => (int) Config::get('firstdayofweek'),
|
||||
"calendarIcon" => get_mttinfo('template_url'). 'images/calendar.svg',
|
||||
"autotag" => Config::get('autotag') ? true : false,
|
||||
"markdown" => Config::get('markup') == 'v1' ? false : true
|
||||
);
|
||||
echo json_encode($a, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
$a = array(
|
||||
"token" => htmlspecialchars(access_token()),
|
||||
"title" => get_unsafe_mttinfo('title'),
|
||||
"lang" => Lang::instance()->jsStrings(),
|
||||
"mttUrl" => get_mttinfo('mtt_url'),
|
||||
"homeUrl" => get_mttinfo('url'),
|
||||
"needAuth" => need_auth() ? true : false,
|
||||
"isLogged" => is_logged() ? true : false,
|
||||
"showdate" => Config::get('showdate') ? true : false,
|
||||
"duedatepickerformat" => htmlspecialchars(Config::get('dateformat2')),
|
||||
"firstdayofweek" => (int) Config::get('firstdayofweek'),
|
||||
"calendarIcon" => get_mttinfo('template_url'). 'images/calendar.svg',
|
||||
"autotag" => Config::get('autotag') ? true : false,
|
||||
"markdown" => Config::get('markup') == 'v1' ? false : true
|
||||
);
|
||||
echo json_encode($a, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
|
|
|||
304
src/init.php
304
src/init.php
|
|
@ -1,15 +1,15 @@
|
|||
<?php
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2011,2019-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2011,2019-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
define('MTT_VERSION', '@VERSION');
|
||||
|
||||
##### MyTinyTodo requires php 7.0 and above! #####
|
||||
if (version_compare(PHP_VERSION, '7.0.0') < 0) {
|
||||
die("PHP 7.0+ is required");
|
||||
die("PHP 7.0+ is required");
|
||||
}
|
||||
|
||||
if(!defined('MTTPATH')) define('MTTPATH', dirname(__FILE__) .'/');
|
||||
|
|
@ -19,15 +19,15 @@ if(!defined('MTTLANG')) define('MTTLANG', MTTCONTENT. 'lang/');
|
|||
if(!defined('MTTTHEMES')) define('MTTTHEMES', MTTCONTENT. 'themes/');
|
||||
|
||||
if (getenv('MTT_ENABLE_DEBUG') == 'YES') {
|
||||
define('MTT_DEBUG', true);
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('log_errors', '1');
|
||||
define('MTT_DEBUG', true);
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('log_errors', '1');
|
||||
}
|
||||
else {
|
||||
//ini_set('display_errors', '0');
|
||||
//ini_set('log_errors', '1');
|
||||
define('MTT_DEBUG', false);
|
||||
//ini_set('display_errors', '0');
|
||||
//ini_set('log_errors', '1');
|
||||
define('MTT_DEBUG', false);
|
||||
}
|
||||
|
||||
requireConfig();
|
||||
|
|
@ -40,32 +40,32 @@ require_once(MTTINC. 'class.config.php');
|
|||
# MySQL Database Connection
|
||||
if (MTT_DB_TYPE == 'mysql')
|
||||
{
|
||||
if (defined('MTT_DB_DRIVER') && MTT_DB_DRIVER == 'mysqli') require_once(MTTINC. 'class.db.mysqli.php');
|
||||
else require_once(MTTINC. 'class.db.mysql.php');
|
||||
$db = DBConnection::init(new Database_Mysql);
|
||||
try {
|
||||
$db->connect( array(
|
||||
'host' => MTT_DB_HOST,
|
||||
'user' => MTT_DB_USER,
|
||||
'password' => MTT_DB_PASSWORD,
|
||||
'db' => MTT_DB_NAME,
|
||||
));
|
||||
}
|
||||
catch(Exception $e) {
|
||||
logAndDie("Failed to connect to mysql database: ". $e->getMessage());
|
||||
}
|
||||
$db->dq("SET NAMES utf8mb4");
|
||||
if (defined('MTT_DB_DRIVER') && MTT_DB_DRIVER == 'mysqli') require_once(MTTINC. 'class.db.mysqli.php');
|
||||
else require_once(MTTINC. 'class.db.mysql.php');
|
||||
$db = DBConnection::init(new Database_Mysql);
|
||||
try {
|
||||
$db->connect( array(
|
||||
'host' => MTT_DB_HOST,
|
||||
'user' => MTT_DB_USER,
|
||||
'password' => MTT_DB_PASSWORD,
|
||||
'db' => MTT_DB_NAME,
|
||||
));
|
||||
}
|
||||
catch(Exception $e) {
|
||||
logAndDie("Failed to connect to mysql database: ". $e->getMessage());
|
||||
}
|
||||
$db->dq("SET NAMES utf8mb4");
|
||||
}
|
||||
|
||||
# SQLite3 Database
|
||||
elseif (MTT_DB_TYPE == 'sqlite')
|
||||
{
|
||||
require_once(MTTINC. 'class.db.sqlite3.php');
|
||||
$db = DBConnection::init(new Database_Sqlite3);
|
||||
$db->connect( array( 'filename' => MTTPATH. 'db/todolist.db' ) );
|
||||
require_once(MTTINC. 'class.db.sqlite3.php');
|
||||
$db = DBConnection::init(new Database_Sqlite3);
|
||||
$db->connect( array( 'filename' => MTTPATH. 'db/todolist.db' ) );
|
||||
}
|
||||
else {
|
||||
die("Incorrect database connection config");
|
||||
die("Incorrect database connection config");
|
||||
}
|
||||
|
||||
DBConnection::setPrefix(MTT_DB_PREFIX);
|
||||
|
|
@ -81,7 +81,7 @@ if( isset($_COOKIE['lang']) ) $forceLang = $_COOKIE['lang'];
|
|||
//else if ( isset($_GET['lang']) ) $forceLang = $_GET['lang'];
|
||||
|
||||
if ( $forceLang != '' && preg_match("/^[a-z-]+$/i", $forceLang) ) {
|
||||
Config::set('lang', $forceLang); //TODO: special for demo, do not change config
|
||||
Config::set('lang', $forceLang); //TODO: special for demo, do not change config
|
||||
}
|
||||
|
||||
require_once(MTTINC. 'class.lang.php');
|
||||
|
|
@ -90,131 +90,131 @@ Lang::loadLang( Config::get('lang') );
|
|||
$_mttinfo = array();
|
||||
|
||||
if (need_auth() && !isset($dontStartSession)) {
|
||||
setup_and_start_session();
|
||||
setup_and_start_session();
|
||||
}
|
||||
|
||||
|
||||
function requireConfig()
|
||||
{
|
||||
$exists = file_exists(MTTPATH. 'config.php');
|
||||
$defined = false;
|
||||
if ($exists) {
|
||||
require_once(MTTPATH. 'config.php');
|
||||
$defined = defined('MTT_DB_TYPE');
|
||||
}
|
||||
# It seems not installed
|
||||
if (!$defined) {
|
||||
die("Not installed. Run <a href=setup.php>setup.php</a> first.");
|
||||
}
|
||||
$exists = file_exists(MTTPATH. 'config.php');
|
||||
$defined = false;
|
||||
if ($exists) {
|
||||
require_once(MTTPATH. 'config.php');
|
||||
$defined = defined('MTT_DB_TYPE');
|
||||
}
|
||||
# It seems not installed
|
||||
if (!$defined) {
|
||||
die("Not installed. Run <a href=setup.php>setup.php</a> first.");
|
||||
}
|
||||
}
|
||||
|
||||
function need_auth(): bool
|
||||
{
|
||||
return (Config::get('password') != '') ? true : false;
|
||||
return (Config::get('password') != '') ? true : false;
|
||||
}
|
||||
|
||||
function is_logged(): bool
|
||||
{
|
||||
if ( !need_auth() ) return true;
|
||||
if ( !isset($_SESSION['logged']) || !isset($_SESSION['sign']) ) return false;
|
||||
if ( !(int)$_SESSION['logged'] ) return false;
|
||||
return isSignatureOk($_SESSION['sign'], session_id(), Config::get('password'), defined('MTT_SALT') ? MTT_SALT : '');
|
||||
if ( !need_auth() ) return true;
|
||||
if ( !isset($_SESSION['logged']) || !isset($_SESSION['sign']) ) return false;
|
||||
if ( !(int)$_SESSION['logged'] ) return false;
|
||||
return isSignatureOk($_SESSION['sign'], session_id(), Config::get('password'), defined('MTT_SALT') ? MTT_SALT : '');
|
||||
}
|
||||
|
||||
function is_readonly(): bool
|
||||
{
|
||||
if ( !is_logged() ) return true;
|
||||
return false;
|
||||
if ( !is_logged() ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function access_token(): string
|
||||
{
|
||||
if (!need_auth()) return '';
|
||||
if (!isset($_SESSION)) return '';
|
||||
if (!isset($_SESSION['token'])) return '';
|
||||
return $_SESSION['token'];
|
||||
if (!need_auth()) return '';
|
||||
if (!isset($_SESSION)) return '';
|
||||
if (!isset($_SESSION['token'])) return '';
|
||||
return $_SESSION['token'];
|
||||
}
|
||||
|
||||
function check_token()
|
||||
{
|
||||
$token = access_token();
|
||||
if ($token == '') return true;
|
||||
if (!isset($_SERVER)) return true;
|
||||
if (!isset($_SERVER['HTTP_MTT_TOKEN']) || $_SERVER['HTTP_MTT_TOKEN'] != $token) {
|
||||
die("Access denied! Try to reload the page.");
|
||||
}
|
||||
$token = access_token();
|
||||
if ($token == '') return true;
|
||||
if (!isset($_SERVER)) return true;
|
||||
if (!isset($_SERVER['HTTP_MTT_TOKEN']) || $_SERVER['HTTP_MTT_TOKEN'] != $token) {
|
||||
die("Access denied! Try to reload the page.");
|
||||
}
|
||||
}
|
||||
|
||||
function setup_and_start_session()
|
||||
{
|
||||
require_once(MTTINC. 'class.sessionhandler.php');
|
||||
session_set_save_handler(new MTTSessionHandler());
|
||||
require_once(MTTINC. 'class.sessionhandler.php');
|
||||
session_set_save_handler(new MTTSessionHandler());
|
||||
|
||||
ini_set('session.use_cookies', true);
|
||||
ini_set('session.use_only_cookies', true);
|
||||
ini_set('session.use_cookies', true);
|
||||
ini_set('session.use_only_cookies', true);
|
||||
|
||||
$lifetime = 5184000; # 60 days session cookie lifetime
|
||||
$path = url_dir(Config::get('url')=='' ? getRequestUri() : Config::getUrl('url'));
|
||||
$samesite = 'lax';
|
||||
$lifetime = 5184000; # 60 days session cookie lifetime
|
||||
$path = url_dir(Config::get('url')=='' ? getRequestUri() : Config::getUrl('url'));
|
||||
$samesite = 'lax';
|
||||
|
||||
if (PHP_VERSION_ID < 70300) {
|
||||
# this is a known samesite flag workaround, was fixed in 7.3
|
||||
session_set_cookie_params($lifetime, $path. '; samesite='.$samesite, null, null, true);
|
||||
} else {
|
||||
session_set_cookie_params(Array(
|
||||
'lifetime' => $lifetime,
|
||||
'path' => $path,
|
||||
'httponly' => true,
|
||||
'samesite' => $samesite
|
||||
));
|
||||
}
|
||||
session_name('mtt-session');
|
||||
session_start();
|
||||
if (PHP_VERSION_ID < 70300) {
|
||||
# this is a known samesite flag workaround, was fixed in 7.3
|
||||
session_set_cookie_params($lifetime, $path. '; samesite='.$samesite, null, null, true);
|
||||
} else {
|
||||
session_set_cookie_params(Array(
|
||||
'lifetime' => $lifetime,
|
||||
'path' => $path,
|
||||
'httponly' => true,
|
||||
'samesite' => $samesite
|
||||
));
|
||||
}
|
||||
session_name('mtt-session');
|
||||
session_start();
|
||||
}
|
||||
|
||||
function timestampToDatetime($timestamp)
|
||||
{
|
||||
$format = Config::get('dateformat') .' '. (Config::get('clock') == 12 ? 'g:i A' : 'H:i');
|
||||
return formatTime($format, $timestamp);
|
||||
$format = Config::get('dateformat') .' '. (Config::get('clock') == 12 ? 'g:i A' : 'H:i');
|
||||
return formatTime($format, $timestamp);
|
||||
}
|
||||
|
||||
function formatTime($format, $timestamp=0)
|
||||
{
|
||||
$lang = Lang::instance();
|
||||
if($timestamp == 0) $timestamp = time();
|
||||
$newformat = strtr($format, array('F'=>'%1', 'M'=>'%2'));
|
||||
$adate = explode(',', date('n,'.$newformat, $timestamp), 2);
|
||||
$s = $adate[1];
|
||||
if($newformat != $format)
|
||||
{
|
||||
$am = (int)$adate[0];
|
||||
$ml = $lang->get('months_long');
|
||||
$ms = $lang->get('months_short');
|
||||
$F = $ml[$am-1];
|
||||
$M = $ms[$am-1];
|
||||
$s = strtr($s, array('%1'=>$F, '%2'=>$M));
|
||||
}
|
||||
return $s;
|
||||
$lang = Lang::instance();
|
||||
if($timestamp == 0) $timestamp = time();
|
||||
$newformat = strtr($format, array('F'=>'%1', 'M'=>'%2'));
|
||||
$adate = explode(',', date('n,'.$newformat, $timestamp), 2);
|
||||
$s = $adate[1];
|
||||
if($newformat != $format)
|
||||
{
|
||||
$am = (int)$adate[0];
|
||||
$ml = $lang->get('months_long');
|
||||
$ms = $lang->get('months_short');
|
||||
$F = $ml[$am-1];
|
||||
$M = $ms[$am-1];
|
||||
$s = strtr($s, array('%1'=>$F, '%2'=>$M));
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
function _e($s)
|
||||
{
|
||||
echo Lang::instance()->get($s);
|
||||
echo Lang::instance()->get($s);
|
||||
}
|
||||
|
||||
function __($s)
|
||||
{
|
||||
return Lang::instance()->get($s);
|
||||
return Lang::instance()->get($s);
|
||||
}
|
||||
|
||||
function mttinfo($v)
|
||||
{
|
||||
echo get_mttinfo($v);
|
||||
echo get_mttinfo($v);
|
||||
}
|
||||
|
||||
function get_mttinfo($v)
|
||||
{
|
||||
return htmlspecialchars( get_unsafe_mttinfo($v) );
|
||||
return htmlspecialchars( get_unsafe_mttinfo($v) );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -223,70 +223,70 @@ function get_mttinfo($v)
|
|||
*/
|
||||
function get_unsafe_mttinfo($v)
|
||||
{
|
||||
global $_mttinfo;
|
||||
if (isset($_mttinfo[$v])) {
|
||||
return $_mttinfo[$v];
|
||||
}
|
||||
switch($v)
|
||||
{
|
||||
case 'template_url':
|
||||
$_mttinfo['template_url'] = get_unsafe_mttinfo('mtt_url'). 'content/themes/'. Config::get('template') . '/';
|
||||
return $_mttinfo['template_url'];
|
||||
case 'includes_url':
|
||||
$_mttinfo['includes_url'] = get_unsafe_mttinfo('mtt_url'). 'includes/';
|
||||
return $_mttinfo['includes_url'];
|
||||
case 'url':
|
||||
/* full url to homepage: directory with root index.php or custom index file in the root. */
|
||||
/* ex: http://my.site/mytinytodo/ or https://my.site/mytinytodo/home_for_2nd_theme.php */
|
||||
/* Should not contain a query string. Have to be set in config if custom port is used or wrong detection. */
|
||||
$_mttinfo['url'] = Config::getUrl('url');
|
||||
if ($_mttinfo['url'] == '') {
|
||||
$is_https = (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false;
|
||||
$_mttinfo['url'] = ($is_https ? 'https://' : 'http://'). $_SERVER['HTTP_HOST']. url_dir(getRequestUri());
|
||||
}
|
||||
return $_mttinfo['url'];
|
||||
case 'mtt_url':
|
||||
/* Directory with ajax.php. No need to set if you use default directory structure. */
|
||||
$_mttinfo['mtt_url'] = Config::getUrl('mtt_url'); // need to have a trailing slash
|
||||
if ($_mttinfo['mtt_url'] == '') {
|
||||
$_mttinfo['mtt_url'] = url_dir( get_unsafe_mttinfo('url'), 0 );
|
||||
}
|
||||
return $_mttinfo['mtt_url'];
|
||||
case 'title':
|
||||
$_mttinfo['title'] = (Config::get('title') != '') ? Config::get('title') : __('My Tiny Todolist');
|
||||
return $_mttinfo['title'];
|
||||
case 'version':
|
||||
if (MTT_VERSION != '@'.'VERSION') {
|
||||
$_mttinfo['version'] = MTT_VERSION;
|
||||
return $_mttinfo['version'];
|
||||
}
|
||||
return time(); //force no-cache for dev needs
|
||||
}
|
||||
global $_mttinfo;
|
||||
if (isset($_mttinfo[$v])) {
|
||||
return $_mttinfo[$v];
|
||||
}
|
||||
switch($v)
|
||||
{
|
||||
case 'template_url':
|
||||
$_mttinfo['template_url'] = get_unsafe_mttinfo('mtt_url'). 'content/themes/'. Config::get('template') . '/';
|
||||
return $_mttinfo['template_url'];
|
||||
case 'includes_url':
|
||||
$_mttinfo['includes_url'] = get_unsafe_mttinfo('mtt_url'). 'includes/';
|
||||
return $_mttinfo['includes_url'];
|
||||
case 'url':
|
||||
/* full url to homepage: directory with root index.php or custom index file in the root. */
|
||||
/* ex: http://my.site/mytinytodo/ or https://my.site/mytinytodo/home_for_2nd_theme.php */
|
||||
/* Should not contain a query string. Have to be set in config if custom port is used or wrong detection. */
|
||||
$_mttinfo['url'] = Config::getUrl('url');
|
||||
if ($_mttinfo['url'] == '') {
|
||||
$is_https = (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') ? true : false;
|
||||
$_mttinfo['url'] = ($is_https ? 'https://' : 'http://'). $_SERVER['HTTP_HOST']. url_dir(getRequestUri());
|
||||
}
|
||||
return $_mttinfo['url'];
|
||||
case 'mtt_url':
|
||||
/* Directory with ajax.php. No need to set if you use default directory structure. */
|
||||
$_mttinfo['mtt_url'] = Config::getUrl('mtt_url'); // need to have a trailing slash
|
||||
if ($_mttinfo['mtt_url'] == '') {
|
||||
$_mttinfo['mtt_url'] = url_dir( get_unsafe_mttinfo('url'), 0 );
|
||||
}
|
||||
return $_mttinfo['mtt_url'];
|
||||
case 'title':
|
||||
$_mttinfo['title'] = (Config::get('title') != '') ? Config::get('title') : __('My Tiny Todolist');
|
||||
return $_mttinfo['title'];
|
||||
case 'version':
|
||||
if (MTT_VERSION != '@'.'VERSION') {
|
||||
$_mttinfo['version'] = MTT_VERSION;
|
||||
return $_mttinfo['version'];
|
||||
}
|
||||
return time(); //force no-cache for dev needs
|
||||
}
|
||||
}
|
||||
|
||||
function reset_mttinfo($key)
|
||||
{
|
||||
global $_mttinfo;
|
||||
unset( $_mttinfo[$key] );
|
||||
global $_mttinfo;
|
||||
unset( $_mttinfo[$key] );
|
||||
}
|
||||
|
||||
function jsonExit($data)
|
||||
{
|
||||
header('Content-type: application/json; charset=utf-8');
|
||||
echo json_encode($data);
|
||||
exit;
|
||||
header('Content-type: application/json; charset=utf-8');
|
||||
echo json_encode($data);
|
||||
exit;
|
||||
}
|
||||
|
||||
function logAndDie($userText, $errText = null)
|
||||
{
|
||||
$errText === null ? error_log($userText) : error_log($errText);
|
||||
if (ini_get('display_errors')) {
|
||||
echo htmlspecialchars($userText);
|
||||
}
|
||||
else {
|
||||
echo "Error! See details in error log.";
|
||||
}
|
||||
exit(1);
|
||||
$errText === null ? error_log($userText) : error_log($errText);
|
||||
if (ini_get('display_errors')) {
|
||||
echo htmlspecialchars($userText);
|
||||
}
|
||||
else {
|
||||
echo "Error! See details in error log.";
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
?>
|
||||
162
src/settings.php
162
src/settings.php
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2011,2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2011,2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
require_once('./init.php');
|
||||
|
|
@ -11,81 +11,81 @@ require_once('./init.php');
|
|||
$lang = Lang::instance();
|
||||
|
||||
if ( !is_logged() ) {
|
||||
die("Access denied!<br/> Disable password protection or Log in.");
|
||||
die("Access denied!<br/> Disable password protection or Log in.");
|
||||
}
|
||||
|
||||
if(isset($_POST['save']))
|
||||
{
|
||||
check_token();
|
||||
check_token();
|
||||
|
||||
$t = array();
|
||||
$langs = getLangs();
|
||||
Config::$params['lang']['options'] = array_keys($langs);
|
||||
Config::set('lang', _post('lang'));
|
||||
$t = array();
|
||||
$langs = getLangs();
|
||||
Config::$params['lang']['options'] = array_keys($langs);
|
||||
Config::set('lang', _post('lang'));
|
||||
|
||||
// in Demo mode we can set only language by cookies
|
||||
if(defined('MTTDEMO')) {
|
||||
setcookie('lang', Config::get('lang'), 0, url_dir(Config::get('url')=='' ? getRequestUri() : Config::getUrl('url')));
|
||||
$t['saved'] = 1;
|
||||
jsonExit($t);
|
||||
}
|
||||
// in Demo mode we can set only language by cookies
|
||||
if(defined('MTTDEMO')) {
|
||||
setcookie('lang', Config::get('lang'), 0, url_dir(Config::get('url')=='' ? getRequestUri() : Config::getUrl('url')));
|
||||
$t['saved'] = 1;
|
||||
jsonExit($t);
|
||||
}
|
||||
|
||||
if (isset($_POST['password']) && $_POST['password'] != '') Config::set('password', passwordHash($_POST['password'])) ;
|
||||
elseif (!_post('allowpassword')) Config::set('password', '');
|
||||
if (isset($_POST['password']) && $_POST['password'] != '') Config::set('password', passwordHash($_POST['password'])) ;
|
||||
elseif (!_post('allowpassword')) Config::set('password', '');
|
||||
|
||||
Config::set('smartsyntax', (int)_post('smartsyntax'));
|
||||
// Do not set invalid timezone
|
||||
try {
|
||||
$tz = trim(_post('timezone'));
|
||||
$testTZ = new DateTimeZone($tz); //will throw Exception on invalid timezone
|
||||
Config::set('timezone', $tz);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
}
|
||||
Config::set('autotag', (int)_post('autotag'));
|
||||
Config::set('markup', (int)_post('markdown') == 0 ? 'v1' : 'markdown');
|
||||
Config::set('firstdayofweek', (int)_post('firstdayofweek'));
|
||||
Config::set('clock', (int)_post('clock'));
|
||||
Config::set('dateformat', removeNewLines(_post('dateformat')) );
|
||||
Config::set('dateformat2', removeNewLines(_post('dateformat2')) );
|
||||
Config::set('dateformatshort', removeNewLines(_post('dateformatshort')) );
|
||||
Config::set('title', removeNewLines(trim(_post('title'))) );
|
||||
Config::set('showdate', (int)_post('showdate'));
|
||||
Config::save();
|
||||
$t['saved'] = 1;
|
||||
jsonExit($t);
|
||||
Config::set('smartsyntax', (int)_post('smartsyntax'));
|
||||
// Do not set invalid timezone
|
||||
try {
|
||||
$tz = trim(_post('timezone'));
|
||||
$testTZ = new DateTimeZone($tz); //will throw Exception on invalid timezone
|
||||
Config::set('timezone', $tz);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
}
|
||||
Config::set('autotag', (int)_post('autotag'));
|
||||
Config::set('markup', (int)_post('markdown') == 0 ? 'v1' : 'markdown');
|
||||
Config::set('firstdayofweek', (int)_post('firstdayofweek'));
|
||||
Config::set('clock', (int)_post('clock'));
|
||||
Config::set('dateformat', removeNewLines(_post('dateformat')) );
|
||||
Config::set('dateformat2', removeNewLines(_post('dateformat2')) );
|
||||
Config::set('dateformatshort', removeNewLines(_post('dateformatshort')) );
|
||||
Config::set('title', removeNewLines(trim(_post('title'))) );
|
||||
Config::set('showdate', (int)_post('showdate'));
|
||||
Config::save();
|
||||
$t['saved'] = 1;
|
||||
jsonExit($t);
|
||||
}
|
||||
|
||||
function _c($key)
|
||||
{
|
||||
return Config::get($key);
|
||||
return Config::get($key);
|
||||
}
|
||||
|
||||
function getLangs($withContents = 0)
|
||||
{
|
||||
$langDir = Lang::instance()->langDir();
|
||||
$langDir = Lang::instance()->langDir();
|
||||
if ( ! $h = opendir($langDir) ) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
$a = array();
|
||||
while ( false !== ($file = readdir($h)) )
|
||||
{
|
||||
if ( preg_match('/(.+)\.json$/', $file, $m) ) {
|
||||
$jsonText = file_get_contents($langDir. $file);
|
||||
if (false === $jsonText) {
|
||||
die("false ");
|
||||
continue;
|
||||
}
|
||||
$a[$m[1]] = $m[1];
|
||||
{
|
||||
if ( preg_match('/(.+)\.json$/', $file, $m) ) {
|
||||
$jsonText = file_get_contents($langDir. $file);
|
||||
if (false === $jsonText) {
|
||||
die("false ");
|
||||
continue;
|
||||
}
|
||||
$a[$m[1]] = $m[1];
|
||||
|
||||
$j = json_decode($jsonText, true);
|
||||
if ( isset($j['_header']['language']) && isset($j['_header']['original_name']) ) {
|
||||
$a[$m[1]]= [
|
||||
'name' => $j['_header']['original_name'],
|
||||
'title' => $j['_header']['language']
|
||||
];
|
||||
}
|
||||
}
|
||||
$j = json_decode($jsonText, true);
|
||||
if ( isset($j['_header']['language']) && isset($j['_header']['original_name']) ) {
|
||||
$a[$m[1]]= [
|
||||
'name' => $j['_header']['original_name'],
|
||||
'title' => $j['_header']['language']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($h);
|
||||
return $a;
|
||||
|
|
@ -94,13 +94,13 @@ function getLangs($withContents = 0)
|
|||
|
||||
function selectOptions($a, $value, $default=null)
|
||||
{
|
||||
if(!$a) return '';
|
||||
$s = '';
|
||||
if($default !== null && !isset($a[$value])) $value = $default;
|
||||
foreach($a as $k=>$v) {
|
||||
$s .= '<option value="'.htmlspecialchars($k).'" '.($k===$value?'selected="selected"':'').'>'.htmlspecialchars($v).'</option>';
|
||||
}
|
||||
return $s;
|
||||
if(!$a) return '';
|
||||
$s = '';
|
||||
if($default !== null && !isset($a[$value])) $value = $default;
|
||||
foreach($a as $k=>$v) {
|
||||
$s .= '<option value="'.htmlspecialchars($k).'" '.($k===$value?'selected="selected"':'').'>'.htmlspecialchars($v).'</option>';
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -110,15 +110,15 @@ function selectOptions($a, $value, $default=null)
|
|||
*/
|
||||
function selectOptionsA($a, $key, $default=null)
|
||||
{
|
||||
if(!$a) return '';
|
||||
$s = '';
|
||||
if($default !== null && !isset($a[$key])) $key = $default;
|
||||
foreach($a as $k=>$v) {
|
||||
$s .= '<option value="'.htmlspecialchars($k).'" '.($k===$key?'selected="selected"':'').
|
||||
(isset($v['title']) ? ' title="'.htmlspecialchars($v['title']).'"' : '').
|
||||
'>'.htmlspecialchars($v['name']).'</option>';
|
||||
}
|
||||
return $s;
|
||||
if(!$a) return '';
|
||||
$s = '';
|
||||
if($default !== null && !isset($a[$key])) $key = $default;
|
||||
foreach($a as $k=>$v) {
|
||||
$s .= '<option value="'.htmlspecialchars($k).'" '.($k===$key?'selected="selected"':'').
|
||||
(isset($v['title']) ? ' title="'.htmlspecialchars($v['title']).'"' : '').
|
||||
'>'.htmlspecialchars($v['name']).'</option>';
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
function timezoneIdentifiers()
|
||||
|
|
@ -138,10 +138,10 @@ header('Content-type:text/html; charset=utf-8');
|
|||
|
||||
|
||||
<?php
|
||||
if (isset($_GET['json'])) {
|
||||
$j = Config::requestDefaultDomain();
|
||||
if ($j['password'] != '') $j['password'] = "<not empty>";
|
||||
$j = json_encode($j, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
||||
if (isset($_GET['json'])) {
|
||||
$j = Config::requestDefaultDomain();
|
||||
if ($j['password'] != '') $j['password'] = "<not empty>";
|
||||
$j = json_encode($j, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
||||
?>
|
||||
<div class="mtt-settings-table">
|
||||
<div class="tr">
|
||||
|
|
@ -150,8 +150,8 @@ header('Content-type:text/html; charset=utf-8');
|
|||
</div>
|
||||
</div>
|
||||
<?php
|
||||
exit;
|
||||
}
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<div id="settings_msg" style="display:none"></div>
|
||||
|
|
@ -221,7 +221,7 @@ header('Content-type:text/html; charset=utf-8');
|
|||
<input name="dateformat" size="8" value="<?php echo htmlspecialchars(_c('dateformat'));?>" />
|
||||
<select onchange="if(this.value!=0) this.form.dateformat.value=this.value;">
|
||||
<?php echo selectOptions(array('F j, Y'=>formatTime('F j, Y'), 'M d, Y'=>formatTime('M d, Y'), 'j M Y'=>formatTime('j M Y'), 'd F Y'=>formatTime('d F Y'),
|
||||
'n/j/Y'=>formatTime('n/j/Y'), 'd.m.Y'=>formatTime('d.m.Y'), 'j. F Y'=>formatTime('j. F Y'), 0=>__('set_custom')), _c('dateformat'), 0); ?>
|
||||
'n/j/Y'=>formatTime('n/j/Y'), 'd.m.Y'=>formatTime('d.m.Y'), 'j. F Y'=>formatTime('j. F Y'), 0=>__('set_custom')), _c('dateformat'), 0); ?>
|
||||
</select>
|
||||
</div></div>
|
||||
|
||||
|
|
|
|||
748
src/setup.php
748
src/setup.php
|
|
@ -1,19 +1,19 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2011,2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2009-2011,2020-2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
// Can be used to upgrade database from myTinyTodo v1.4 or later
|
||||
$lastVer = '1.7';
|
||||
|
||||
if (getenv('MTT_ENABLE_DEBUG') == 'YES') {
|
||||
set_exception_handler('debugExceptionHandler');
|
||||
set_exception_handler('debugExceptionHandler');
|
||||
}
|
||||
else {
|
||||
set_exception_handler('myExceptionHandler');
|
||||
set_exception_handler('myExceptionHandler');
|
||||
}
|
||||
|
||||
if (!defined('MTTPATH')) define('MTTPATH', dirname(__FILE__) .'/');
|
||||
|
|
@ -35,141 +35,141 @@ echo "<big><b>myTinyTodo @VERSION Setup</b></big><br><br>";
|
|||
|
||||
if (!$configExists && $oldConfigExists)
|
||||
{
|
||||
// First we need to migrate database config
|
||||
require_once(MTTPATH. 'db/config.php');
|
||||
if (isset($config['password']) && $config['password'] != '') {
|
||||
if (!isset($_POST['configpassword']) || $_POST['configpassword'] != $config['password']) {
|
||||
exitMessage("Enter current password to continue. <form method=post><input type=password name=configpassword> <input type=submit value=' Continue '></form>");
|
||||
}
|
||||
}
|
||||
Config::loadConfigV14($config);
|
||||
tryToSaveDBConfig();
|
||||
$configExists = true;
|
||||
// First we need to migrate database config
|
||||
require_once(MTTPATH. 'db/config.php');
|
||||
if (isset($config['password']) && $config['password'] != '') {
|
||||
if (!isset($_POST['configpassword']) || $_POST['configpassword'] != $config['password']) {
|
||||
exitMessage("Enter current password to continue. <form method=post><input type=password name=configpassword> <input type=submit value=' Continue '></form>");
|
||||
}
|
||||
}
|
||||
Config::loadConfigV14($config);
|
||||
tryToSaveDBConfig();
|
||||
$configExists = true;
|
||||
}
|
||||
|
||||
if ($configExists)
|
||||
{
|
||||
// No need to migrate database config
|
||||
require_once(MTTPATH. 'config.php');
|
||||
$db = testConnect($error);
|
||||
if (!$db) {
|
||||
exitMessage( "Database connection config file seems to be incorrect. You can remove config.php or edit it manually and then reload setup.<br><br>".
|
||||
"<b>Error:</b> ". htmlspecialchars($error) );
|
||||
}
|
||||
// Config file v1.7 already exists and set up correctly
|
||||
$dbtype = MTT_DB_TYPE;
|
||||
// No need to migrate database config
|
||||
require_once(MTTPATH. 'config.php');
|
||||
$db = testConnect($error);
|
||||
if (!$db) {
|
||||
exitMessage( "Database connection config file seems to be incorrect. You can remove config.php or edit it manually and then reload setup.<br><br>".
|
||||
"<b>Error:</b> ". htmlspecialchars($error) );
|
||||
}
|
||||
// Config file v1.7 already exists and set up correctly
|
||||
$dbtype = MTT_DB_TYPE;
|
||||
|
||||
// Determine current installed db version
|
||||
$ver = databaseVersion($db);
|
||||
// Determine current installed db version
|
||||
$ver = databaseVersion($db);
|
||||
|
||||
if ($ver == '1.4') {
|
||||
// Need to upgrade. Do not ask for old password
|
||||
require_once(MTTPATH. 'db/config.php');
|
||||
Config::loadConfigV14($config);
|
||||
unset($config);
|
||||
DBConnection::init($db);
|
||||
}
|
||||
else {
|
||||
if ($ver != '1.7') {
|
||||
Config::$noDatabase = true; //will not load settings from database in init.php
|
||||
}
|
||||
require_once('./init.php');
|
||||
if ( !is_logged() ) {
|
||||
die("Access denied!<br> Disable password protection or Log in.");
|
||||
}
|
||||
}
|
||||
if ($ver == '1.4') {
|
||||
// Need to upgrade. Do not ask for old password
|
||||
require_once(MTTPATH. 'db/config.php');
|
||||
Config::loadConfigV14($config);
|
||||
unset($config);
|
||||
DBConnection::init($db);
|
||||
}
|
||||
else {
|
||||
if ($ver != '1.7') {
|
||||
Config::$noDatabase = true; //will not load settings from database in init.php
|
||||
}
|
||||
require_once('./init.php');
|
||||
if ( !is_logged() ) {
|
||||
die("Access denied!<br> Disable password protection or Log in.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($ver == '')
|
||||
{
|
||||
$install = trim(_post('install'));
|
||||
$install = trim(_post('install'));
|
||||
|
||||
if ($install == '' && $db !== null)
|
||||
{
|
||||
# We already have settings file and need to create tables.
|
||||
exitMessage("<form method=post>Click next to create tables in '". htmlspecialchars($dbtype). "' database.<br><br>
|
||||
<input type=hidden name=install value=create><input type=submit value=' Next '></form>");
|
||||
}
|
||||
elseif ($install == '')
|
||||
{
|
||||
# Specify database type and connection settings to save.
|
||||
exitMessage("
|
||||
<form method=post>Select database type to use:<br><br>
|
||||
<input type=hidden name=install value=config>
|
||||
<label><input type=radio name=db_type value=sqlite checked=checked onclick=\"document.getElementById('mysqlsettings').style.display='none'\">SQLite</label><br><br>
|
||||
<label><input type=radio name=db_type value=mysql onclick=\"document.getElementById('mysqlsettings').style.display=''\">MySQL</label><br>
|
||||
<div id='mysqlsettings' style='display:none; margin-left:30px;'><br><table>
|
||||
<tr><td>Host:</td><td><input name=db_host value=localhost></td></tr>
|
||||
<tr><td>Database:</td><td><input name=db_name value=mytinytodo></td></tr>
|
||||
<tr><td>User:</td><td><input name=db_user value=mtt></td></tr>
|
||||
<tr><td>Password:</td><td><input type=password name=db_password></td></tr>
|
||||
<tr><td>Table prefix:</td><td><input name=db_prefix value='mtt_'></td></tr>
|
||||
</table></div><br><input type=submit value=' Next '></form>
|
||||
");
|
||||
}
|
||||
elseif ($install == 'config')
|
||||
{
|
||||
# Save configuration
|
||||
$dbtype = ($_POST['db_type'] == 'mysql') ? 'mysql' : 'sqlite';
|
||||
Config::set('db.type', $dbtype);
|
||||
if ($dbtype == 'mysql') {
|
||||
Config::set('db.host', _post('db_host'));
|
||||
Config::set('db.name', _post('db_name'));
|
||||
Config::set('db.user', _post('db_user'));
|
||||
Config::set('db.password', _post('db_password'));
|
||||
Config::set('db.prefix', trim(_post('db_prefix')));
|
||||
}
|
||||
Config::defineDbConstants();
|
||||
$db = testConnect($error);
|
||||
if (!$db) {
|
||||
exitMessage("Database connection error: ". htmlspecialchars($error));
|
||||
}
|
||||
if (defined('MTT_DB_DRIVER')) {
|
||||
Config::set('db.driver', MTT_DB_DRIVER);
|
||||
}
|
||||
tryToSaveDBConfig();
|
||||
exitMessage("This will create myTinyTodo database <br> <form method=post><input type=hidden name=install value=create><input type=submit value=' Install '></form>");
|
||||
}
|
||||
elseif ($install == 'create')
|
||||
{
|
||||
# install database
|
||||
try {
|
||||
createAllTables($db, $dbtype);
|
||||
} catch (Exception $e) {
|
||||
exitMessage("<b>Error:</b> ". htmlarray($e->getMessage()));
|
||||
}
|
||||
if ($install == '' && $db !== null)
|
||||
{
|
||||
# We already have settings file and need to create tables.
|
||||
exitMessage("<form method=post>Click next to create tables in '". htmlspecialchars($dbtype). "' database.<br><br>
|
||||
<input type=hidden name=install value=create><input type=submit value=' Next '></form>");
|
||||
}
|
||||
elseif ($install == '')
|
||||
{
|
||||
# Specify database type and connection settings to save.
|
||||
exitMessage("
|
||||
<form method=post>Select database type to use:<br><br>
|
||||
<input type=hidden name=install value=config>
|
||||
<label><input type=radio name=db_type value=sqlite checked=checked onclick=\"document.getElementById('mysqlsettings').style.display='none'\">SQLite</label><br><br>
|
||||
<label><input type=radio name=db_type value=mysql onclick=\"document.getElementById('mysqlsettings').style.display=''\">MySQL</label><br>
|
||||
<div id='mysqlsettings' style='display:none; margin-left:30px;'><br><table>
|
||||
<tr><td>Host:</td><td><input name=db_host value=localhost></td></tr>
|
||||
<tr><td>Database:</td><td><input name=db_name value=mytinytodo></td></tr>
|
||||
<tr><td>User:</td><td><input name=db_user value=mtt></td></tr>
|
||||
<tr><td>Password:</td><td><input type=password name=db_password></td></tr>
|
||||
<tr><td>Table prefix:</td><td><input name=db_prefix value='mtt_'></td></tr>
|
||||
</table></div><br><input type=submit value=' Next '></form>
|
||||
");
|
||||
}
|
||||
elseif ($install == 'config')
|
||||
{
|
||||
# Save configuration
|
||||
$dbtype = ($_POST['db_type'] == 'mysql') ? 'mysql' : 'sqlite';
|
||||
Config::set('db.type', $dbtype);
|
||||
if ($dbtype == 'mysql') {
|
||||
Config::set('db.host', _post('db_host'));
|
||||
Config::set('db.name', _post('db_name'));
|
||||
Config::set('db.user', _post('db_user'));
|
||||
Config::set('db.password', _post('db_password'));
|
||||
Config::set('db.prefix', trim(_post('db_prefix')));
|
||||
}
|
||||
Config::defineDbConstants();
|
||||
$db = testConnect($error);
|
||||
if (!$db) {
|
||||
exitMessage("Database connection error: ". htmlspecialchars($error));
|
||||
}
|
||||
if (defined('MTT_DB_DRIVER')) {
|
||||
Config::set('db.driver', MTT_DB_DRIVER);
|
||||
}
|
||||
tryToSaveDBConfig();
|
||||
exitMessage("This will create myTinyTodo database <br> <form method=post><input type=hidden name=install value=create><input type=submit value=' Install '></form>");
|
||||
}
|
||||
elseif ($install == 'create')
|
||||
{
|
||||
# install database
|
||||
try {
|
||||
createAllTables($db, $dbtype);
|
||||
} catch (Exception $e) {
|
||||
exitMessage("<b>Error:</b> ". htmlarray($e->getMessage()));
|
||||
}
|
||||
|
||||
# create default list
|
||||
$db->ex( "INSERT INTO {$db->prefix}lists (uuid,name,d_created,taskview) VALUES (?,?,?,?)", array(generateUUID(), 'Todo', time(), 1) );
|
||||
# create default list
|
||||
$db->ex( "INSERT INTO {$db->prefix}lists (uuid,name,d_created,taskview) VALUES (?,?,?,?)", array(generateUUID(), 'Todo', time(), 1) );
|
||||
|
||||
Config::save();
|
||||
}
|
||||
else {
|
||||
exitMessage("Unknown action");
|
||||
}
|
||||
Config::save();
|
||||
}
|
||||
else {
|
||||
exitMessage("Unknown action");
|
||||
}
|
||||
}
|
||||
elseif ($ver == $lastVer)
|
||||
{
|
||||
exitMessage("Installed version does not require database update.");
|
||||
exitMessage("Installed version does not require database update.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!in_array($ver, array('1.4'))) {
|
||||
exitMessage(htmlspecialchars("Can not update. Unsupported database version ($ver)."));
|
||||
}
|
||||
if (!in_array($ver, array('1.4'))) {
|
||||
exitMessage(htmlspecialchars("Can not update. Unsupported database version ($ver)."));
|
||||
}
|
||||
|
||||
if (!isset($_POST['update'])) {
|
||||
exitMessage(htmlspecialchars("Update database v$ver to v$lastVer"). "<br><br>
|
||||
<form name=frm method=post><input type=hidden name=update value=1>
|
||||
<input type=submit value=' Update '>
|
||||
</form>");
|
||||
}
|
||||
if (!isset($_POST['update'])) {
|
||||
exitMessage(htmlspecialchars("Update database v$ver to v$lastVer"). "<br><br>
|
||||
<form name=frm method=post><input type=hidden name=update value=1>
|
||||
<input type=submit value=' Update '>
|
||||
</form>");
|
||||
}
|
||||
|
||||
# update process
|
||||
if ($ver == '1.4')
|
||||
{
|
||||
update_14_17($db, $dbtype);
|
||||
}
|
||||
# update process
|
||||
if ($ver == '1.4')
|
||||
{
|
||||
update_14_17($db, $dbtype);
|
||||
}
|
||||
}
|
||||
|
||||
echo "Done<br><br> <b>Attention!</b> Delete this file for security reasons. <br><br> Go to <a href='". htmlspecialchars(url_dir(getRequestUri())). "'>homepage</a>.";
|
||||
|
|
@ -178,358 +178,358 @@ printFooter();
|
|||
|
||||
function createAllTables($db, $dbtype)
|
||||
{
|
||||
if ($dbtype == 'mysql') {
|
||||
createMysqlTables($db);
|
||||
}
|
||||
else {
|
||||
createSqliteTables($db);
|
||||
}
|
||||
if ($dbtype == 'mysql') {
|
||||
createMysqlTables($db);
|
||||
}
|
||||
else {
|
||||
createSqliteTables($db);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function createMysqlTables($db)
|
||||
{
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}lists (
|
||||
`id` INT UNSIGNED NOT NULL auto_increment,
|
||||
`uuid` CHAR(36) NOT NULL default '',
|
||||
`ow` INT NOT NULL default 0,
|
||||
`name` VARCHAR(50) NOT NULL default '',
|
||||
`d_created` INT UNSIGNED NOT NULL default 0,
|
||||
`d_edited` INT UNSIGNED NOT NULL default 0,
|
||||
`sorting` TINYINT UNSIGNED NOT NULL default 0,
|
||||
`published` TINYINT UNSIGNED NOT NULL default 0,
|
||||
`taskview` INT UNSIGNED NOT NULL default 0,
|
||||
PRIMARY KEY(`id`),
|
||||
UNIQUE KEY(`uuid`)
|
||||
`id` INT UNSIGNED NOT NULL auto_increment,
|
||||
`uuid` CHAR(36) NOT NULL default '',
|
||||
`ow` INT NOT NULL default 0,
|
||||
`name` VARCHAR(50) NOT NULL default '',
|
||||
`d_created` INT UNSIGNED NOT NULL default 0,
|
||||
`d_edited` INT UNSIGNED NOT NULL default 0,
|
||||
`sorting` TINYINT UNSIGNED NOT NULL default 0,
|
||||
`published` TINYINT UNSIGNED NOT NULL default 0,
|
||||
`taskview` INT UNSIGNED NOT NULL default 0,
|
||||
PRIMARY KEY(`id`),
|
||||
UNIQUE KEY(`uuid`)
|
||||
) CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci ");
|
||||
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}todolist (
|
||||
`id` INT UNSIGNED NOT NULL auto_increment,
|
||||
`uuid` CHAR(36) NOT NULL default '',
|
||||
`list_id` INT UNSIGNED NOT NULL default 0,
|
||||
`d_created` INT UNSIGNED NOT NULL default 0, /* time() timestamp */
|
||||
`d_completed` INT UNSIGNED NOT NULL default 0, /* time() timestamp */
|
||||
`d_edited` INT UNSIGNED NOT NULL default 0, /* time() timestamp */
|
||||
`compl` TINYINT UNSIGNED NOT NULL default 0,
|
||||
`title` VARCHAR(250) NOT NULL,
|
||||
`note` TEXT,
|
||||
`prio` TINYINT NOT NULL default 0, /* priority -,0,+ */
|
||||
`ow` INT NOT NULL default 0, /* order weight */
|
||||
`tags` VARCHAR(600) NOT NULL default '', /* for fast access to task tags */
|
||||
`tags_ids` VARCHAR(250) NOT NULL default '', /* no more than 22 tags (x11 chars) */
|
||||
`duedate` DATE default NULL,
|
||||
PRIMARY KEY(`id`),
|
||||
KEY(`list_id`),
|
||||
UNIQUE KEY(`uuid`)
|
||||
`id` INT UNSIGNED NOT NULL auto_increment,
|
||||
`uuid` CHAR(36) NOT NULL default '',
|
||||
`list_id` INT UNSIGNED NOT NULL default 0,
|
||||
`d_created` INT UNSIGNED NOT NULL default 0, /* time() timestamp */
|
||||
`d_completed` INT UNSIGNED NOT NULL default 0, /* time() timestamp */
|
||||
`d_edited` INT UNSIGNED NOT NULL default 0, /* time() timestamp */
|
||||
`compl` TINYINT UNSIGNED NOT NULL default 0,
|
||||
`title` VARCHAR(250) NOT NULL,
|
||||
`note` TEXT,
|
||||
`prio` TINYINT NOT NULL default 0, /* priority -,0,+ */
|
||||
`ow` INT NOT NULL default 0, /* order weight */
|
||||
`tags` VARCHAR(600) NOT NULL default '', /* for fast access to task tags */
|
||||
`tags_ids` VARCHAR(250) NOT NULL default '', /* no more than 22 tags (x11 chars) */
|
||||
`duedate` DATE default NULL,
|
||||
PRIMARY KEY(`id`),
|
||||
KEY(`list_id`),
|
||||
UNIQUE KEY(`uuid`)
|
||||
) CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci ");
|
||||
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}tags (
|
||||
`id` INT UNSIGNED NOT NULL auto_increment,
|
||||
`name` VARCHAR(50) NOT NULL,
|
||||
PRIMARY KEY(`id`),
|
||||
UNIQUE KEY `name` (`name`)
|
||||
`id` INT UNSIGNED NOT NULL auto_increment,
|
||||
`name` VARCHAR(50) NOT NULL,
|
||||
PRIMARY KEY(`id`),
|
||||
UNIQUE KEY `name` (`name`)
|
||||
) CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci ");
|
||||
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}tag2task (
|
||||
`tag_id` INT UNSIGNED NOT NULL,
|
||||
`task_id` INT UNSIGNED NOT NULL,
|
||||
`list_id` INT UNSIGNED NOT NULL,
|
||||
KEY(`tag_id`),
|
||||
KEY(`task_id`),
|
||||
KEY(`list_id`) /* for tagcloud */
|
||||
`tag_id` INT UNSIGNED NOT NULL,
|
||||
`task_id` INT UNSIGNED NOT NULL,
|
||||
`list_id` INT UNSIGNED NOT NULL,
|
||||
KEY(`tag_id`),
|
||||
KEY(`task_id`),
|
||||
KEY(`list_id`) /* for tagcloud */
|
||||
) CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci ");
|
||||
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}settings (
|
||||
`param_key` VARCHAR(100) NOT NULL default '',
|
||||
`param_value` TEXT,
|
||||
UNIQUE KEY `param_key` (`param_key`)
|
||||
`param_key` VARCHAR(100) NOT NULL default '',
|
||||
`param_value` TEXT,
|
||||
UNIQUE KEY `param_key` (`param_key`)
|
||||
) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ");
|
||||
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}sessions (
|
||||
`id` VARCHAR(64) NOT NULL default '', /* upto 64 bytes for sha256 */
|
||||
`data` TEXT,
|
||||
`last_access` INT UNSIGNED NOT NULL default 0, /* time() timestamp */
|
||||
`expires` INT UNSIGNED NOT NULL default 0, /* time() timestamp */
|
||||
UNIQUE KEY `id` (`id`)
|
||||
`id` VARCHAR(64) NOT NULL default '', /* upto 64 bytes for sha256 */
|
||||
`data` TEXT,
|
||||
`last_access` INT UNSIGNED NOT NULL default 0, /* time() timestamp */
|
||||
`expires` INT UNSIGNED NOT NULL default 0, /* time() timestamp */
|
||||
UNIQUE KEY `id` (`id`)
|
||||
) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ");
|
||||
}
|
||||
|
||||
|
||||
function createSqliteTables($db)
|
||||
{
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}lists (
|
||||
id INTEGER PRIMARY KEY,
|
||||
uuid CHAR(36) NOT NULL,
|
||||
ow INTEGER NOT NULL default 0,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
d_created INTEGER UNSIGNED NOT NULL default 0,
|
||||
d_edited INTEGER UNSIGNED NOT NULL default 0,
|
||||
sorting TINYINT UNSIGNED NOT NULL default 0,
|
||||
published TINYINT UNSIGNED NOT NULL default 0,
|
||||
taskview INTEGER UNSIGNED NOT NULL default 0
|
||||
id INTEGER PRIMARY KEY,
|
||||
uuid CHAR(36) NOT NULL,
|
||||
ow INTEGER NOT NULL default 0,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
d_created INTEGER UNSIGNED NOT NULL default 0,
|
||||
d_edited INTEGER UNSIGNED NOT NULL default 0,
|
||||
sorting TINYINT UNSIGNED NOT NULL default 0,
|
||||
published TINYINT UNSIGNED NOT NULL default 0,
|
||||
taskview INTEGER UNSIGNED NOT NULL default 0
|
||||
) ");
|
||||
|
||||
$db->ex("CREATE UNIQUE INDEX lists_uuid ON {$db->prefix}lists (uuid)");
|
||||
$db->ex("CREATE UNIQUE INDEX lists_uuid ON {$db->prefix}lists (uuid)");
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}todolist (
|
||||
id INTEGER PRIMARY KEY,
|
||||
uuid CHAR(36) NOT NULL,
|
||||
list_id INTEGER UNSIGNED NOT NULL default 0,
|
||||
d_created INTEGER UNSIGNED NOT NULL default 0,
|
||||
d_completed INTEGER UNSIGNED NOT NULL default 0,
|
||||
d_edited INTEGER UNSIGNED NOT NULL default 0,
|
||||
compl TINYINT UNSIGNED NOT NULL default 0,
|
||||
title VARCHAR(250) NOT NULL,
|
||||
note TEXT,
|
||||
prio TINYINT NOT NULL default 0,
|
||||
ow INTEGER NOT NULL default 0,
|
||||
tags VARCHAR(600) NOT NULL default '',
|
||||
tags_ids VARCHAR(250) NOT NULL default '',
|
||||
duedate DATE default NULL
|
||||
id INTEGER PRIMARY KEY,
|
||||
uuid CHAR(36) NOT NULL,
|
||||
list_id INTEGER UNSIGNED NOT NULL default 0,
|
||||
d_created INTEGER UNSIGNED NOT NULL default 0,
|
||||
d_completed INTEGER UNSIGNED NOT NULL default 0,
|
||||
d_edited INTEGER UNSIGNED NOT NULL default 0,
|
||||
compl TINYINT UNSIGNED NOT NULL default 0,
|
||||
title VARCHAR(250) NOT NULL,
|
||||
note TEXT,
|
||||
prio TINYINT NOT NULL default 0,
|
||||
ow INTEGER NOT NULL default 0,
|
||||
tags VARCHAR(600) NOT NULL default '',
|
||||
tags_ids VARCHAR(250) NOT NULL default '',
|
||||
duedate DATE default NULL
|
||||
) ");
|
||||
$db->ex("CREATE INDEX todo_list_id ON {$db->prefix}todolist (list_id)");
|
||||
$db->ex("CREATE UNIQUE INDEX todo_uuid ON {$db->prefix}todolist (uuid)");
|
||||
$db->ex("CREATE INDEX todo_list_id ON {$db->prefix}todolist (list_id)");
|
||||
$db->ex("CREATE UNIQUE INDEX todo_uuid ON {$db->prefix}todolist (uuid)");
|
||||
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}tags (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(50) NOT NULL COLLATE NOCASE
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name VARCHAR(50) NOT NULL COLLATE NOCASE
|
||||
) ");
|
||||
$db->ex("CREATE UNIQUE INDEX tags_name ON {$db->prefix}tags (name COLLATE NOCASE)");
|
||||
$db->ex("CREATE UNIQUE INDEX tags_name ON {$db->prefix}tags (name COLLATE NOCASE)");
|
||||
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}tag2task (
|
||||
tag_id INTEGER NOT NULL,
|
||||
task_id INTEGER NOT NULL,
|
||||
list_id INTEGER NOT NULL
|
||||
tag_id INTEGER NOT NULL,
|
||||
task_id INTEGER NOT NULL,
|
||||
list_id INTEGER NOT NULL
|
||||
) ");
|
||||
$db->ex("CREATE INDEX tag2task_tag_id ON {$db->prefix}tag2task (tag_id)");
|
||||
$db->ex("CREATE INDEX tag2task_task_id ON {$db->prefix}tag2task (task_id)");
|
||||
$db->ex("CREATE INDEX tag2task_list_id ON {$db->prefix}tag2task (list_id)"); /* for tagcloud */
|
||||
$db->ex("CREATE INDEX tag2task_tag_id ON {$db->prefix}tag2task (tag_id)");
|
||||
$db->ex("CREATE INDEX tag2task_task_id ON {$db->prefix}tag2task (task_id)");
|
||||
$db->ex("CREATE INDEX tag2task_list_id ON {$db->prefix}tag2task (list_id)"); /* for tagcloud */
|
||||
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}settings (
|
||||
param_key VARCHAR(100) NOT NULL default '',
|
||||
param_value TEXT
|
||||
param_key VARCHAR(100) NOT NULL default '',
|
||||
param_value TEXT
|
||||
) ");
|
||||
|
||||
$db->ex("CREATE UNIQUE INDEX settings_key ON {$db->prefix}settings (param_key COLLATE NOCASE)");
|
||||
$db->ex("CREATE UNIQUE INDEX settings_key ON {$db->prefix}settings (param_key COLLATE NOCASE)");
|
||||
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}sessions (
|
||||
id VARCHAR(64) NOT NULL default '',
|
||||
data TEXT,
|
||||
last_access INTEGER UNSIGNED NOT NULL default 0,
|
||||
expires INTEGER UNSIGNED NOT NULL default 0
|
||||
id VARCHAR(64) NOT NULL default '',
|
||||
data TEXT,
|
||||
last_access INTEGER UNSIGNED NOT NULL default 0,
|
||||
expires INTEGER UNSIGNED NOT NULL default 0
|
||||
) ");
|
||||
|
||||
$db->ex("CREATE UNIQUE INDEX sessions_id ON {$db->prefix}sessions (id COLLATE NOCASE)");
|
||||
$db->ex("CREATE UNIQUE INDEX sessions_id ON {$db->prefix}sessions (id COLLATE NOCASE)");
|
||||
}
|
||||
|
||||
|
||||
function databaseVersion(Database_Abstract $db): string
|
||||
{
|
||||
if ( !$db ) return '';
|
||||
if ( !$db->tableExists($db->prefix.'todolist') ) return '';
|
||||
$v = '1.0';
|
||||
if ( !$db->tableExists($db->prefix.'tags') ) return $v;
|
||||
$v = '1.1';
|
||||
if ( !$db->tableFieldExists($db->prefix.'todolist', 'duedate') ) return $v;
|
||||
$v = '1.2';
|
||||
if ( !$db->tableExists($db->prefix.'lists') ) return $v;
|
||||
$v = '1.3.0';
|
||||
if ( !$db->tableFieldExists($db->prefix.'todolist', 'd_completed') ) return $v;
|
||||
$v = '1.3.1';
|
||||
if ( !$db->tableFieldExists($db->prefix.'todolist', 'd_edited') ) return $v;
|
||||
$v = '1.4';
|
||||
if ( !$db->tableExists($db->prefix.'settings') ) return $v;
|
||||
$v = '1.7';
|
||||
return $v;
|
||||
if ( !$db ) return '';
|
||||
if ( !$db->tableExists($db->prefix.'todolist') ) return '';
|
||||
$v = '1.0';
|
||||
if ( !$db->tableExists($db->prefix.'tags') ) return $v;
|
||||
$v = '1.1';
|
||||
if ( !$db->tableFieldExists($db->prefix.'todolist', 'duedate') ) return $v;
|
||||
$v = '1.2';
|
||||
if ( !$db->tableExists($db->prefix.'lists') ) return $v;
|
||||
$v = '1.3.0';
|
||||
if ( !$db->tableFieldExists($db->prefix.'todolist', 'd_completed') ) return $v;
|
||||
$v = '1.3.1';
|
||||
if ( !$db->tableFieldExists($db->prefix.'todolist', 'd_edited') ) return $v;
|
||||
$v = '1.4';
|
||||
if ( !$db->tableExists($db->prefix.'settings') ) return $v;
|
||||
$v = '1.7';
|
||||
return $v;
|
||||
}
|
||||
|
||||
function exitMessage($s)
|
||||
{
|
||||
echo $s;
|
||||
printFooter();
|
||||
exit;
|
||||
echo $s;
|
||||
printFooter();
|
||||
exit;
|
||||
}
|
||||
|
||||
function printFooter()
|
||||
{
|
||||
echo "</body></html>";
|
||||
echo "</body></html>";
|
||||
}
|
||||
|
||||
function tryToSaveDbConfig()
|
||||
{
|
||||
if (!file_exists(MTTPATH.'config.php')) {
|
||||
@touch(MTTPATH.'config.php');
|
||||
}
|
||||
if (!is_writable(MTTPATH.'config.php')) {
|
||||
exitMessage("Database connection config file ('config.php') is not writable. You need to edit it manually, set contents to this and run setup once more. <br><br> \n".
|
||||
"<textarea id='contents' style='width:90%; min-height:300px;'>\n".
|
||||
htmlspecialchars(Config::dbConfigAsFileContents()).
|
||||
"</textarea>\n".
|
||||
"<script type='text/javascript'>document.getElementById('contents').select();</script>"
|
||||
);
|
||||
}
|
||||
Config::saveDbConfig();
|
||||
if (!file_exists(MTTPATH.'config.php')) {
|
||||
@touch(MTTPATH.'config.php');
|
||||
}
|
||||
if (!is_writable(MTTPATH.'config.php')) {
|
||||
exitMessage("Database connection config file ('config.php') is not writable. You need to edit it manually, set contents to this and run setup once more. <br><br> \n".
|
||||
"<textarea id='contents' style='width:90%; min-height:300px;'>\n".
|
||||
htmlspecialchars(Config::dbConfigAsFileContents()).
|
||||
"</textarea>\n".
|
||||
"<script type='text/javascript'>document.getElementById('contents').select();</script>"
|
||||
);
|
||||
}
|
||||
Config::saveDbConfig();
|
||||
}
|
||||
|
||||
function testConnect(&$error)
|
||||
{
|
||||
$db = null;
|
||||
try
|
||||
{
|
||||
if (!defined('MTT_DB_TYPE')) throw new Exception("MTT_DB_TYPE is not defined");
|
||||
$db = null;
|
||||
try
|
||||
{
|
||||
if (!defined('MTT_DB_TYPE')) throw new Exception("MTT_DB_TYPE is not defined");
|
||||
|
||||
if (MTT_DB_TYPE == 'mysql')
|
||||
{
|
||||
$hasPDO = false;
|
||||
$hasMysqli = false;
|
||||
if (defined('PDO::MYSQL_ATTR_FOUND_ROWS')) {
|
||||
$hasPDO = true;
|
||||
}
|
||||
if (function_exists("mysqli_connect")) {
|
||||
$hasMysqli = true;
|
||||
}
|
||||
if (MTT_DB_TYPE == 'mysql')
|
||||
{
|
||||
$hasPDO = false;
|
||||
$hasMysqli = false;
|
||||
if (defined('PDO::MYSQL_ATTR_FOUND_ROWS')) {
|
||||
$hasPDO = true;
|
||||
}
|
||||
if (function_exists("mysqli_connect")) {
|
||||
$hasMysqli = true;
|
||||
}
|
||||
|
||||
$driver = '';
|
||||
if (defined('MTT_DB_DRIVER')) {
|
||||
// forced to use specific mysql interface
|
||||
if ( in_array(MTT_DB_DRIVER, ['mysqli', 'pdo', '']) ) {
|
||||
$driver = MTT_DB_DRIVER;
|
||||
if ($driver == '') $driver = 'pdo'; // default
|
||||
}
|
||||
else {
|
||||
throw new Exception("Unknown database driver");
|
||||
}
|
||||
}
|
||||
$driver = '';
|
||||
if (defined('MTT_DB_DRIVER')) {
|
||||
// forced to use specific mysql interface
|
||||
if ( in_array(MTT_DB_DRIVER, ['mysqli', 'pdo', '']) ) {
|
||||
$driver = MTT_DB_DRIVER;
|
||||
if ($driver == '') $driver = 'pdo'; // default
|
||||
}
|
||||
else {
|
||||
throw new Exception("Unknown database driver");
|
||||
}
|
||||
}
|
||||
|
||||
if ($driver == '') {
|
||||
// auto-detect driver
|
||||
if ($hasPDO) $driver = 'pdo';
|
||||
else if ($hasMysqli) $driver = 'mysqli';
|
||||
}
|
||||
if ($driver == '') {
|
||||
// auto-detect driver
|
||||
if ($hasPDO) $driver = 'pdo';
|
||||
else if ($hasMysqli) $driver = 'mysqli';
|
||||
}
|
||||
|
||||
if ($driver == 'mysqli') {
|
||||
if ($hasMysqli) {
|
||||
require_once(MTTINC. 'class.db.mysqli.php');
|
||||
if (!defined('MTT_DB_DRIVER')) define('MTT_DB_DRIVER', 'mysqli');
|
||||
}
|
||||
else {
|
||||
throw new Exception("Required PHP extension 'MySQLi' is not installed.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($hasPDO) {
|
||||
require_once(MTTINC. 'class.db.mysql.php');
|
||||
if (!defined('MTT_DB_DRIVER')) define('MTT_DB_DRIVER', ''); // set pdo?
|
||||
}
|
||||
else {
|
||||
throw new Exception("Required PHP extension 'PDO_MySQL' is not installed.");
|
||||
}
|
||||
}
|
||||
if ($driver == 'mysqli') {
|
||||
if ($hasMysqli) {
|
||||
require_once(MTTINC. 'class.db.mysqli.php');
|
||||
if (!defined('MTT_DB_DRIVER')) define('MTT_DB_DRIVER', 'mysqli');
|
||||
}
|
||||
else {
|
||||
throw new Exception("Required PHP extension 'MySQLi' is not installed.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($hasPDO) {
|
||||
require_once(MTTINC. 'class.db.mysql.php');
|
||||
if (!defined('MTT_DB_DRIVER')) define('MTT_DB_DRIVER', ''); // set pdo?
|
||||
}
|
||||
else {
|
||||
throw new Exception("Required PHP extension 'PDO_MySQL' is not installed.");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['MTT_DB_HOST', 'MTT_DB_USER', 'MTT_DB_PASSWORD', 'MTT_DB_NAME', 'MTT_DB_PREFIX'] as $c) {
|
||||
if (!defined($c)) throw new Exception("$c is not defined");
|
||||
}
|
||||
foreach (['MTT_DB_HOST', 'MTT_DB_USER', 'MTT_DB_PASSWORD', 'MTT_DB_NAME', 'MTT_DB_PREFIX'] as $c) {
|
||||
if (!defined($c)) throw new Exception("$c is not defined");
|
||||
}
|
||||
|
||||
$db = new Database_Mysql;
|
||||
$db->connect( array(
|
||||
'host' => MTT_DB_HOST,
|
||||
'user' => MTT_DB_USER,
|
||||
'password' => MTT_DB_PASSWORD,
|
||||
'db' => MTT_DB_NAME
|
||||
));
|
||||
}
|
||||
else if (MTT_DB_TYPE == 'sqlite')
|
||||
{
|
||||
if (false === $f = @fopen(MTTPATH. 'db/todolist.db', 'a+')) {
|
||||
throw new Exception("database file is not readable/writable");
|
||||
}
|
||||
else {
|
||||
fclose($f);
|
||||
}
|
||||
if (!is_writable(MTTPATH. 'db/')) {
|
||||
throw new Exception("database directory ('db') is not writable");
|
||||
}
|
||||
require_once(MTTINC. 'class.db.sqlite3.php');
|
||||
$db = new Database_Sqlite3;
|
||||
$db->connect( array( 'filename' => MTTPATH. 'db/todolist.db' ) );
|
||||
}
|
||||
else {
|
||||
new Exception("Unsupported database type");
|
||||
}
|
||||
$db = new Database_Mysql;
|
||||
$db->connect( array(
|
||||
'host' => MTT_DB_HOST,
|
||||
'user' => MTT_DB_USER,
|
||||
'password' => MTT_DB_PASSWORD,
|
||||
'db' => MTT_DB_NAME
|
||||
));
|
||||
}
|
||||
else if (MTT_DB_TYPE == 'sqlite')
|
||||
{
|
||||
if (false === $f = @fopen(MTTPATH. 'db/todolist.db', 'a+')) {
|
||||
throw new Exception("database file is not readable/writable");
|
||||
}
|
||||
else {
|
||||
fclose($f);
|
||||
}
|
||||
if (!is_writable(MTTPATH. 'db/')) {
|
||||
throw new Exception("database directory ('db') is not writable");
|
||||
}
|
||||
require_once(MTTINC. 'class.db.sqlite3.php');
|
||||
$db = new Database_Sqlite3;
|
||||
$db->connect( array( 'filename' => MTTPATH. 'db/todolist.db' ) );
|
||||
}
|
||||
else {
|
||||
new Exception("Unsupported database type");
|
||||
}
|
||||
|
||||
if (!defined('MTT_DB_PREFIX')) define('MTT_DB_PREFIX', '');
|
||||
$db->setPrefix(MTT_DB_PREFIX);
|
||||
}
|
||||
catch(Exception $e) {
|
||||
//if (MTT_DEBUG) throw $e;
|
||||
$error = $e->getMessage();
|
||||
return null;
|
||||
}
|
||||
$error = '';
|
||||
return $db;
|
||||
if (!defined('MTT_DB_PREFIX')) define('MTT_DB_PREFIX', '');
|
||||
$db->setPrefix(MTT_DB_PREFIX);
|
||||
}
|
||||
catch(Exception $e) {
|
||||
//if (MTT_DEBUG) throw $e;
|
||||
$error = $e->getMessage();
|
||||
return null;
|
||||
}
|
||||
$error = '';
|
||||
return $db;
|
||||
}
|
||||
|
||||
function debugExceptionHandler($e)
|
||||
{
|
||||
echo '<br><b>Error ('. htmlspecialchars(get_class($e)) .'):</b> \''. htmlspecialchars($e->getMessage()) .'\' in <i>'. htmlspecialchars($e->getFile() .':'. $e->getLine()). '</i>'.
|
||||
"\n<pre>". htmlspecialchars($e->getTraceAsString()) . "</pre>\n";
|
||||
exit;
|
||||
echo '<br><b>Error ('. htmlspecialchars(get_class($e)) .'):</b> \''. htmlspecialchars($e->getMessage()) .'\' in <i>'. htmlspecialchars($e->getFile() .':'. $e->getLine()). '</i>'.
|
||||
"\n<pre>". htmlspecialchars($e->getTraceAsString()) . "</pre>\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
function myExceptionHandler($e)
|
||||
{
|
||||
echo '<br><b>Error:</b> '. htmlspecialchars($e->getMessage()) ;
|
||||
exit;
|
||||
echo '<br><b>Error:</b> '. htmlspecialchars($e->getMessage()) ;
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
### update v1.4 to v1.7 ##########
|
||||
function update_14_17(Database_Abstract $db, $dbtype)
|
||||
{
|
||||
$db->ex("BEGIN");
|
||||
$db->ex("BEGIN");
|
||||
|
||||
if($dbtype=='mysql')
|
||||
{
|
||||
# convert charset to utf8mb4
|
||||
if($dbtype=='mysql')
|
||||
{
|
||||
# convert charset to utf8mb4
|
||||
|
||||
$db->ex("ALTER TABLE {$db->prefix}lists CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||
$db->ex("ALTER TABLE {$db->prefix}todolist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||
$db->ex("ALTER TABLE {$db->prefix}tags CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||
$db->ex("ALTER TABLE {$db->prefix}tag2task CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||
$db->ex("ALTER TABLE {$db->prefix}lists CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||
$db->ex("ALTER TABLE {$db->prefix}todolist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||
$db->ex("ALTER TABLE {$db->prefix}tags CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||
$db->ex("ALTER TABLE {$db->prefix}tag2task CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
|
||||
|
||||
# create settings table
|
||||
# create settings table
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}settings (
|
||||
`param_key` VARCHAR(100) NOT NULL default '',
|
||||
`param_value` TEXT,
|
||||
UNIQUE KEY `param_key` (`param_key`)
|
||||
) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ");
|
||||
|
||||
# create sessions table
|
||||
# create sessions table
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}sessions (
|
||||
`id` VARCHAR(64) NOT NULL default '',
|
||||
`data` TEXT,
|
||||
|
|
@ -538,20 +538,20 @@ UNIQUE KEY `param_key` (`param_key`)
|
|||
UNIQUE KEY `id` (`id`)
|
||||
) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
else #sqlite
|
||||
{
|
||||
$db->ex(
|
||||
else #sqlite
|
||||
{
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}settings (
|
||||
param_key VARCHAR(100) NOT NULL default '',
|
||||
param_value TEXT
|
||||
) ");
|
||||
$db->ex("CREATE UNIQUE INDEX settings_key ON {$db->prefix}settings (param_key COLLATE NOCASE)");
|
||||
$db->ex("CREATE UNIQUE INDEX settings_key ON {$db->prefix}settings (param_key COLLATE NOCASE)");
|
||||
|
||||
# sessions
|
||||
# sessions
|
||||
|
||||
$db->ex(
|
||||
$db->ex(
|
||||
"CREATE TABLE {$db->prefix}sessions (
|
||||
id VARCHAR(100) NOT NULL default '',
|
||||
data TEXT,
|
||||
|
|
@ -559,12 +559,12 @@ UNIQUE KEY `id` (`id`)
|
|||
expires INTEGER UNSIGNED NOT NULL default 0
|
||||
) ");
|
||||
|
||||
$db->ex("CREATE UNIQUE INDEX sessions_id ON {$db->prefix}sessions (id COLLATE NOCASE)");
|
||||
}
|
||||
$db->ex("CREATE UNIQUE INDEX sessions_id ON {$db->prefix}sessions (id COLLATE NOCASE)");
|
||||
}
|
||||
|
||||
$db->ex("COMMIT");
|
||||
$db->ex("COMMIT");
|
||||
|
||||
Config::save();
|
||||
Config::saveDbConfig();
|
||||
Config::save();
|
||||
Config::saveDbConfig();
|
||||
}
|
||||
### end of 1.7 #####
|
||||
|
|
|
|||
Loading…
Reference in a new issue