public function testCreateNote() { $data = Filter_Client::createNoteEncode("bible", 1, 2, 3, "summary", "line1\nline2", false); $standard = <<<EOD bible 1 2 3 summary line1 line2 EOD; $this->assertEquals($standard, $data); $data = Filter_Client::createNoteDecode($standard); $this->assertEquals("bible", $data["bible"]); $this->assertEquals(1, $data["book"]); $this->assertEquals(2, $data["chapter"]); $this->assertEquals(3, $data["verse"]); $this->assertEquals("summary", $data["summary"]); $this->assertEquals("", $data["raw"]); $contents = <<<EOD line1 line2 EOD; $this->assertEquals($contents, $data["contents"]); }
public function tearDown() { $database_bibles = Database_Bibles::getInstance(); $database_modifications = Database_Modifications::getInstance(); Filter_Client::set(false); $database_bibles->deleteBible("phpunit"); $database_modifications->truncateTeams(); Filter_Rmdir::rmdir($this->temporary_folder); }
public function create() { // No user menu in client mode. if (Filter_Client::enabled()) { return ""; } // Modify the menu based on user access level. $mainmenu = $this->accesscontrol($this->mainmenu()); // To create CSS menu the HTML structure needs to be like this: // <ul id="menu" class="menu"> // <li> // Menu entry // <li>Subitem</li> // </ul> // </li> // <li>Another entry</li> // </ul> $document = new DOMDocument("1.0", "UTF-8"); $document->encoding = "UTF-8"; $document->preserveWhiteSpace = false; $document->loadXML('<ul id="usermenu" class="menu"></ul>'); $xpath = new DOMXpath($document); $nodes = $xpath->query("//ul"); $mainul = $nodes->item(0); // Go through the main menu. foreach ($mainmenu as $mainitem) { // Build the main menu. $mainhref = $mainitem[0]; $maintext = $mainitem[1]; $mainli = $document->createElement("li"); $attribute = $document->createAttribute("class"); $mainli->appendChild($attribute); $attribute->value = "toggle"; $mainul->appendChild($mainli); if ($mainhref == "") { $mainaspan = $document->createElement("span"); } else { $mainaspan = $document->createElement("a"); $attribute = $document->createAttribute("href"); $mainaspan->appendChild($attribute); $attribute->value = $mainhref; } $mainli->appendChild($mainaspan); $mainaspan->nodeValue = $maintext; // Build the submenu. $submenu = $mainitem[2]; if (!$submenu) { continue; } $this->submenu($document, $mainli, $submenu); } // Get the result. $document->formatOutput = true; $menu = $document->saveXML($mainul); return $menu; }
public static function client_demo_warning() { $warning = ""; if (Filter_Client::enabled()) { $database_config_general = Database_Config_General::getInstance(); $address = $database_config_general->getServerAddress(); if ($address == self::demo_address()) { $warning = Locale_Translate::_("Warning:") . " " . Locale_Translate::_("The client is connected to a public demo server.") . " " . Locale_Translate::_("Everybody can modify the data on that server.") . " " . Locale_Translate::_("After send and receive your data will reflect the data on the server."); } } return $warning; }
public static function not_yet_ready() { // While setup is not yet complete, it is not yet ready. $path = dirname(__DIR__) . "../setup"; if (file_exists($path)) { return true; } // When client mode is prepared, but not yet enabled, it is not yet ready. if (Filter_Client::prepared()) { if (!Filter_Client::enabled()) { return true; } } // Ready to run. return false; }
public static function write($bible, $user = "") { // Client: User has access to all Bibles. if (Filter_Client::enabled()) { return true; } if ($user == "") { $session_logic = Session_Logic::getInstance(); $user = $session_logic->currentUser(); } $database_users = Database_Users::getInstance(); if (!$database_users->hasAccess2Bible($user, $bible)) { return false; } $readonly = $database_users->hasReadOnlyAccess2Bible($user, $bible); return !$readonly; }
public static function queuesync($control) { // Send / receive only works in Client mode. if (!Filter_Client::enabled()) { return; } // Deal with a numerical minute to find out whether it's time to automatically sync. if (is_numeric($control)) { $database_config_general = Database_Config_General::getInstance(); $repeat = $database_config_general->getRepeatSendReceive(); // Sync every hour. if ($repeat == 1) { $control = $control % 60; if ($control == 0) { $control = true; } } // Sync every five minutes. if ($repeat == 2) { $control = $control % 5; if ($control == 0) { $control = true; } } } // Send and receive: It is time now, or it is manual. if ($control === true) { // Only queue the sync tasks if none are running at the moment. if (SendReceive_Logic::syncqueued()) { $database_logs = Database_Logs::getInstance(); $database_logs->log("Not scheduling sync tasks, because the previous ones have not yet finished"); } else { Tasks_Logic::queue(Tasks_Logic::PHP, array(__DIR__ . "/sendnotes.php")); Tasks_Logic::queue(Tasks_Logic::PHP, array(__DIR__ . "/sendbibles.php")); Tasks_Logic::queue(Tasks_Logic::PHP, array(__DIR__ . "/sendsettings.php")); Tasks_Logic::queue(Tasks_Logic::PHP, array(__DIR__ . "/externalresources.php")); Tasks_Logic::queue(Tasks_Logic::PHP, array(__DIR__ . "/usfmresources.php")); } } }
public static function deleteBible($bible) { $database_bibles = Database_Bibles::getInstance(); $database_modifications = Database_Modifications::getInstance(); $database_bibleactions = Database_BibleActions::getInstance(); // Record data of the Bible to be deleted prior to deletion. if (Filter_Client::enabled()) { // Client stores Bible actions. $books = $database_bibles->getBooks($bible); foreach ($books as $book) { $chapters = $database_bibles->getChapters($bible, $book); foreach ($chapters as $chapter) { $usfm = $database_bibles->getChapter($bible, $book, $chapter); $database_bibleactions->record($bible, $book, $chapter, $usfm); } } } else { // Server stores diff data. $database_modifications->storeTeamDiffBible($bible); } // Delete the Bible from the database. $database_bibles->deleteBible($bible); }
function enable_client($username, $password, $level) { // Enable client mode upon a successful connection. Filter_Client::set(true); // Remove all users from the database, and add the current one. remove_all_users(); $database_users = Database_Users::getInstance(); $database_users->addNewUser($username, $password, $level, ""); // Clear all pending note actions and Bible actions and settings updates. $database_noteactions = Database_NoteActions::getInstance(); $database_bibleactions = Database_BibleActions::getInstance(); $database_config_user = Database_Config_User::getInstance(); $session_logic = Session_Logic::getInstance(); $database_noteactions->clear(); $database_noteactions->create(); $database_bibleactions->clear(); $database_bibleactions->create(); $session_logic->setUsername($username); $database_config_user->setUpdatedSettings(array()); // Set it repeats sync every so often. $database_config_general = Database_Config_General::getInstance(); $database_config_general->setRepeatSendReceive(2); // Schedule a sync operation straight-away. SendReceive_Logic::queuesync(true); }
} if (isset($_GET['runsync'])) { if (SendReceive_Logic::syncqueued()) { $view->view->successnotes = Locale_Translate::_("Still sending and receiving from the last time."); } else { SendReceive_Logic::queuesync(true); $view->view->successnotes = Locale_Translate::_("Will send and receive."); } } $view->view->client = Filter_Client::enabled(); if (isset($_GET['repeatsync'])) { $repeatsync = $_GET['repeatsync']; if (!is_numeric($repeatsync)) { $repeatsync = 0; } if ($repeatsync < 0) { $repeatsync = 0; } if ($repeatsync > 2) { $repeatsync = 2; } $database_config_general->setRepeatSendReceive($repeatsync); } $view->view->repeatsync = $database_config_general->getRepeatSendReceive(); if ($database_config_general->getServerAddress() == "") { $view->view->errornotes = Locale_Translate::_("Collaboration has not been set up for the Bibles and Consultation Notes"); } $view->view->clientmode = Filter_Client::enabled(); $view->view->demo = Filter_Demo::client_demo_warning(); $view->render("index.php"); Assets_Page::footer();
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ require_once "../bootstrap/bootstrap.php"; // Security: The script runs from the cli SAPI only. Filter_Cli::assert(); $database_logs = Database_Logs::getInstance(); $database_config_bible = Database_Config_Bible::getInstance(); $database_config_general = Database_Config_General::getInstance(); $database_bibles = Database_Bibles::getInstance(); $database_bibleactions = Database_BibleActions::getInstance(); $database_users = Database_Users::getInstance(); $database_books = Database_Books::getInstance(); $database_logs->log(Locale_Translate::_("Sending and receiving Bibles"), Filter_Roles::TRANSLATOR_LEVEL); $response = Filter_Client::setup(); if ($response === false || $response < Filter_Roles::GUEST_LEVEL || $response > Filter_Roles::ADMIN_LEVEL) { $database_logs->log(Locale_Translate::_("Failure initializing sending and receiving Bibles"), Filter_Roles::TRANSLATOR_LEVEL); die; } $address = $database_config_general->getServerAddress(); $users = $database_users->getUsers(); $user = $users[0]; $hash = $database_users->getmd5($user); $communication_errors = false; // Go through the Bibles / books / chapters that have actions recorded for them. $bibles = $database_bibleactions->getBibles(); foreach ($bibles as $bible) { $books = $database_bibleactions->getBooks($bible); foreach ($books as $book) { $chapters = $database_bibleactions->getChapters($bible, $book);
/** * This handles email to users. * $identifier: the note that is being handled. * $label: prefix to the subject line of the email. * $users: array of users to be mailed. * $postpone: whether to postpone sending the email till the evening. */ private function emailUsers($identifier, $label, $users, $postpone) { // Databases. $database_notes = Database_Notes::getInstance(); $database_config_user = Database_Config_User::getInstance(); $database_users = Database_Users::getInstance(); $database_mail = Database_Mail::getInstance(); $database_config_general = Database_Config_General::getInstance(); // Send mail to all users. $summary = $database_notes->getSummary($identifier); $passages = Filter_Books::passagesDisplayInline($database_notes->getPassages($identifier)); $contents = $database_notes->getContents($identifier); // Include a link to the note on the site. $contents .= "<br>\n"; $siteUrl = $database_config_general->getSiteURL(); $link = "{$siteUrl}/notes/note.php?id={$identifier}"; $contents .= "<p><a href=\"{$link}\">View or respond online</a></p>\n"; $mailto = "mailto:" . $database_config_general->getSiteMailAddress() . "?subject=(CNID{$identifier})"; $contents .= "<p><a href=\"{$mailto}\">Respond by email</a></p>\n"; // Deal with possible postponing email. $timestamp = time(); if ($postpone) { $postpone = strtotime("today +21 hours"); if ($postpone > $timestamp) { $timestamp = $postpone; } } // Send (but not in client mode). foreach ($users as $user) { if (!Filter_Client::enabled()) { $database_mail->send($user, "{$label} | {$passages} | {$summary} | (CNID{$identifier})", $contents, $timestamp); } } }
function clientAccess() { // If client mode is prepared, // log in as the first username in the users database, // of as the admin in case no user have been set up yet. if (Filter_Client::prepared()) { $database_users = Database_Users::getInstance(); $users = $database_users->getUsers(); if (empty($users)) { $user = "******"; $level = Filter_Roles::ADMIN_LEVEL; } else { $user = $users[0]; $level = $database_users->getUserLevel($user); } $this->setUsername($user); $this->level = $level; $this->logged_in = true; return true; } return false; }
private function settingsmenu() { $menu = array("users" => array("manage/users", Locale_Translate::_("Users"), NULL), array("manage/indexing", Locale_Translate::_("Indexing"), NULL), array("administration/language", Locale_Translate::_("Language"), NULL), array("administration/timezone", Locale_Translate::_("Timezone"), NULL), "mail" => array("administration/mail", Locale_Translate::_("Mail"), NULL), array("styles/indext", Locale_Translate::_("Styles"), $this->stylessubmenu()), array("versification/index", Locale_Translate::_("Versifications"), NULL), array("mapping/index", Locale_Translate::_("Verse mappings"), NULL), "collaboration" => array("administration/collaboration", Locale_Translate::_("Collaboration"), NULL), "client" => array("administration/client", Locale_Translate::_("Client"), NULL), array("fonts/index", Locale_Translate::_("Fonts"), NULL)); // If the installation is not prepared for Client mode, disable the menu. // But keep the menu item in an open installation. include "config/open.php"; if (!$open_installation) { if (!Filter_Client::prepared()) { unset($menu["client"]); } } // If Client mode is enabled, disable certain menu entries. if (Filter_Client::enabled()) { unset($menu["mail"]); unset($menu["users"]); unset($menu["collaboration"]); } return $menu; }
} } // Identifier for this $bible. $bibleID = $database_bibles->getID($bible); // Create an email with the checking results for this $bible. $emailBody = array(); $hits = $database_check->getHits(); foreach ($hits as $hit) { if ($hit['bible'] == $bibleID) { $passage = Filter_Books::passagesDisplayInline(array(array($hit['book'], $hit['chapter'], $hit['verse']))); $data = Filter_Html::sanitize($hit['data']); $result = "<p>{$passage} {$data}</p>"; $emailBody[] = $result; } } // Send email to users with write access to the Bible and a subscription to the notification. if (count($emailBody) > 0) { $subject = Locale_Translate::_("Bible Checks") . " " . $bible; $emailBody = implode("\n", $emailBody); $users = $database_users->getUsers(); foreach ($users as $user) { if ($database_config_user->getUserBibleChecksNotification($user)) { if (Access_Bible::write($bible, $user)) { if (!Filter_Client::enabled()) { $database_mail->send($user, $subject, $emailBody); } } } } } $database_logs->log("Check {$bible}: Complete", Filter_Roles::TRANSLATOR_LEVEL);
chdir(__DIR__); require_once "../bootstrap/bootstrap.php"; if (Filter_Cli::not_yet_ready()) { die; } // The script runs through the cli Server API only. Filter_Cli::assert(); ignore_user_abort(true); set_time_limit(0); // CPU-intensive actions run at night. // This keeps the site more responsive during the day. $config_general = Database_Config_General::getInstance(); $database_logs = Database_Logs::getInstance(); $hour = date('G'); $minute = date('i'); $client = Filter_Client::enabled(); // At midnight, for five minutes, do nothing to allow time for external backup // without corrupting the SQLite databases due to simultaneous access by // Bibledit-Web and the backup program. if ($hour == 0) { if ($minute <= 5) { die; } } // At the sixth minute after midnight, after the backup silence, and any hour after, rotate the logbook. if ($minute == 6) { $directory = dirname(__DIR__) . "/journal"; Tasks_Logic::queue(Tasks_Logic::PHP, array("{$directory}/rotate.php")); } // Every minute send out queued email, except in offline mode. if (!$client) {
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ require_once "../bootstrap/bootstrap.php"; // Security: Page only runs from the cli SAPI. Filter_Cli::assert(); $database_logs = Database_Logs::getInstance(); $database_logs->log("Database maintenance running", Filter_Roles::ADMIN_LEVEL); // Whether running in client mode. $database_config_general = Database_Config_General::getInstance(); $client_mode = Filter_Client::enabled(); // While VACUUM or REINDEX on a SQLite database are running, // querying the database then introduces errors like "database schema has changed". // Therefore this type of maintenance should not be done automatically. $database = Database_Users::getInstance(); $database->trim(); $database->optimize(); $database = Database_Mail::getInstance(); $database->trim(); $database->optimize(); $database = Database_Confirm::getInstance(); $database->trim(); $database->optimize(); // No need to optimize the following because it is hardly ever written to. $database = Database_Books::getInstance(); $database = Database_Styles::getInstance();
private function __construct() { // Default encoding. mb_internal_encoding("UTF-8"); // On shared hosting the temporal location may give read or write failures. // Set private temporal location for PHP. // Set private temporal location for SQLite. // http://stackoverflow.com/questions/10394517/setting-sqlite-temp-store-directory $tmpdir = realpath(__DIR__ . "/../tmp"); putenv("TMPDIR={$tmpdir}"); // Check whether to run the website setup script. // On Linux it is sufficient to check whether the "setup" folder exists. // But on Windows, this setup folder cannot be deleted, so it would exist always. // Therefore, to support Windows, it checks whether the index file in in the setup folder. if (file_exists("../setup/index.php")) { $setupfolder = realpath("../setup"); $myfolder = realpath("."); if ($setupfolder != $myfolder) { include "../filter/url.php"; Filter_Url::redirect("../setup/index.php"); die; } } // Set the include path: Where to look for included files. $this->bibledit_root_folder = dirname(dirname(__FILE__)); $include_path = get_include_path() . PATH_SEPARATOR . $this->bibledit_root_folder; set_include_path($include_path); ini_set('include_path', $include_path); // Autoloader. // Automatically include the file that contains the $class_name. // E.g. class Database_Bibles would require file database/bibles.php. // Thus the name of the class determines which file gets required. // The above implies that all classes translate to files and folders in lower case. // An exception is made for the Zend_* classes. function __autoload($class_name) { if (substr($class_name, 0, 4) != "Zend") { $class_name = strtolower($class_name); } $path = str_replace("_", "/", $class_name); require_once $path . ".php"; } // Register the function. spl_autoload_register('__autoload'); // Disable magic quotes. if (function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) { foreach ($_GET as $k => $v) { $_GET[$k] = stripslashes($v); } foreach ($_POST as $k => $v) { $_POST[$k] = stripslashes($v); } foreach ($_COOKIE as $k => $v) { $_COOKIE[$k] = stripslashes($v); } } // General configuration database. $database_config_general = Database_Config_General::getInstance(); // The site's timezone. $timezone = $database_config_general->getTimezone(); if ($timezone) { date_default_timezone_set($timezone); } // Client mode setup. // In case the client mode is prepared, but not enabled, // the bootstrap script forwards to the client mode setup page, // unless it is already going to that page. if (Filter_Client::prepared()) { if (!Filter_Client::enabled()) { @($uri = $_SERVER["REQUEST_URI"]); $path = parse_url($uri, PHP_URL_PATH); $folder = pathinfo($path, PATHINFO_DIRNAME); $folder = basename($folder); $page = pathinfo($path, PATHINFO_BASENAME); if ($folder != "setup") { if ($page != "topbar.php") { if ($page != "client.php") { Filter_Url::redirect("../administration/client.php"); die; } } } } } }
if (!$pass_ok) { $database_logs->log("Incorrect password {$password} for user {$username}", Filter_Roles::MANAGER_LEVEL); } $level_ok = $level == $database_users->getUserLevel($username); if (!$level_ok) { $database_logs->log("Incorrect role {$level} for user {$username}", Filter_Roles::MANAGER_LEVEL); } if (!$user_ok || !$pass_ok || !$level_ok) { // Unauthorized. http_response_code(401); die; } $session_logic->setUsername($username); if ($action == Notes_Logic::noteActionCreate) { // Create the note on the server. $data = Filter_Client::createNoteDecode($content); $bible = $data["bible"]; $book = $data["book"]; $chapter = $data["chapter"]; $verse = $data["verse"]; $summary = $data["summary"]; $raw = $data["raw"]; $contents = $data["contents"]; $server_id = $notes_logic->createNote($bible, $book, $chapter, $verse, $summary, $contents, $raw); // Update the note identifier on the server to be same as the client. $database_notes->setIdentifier($server_id, $note); // Update search field. $database_notes->updateSearchFields($note); $database_logs->log("Client created note on server" . ": {$summary}", Filter_Roles::MANAGER_LEVEL); echo "The server created the note"; } else {