diff --git a/.editorconfig b/.editorconfig index af6284b..5dfd8f5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -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 diff --git a/buildzip.php b/buildzip.php index 5d48d63..59b4713 100755 --- a/buildzip.php +++ b/buildzip.php @@ -4,7 +4,7 @@ // PHP 5.4 is required if ( !isset($argv) || !isset($argv[1]) ) { - die("Usage: buildzip.php [-o source.zip] [-v VERSION]\n"); + die("Usage: buildzip.php [-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"); } \ No newline at end of file diff --git a/src/ajax.php b/src/ajax.php index 4fceba3..8a97563 100644 --- a/src/ajax.php +++ b/src/ajax.php @@ -1,546 +1,546 @@ - 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 + Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details. */ require_once('./init.php'); require_once(MTTINC. 'markup.php'); if (MTT_DEBUG) { - set_error_handler('myErrorHandler'); //catch Notices, Warnings - set_exception_handler('myExceptionHandler'); + set_error_handler('myErrorHandler'); //catch Notices, Warnings + set_exception_handler('myExceptionHandler'); } else { - ini_set('display_errors', '0'); + ini_set('display_errors', '0'); } $db = DBConnection::instance(); if(isset($_GET['loadLists'])) { - check_token(); - $t = array(); - $t['total'] = 0; - if (!is_logged()) $sqlWhere = 'WHERE published=1'; - else { - $sqlWhere = ''; - $t['list'][] = prepareAllTasksList(); // show alltasks lists only for authorized user - $t['total'] = 1; - } - $q = $db->dq("SELECT * FROM {$db->prefix}lists $sqlWhere ORDER BY ow ASC, id ASC"); - while($r = $q->fetchAssoc()) - { - $t['total']++; - $t['list'][] = prepareList($r); - } - jsonExit($t); + check_token(); + $t = array(); + $t['total'] = 0; + if (!is_logged()) $sqlWhere = 'WHERE published=1'; + else { + $sqlWhere = ''; + $t['list'][] = prepareAllTasksList(); // show alltasks lists only for authorized user + $t['total'] = 1; + } + $q = $db->dq("SELECT * FROM {$db->prefix}lists $sqlWhere ORDER BY ow ASC, id ASC"); + while($r = $q->fetchAssoc()) + { + $t['total']++; + $t['list'][] = prepareList($r); + } + jsonExit($t); } elseif(isset($_GET['loadTasks'])) { - $listId = (int)_get('list'); - check_read_access($listId); + $listId = (int)_get('list'); + check_read_access($listId); - $sqlWhere = $inner = $sqlWhereListId = $sqlInnerWhereListId = ''; - if ($listId == -1) { - $userLists = getUserListsSimple(); - $sqlWhereListId = "{$db->prefix}todolist.list_id IN (". implode(',', array_keys($userLists)). ") "; - $sqlInnerWhereListId = "list_id IN (". implode(',', array_keys($userLists)). ") "; - } - else { - $sqlWhereListId = "{$db->prefix}todolist.list_id=". $listId; - $sqlInnerWhereListId = "list_id=$listId "; - } - if (_get('compl') == 0) { - $sqlWhere .= ' AND compl=0'; - } + $sqlWhere = $inner = $sqlWhereListId = $sqlInnerWhereListId = ''; + if ($listId == -1) { + $userLists = getUserListsSimple(); + $sqlWhereListId = "{$db->prefix}todolist.list_id IN (". implode(',', array_keys($userLists)). ") "; + $sqlInnerWhereListId = "list_id IN (". implode(',', array_keys($userLists)). ") "; + } + else { + $sqlWhereListId = "{$db->prefix}todolist.list_id=". $listId; + $sqlInnerWhereListId = "list_id=$listId "; + } + if (_get('compl') == 0) { + $sqlWhere .= ' AND compl=0'; + } - $tag = trim(_get('t')); - if($tag != '') - { - $at = explode(',', $tag); - $tagIds = array(); - $tagExIds = array(); - foreach($at as $i=>$atv) { - $atv = trim($atv); - if($atv == '' || $atv == '^') continue; - if(substr($atv,0,1) == '^') { - $tagExIds[] = getTagId(substr($atv,1)); - } else { - $tagIds[] = getTagId($atv); - } - } + $tag = trim(_get('t')); + if($tag != '') + { + $at = explode(',', $tag); + $tagIds = array(); + $tagExIds = array(); + foreach($at as $i=>$atv) { + $atv = trim($atv); + if($atv == '' || $atv == '^') continue; + if(substr($atv,0,1) == '^') { + $tagExIds[] = getTagId(substr($atv,1)); + } else { + $tagIds[] = getTagId($atv); + } + } - // Include tags: All - if (sizeof($tagIds) > 1) { - $inner .= "INNER JOIN (SELECT task_id, COUNT(tag_id) AS c FROM {$db->prefix}tag2task WHERE $sqlInnerWhereListId AND tag_id IN (". - implode(',',$tagIds). ") GROUP BY task_id) AS t2t ON id=t2t.task_id"; - $sqlWhere .= " AND c=". sizeof($tagIds); - } - elseif ($tagIds) { - $inner .= "INNER JOIN {$db->prefix}tag2task ON id=task_id"; - $sqlWhere .= " AND tag_id = {$tagIds[0]}"; - } + // Include tags: All + if (sizeof($tagIds) > 1) { + $inner .= "INNER JOIN (SELECT task_id, COUNT(tag_id) AS c FROM {$db->prefix}tag2task WHERE $sqlInnerWhereListId AND tag_id IN (". + implode(',',$tagIds). ") GROUP BY task_id) AS t2t ON id=t2t.task_id"; + $sqlWhere .= " AND c=". sizeof($tagIds); + } + elseif ($tagIds) { + $inner .= "INNER JOIN {$db->prefix}tag2task ON id=task_id"; + $sqlWhere .= " AND tag_id = {$tagIds[0]}"; + } - // Exclude tags - if (sizeof($tagExIds) > 0) { - $sqlWhere .= " AND {$db->prefix}todolist.id NOT IN (SELECT DISTINCT task_id FROM {$db->prefix}tag2task WHERE $sqlInnerWhereListId AND tag_id IN (". - implode(',',$tagExIds). "))"; - } - //no optimization for single exTag - } + // Exclude tags + if (sizeof($tagExIds) > 0) { + $sqlWhere .= " AND {$db->prefix}todolist.id NOT IN (SELECT DISTINCT task_id FROM {$db->prefix}tag2task WHERE $sqlInnerWhereListId AND tag_id IN (". + implode(',',$tagExIds). "))"; + } + //no optimization for single exTag + } - $s = trim(_get('s')); - if ($s != '') { - if (preg_match("|^#(\d+)$|", $s, $m)) $sqlWhere .= " AND {$db->prefix}todolist.id = ". (int)$m[1]; - else $sqlWhere .= " AND (title LIKE ". $db->quoteForLike("%%%s%%",$s). " OR note LIKE ". $db->quoteForLike("%%%s%%",$s). ")"; - } + $s = trim(_get('s')); + if ($s != '') { + if (preg_match("|^#(\d+)$|", $s, $m)) $sqlWhere .= " AND {$db->prefix}todolist.id = ". (int)$m[1]; + else $sqlWhere .= " AND (title LIKE ". $db->quoteForLike("%%%s%%",$s). " OR note LIKE ". $db->quoteForLike("%%%s%%",$s). ")"; + } - $sort = (int)_get('sort'); - $sqlSort = "ORDER BY compl ASC, "; - if($sort == 1) $sqlSort .= "prio DESC, ddn ASC, duedate ASC, ow ASC"; // byPrio - elseif($sort == 101) $sqlSort .= "prio ASC, ddn DESC, duedate DESC, ow DESC"; // byPrio (reverse) - elseif($sort == 2) $sqlSort .= "ddn ASC, duedate ASC, prio DESC, ow ASC"; // byDueDate - elseif($sort == 102) $sqlSort .= "ddn DESC, duedate DESC, prio ASC, ow DESC";// byDueDate (reverse) - elseif($sort == 3) $sqlSort .= "d_created ASC, prio DESC, ow ASC"; // byDateCreated - elseif($sort == 103) $sqlSort .= "d_created DESC, prio ASC, ow DESC"; // byDateCreated (reverse) - elseif($sort == 4) $sqlSort .= "d_edited ASC, prio DESC, ow ASC"; // byDateModified - elseif($sort == 104) $sqlSort .= "d_edited DESC, prio ASC, ow DESC"; // byDateModified (reverse) - else $sqlSort .= "ow ASC"; + $sort = (int)_get('sort'); + $sqlSort = "ORDER BY compl ASC, "; + if($sort == 1) $sqlSort .= "prio DESC, ddn ASC, duedate ASC, ow ASC"; // byPrio + elseif($sort == 101) $sqlSort .= "prio ASC, ddn DESC, duedate DESC, ow DESC"; // byPrio (reverse) + elseif($sort == 2) $sqlSort .= "ddn ASC, duedate ASC, prio DESC, ow ASC"; // byDueDate + elseif($sort == 102) $sqlSort .= "ddn DESC, duedate DESC, prio ASC, ow DESC";// byDueDate (reverse) + elseif($sort == 3) $sqlSort .= "d_created ASC, prio DESC, ow ASC"; // byDateCreated + elseif($sort == 103) $sqlSort .= "d_created DESC, prio ASC, ow DESC"; // byDateCreated (reverse) + elseif($sort == 4) $sqlSort .= "d_edited ASC, prio DESC, ow ASC"; // byDateModified + elseif($sort == 104) $sqlSort .= "d_edited DESC, prio ASC, ow DESC"; // byDateModified (reverse) + else $sqlSort .= "ow ASC"; - $t = array(); - $t['total'] = 0; - $t['list'] = array(); - $q = $db->dq("SELECT *, duedate IS NULL AS ddn FROM {$db->prefix}todolist $inner WHERE $sqlWhereListId $sqlWhere $sqlSort"); - while($r = $q->fetchAssoc()) - { - $t['total']++; - $t['list'][] = prepareTaskRow($r); - } - if(_get('setCompl') && have_write_access($listId)) { - $bitwise = (_get('compl') == 0) ? 'taskview & ~1' : 'taskview | 1'; - $db->dq("UPDATE {$db->prefix}lists SET taskview=$bitwise WHERE id=$listId"); - } - jsonExit($t); + $t = array(); + $t['total'] = 0; + $t['list'] = array(); + $q = $db->dq("SELECT *, duedate IS NULL AS ddn FROM {$db->prefix}todolist $inner WHERE $sqlWhereListId $sqlWhere $sqlSort"); + while($r = $q->fetchAssoc()) + { + $t['total']++; + $t['list'][] = prepareTaskRow($r); + } + if(_get('setCompl') && have_write_access($listId)) { + $bitwise = (_get('compl') == 0) ? 'taskview & ~1' : 'taskview | 1'; + $db->dq("UPDATE {$db->prefix}lists SET taskview=$bitwise WHERE id=$listId"); + } + jsonExit($t); } elseif(isset($_GET['newTask'])) { - $listId = (int)_post('list'); - check_write_access($listId); - $t = array(); - $t['total'] = 0; - $title = trim(_post('title')); - $prio = 0; - $tags = ''; - if(Config::get('smartsyntax') != 0) - { - $a = parse_smartsyntax($title); - if($a === false) { - jsonExit($t); - } - $title = $a['title']; - $prio = $a['prio']; - $tags = $a['tags']; - } - if($title == '') { - jsonExit($t); - } - if(Config::get('autotag')) $tags .= ','._post('tag'); - $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0"); - $db->ex("BEGIN"); - $db->dq("INSERT INTO {$db->prefix}todolist (uuid,list_id,title,d_created,d_edited,ow,prio) VALUES (?,?,?,?,?,?,?)", - array(generateUUID(), $listId, $title, time(), time(), $ow, $prio) ); - $id = $db->lastInsertId(); - if($tags != '') - { - $aTags = prepareTags($tags); - if($aTags) { - addTaskTags($id, $aTags['ids'], $listId); - $db->ex("UPDATE {$db->prefix}todolist SET tags=?,tags_ids=? WHERE id=$id", array(implode(',',$aTags['tags']), implode(',',$aTags['ids']))); - } - } - $db->ex("COMMIT"); - $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id"); - $t['list'][] = prepareTaskRow($r); - $t['total'] = 1; - jsonExit($t); + $listId = (int)_post('list'); + check_write_access($listId); + $t = array(); + $t['total'] = 0; + $title = trim(_post('title')); + $prio = 0; + $tags = ''; + if(Config::get('smartsyntax') != 0) + { + $a = parse_smartsyntax($title); + if($a === false) { + jsonExit($t); + } + $title = $a['title']; + $prio = $a['prio']; + $tags = $a['tags']; + } + if($title == '') { + jsonExit($t); + } + if(Config::get('autotag')) $tags .= ','._post('tag'); + $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0"); + $db->ex("BEGIN"); + $db->dq("INSERT INTO {$db->prefix}todolist (uuid,list_id,title,d_created,d_edited,ow,prio) VALUES (?,?,?,?,?,?,?)", + array(generateUUID(), $listId, $title, time(), time(), $ow, $prio) ); + $id = $db->lastInsertId(); + if($tags != '') + { + $aTags = prepareTags($tags); + if($aTags) { + addTaskTags($id, $aTags['ids'], $listId); + $db->ex("UPDATE {$db->prefix}todolist SET tags=?,tags_ids=? WHERE id=$id", array(implode(',',$aTags['tags']), implode(',',$aTags['ids']))); + } + } + $db->ex("COMMIT"); + $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id"); + $t['list'][] = prepareTaskRow($r); + $t['total'] = 1; + jsonExit($t); } elseif(isset($_GET['fullNewTask'])) { - $listId = (int)_post('list'); - check_write_access($listId); - $title = trim(_post('title')); - $note = str_replace("\r\n", "\n", trim(_post('note'))); - $prio = (int)_post('prio'); - if($prio < -1) $prio = -1; - elseif($prio > 2) $prio = 2; - $duedate = parse_duedate(trim(_post('duedate'))); - $t = array(); - $t['total'] = 0; - if($title == '') { - jsonExit($t); - } - $tags = trim(_post('tags')); - if(Config::get('autotag')) $tags .= ','._post('tag'); - $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0"); - $db->ex("BEGIN"); - $db->dq("INSERT INTO {$db->prefix}todolist (uuid,list_id,title,d_created,d_edited,ow,prio,note,duedate) VALUES(?,?,?,?,?,?,?,?,?)", - array(generateUUID(), $listId, $title, time(), time(), $ow, $prio, $note, $duedate) ); - $id = $db->lastInsertId(); - if($tags != '') - { - $aTags = prepareTags($tags); - if($aTags) { - addTaskTags($id, $aTags['ids'], $listId); - $db->ex("UPDATE {$db->prefix}todolist SET tags=?,tags_ids=? WHERE id=$id", array(implode(',',$aTags['tags']), implode(',',$aTags['ids']))); - } - } - $db->ex("COMMIT"); - $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id"); - $t['list'][] = prepareTaskRow($r); - $t['total'] = 1; - jsonExit($t); + $listId = (int)_post('list'); + check_write_access($listId); + $title = trim(_post('title')); + $note = str_replace("\r\n", "\n", trim(_post('note'))); + $prio = (int)_post('prio'); + if($prio < -1) $prio = -1; + elseif($prio > 2) $prio = 2; + $duedate = parse_duedate(trim(_post('duedate'))); + $t = array(); + $t['total'] = 0; + if($title == '') { + jsonExit($t); + } + $tags = trim(_post('tags')); + if(Config::get('autotag')) $tags .= ','._post('tag'); + $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0"); + $db->ex("BEGIN"); + $db->dq("INSERT INTO {$db->prefix}todolist (uuid,list_id,title,d_created,d_edited,ow,prio,note,duedate) VALUES(?,?,?,?,?,?,?,?,?)", + array(generateUUID(), $listId, $title, time(), time(), $ow, $prio, $note, $duedate) ); + $id = $db->lastInsertId(); + if($tags != '') + { + $aTags = prepareTags($tags); + if($aTags) { + addTaskTags($id, $aTags['ids'], $listId); + $db->ex("UPDATE {$db->prefix}todolist SET tags=?,tags_ids=? WHERE id=$id", array(implode(',',$aTags['tags']), implode(',',$aTags['ids']))); + } + } + $db->ex("COMMIT"); + $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id"); + $t['list'][] = prepareTaskRow($r); + $t['total'] = 1; + jsonExit($t); } elseif(isset($_GET['deleteTask'])) { - $id = (int)_post('id'); - $deleted = deleteTask($id); - $t = array(); - $t['total'] = $deleted; - $t['list'][] = array('id'=>$id); - jsonExit($t); + $id = (int)_post('id'); + $deleted = deleteTask($id); + $t = array(); + $t['total'] = $deleted; + $t['list'][] = array('id'=>$id); + jsonExit($t); } elseif(isset($_GET['completeTask'])) { - check_write_access(); - $id = (int)_post('id'); - $compl = _post('compl') ? 1 : 0; - $listId = (int)$db->sq("SELECT list_id FROM {$db->prefix}todolist WHERE id=$id"); - if($compl) $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=1"); - else $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0"); - $dateCompleted = $compl ? time() : 0; - $db->dq("UPDATE {$db->prefix}todolist SET compl=$compl,ow=$ow,d_completed=?,d_edited=? WHERE id=$id", - array($dateCompleted, time()) ); - $t = array(); - $t['total'] = 1; - $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id"); - $t['list'][] = prepareTaskRow($r); - jsonExit($t); + check_write_access(); + $id = (int)_post('id'); + $compl = _post('compl') ? 1 : 0; + $listId = (int)$db->sq("SELECT list_id FROM {$db->prefix}todolist WHERE id=$id"); + if($compl) $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=1"); + else $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=$listId AND compl=0"); + $dateCompleted = $compl ? time() : 0; + $db->dq("UPDATE {$db->prefix}todolist SET compl=$compl,ow=$ow,d_completed=?,d_edited=? WHERE id=$id", + array($dateCompleted, time()) ); + $t = array(); + $t['total'] = 1; + $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id"); + $t['list'][] = prepareTaskRow($r); + jsonExit($t); } elseif(isset($_GET['editNote'])) { - check_write_access(); - $id = (int)_post('id'); - $note = str_replace("\r\n", "\n", trim(_post('note'))); - $db->dq("UPDATE {$db->prefix}todolist SET note=?,d_edited=? WHERE id=$id", array($note, time()) ); - $t = array(); - $t['total'] = 1; - $t['list'][] = array('id'=>$id, 'note'=> noteMarkup($note), 'noteText'=>(string)$note); - jsonExit($t); + check_write_access(); + $id = (int)_post('id'); + $note = str_replace("\r\n", "\n", trim(_post('note'))); + $db->dq("UPDATE {$db->prefix}todolist SET note=?,d_edited=? WHERE id=$id", array($note, time()) ); + $t = array(); + $t['total'] = 1; + $t['list'][] = array('id'=>$id, 'note'=> noteMarkup($note), 'noteText'=>(string)$note); + jsonExit($t); } elseif(isset($_GET['editTask'])) { - check_write_access(); - $id = (int)_post('id'); - $title = trim(_post('title')); - $note = str_replace("\r\n", "\n", trim(_post('note'))); - $prio = (int)_post('prio'); - if($prio < -1) $prio = -1; - elseif($prio > 2) $prio = 2; - $duedate = parse_duedate(trim(_post('duedate'))); - $t = array(); - $t['total'] = 0; - if($title == '') { - jsonExit($t); - } - $listId = $db->sq("SELECT list_id FROM {$db->prefix}todolist WHERE id=$id"); - $tags = trim(_post('tags')); - $db->ex("BEGIN"); - $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id"); - $aTags = prepareTags($tags); - if($aTags) { - $tags = implode(',', $aTags['tags']); - $tags_ids = implode(',',$aTags['ids']); - addTaskTags($id, $aTags['ids'], $listId); - } - $db->dq("UPDATE {$db->prefix}todolist SET title=?,note=?,prio=?,tags=?,tags_ids=?,duedate=?,d_edited=? WHERE id=$id", - array($title, $note, $prio, $tags, $tags_ids, $duedate, time()) ); - $db->ex("COMMIT"); - $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id"); - if($r) { - $t['list'][] = prepareTaskRow($r); - $t['total'] = 1; - } - jsonExit($t); + check_write_access(); + $id = (int)_post('id'); + $title = trim(_post('title')); + $note = str_replace("\r\n", "\n", trim(_post('note'))); + $prio = (int)_post('prio'); + if($prio < -1) $prio = -1; + elseif($prio > 2) $prio = 2; + $duedate = parse_duedate(trim(_post('duedate'))); + $t = array(); + $t['total'] = 0; + if($title == '') { + jsonExit($t); + } + $listId = $db->sq("SELECT list_id FROM {$db->prefix}todolist WHERE id=$id"); + $tags = trim(_post('tags')); + $db->ex("BEGIN"); + $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id"); + $aTags = prepareTags($tags); + if($aTags) { + $tags = implode(',', $aTags['tags']); + $tags_ids = implode(',',$aTags['ids']); + addTaskTags($id, $aTags['ids'], $listId); + } + $db->dq("UPDATE {$db->prefix}todolist SET title=?,note=?,prio=?,tags=?,tags_ids=?,duedate=?,d_edited=? WHERE id=$id", + array($title, $note, $prio, $tags, $tags_ids, $duedate, time()) ); + $db->ex("COMMIT"); + $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id"); + if($r) { + $t['list'][] = prepareTaskRow($r); + $t['total'] = 1; + } + jsonExit($t); } elseif(isset($_GET['changeOrder'])) { - check_write_access(); - $s = _post('order'); - parse_str($s, $order); - $t = array(); - $t['total'] = 0; - if($order) - { - $ad = array(); - foreach($order as $id=>$diff) { - $ad[(int)$diff][] = (int)$id; - } - $db->ex("BEGIN"); - foreach($ad as $diff=>$ids) { - if($diff >=0) $set = "ow=ow+".$diff; - else $set = "ow=ow-".abs($diff); - $db->dq("UPDATE {$db->prefix}todolist SET $set,d_edited=? WHERE id IN (".implode(',',$ids).")", array(time()) ); - } - $db->ex("COMMIT"); - $t['total'] = 1; - } - jsonExit($t); + check_write_access(); + $s = _post('order'); + parse_str($s, $order); + $t = array(); + $t['total'] = 0; + if($order) + { + $ad = array(); + foreach($order as $id=>$diff) { + $ad[(int)$diff][] = (int)$id; + } + $db->ex("BEGIN"); + foreach($ad as $diff=>$ids) { + if($diff >=0) $set = "ow=ow+".$diff; + else $set = "ow=ow-".abs($diff); + $db->dq("UPDATE {$db->prefix}todolist SET $set,d_edited=? WHERE id IN (".implode(',',$ids).")", array(time()) ); + } + $db->ex("COMMIT"); + $t['total'] = 1; + } + jsonExit($t); } elseif(isset($_POST['login'])) { - $t = array('logged' => 0); - if (!need_auth()) { - $t['disabled'] = 1; - jsonExit($t); - } - if ( isPasswordEqualsToHash(_post('password'), Config::get('password')) ) { - $t['logged'] = 1; - session_regenerate_id(1); - $_SESSION['logged'] = 1; - $_SESSION['token'] = generateUUID(); - $_SESSION['sign'] = idSignature(session_id(), Config::get('password'), defined('MTT_SALT') ? MTT_SALT : ''); - } - jsonExit($t); + $t = array('logged' => 0); + if (!need_auth()) { + $t['disabled'] = 1; + jsonExit($t); + } + if ( isPasswordEqualsToHash(_post('password'), Config::get('password')) ) { + $t['logged'] = 1; + session_regenerate_id(1); + $_SESSION['logged'] = 1; + $_SESSION['token'] = generateUUID(); + $_SESSION['sign'] = idSignature(session_id(), Config::get('password'), defined('MTT_SALT') ? MTT_SALT : ''); + } + jsonExit($t); } elseif(isset($_POST['logout'])) { - check_token(); - unset($_SESSION['logged']); - unset($_SESSION['token']); - unset($_SESSION['sign']); - $t = array('logged' => 0); - jsonExit($t); + check_token(); + unset($_SESSION['logged']); + unset($_SESSION['token']); + unset($_SESSION['sign']); + $t = array('logged' => 0); + jsonExit($t); } elseif(isset($_GET['suggestTags'])) { - $listId = (int)_get('list'); - check_read_access($listId); - $begin = trim(_get('q')); - $limit = 8; - $q = $db->dq("SELECT name,id FROM {$db->prefix}tags INNER JOIN {$db->prefix}tag2task ON id=tag_id WHERE list_id=$listId AND name LIKE ". - $db->quoteForLike('%s%%',$begin) ." GROUP BY tag_id ORDER BY name LIMIT $limit"); - $t = array(); - while($r = $q->fetchRow()) { - $t[] = $r[0]; - } - jsonExit($t); + $listId = (int)_get('list'); + check_read_access($listId); + $begin = trim(_get('q')); + $limit = 8; + $q = $db->dq("SELECT name,id FROM {$db->prefix}tags INNER JOIN {$db->prefix}tag2task ON id=tag_id WHERE list_id=$listId AND name LIKE ". + $db->quoteForLike('%s%%',$begin) ." GROUP BY tag_id ORDER BY name LIMIT $limit"); + $t = array(); + while($r = $q->fetchRow()) { + $t[] = $r[0]; + } + jsonExit($t); } elseif(isset($_GET['setPrio'])) { - check_write_access(); - $id = (int)$_GET['setPrio']; - $prio = (int)_get('prio'); - if($prio < -1) $prio = -1; - elseif($prio > 2) $prio = 2; - $db->ex("UPDATE {$db->prefix}todolist SET prio=$prio,d_edited=? WHERE id=$id", array(time()) ); - $t = array(); - $t['total'] = 1; - $t['list'][] = array('id'=>$id, 'prio'=>$prio); - jsonExit($t); + check_write_access(); + $id = (int)$_GET['setPrio']; + $prio = (int)_get('prio'); + if($prio < -1) $prio = -1; + elseif($prio > 2) $prio = 2; + $db->ex("UPDATE {$db->prefix}todolist SET prio=$prio,d_edited=? WHERE id=$id", array(time()) ); + $t = array(); + $t['total'] = 1; + $t['list'][] = array('id'=>$id, 'prio'=>$prio); + jsonExit($t); } elseif(isset($_GET['tagCloud'])) { - $listId = (int)_get('list'); - check_read_access($listId); + $listId = (int)_get('list'); + check_read_access($listId); - $q = $db->dq("SELECT name,tag_id,COUNT(tag_id) AS tags_count FROM {$db->prefix}tag2task INNER JOIN {$db->prefix}tags ON tag_id=id ". - "WHERE list_id=$listId GROUP BY (tag_id) ORDER BY tags_count ASC"); - $at = array(); - $ac = array(); - while($r = $q->fetchAssoc()) { - $at[] = array('name'=>$r['name'], 'id'=>$r['tag_id']); - $ac[] = $r['tags_count']; - } + $q = $db->dq("SELECT name,tag_id,COUNT(tag_id) AS tags_count FROM {$db->prefix}tag2task INNER JOIN {$db->prefix}tags ON tag_id=id ". + "WHERE list_id=$listId GROUP BY (tag_id) ORDER BY tags_count ASC"); + $at = array(); + $ac = array(); + while($r = $q->fetchAssoc()) { + $at[] = array('name'=>$r['name'], 'id'=>$r['tag_id']); + $ac[] = $r['tags_count']; + } - $t = array(); - $t['total'] = 0; - $count = sizeof($at); - if(!$count) { - jsonExit($t); - } + $t = array(); + $t['total'] = 0; + $count = sizeof($at); + if(!$count) { + jsonExit($t); + } - $qmax = max($ac); - $qmin = min($ac); - if($count >= 10) $grades = 10; - else $grades = $count; - $step = ($qmax - $qmin)/$grades; - foreach($at as $i=>$tag) - { - $t['cloud'][] = array('tag'=>htmlarray($tag['name']), 'id'=>(int)$tag['id'], 'w'=> tag_size($qmin,$ac[$i],$step) ); - } - $t['total'] = $count; - jsonExit($t); + $qmax = max($ac); + $qmin = min($ac); + if($count >= 10) $grades = 10; + else $grades = $count; + $step = ($qmax - $qmin)/$grades; + foreach($at as $i=>$tag) + { + $t['cloud'][] = array('tag'=>htmlarray($tag['name']), 'id'=>(int)$tag['id'], 'w'=> tag_size($qmin,$ac[$i],$step) ); + } + $t['total'] = $count; + jsonExit($t); } elseif(isset($_GET['addList'])) { - check_write_access(); - $t = array(); - $t['total'] = 0; - $name = str_replace( array('"',"'",'<','>','&'), '', trim(_post('name')) ); - $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}lists"); - $db->dq("INSERT INTO {$db->prefix}lists (uuid,name,ow,d_created,d_edited,taskview) VALUES (?,?,?,?,?,?)", - array(generateUUID(), $name, $ow, time(), time(), 1) ); - $id = $db->lastInsertId(); - $t['total'] = 1; - $r = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$id"); - $t['list'][] = prepareList($r); - jsonExit($t); + check_write_access(); + $t = array(); + $t['total'] = 0; + $name = str_replace( array('"',"'",'<','>','&'), '', trim(_post('name')) ); + $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}lists"); + $db->dq("INSERT INTO {$db->prefix}lists (uuid,name,ow,d_created,d_edited,taskview) VALUES (?,?,?,?,?,?)", + array(generateUUID(), $name, $ow, time(), time(), 1) ); + $id = $db->lastInsertId(); + $t['total'] = 1; + $r = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$id"); + $t['list'][] = prepareList($r); + jsonExit($t); } elseif(isset($_GET['renameList'])) { - check_write_access(); - $t = array(); - $t['total'] = 0; - $id = (int)_post('list'); - $name = str_replace(array('"',"'",'<','>','&'),array('','','','',''),trim(_post('name'))); - $db->dq("UPDATE {$db->prefix}lists SET name=?,d_edited=? WHERE id=$id", array($name, time()) ); - $t['total'] = $db->affected(); - $r = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$id"); - $t['list'][] = prepareList($r); - jsonExit($t); + check_write_access(); + $t = array(); + $t['total'] = 0; + $id = (int)_post('list'); + $name = str_replace(array('"',"'",'<','>','&'),array('','','','',''),trim(_post('name'))); + $db->dq("UPDATE {$db->prefix}lists SET name=?,d_edited=? WHERE id=$id", array($name, time()) ); + $t['total'] = $db->affected(); + $r = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$id"); + $t['list'][] = prepareList($r); + jsonExit($t); } elseif(isset($_GET['deleteList'])) { - check_write_access(); - $t = array(); - $t['total'] = 0; - $id = (int)_post('list'); - $db->ex("BEGIN"); - $db->ex("DELETE FROM {$db->prefix}lists WHERE id=$id"); - $t['total'] = $db->affected(); - if($t['total']) { - $db->ex("DELETE FROM {$db->prefix}tag2task WHERE list_id=$id"); - $db->ex("DELETE FROM {$db->prefix}todolist WHERE list_id=$id"); - } - $db->ex("COMMIT"); - jsonExit($t); + check_write_access(); + $t = array(); + $t['total'] = 0; + $id = (int)_post('list'); + $db->ex("BEGIN"); + $db->ex("DELETE FROM {$db->prefix}lists WHERE id=$id"); + $t['total'] = $db->affected(); + if($t['total']) { + $db->ex("DELETE FROM {$db->prefix}tag2task WHERE list_id=$id"); + $db->ex("DELETE FROM {$db->prefix}todolist WHERE list_id=$id"); + } + $db->ex("COMMIT"); + jsonExit($t); } elseif(isset($_GET['setSort'])) { - check_write_access(); - $listId = (int)_post('list'); - $sort = (int)_post('sort'); - if($sort < 0 || $sort > 104) $sort = 0; - elseif($sort < 101 && $sort > 4) $sort = 0; - if ($listId == -1) { - $opts = Config::requestDomain('alltasks.json'); - $opts['sort'] = $sort; - Config::saveDomain('alltasks.json', $opts); - } - else { - $db->ex("UPDATE {$db->prefix}lists SET sorting=$sort,d_edited=? WHERE id=$listId", array(time())); - } - jsonExit(array('total'=>1)); + check_write_access(); + $listId = (int)_post('list'); + $sort = (int)_post('sort'); + if($sort < 0 || $sort > 104) $sort = 0; + elseif($sort < 101 && $sort > 4) $sort = 0; + if ($listId == -1) { + $opts = Config::requestDomain('alltasks.json'); + $opts['sort'] = $sort; + Config::saveDomain('alltasks.json', $opts); + } + else { + $db->ex("UPDATE {$db->prefix}lists SET sorting=$sort,d_edited=? WHERE id=$listId", array(time())); + } + jsonExit(array('total'=>1)); } elseif(isset($_GET['publishList'])) { - check_write_access(); - $listId = (int)_post('list'); - $publish = (int)_post('publish'); - $db->ex("UPDATE {$db->prefix}lists SET published=?,d_created=? WHERE id=$listId", array($publish ? 1 : 0, time())); - jsonExit(array('total'=>1)); + check_write_access(); + $listId = (int)_post('list'); + $publish = (int)_post('publish'); + $db->ex("UPDATE {$db->prefix}lists SET published=?,d_created=? WHERE id=$listId", array($publish ? 1 : 0, time())); + jsonExit(array('total'=>1)); } elseif(isset($_GET['moveTask'])) { - check_write_access(); - $id = (int)_post('id'); - $fromId = (int)_post('from'); - $toId = (int)_post('to'); - $result = moveTask($id, $toId); - $t = array('total' => $result ? 1 : 0); - if($fromId == -1 && $result && $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id")) { - $t['list'][] = prepareTaskRow($r); - } - jsonExit($t); + check_write_access(); + $id = (int)_post('id'); + $fromId = (int)_post('from'); + $toId = (int)_post('to'); + $result = moveTask($id, $toId); + $t = array('total' => $result ? 1 : 0); + if($fromId == -1 && $result && $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=$id")) { + $t['list'][] = prepareTaskRow($r); + } + jsonExit($t); } elseif(isset($_GET['changeListOrder'])) { - check_write_access(); - $order = (array)_post('order'); - $t = array(); - $t['total'] = 0; - if($order) - { - $a = array(); - $setCase = ''; - foreach($order as $ow=>$id) { - $id = (int)$id; - $a[] = $id; - $setCase .= "WHEN id=$id THEN $ow\n"; - } - $ids = implode(',', $a); - $db->dq("UPDATE {$db->prefix}lists SET d_edited=?, ow = CASE\n $setCase END WHERE id IN ($ids)", - array(time()) ); - $t['total'] = 1; - } - jsonExit($t); + check_write_access(); + $order = (array)_post('order'); + $t = array(); + $t['total'] = 0; + if($order) + { + $a = array(); + $setCase = ''; + foreach($order as $ow=>$id) { + $id = (int)$id; + $a[] = $id; + $setCase .= "WHEN id=$id THEN $ow\n"; + } + $ids = implode(',', $a); + $db->dq("UPDATE {$db->prefix}lists SET d_edited=?, ow = CASE\n $setCase END WHERE id IN ($ids)", + array(time()) ); + $t['total'] = 1; + } + jsonExit($t); } elseif(isset($_GET['parseTaskStr'])) { - check_write_access(); - $t = array( - 'title' => trim(_post('title')), - 'prio' => 0, - 'tags' => '' - ); - if(Config::get('smartsyntax') != 0 && (false !== $a = parse_smartsyntax($t['title']))) - { - $t['title'] = $a['title']; - $t['prio'] = $a['prio']; - $t['tags'] = $a['tags']; - } - jsonExit($t); + check_write_access(); + $t = array( + 'title' => trim(_post('title')), + 'prio' => 0, + 'tags' => '' + ); + if(Config::get('smartsyntax') != 0 && (false !== $a = parse_smartsyntax($t['title']))) + { + $t['title'] = $a['title']; + $t['prio'] = $a['prio']; + $t['tags'] = $a['tags']; + } + jsonExit($t); } elseif(isset($_GET['clearCompletedInList'])) { - check_write_access(); - $t = array(); - $t['total'] = 0; - $listId = (int)_post('list'); - $db->ex("BEGIN"); - $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id IN (SELECT id FROM {$db->prefix}todolist WHERE list_id=? and compl=1)", array($listId)); - $db->ex("DELETE FROM {$db->prefix}todolist WHERE list_id=$listId and compl=1"); - $t['total'] = $db->affected(); - $db->ex("COMMIT"); - jsonExit($t); + check_write_access(); + $t = array(); + $t['total'] = 0; + $listId = (int)_post('list'); + $db->ex("BEGIN"); + $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id IN (SELECT id FROM {$db->prefix}todolist WHERE list_id=? and compl=1)", array($listId)); + $db->ex("DELETE FROM {$db->prefix}todolist WHERE list_id=$listId and compl=1"); + $t['total'] = $db->affected(); + $db->ex("COMMIT"); + jsonExit($t); } elseif(isset($_GET['setShowNotesInList'])) { - check_write_access(); - $listId = (int)_post('list'); - $flag = (int)_post('shownotes'); - $bitwise = ($flag == 0) ? 'taskview & ~2' : 'taskview | 2'; - $db->dq("UPDATE {$db->prefix}lists SET taskview=$bitwise WHERE id=$listId"); - jsonExit(array('total'=>1)); + check_write_access(); + $listId = (int)_post('list'); + $flag = (int)_post('shownotes'); + $bitwise = ($flag == 0) ? 'taskview & ~2' : 'taskview | 2'; + $db->dq("UPDATE {$db->prefix}lists SET taskview=$bitwise WHERE id=$listId"); + jsonExit(array('total'=>1)); } elseif(isset($_GET['setHideList'])) { - check_write_access(); - $listId = (int)_post('list'); - $flag = (int)_post('hide') ? 1 : 0; - if ($listId == -1) { - $opts = Config::requestDomain('alltasks.json'); - $opts['hidden'] = $flag; - Config::saveDomain('alltasks.json', $opts); - } - else { - $bitwise = ($flag == 0) ? 'taskview & ~4' : 'taskview | 4'; - $db->dq("UPDATE {$db->prefix}lists SET taskview=$bitwise WHERE id=$listId"); - } - jsonExit(array('total'=>1)); + check_write_access(); + $listId = (int)_post('list'); + $flag = (int)_post('hide') ? 1 : 0; + if ($listId == -1) { + $opts = Config::requestDomain('alltasks.json'); + $opts['hidden'] = $flag; + Config::saveDomain('alltasks.json', $opts); + } + else { + $bitwise = ($flag == 0) ? 'taskview & ~4' : 'taskview | 4'; + $db->dq("UPDATE {$db->prefix}lists SET taskview=$bitwise WHERE id=$listId"); + } + jsonExit(array('total'=>1)); } @@ -548,407 +548,407 @@ elseif(isset($_GET['setHideList'])) function prepareTaskRow($r) { - $lang = Lang::instance(); - $dueA = prepare_duedate($r['duedate']); - $formatCreatedInline = $formatCompletedInline = Config::get('dateformatshort'); - if(date('Y') != date('Y',$r['d_created'])) $formatCreatedInline = Config::get('dateformat2'); - if($r['d_completed'] && date('Y') != date('Y',$r['d_completed'])) $formatCompletedInline = Config::get('dateformat2'); + $lang = Lang::instance(); + $dueA = prepare_duedate($r['duedate']); + $formatCreatedInline = $formatCompletedInline = Config::get('dateformatshort'); + if(date('Y') != date('Y',$r['d_created'])) $formatCreatedInline = Config::get('dateformat2'); + if($r['d_completed'] && date('Y') != date('Y',$r['d_completed'])) $formatCompletedInline = Config::get('dateformat2'); - $dCreated = timestampToDatetime($r['d_created']); - $dCompleted = $r['d_completed'] ? timestampToDatetime($r['d_completed']) : ''; + $dCreated = timestampToDatetime($r['d_created']); + $dCompleted = $r['d_completed'] ? timestampToDatetime($r['d_completed']) : ''; - return array( - 'id' => $r['id'], - 'title' => titleMarkup( $r['title'] ), - 'titleText' => (string)$r['title'], - 'listId' => $r['list_id'], - 'date' => htmlarray($dCreated), - 'dateInt' => (int)$r['d_created'], - 'dateInline' => htmlarray(formatTime($formatCreatedInline, $r['d_created'])), - 'dateInlineTitle' => htmlarray(sprintf($lang->get('taskdate_inline_created'), $dCreated)), - 'dateEditedInt' => (int)$r['d_edited'], - 'dateCompleted' => htmlarray($dCompleted), - 'dateCompletedInline' => $r['d_completed'] ? htmlarray(formatTime($formatCompletedInline, $r['d_completed'])) : '', - 'dateCompletedInlineTitle' => htmlarray(sprintf($lang->get('taskdate_inline_completed'), $dCompleted)), - 'compl' => (int)$r['compl'], - 'prio' => $r['prio'], - 'note' => noteMarkup($r['note']), - 'noteText' => (string)$r['note'], - 'ow' => (int)$r['ow'], - 'tags' => htmlarray($r['tags']), - 'tags_ids' => htmlarray($r['tags_ids']), - 'duedate' => $dueA['formatted'], - 'dueClass' => $dueA['class'], - 'dueStr' => htmlarray($r['compl'] && $dueA['timestamp'] ? formatTime($formatCompletedInline, $dueA['timestamp']) : $dueA['str']), - 'dueInt' => date2int($r['duedate']), - 'dueTitle' => htmlarray(sprintf($lang->get('taskdate_inline_duedate'), $dueA['formattedlong'])), - ); + return array( + 'id' => $r['id'], + 'title' => titleMarkup( $r['title'] ), + 'titleText' => (string)$r['title'], + 'listId' => $r['list_id'], + 'date' => htmlarray($dCreated), + 'dateInt' => (int)$r['d_created'], + 'dateInline' => htmlarray(formatTime($formatCreatedInline, $r['d_created'])), + 'dateInlineTitle' => htmlarray(sprintf($lang->get('taskdate_inline_created'), $dCreated)), + 'dateEditedInt' => (int)$r['d_edited'], + 'dateCompleted' => htmlarray($dCompleted), + 'dateCompletedInline' => $r['d_completed'] ? htmlarray(formatTime($formatCompletedInline, $r['d_completed'])) : '', + 'dateCompletedInlineTitle' => htmlarray(sprintf($lang->get('taskdate_inline_completed'), $dCompleted)), + 'compl' => (int)$r['compl'], + 'prio' => $r['prio'], + 'note' => noteMarkup($r['note']), + 'noteText' => (string)$r['note'], + 'ow' => (int)$r['ow'], + 'tags' => htmlarray($r['tags']), + 'tags_ids' => htmlarray($r['tags_ids']), + 'duedate' => $dueA['formatted'], + 'dueClass' => $dueA['class'], + 'dueStr' => htmlarray($r['compl'] && $dueA['timestamp'] ? formatTime($formatCompletedInline, $dueA['timestamp']) : $dueA['str']), + 'dueInt' => date2int($r['duedate']), + 'dueTitle' => htmlarray(sprintf($lang->get('taskdate_inline_duedate'), $dueA['formattedlong'])), + ); } function check_read_access($listId = null) { - check_token(); - $db = DBConnection::instance(); - if(is_logged()) return true; - if($listId !== null) - { - $id = $db->sq("SELECT id FROM {$db->prefix}lists WHERE id=? AND published=1", array($listId)); - if($id) return; - } - jsonExit( array('total'=>0, 'list'=>array(), 'denied'=>1) ); + check_token(); + $db = DBConnection::instance(); + if(is_logged()) return true; + if($listId !== null) + { + $id = $db->sq("SELECT id FROM {$db->prefix}lists WHERE id=? AND published=1", array($listId)); + if($id) return; + } + jsonExit( array('total'=>0, 'list'=>array(), 'denied'=>1) ); } function have_write_access($listId = null) { - if(is_readonly()) return false; - // check list exist - if($listId !== null) - { - $db = DBConnection::instance(); - $count = $db->sq("SELECT COUNT(*) FROM {$db->prefix}lists WHERE id=?", array($listId)); - if(!$count) return false; - } - return true; + if(is_readonly()) return false; + // check list exist + if($listId !== null) + { + $db = DBConnection::instance(); + $count = $db->sq("SELECT COUNT(*) FROM {$db->prefix}lists WHERE id=?", array($listId)); + if(!$count) return false; + } + return true; } function check_write_access($listId = null) { - check_token(); - if(have_write_access($listId)) return; - jsonExit( array('total'=>0, 'list'=>array(), 'denied'=>1) ); + check_token(); + if(have_write_access($listId)) return; + jsonExit( array('total'=>0, 'list'=>array(), 'denied'=>1) ); } function inputTaskParams() { - $a = array( - 'id' => _post('id'), - 'title'=> trim(_post('title')), - 'note' => str_replace("\r\n", "\n", trim(_post('note'))), - 'prio' => (int)_post('prio'), - 'duedate' => '', - 'tags' => trim(_post('tags')), - 'listId' => (int)_post('list'), + $a = array( + 'id' => _post('id'), + 'title'=> trim(_post('title')), + 'note' => str_replace("\r\n", "\n", trim(_post('note'))), + 'prio' => (int)_post('prio'), + 'duedate' => '', + 'tags' => trim(_post('tags')), + 'listId' => (int)_post('list'), - ); - if($a['prio'] < -1) $a['prio'] = -1; - elseif($a['prio'] > 2) $a['prio'] = 2; - return $a; + ); + if($a['prio'] < -1) $a['prio'] = -1; + elseif($a['prio'] > 2) $a['prio'] = 2; + return $a; } function prepareTags($tagsStr) { - $tags = explode(',', $tagsStr); - if(!$tags) return 0; + $tags = explode(',', $tagsStr); + if(!$tags) return 0; - $aTags = array('tags'=>array(), 'ids'=>array()); - foreach($tags as $tag) - { - $tag = str_replace(array('"',"'",'<','>','&','/','\\','^','#'),'',trim($tag)); - if($tag == '') continue; + $aTags = array('tags'=>array(), 'ids'=>array()); + foreach($tags as $tag) + { + $tag = str_replace(array('"',"'",'<','>','&','/','\\','^','#'),'',trim($tag)); + if($tag == '') continue; - $aTag = getOrCreateTag($tag); - if($aTag && !in_array($aTag['id'], $aTags['ids'])) { - $aTags['tags'][] = $aTag['name']; - $aTags['ids'][] = $aTag['id']; - } - } - return $aTags; + $aTag = getOrCreateTag($tag); + if($aTag && !in_array($aTag['id'], $aTags['ids'])) { + $aTags['tags'][] = $aTag['name']; + $aTags['ids'][] = $aTag['id']; + } + } + return $aTags; } function getOrCreateTag($name) { - $db = DBConnection::instance(); - $tagId = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($name)); - if($tagId) return array('id'=>$tagId, 'name'=>$name); + $db = DBConnection::instance(); + $tagId = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($name)); + if($tagId) return array('id'=>$tagId, 'name'=>$name); - $db->ex("INSERT INTO {$db->prefix}tags (name) VALUES (?)", array($name)); - return array('id'=>$db->lastInsertId(), 'name'=>$name); + $db->ex("INSERT INTO {$db->prefix}tags (name) VALUES (?)", array($name)); + return array('id'=>$db->lastInsertId(), 'name'=>$name); } function getTagId($tag) { - $db = DBConnection::instance(); - $id = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($tag)); - return $id ? $id : 0; + $db = DBConnection::instance(); + $id = $db->sq("SELECT id FROM {$db->prefix}tags WHERE name=?", array($tag)); + return $id ? $id : 0; } function get_task_tags($id) { - $db = DBConnection::instance(); - $q = $db->dq("SELECT tag_id FROM {$db->prefix}tag2task WHERE task_id=?", $id); - $a = array(); - while($r = $q->fetchRow()) { - $a[] = $r[0]; - } - return $a; + $db = DBConnection::instance(); + $q = $db->dq("SELECT tag_id FROM {$db->prefix}tag2task WHERE task_id=?", $id); + $a = array(); + while($r = $q->fetchRow()) { + $a[] = $r[0]; + } + return $a; } function addTaskTags($taskId, $tagIds, $listId) { - $db = DBConnection::instance(); - if(!$tagIds) return; - foreach($tagIds as $tagId) - { - $db->ex("INSERT INTO {$db->prefix}tag2task (task_id,tag_id,list_id) VALUES (?,?,?)", array($taskId,$tagId,$listId)); - } + $db = DBConnection::instance(); + if(!$tagIds) return; + foreach($tagIds as $tagId) + { + $db->ex("INSERT INTO {$db->prefix}tag2task (task_id,tag_id,list_id) VALUES (?,?,?)", array($taskId,$tagId,$listId)); + } } function parse_smartsyntax($title) { - $a = [ - 'prio' => 0, - 'title' => $title, - 'tags' => '' - ]; - if ( preg_match("|^([-+]{1}\d+)(.+)|", $a['title'], $m) ) { - $a['prio'] = (int) $m[1]; - if ( $a['prio'] < -1 ) $a['prio'] = -1; - elseif ( $a['prio'] > 2 ) $a['prio'] = 2; - $a['title'] = trim($m[2]); - } - $tags = []; - $a['title'] = trim( preg_replace_callback( - "/(?:^|\s+)#([^#\s]+)/", - function ($matches) use (&$tags) { - $tags[] = $matches[1]; - return ''; - }, - $a['title'] - ) ); - if (count($tags) > 0) { - $a['tags'] = implode( ',' , $tags ); - } - return $a; + $a = [ + 'prio' => 0, + 'title' => $title, + 'tags' => '' + ]; + if ( preg_match("|^([-+]{1}\d+)(.+)|", $a['title'], $m) ) { + $a['prio'] = (int) $m[1]; + if ( $a['prio'] < -1 ) $a['prio'] = -1; + elseif ( $a['prio'] > 2 ) $a['prio'] = 2; + $a['title'] = trim($m[2]); + } + $tags = []; + $a['title'] = trim( preg_replace_callback( + "/(?:^|\s+)#([^#\s]+)/", + function ($matches) use (&$tags) { + $tags[] = $matches[1]; + return ''; + }, + $a['title'] + ) ); + if (count($tags) > 0) { + $a['tags'] = implode( ',' , $tags ); + } + return $a; } function tag_size($qmin, $q, $step) { - if($step == 0) return 1; - $v = ceil(($q - $qmin)/$step); - if($v == 0) return 0; - else return $v-1; + if($step == 0) return 1; + $v = ceil(($q - $qmin)/$step); + if($v == 0) return 0; + else return $v-1; } function parse_duedate($s) { - $df2 = Config::get('dateformat2'); - if(max((int)strpos($df2,'n'), (int)strpos($df2,'m')) > max((int)strpos($df2,'d'), (int)strpos($df2,'j'))) $formatDayFirst = true; - else $formatDayFirst = false; + $df2 = Config::get('dateformat2'); + if(max((int)strpos($df2,'n'), (int)strpos($df2,'m')) > max((int)strpos($df2,'d'), (int)strpos($df2,'j'))) $formatDayFirst = true; + else $formatDayFirst = false; - $y = $m = $d = 0; - if(preg_match("|^(\d+)-(\d+)-(\d+)\b|", $s, $ma)) { - $y = (int)$ma[1]; $m = (int)$ma[2]; $d = (int)$ma[3]; - } - elseif(preg_match("|^(\d+)\/(\d+)\/(\d+)\b|", $s, $ma)) - { - if($formatDayFirst) { - $d = (int)$ma[1]; $m = (int)$ma[2]; $y = (int)$ma[3]; - } else { - $m = (int)$ma[1]; $d = (int)$ma[2]; $y = (int)$ma[3]; - } - } - elseif(preg_match("|^(\d+)\.(\d+)\.(\d+)\b|", $s, $ma)) { - $d = (int)$ma[1]; $m = (int)$ma[2]; $y = (int)$ma[3]; - } - elseif(preg_match("|^(\d+)\.(\d+)\b|", $s, $ma)) { - $d = (int)$ma[1]; $m = (int)$ma[2]; - $a = explode(',', date('Y,m,d')); - if( $m<(int)$a[1] || ($m==(int)$a[1] && $d<(int)$a[2]) ) $y = (int)$a[0]+1; - else $y = (int)$a[0]; - } - elseif(preg_match("|^(\d+)\/(\d+)\b|", $s, $ma)) - { - if($formatDayFirst) { - $d = (int)$ma[1]; $m = (int)$ma[2]; - } else { - $m = (int)$ma[1]; $d = (int)$ma[2]; - } - $a = explode(',', date('Y,m,d')); - if( $m<(int)$a[1] || ($m==(int)$a[1] && $d<(int)$a[2]) ) $y = (int)$a[0]+1; - else $y = (int)$a[0]; - } - else return null; - if($y < 100) $y = 2000 + $y; - elseif($y < 1000 || $y > 2099) $y = 2000 + (int)substr((string)$y, -2); - if($m > 12) $m = 12; - $maxdays = daysInMonth($m,$y); - if($m < 10) $m = '0'.$m; - if($d > $maxdays) $d = $maxdays; - elseif($d < 10) $d = '0'.$d; - return "$y-$m-$d"; + $y = $m = $d = 0; + if(preg_match("|^(\d+)-(\d+)-(\d+)\b|", $s, $ma)) { + $y = (int)$ma[1]; $m = (int)$ma[2]; $d = (int)$ma[3]; + } + elseif(preg_match("|^(\d+)\/(\d+)\/(\d+)\b|", $s, $ma)) + { + if($formatDayFirst) { + $d = (int)$ma[1]; $m = (int)$ma[2]; $y = (int)$ma[3]; + } else { + $m = (int)$ma[1]; $d = (int)$ma[2]; $y = (int)$ma[3]; + } + } + elseif(preg_match("|^(\d+)\.(\d+)\.(\d+)\b|", $s, $ma)) { + $d = (int)$ma[1]; $m = (int)$ma[2]; $y = (int)$ma[3]; + } + elseif(preg_match("|^(\d+)\.(\d+)\b|", $s, $ma)) { + $d = (int)$ma[1]; $m = (int)$ma[2]; + $a = explode(',', date('Y,m,d')); + if( $m<(int)$a[1] || ($m==(int)$a[1] && $d<(int)$a[2]) ) $y = (int)$a[0]+1; + else $y = (int)$a[0]; + } + elseif(preg_match("|^(\d+)\/(\d+)\b|", $s, $ma)) + { + if($formatDayFirst) { + $d = (int)$ma[1]; $m = (int)$ma[2]; + } else { + $m = (int)$ma[1]; $d = (int)$ma[2]; + } + $a = explode(',', date('Y,m,d')); + if( $m<(int)$a[1] || ($m==(int)$a[1] && $d<(int)$a[2]) ) $y = (int)$a[0]+1; + else $y = (int)$a[0]; + } + else return null; + if($y < 100) $y = 2000 + $y; + elseif($y < 1000 || $y > 2099) $y = 2000 + (int)substr((string)$y, -2); + if($m > 12) $m = 12; + $maxdays = daysInMonth($m,$y); + if($m < 10) $m = '0'.$m; + if($d > $maxdays) $d = $maxdays; + elseif($d < 10) $d = '0'.$d; + return "$y-$m-$d"; } function prepare_duedate($duedate) { - $lang = Lang::instance(); + $lang = Lang::instance(); - $a = array( 'class'=>'', 'str'=>'', 'formatted'=>'', 'formattedlong'=>'', 'timestamp'=>0 ); - if($duedate == '') { - return $a; - } - $ad = explode('-', $duedate); - $at = explode('-', date('Y-m-d')); - $a['timestamp'] = mktime(0,0,0,$ad[1],$ad[2],$ad[0]); - $diff = mktime(0,0,0,$ad[1],$ad[2],$ad[0]) - mktime(0,0,0,$at[1],$at[2],$at[0]); + $a = array( 'class'=>'', 'str'=>'', 'formatted'=>'', 'formattedlong'=>'', 'timestamp'=>0 ); + if($duedate == '') { + return $a; + } + $ad = explode('-', $duedate); + $at = explode('-', date('Y-m-d')); + $a['timestamp'] = mktime(0,0,0,$ad[1],$ad[2],$ad[0]); + $diff = mktime(0,0,0,$ad[1],$ad[2],$ad[0]) - mktime(0,0,0,$at[1],$at[2],$at[0]); - if($diff < -604800 && $ad[0] == $at[0]) { $a['class'] = 'past'; $a['str'] = formatDate3(Config::get('dateformatshort'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang); } - elseif($diff < -604800) { $a['class'] = 'past'; $a['str'] = formatDate3(Config::get('dateformat2'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang); } - elseif($diff < -86400) { $a['class'] = 'past'; $a['str'] = sprintf($lang->get('daysago'),ceil(abs($diff)/86400)); } - elseif($diff < 0) { $a['class'] = 'past'; $a['str'] = $lang->get('yesterday'); } - elseif($diff < 86400) { $a['class'] = 'today'; $a['str'] = $lang->get('today'); } - elseif($diff < 172800) { $a['class'] = 'today'; $a['str'] = $lang->get('tomorrow'); } - elseif($diff < 691200) { $a['class'] = 'soon'; $a['str'] = sprintf($lang->get('indays'),ceil($diff/86400)); } - elseif($ad[0] == $at[0]) { $a['class'] = 'future'; $a['str'] = formatDate3(Config::get('dateformatshort'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang); } - else { $a['class'] = 'future'; $a['str'] = formatDate3(Config::get('dateformat2'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang); } + if($diff < -604800 && $ad[0] == $at[0]) { $a['class'] = 'past'; $a['str'] = formatDate3(Config::get('dateformatshort'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang); } + elseif($diff < -604800) { $a['class'] = 'past'; $a['str'] = formatDate3(Config::get('dateformat2'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang); } + elseif($diff < -86400) { $a['class'] = 'past'; $a['str'] = sprintf($lang->get('daysago'),ceil(abs($diff)/86400)); } + elseif($diff < 0) { $a['class'] = 'past'; $a['str'] = $lang->get('yesterday'); } + elseif($diff < 86400) { $a['class'] = 'today'; $a['str'] = $lang->get('today'); } + elseif($diff < 172800) { $a['class'] = 'today'; $a['str'] = $lang->get('tomorrow'); } + elseif($diff < 691200) { $a['class'] = 'soon'; $a['str'] = sprintf($lang->get('indays'),ceil($diff/86400)); } + elseif($ad[0] == $at[0]) { $a['class'] = 'future'; $a['str'] = formatDate3(Config::get('dateformatshort'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang); } + else { $a['class'] = 'future'; $a['str'] = formatDate3(Config::get('dateformat2'), (int)$ad[0], (int)$ad[1], (int)$ad[2], $lang); } - #avoid short year - $fmt = str_replace('y', 'Y', Config::get('dateformat2')); - $a['formatted'] = formatTime($fmt, $a['timestamp']); - $a['formattedlong'] = formatTime(Config::get('dateformat'), $a['timestamp']); + #avoid short year + $fmt = str_replace('y', 'Y', Config::get('dateformat2')); + $a['formatted'] = formatTime($fmt, $a['timestamp']); + $a['formattedlong'] = formatTime(Config::get('dateformat'), $a['timestamp']); - return $a; + return $a; } function date2int($d) { - if(!$d) return 33330000; - $ad = explode('-', $d); - $s = $ad[0]; - if(strlen($ad[1]) < 2) $s .= "0$ad[1]"; else $s .= $ad[1]; - if(strlen($ad[2]) < 2) $s .= "0$ad[2]"; else $s .= $ad[2]; - return (int)$s; + if(!$d) return 33330000; + $ad = explode('-', $d); + $s = $ad[0]; + if(strlen($ad[1]) < 2) $s .= "0$ad[1]"; else $s .= $ad[1]; + if(strlen($ad[2]) < 2) $s .= "0$ad[2]"; else $s .= $ad[2]; + return (int)$s; } function daysInMonth($m, $y=0) { - if($y == 0) $y = (int)date('Y'); - $a = array(1=>31,(($y-2000)%4?28:29),31,30,31,30,31,31,30,31,30,31); - if(isset($a[$m])) return $a[$m]; else return 0; + if($y == 0) $y = (int)date('Y'); + $a = array(1=>31,(($y-2000)%4?28:29),31,30,31,30,31,31,30,31,30,31); + if(isset($a[$m])) return $a[$m]; else return 0; } function myErrorHandler($errno, $errstr, $errfile, $errline) { - if ($errno==E_ERROR || $errno==E_CORE_ERROR || $errno==E_COMPILE_ERROR || $errno==E_USER_ERROR || $errno==E_PARSE) { - $error = 'Error'; - } - elseif ($errno==E_WARNING || $errno==E_CORE_WARNING || $errno==E_COMPILE_WARNING || $errno==E_USER_WARNING || $errno==E_STRICT) { - if (error_reporting() & $errno) $error = 'Warning'; else return; - } - elseif ($errno==E_NOTICE || $errno==E_USER_NOTICE || $errno==E_DEPRECATED || $errno==E_USER_DEPRECATED) { - if (error_reporting() & $errno) $error = 'Notice'; else return; - } - else $error = "Error ($errno)"; # here may be E_RECOVERABLE_ERROR - throw new Exception("$error: '$errstr' in $errfile:$errline", -1); + if ($errno==E_ERROR || $errno==E_CORE_ERROR || $errno==E_COMPILE_ERROR || $errno==E_USER_ERROR || $errno==E_PARSE) { + $error = 'Error'; + } + elseif ($errno==E_WARNING || $errno==E_CORE_WARNING || $errno==E_COMPILE_WARNING || $errno==E_USER_WARNING || $errno==E_STRICT) { + if (error_reporting() & $errno) $error = 'Warning'; else return; + } + elseif ($errno==E_NOTICE || $errno==E_USER_NOTICE || $errno==E_DEPRECATED || $errno==E_USER_DEPRECATED) { + if (error_reporting() & $errno) $error = 'Notice'; else return; + } + else $error = "Error ($errno)"; # here may be E_RECOVERABLE_ERROR + throw new Exception("$error: '$errstr' in $errfile:$errline", -1); } function myExceptionHandler($e) { - // to avoid Exception thrown without a stack frame - try - { - if (-1 == $e->getCode()) { - //thrown in myErrorHandler - logAndDie( $e->getMessage() ); - } + // to avoid Exception thrown without a stack frame + try + { + if (-1 == $e->getCode()) { + //thrown in myErrorHandler + logAndDie( $e->getMessage() ); + } - $c = get_class($e); - $errText = "Exception ($c): '". $e->getMessage(). "' in ". $e->getFile(). ":". $e->getLine() ; + $c = get_class($e); + $errText = "Exception ($c): '". $e->getMessage(). "' in ". $e->getFile(). ":". $e->getLine() ; - if (MTT_DEBUG) { - if ( count($e->getTrace()) > 0 ) { - $errText .= "\n". $e->getTraceAsString() ; - } - } - logAndDie($errText); - } - catch (Exception $e) { - logAndDie('Exception in ExceptionHandler: \''. $e->getMessage() .'\' in '. $e->getFile() .':'. $e->getLine()); - } - exit; + if (MTT_DEBUG) { + if ( count($e->getTrace()) > 0 ) { + $errText .= "\n". $e->getTraceAsString() ; + } + } + logAndDie($errText); + } + catch (Exception $e) { + logAndDie('Exception in ExceptionHandler: \''. $e->getMessage() .'\' in '. $e->getFile() .':'. $e->getLine()); + } + exit; } function deleteTask($id) { - check_write_access(); - $db = DBConnection::instance(); - $db->ex("BEGIN"); - $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id"); - //TODO: delete unused tags? - $db->dq("DELETE FROM {$db->prefix}todolist WHERE id=$id"); - $affected = $db->affected(); - $db->ex("COMMIT"); - return $affected; + check_write_access(); + $db = DBConnection::instance(); + $db->ex("BEGIN"); + $db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id"); + //TODO: delete unused tags? + $db->dq("DELETE FROM {$db->prefix}todolist WHERE id=$id"); + $affected = $db->affected(); + $db->ex("COMMIT"); + return $affected; } function moveTask($id, $listId) { - check_write_access(); - $db = DBConnection::instance(); + check_write_access(); + $db = DBConnection::instance(); - // Check task exists and not in target list - $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=?", array($id)); - if(!$r || $listId == $r['list_id']) return false; + // Check task exists and not in target list + $r = $db->sqa("SELECT * FROM {$db->prefix}todolist WHERE id=?", array($id)); + if(!$r || $listId == $r['list_id']) return false; - // Check target list exists - if(!$db->sq("SELECT COUNT(*) FROM {$db->prefix}lists WHERE id=?", $listId)) - return false; + // Check target list exists + if(!$db->sq("SELECT COUNT(*) FROM {$db->prefix}lists WHERE id=?", $listId)) + return false; - $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=? AND compl=?", array($listId, $r['compl']?1:0)); + $ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}todolist WHERE list_id=? AND compl=?", array($listId, $r['compl']?1:0)); - $db->ex("BEGIN"); - $db->ex("UPDATE {$db->prefix}tag2task SET list_id=? WHERE task_id=?", array($listId, $id)); - $db->dq("UPDATE {$db->prefix}todolist SET list_id=?, ow=?, d_edited=? WHERE id=?", array($listId, $ow, time(), $id)); - $db->ex("COMMIT"); - return true; + $db->ex("BEGIN"); + $db->ex("UPDATE {$db->prefix}tag2task SET list_id=? WHERE task_id=?", array($listId, $id)); + $db->dq("UPDATE {$db->prefix}todolist SET list_id=?, ow=?, d_edited=? WHERE id=?", array($listId, $ow, time(), $id)); + $db->ex("COMMIT"); + return true; } function prepareList($row) { - $taskview = (int)$row['taskview']; - return array( - 'id' => $row['id'], - 'name' => htmlarray($row['name']), - 'sort' => (int)$row['sorting'], - 'published' => $row['published'] ? 1 :0, - 'showCompl' => $taskview & 1 ? 1 : 0, - 'showNotes' => $taskview & 2 ? 1 : 0, - 'hidden' => $taskview & 4 ? 1 : 0, - ); + $taskview = (int)$row['taskview']; + return array( + 'id' => $row['id'], + 'name' => htmlarray($row['name']), + 'sort' => (int)$row['sorting'], + 'published' => $row['published'] ? 1 :0, + 'showCompl' => $taskview & 1 ? 1 : 0, + 'showNotes' => $taskview & 2 ? 1 : 0, + 'hidden' => $taskview & 4 ? 1 : 0, + ); } function prepareAllTasksList() { - //default values - $hidden = 1; - $sort = 3; + //default values + $hidden = 1; + $sort = 3; - $opts = Config::requestDomain('alltasks.json'); - if ( isset($opts['hidden']) ) $hidden = (int)$opts['hidden'] ? 1 : 0; - if ( isset($opts['sort']) ) $sort = (int)$opts['sort']; + $opts = Config::requestDomain('alltasks.json'); + if ( isset($opts['hidden']) ) $hidden = (int)$opts['hidden'] ? 1 : 0; + if ( isset($opts['sort']) ) $sort = (int)$opts['sort']; - return array( - 'id' => -1, - 'name' => htmlarray(__('alltasks')), - 'sort' => $sort, - 'published' => 0, - 'showCompl' => 1, - 'showNotes' => 0, - 'hidden' => $hidden, - ); + return array( + 'id' => -1, + 'name' => htmlarray(__('alltasks')), + 'sort' => $sort, + 'published' => 0, + 'showCompl' => 1, + 'showNotes' => 0, + 'hidden' => $hidden, + ); } function getUserListsSimple() { - $db = DBConnection::instance(); - $a = array(); - $q = $db->dq("SELECT id,name FROM {$db->prefix}lists ORDER BY id ASC"); - while($r = $q->fetchRow()) { - $a[$r[0]] = $r[1]; - } - return $a; + $db = DBConnection::instance(); + $a = array(); + $q = $db->dq("SELECT id,name FROM {$db->prefix}lists ORDER BY id ASC"); + while($r = $q->fetchRow()) { + $a[$r[0]] = $r[1]; + } + return $a; } diff --git a/src/docker-config.php b/src/docker-config.php index ec074ab..9f643a2 100644 --- a/src/docker-config.php +++ b/src/docker-config.php @@ -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"); \ No newline at end of file diff --git a/src/export.php b/src/export.php index d0f74d9..7af704e 100644 --- a/src/export.php +++ b/src/export.php @@ -1,9 +1,9 @@ - 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 + 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); } ?> \ No newline at end of file diff --git a/src/feed.php b/src/feed.php index b74f298..74ae233 100644 --- a/src/feed.php +++ b/src/feed.php @@ -1,9 +1,9 @@ - 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 + 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!
List is not published."); + die("Access denied!
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("
", htmlarray($a)). "

". $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("
", htmlarray($a)). "

". $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 = "\n". - "\n". - "\n". - "$listData[_feed_title]\n". - "$link\n". - "\n". - "$listData[_feed_descr]\n". - "$buildDate\n\n"; + $s = "\n". + "\n". + "\n". + "$listData[_feed_title]\n". + "$link\n". + "\n". + "$listData[_feed_descr]\n". + "$buildDate\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 .= "\n". - "". $status. $v['title']. "\n". - "". $itemLink. "\n". - "". $v['_d']. "\n". - "\n". - "$guid\n". - "\n\n"; - } + $s .= "\n". + "". $status. $v['title']. "\n". + "". $itemLink. "\n". + "". $v['_d']. "\n". + "\n". + "$guid\n". + "\n\n"; + } - $s .= "\n"; + $s .= "\n"; - header("Content-type: text/xml; charset=utf-8"); - print $s; + header("Content-type: text/xml; charset=utf-8"); + print $s; } ?> \ No newline at end of file diff --git a/src/includes/class.config.php b/src/includes/class.config.php index 519a227..f21ec54 100644 --- a/src/includes/class.config.php +++ b/src/includes/class.config.php @@ -1,309 +1,309 @@ - 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 + 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[] = " \ No newline at end of file diff --git a/src/includes/class.db.mysql.php b/src/includes/class.db.mysql.php index 555a47e..0eecc79 100644 --- a/src/includes/class.db.mysql.php +++ b/src/includes/class.db.mysql.php @@ -1,192 +1,192 @@ - 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 + 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; $iquote($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; $iquote($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; + } } ?> \ No newline at end of file diff --git a/src/includes/class.db.mysqli.php b/src/includes/class.db.mysqli.php index 8a5d456..25e9728 100644 --- a/src/includes/class.db.mysqli.php +++ b/src/includes/class.db.mysqli.php @@ -1,157 +1,157 @@ - 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 + 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; + } } ?> \ No newline at end of file diff --git a/src/includes/class.db.sqlite3.php b/src/includes/class.db.sqlite3.php index fefbc13..fcd3a8b 100644 --- a/src/includes/class.db.sqlite3.php +++ b/src/includes/class.db.sqlite3.php @@ -1,185 +1,185 @@ - 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 + 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; $iquote($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; $iquote($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; + } } ?> \ No newline at end of file diff --git a/src/includes/class.dbconnection.php b/src/includes/class.dbconnection.php index 3011cc7..5682ea2 100644 --- a/src/includes/class.dbconnection.php +++ b/src/includes/class.dbconnection.php @@ -1,67 +1,67 @@ - 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 + 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(); } diff --git a/src/includes/class.dbcore.php b/src/includes/class.dbcore.php index 95a2ede..8aaa47f 100644 --- a/src/includes/class.dbcore.php +++ b/src/includes/class.dbcore.php @@ -1,9 +1,9 @@ - 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 + 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; + } } diff --git a/src/includes/class.lang.php b/src/includes/class.lang.php index 82d74ea..65ee328 100644 --- a/src/includes/class.lang.php +++ b/src/includes/class.lang.php @@ -1,165 +1,165 @@ - 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 + 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; + } } diff --git a/src/includes/class.sessionhandler.php b/src/includes/class.sessionhandler.php index f6e8e14..089f3eb 100644 --- a/src/includes/class.sessionhandler.php +++ b/src/includes/class.sessionhandler.php @@ -1,105 +1,105 @@ - 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 + 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; + } } diff --git a/src/includes/common.php b/src/includes/common.php index 50123b6..7e6b07d 100644 --- a/src/includes/common.php +++ b/src/includes/common.php @@ -1,123 +1,123 @@ - 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 + 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; } ?> \ No newline at end of file diff --git a/src/includes/markup.php b/src/includes/markup.php index 886f9f7..3f1c32e 100644 --- a/src/includes/markup.php +++ b/src/includes/markup.php @@ -1,9 +1,9 @@ - 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 + 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("~([\s\S]*?)~i", "${c1}b${c2}\$1${c1}/b${c2}", $s); - $s = preg_replace("~([\s\S]*?)~i", "${c1}i${c2}\$1${c1}/i${c2}", $s); - $s = preg_replace("~([\s\S]*?)~i", "${c1}u${c2}\$1${c1}/u${c2}", $s); - $s = preg_replace("~([\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("~([\s\S]*?)~i", "${c1}b${c2}\$1${c1}/b${c2}", $s); + $s = preg_replace("~([\s\S]*?)~i", "${c1}i${c2}\$1${c1}/i${c2}", $s); + $s = preg_replace("~([\s\S]*?)~i", "${c1}u${c2}\$1${c1}/u${c2}", $s); + $s = preg_replace("~([\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$2$4' , - $s - ); + // make links from text starting with 'www.' + $s = preg_replace( + "/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" , + '$1$2$4' , + $s + ); - // make link from text starting with protocol like 'http://' - $s = preg_replace( - "/(^|\s|>)([a-z]+:\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" , - '$1$2$4' , - $s - ); + // make link from text starting with protocol like 'http://' + $s = preg_replace( + "/(^|\s|>)([a-z]+:\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" , + '$1$2$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$2$4' , - $title - ); + // make links from text starting with 'www.' + $title = preg_replace( + "/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" , + '$1$2$4' , + $title + ); - // make link from text starting with protocol like 'http://' - $title = preg_replace( - "/(^|\s|>)([a-z]+:\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" , - '$1$2$4' , - $title - ); - return $title; + // make link from text starting with protocol like 'http://' + $title = preg_replace( + "/(^|\s|>)([a-z]+:\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/iu" , + '$1$2$4' , + $title + ); + return $title; } diff --git a/src/includes/parsedown/MTTParsedown.php b/src/includes/parsedown/MTTParsedown.php index 639f8e9..40aa03e 100644 --- a/src/includes/parsedown/MTTParsedown.php +++ b/src/includes/parsedown/MTTParsedown.php @@ -1,41 +1,41 @@ - 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 + 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 diff --git a/src/index.php b/src/index.php index 1749685..f82e461 100644 --- a/src/index.php +++ b/src/index.php @@ -1,26 +1,26 @@ - 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 + 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); } diff --git a/src/init.php b/src/init.php index 7ed3efd..5b3df13 100644 --- a/src/init.php +++ b/src/init.php @@ -1,15 +1,15 @@ - 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 + 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 setup.php 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 setup.php 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); } ?> \ No newline at end of file diff --git a/src/settings.php b/src/settings.php index 2c9a9e9..a5c43df 100644 --- a/src/settings.php +++ b/src/settings.php @@ -1,9 +1,9 @@ - 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 + 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!
Disable password protection or Log in."); + die("Access denied!
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 .= ''; - } - return $s; + if(!$a) return ''; + $s = ''; + if($default !== null && !isset($a[$value])) $value = $default; + foreach($a as $k=>$v) { + $s .= ''; + } + 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 .= ''; - } - return $s; + if(!$a) return ''; + $s = ''; + if($default !== null && !isset($a[$key])) $key = $default; + foreach($a as $k=>$v) { + $s .= ''; + } + return $s; } function timezoneIdentifiers() @@ -138,10 +138,10 @@ header('Content-type:text/html; charset=utf-8'); "; - $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'] = ""; + $j = json_encode($j, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); ?>
@@ -150,8 +150,8 @@ header('Content-type:text/html; charset=utf-8');
@@ -221,7 +221,7 @@ header('Content-type:text/html; charset=utf-8'); diff --git a/src/setup.php b/src/setup.php index 8718290..f461544 100644 --- a/src/setup.php +++ b/src/setup.php @@ -1,19 +1,19 @@ - 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 + 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 "myTinyTodo @VERSION Setup

"; 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.
"); - } - } - 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.
"); + } + } + 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.

". - "Error: ". 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.

". + "Error: ". 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!
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!
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("
Click next to create tables in '". htmlspecialchars($dbtype). "' database.

-
"); - } - elseif ($install == '') - { - # Specify database type and connection settings to save. - exitMessage(" -
Select database type to use:

- -

-
-
- "); - } - 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
"); - } - elseif ($install == 'create') - { - # install database - try { - createAllTables($db, $dbtype); - } catch (Exception $e) { - exitMessage("Error: ". htmlarray($e->getMessage())); - } + if ($install == '' && $db !== null) + { + # We already have settings file and need to create tables. + exitMessage("
Click next to create tables in '". htmlspecialchars($dbtype). "' database.

+
"); + } + elseif ($install == '') + { + # Specify database type and connection settings to save. + exitMessage(" +
Select database type to use:

+ +

+
+
+ "); + } + 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
"); + } + elseif ($install == 'create') + { + # install database + try { + createAllTables($db, $dbtype); + } catch (Exception $e) { + exitMessage("Error: ". 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"). "

-
- -
"); - } + if (!isset($_POST['update'])) { + exitMessage(htmlspecialchars("Update database v$ver to v$lastVer"). "

+
+ +
"); + } - # update process - if ($ver == '1.4') - { - update_14_17($db, $dbtype); - } + # update process + if ($ver == '1.4') + { + update_14_17($db, $dbtype); + } } echo "Done

Attention! Delete this file for security reasons.

Go to homepage."; @@ -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 ""; + echo ""; } 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.

\n". - "\n". - "" - ); - } - 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.

\n". + "\n". + "" + ); + } + 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 '
Error ('. htmlspecialchars(get_class($e)) .'): \''. htmlspecialchars($e->getMessage()) .'\' in '. htmlspecialchars($e->getFile() .':'. $e->getLine()). ''. - "\n
". htmlspecialchars($e->getTraceAsString()) . "
\n"; - exit; + echo '
Error ('. htmlspecialchars(get_class($e)) .'): \''. htmlspecialchars($e->getMessage()) .'\' in '. htmlspecialchars($e->getFile() .':'. $e->getLine()). ''. + "\n
". htmlspecialchars($e->getTraceAsString()) . "
\n"; + exit; } function myExceptionHandler($e) { - echo '
Error: '. htmlspecialchars($e->getMessage()) ; - exit; + echo '
Error: '. 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 #####