Ejemplo n.º 1
0
 public static function getInstance()
 {
     if (empty(self::$instance)) {
         self::$instance = new Database_Logs();
     }
     return self::$instance;
 }
Ejemplo n.º 2
0
 public static function post($post, $url)
 {
     // Use key 'http' even if you send the request to https.
     $options = array('http' => array('header' => "Content-type: application/x-www-form-urlencoded\r\n", 'method' => 'POST', 'content' => http_build_query($post), 'timeout' => 3600));
     $context = stream_context_create($options);
     // After failure, retry a few times more.
     $retry = 0;
     while (++$retry <= 3) {
         @($response = file_get_contents($url, false, $context));
         if ($response === false) {
             // Log failure.
             $database_logs = Database_Logs::getInstance();
             // If the server or connection is down entirely there won't be even a response header.
             @($response_header = $http_response_header[0]);
             if ($response_header) {
                 $database_logs->log($response_header, Filter_Roles::TRANSLATOR_LEVEL);
             }
         } else {
             // Return successful response.
             return $response;
         }
     }
     // Failure: Give up.
     return false;
 }
Ejemplo n.º 3
0
    public function create()
    {
        $database_logs = Database_Logs::getInstance();
        Database_SQLite::exec($this->db, "PRAGMA temp_store = MEMORY;");
        Database_SQLite::exec($this->db, "PRAGMA synchronous = OFF;");
        Database_SQLite::exec($this->db, "PRAGMA journal_mode = OFF;");
        $sql = <<<'EOD'
CREATE TABLE IF NOT EXISTS morphhb (
  book integer,
  chapter integer,
  verse integer,
  hebrew text
);
EOD;
        Database_SQLite::exec($this->db, $sql);
        $books = array("Gen", "Exod", "Lev", "Num", "Deut", "Josh", "Judg", "Ruth", "1Sam", "2Sam", "1Kgs", "2Kgs", "1Chr", "2Chr", "Ezra", "Neh", "Esth", "Job", "Ps", "Prov", "Eccl", "Song", "Isa", "Jer", "Lam", "Ezek", "Dan", "Hos", "Joel", "Amos", "Obad", "Jonah", "Mic", "Nah", "Hab", "Zeph", "Hag", "Zech", "Mal");
        foreach ($books as $book => $osis) {
            $book++;
            $database_logs->log("Importing Hebrew data for {$book} {$osis}");
            $xml = new XMLReader();
            $xml->open("../morphhb/{$osis}.xml");
            $chapter = 0;
            $verse = 0;
            $word = false;
            $hebrew = "";
            while ($xml->read()) {
                $nodeType = $xml->nodeType;
                $name = $xml->name;
                if ($nodeType == XMLReader::ELEMENT) {
                    if ($name == "verse") {
                        $osisID = $xml->getAttribute("osisID");
                        $osisID = explode(".", $osisID);
                        $chapter = intval($osisID[1]);
                        $verse = intval($osisID[2]);
                    }
                    if ($name == "w") {
                        $word = true;
                    }
                }
                if ($nodeType == XMLReader::TEXT) {
                    if ($word) {
                        $hebrew = $xml->value;
                        $hebrew = trim($hebrew);
                        $hebrew = str_replace("/", "", $hebrew);
                        $hebrew = str_replace("'", "''", $hebrew);
                        $sql = "INSERT INTO morphhb (book, chapter, verse, hebrew) VALUES ({$book}, {$chapter}, {$verse}, '{$hebrew}');";
                        Database_SQLite::exec($this->db, $sql);
                    }
                }
                if ($nodeType == XMLReader::END_ELEMENT) {
                    if ($name == "w") {
                        $word = false;
                    }
                }
            }
            $xml->close();
        }
    }
Ejemplo n.º 4
0
 /**
  * Creates book template with ID $book in Bible $bible.
  * If a $chapter is given instead of NULL, it creates that chapter only.
  */
 public static function create($bible, $book, $chapter, &$feedback)
 {
     $database_bibles = Database_Bibles::getInstance();
     $database_versifications = Database_Versifications::getInstance();
     $database_books = Database_Books::getInstance();
     $database_logs = Database_Logs::getInstance();
     $database_config_bible = Database_Config_Bible::getInstance();
     $bible_id = $database_bibles->getID($bible);
     if ($bible_id == 0) {
         $feedback[] = Locale_Translate::_("Bible {$bible} does not exist: Cannot create book");
         return false;
     }
     if ($book == 0) {
         $feedback[] = Locale_Translate::_("Invalid book while creating a book template");
         return false;
     }
     // The chapters that have been created.
     $chaptersCreated = array();
     // Chapter 0.
     if (!isset($chapter) || $chapter == 0) {
         $data = "\\id " . $database_books->getUsfmFromId($book) . "\n";
         $data .= "\\h " . $database_books->getEnglishFromId($book) . "\n";
         $data .= "\\toc2 " . $database_books->getEnglishFromId($book) . "\n";
         Bible_Logic::storeChapter($bible, $book, 0, $data);
         $chaptersCreated[] = 0;
     }
     // Subsequent chapters.
     $versification = $database_config_bible->getVersificationSystem($bible);
     $versification_data = $database_versifications->getBooksChaptersVerses($versification);
     foreach ($versification_data as $row) {
         if ($book == $row["book"]) {
             $ch = $row["chapter"];
             $verse = $row["verse"];
             if (!isset($chapter) || $chapter == $ch) {
                 $data = "\\c {$ch}\n";
                 $data .= "\\p\n";
                 for ($i = 1; $i <= $verse; $i++) {
                     $data .= "\\v {$i}\n";
                 }
                 Bible_Logic::storeChapter($bible, $book, $ch, $data);
                 $chaptersCreated[] = $ch;
             }
         }
     }
     // Done.
     if (count($chaptersCreated) == 0) {
         $feedback[] = Locale_Translate::_("No chapters have been craeted");
         return false;
     }
     $chaptersCreated = implode(" ", $chaptersCreated);
     $feedback[] = Locale_Translate::_("The following chapters have been created:") . " " . $chaptersCreated;
     return true;
 }
Ejemplo n.º 5
0
 public function consultationNote($id)
 {
     $database_notes = Database_Notes::getInstance();
     $database_logs = Database_Logs::getInstance();
     $passage = $database_notes->getPassages($id);
     $passageText = Filter_Books::passagesDisplayInline($passage);
     $summary = $database_notes->getSummary($id);
     $contents = $database_notes->getContents($id);
     $contents = Filter_Html::html2text($contents);
     $session_logic = Session_Logic::getInstance();
     $username = $session_logic->currentUser();
     $database_logs->log("{$username} deleted / marked for deletion consultation note {$passageText} | {$summary} | {$contents}");
 }
Ejemplo n.º 6
0
/**
* Sends email $id
*/
function sendMail($id)
{
    // The databases involved.
    $database_mail = Database_Mail::getInstance();
    $database_log = Database_Logs::getInstance();
    $database_users = Database_Users::getInstance();
    // Get all details of the mail.
    $details = $database_mail->get($id);
    $username = $details['username'];
    $email = $database_users->getUserToEmail($username);
    $subject = $details['subject'];
    $body = $details['body'];
    // Bail out when username was empty.
    if ($username == "") {
        return;
    }
    // If this username was not found, it could be that the email was addressed to a non-user,
    // and that the To: address was actually contained in the $username.
    if ($email == "") {
        $email = $username;
        $username = "";
    }
    // If the email address validates, ok, else remove this mail from the queue and log the action.
    $validator = new Zend_Validate_EmailAddress();
    if (!$validator->isValid($email)) {
        $database_mail->delete($id);
        $message = "Email to {$email} was deleted because of an invalid email address";
        $database_log->log($message);
        return;
    }
    // Send the email.
    try {
        $mail = new Mail_Send($email, $username, $subject, $body);
        unset($mail);
        $database_mail->delete($id);
        $message = "Email to {$email} with subject {$subject} was sent successfully";
        $database_log->log($message, Filter_Roles::MANAGER_LEVEL);
    } catch (Exception $e) {
        $database_mail->postpone($id);
        $message = $e->getMessage();
        $message = "Email to {$email} could not be sent - reason: {$message}";
        $database_log->log($message);
    }
}
Ejemplo n.º 7
0
 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"));
         }
     }
 }
Ejemplo n.º 8
0
 /**
  * This filter runs a Java class.
  * $directory: Directory that holds the program that has the class.
  * $classpath: An array holding class paths.
  * $runclass: The name of the class to run.
  * It returns the exid code of the program.
  */
 public static function run($directory, $classpath, $runclass)
 {
     // Assemble the class path.
     $cp = ".";
     if (is_array($classpath)) {
         foreach ($classpath as $path) {
             $cp = "{$cp}:{$path}";
         }
     }
     $database_logs = Database_Logs::getInstance();
     // Run the class.
     $workingdirectory = escapeshellarg($directory);
     $cp = escapeshellarg($cp);
     $runclass = escapeshellarg($runclass);
     $command = "cd {$workingdirectory} && java -cp {$cp} {$runclass} 2>&1";
     $database_logs->log($command);
     exec($command, $output, $return_var);
     foreach ($output as $line) {
         $database_logs->log($line);
     }
     return $return_var;
 }
Ejemplo n.º 9
0
 public static function safeStoreChapter($bible, $book, $chapter, $usfm)
 {
     $database_bibles = Database_Bibles::getInstance();
     $database_logs = Database_Logs::getInstance();
     $database_books = Database_Books::getInstance();
     // Existing chapter contents.
     $existing = $database_bibles->getChapter($bible, $book, $chapter);
     // Bail out if the existing chapter equals the USFM to be saved.
     if ($usfm == $existing) {
         return true;
     }
     // The length of the new USFM code should not differ more than 20% from the existing USFM code.
     $existingLength = strlen($existing);
     $newLength = strlen($usfm);
     $percentage = 100 * ($newLength - $existingLength) / $existingLength;
     $percentage = abs($percentage);
     $percentage = round($percentage);
     if ($percentage > 20) {
         $database_logs->log("The chapter was not saved for safety reasons. The length differs {$percentage}% from the existing chapter. Make minor changes and save often.");
         $database_logs->log("{$bible} " . $database_books->getEnglishFromId($book) . " {$chapter}");
         $database_logs->log($usfm);
         return false;
     }
     // The text of the new chapter should not differ more than 20% from the existing text.
     similar_text($existing, $usfm, $percentage);
     $percentage = abs($percentage);
     $percentage = 100 - $percentage;
     $percentage = round($percentage);
     if ($percentage > 20) {
         $database_logs->log("The chapter was not saved for safety reasons. The new text differs {$percentage}% from the existing text. Make minor changes and save often.");
         $database_logs->log("{$bible} " . $database_books->getEnglishFromId($book) . " {$chapter}");
         $database_logs->log($usfm);
         return false;
     }
     // Safety checks have passed: Save chapter.
     Bible_Logic::storeChapter($bible, $book, $chapter, $usfm);
     return true;
 }
Ejemplo n.º 10
0
 private function cleanUSFM($usfm)
 {
     // The user may accidentally omit or erase the note caller.
     // The note caller is one character that immediately follows the note opener.
     // E.g.: \f + ...\f*.
     // Check for missing note caller, and if it's not there, add the default "+".
     // Also replace a double space after a note opener.
     foreach ($this->noteOpeners as $noteOpener) {
         $opener = Filter_Usfm::getOpeningUsfm($noteOpener);
         $usfm = str_replace($opener . " ", $opener, $usfm);
         $pos = mb_strpos($usfm, $opener);
         while ($pos !== false) {
             $isClean = true;
             // Check that the character that follows the note opener is a non-space.
             $pos2 = $pos + mb_strlen($opener);
             $character = mb_substr($usfm, $pos2, 1);
             if ($character == " ") {
                 $isClean = false;
             }
             // Check that the following character is not a space.
             $pos2++;
             $character = mb_substr($usfm, $pos2, 1);
             if ($character != " ") {
                 $isClean = false;
             }
             // Fix the note caller is necessary.
             if (!$isClean) {
                 $database_logs = Database_Logs::getInstance();
                 $database_logs->log("Fixing note caller in {$usfm}");
                 $pos2--;
                 $usfm = mb_substr($usfm, 0, $pos2) . "+" . mb_substr($usfm, $pos2);
             }
             // Next iteration.
             $pos = mb_strpos($usfm, $opener, $pos + 5);
         }
     }
     return $usfm;
 }
Ejemplo n.º 11
0
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
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("Removing expired temporal files", Filter_Roles::ADMIN_LEVEL);
$expired = strtotime("-3 days");
$directory = dirname(__DIR__) . "/tmp";
$names = scandir($directory);
$names = Filter_Folders::cleanup($names);
foreach ($names as $name) {
    $filename = "{$directory}/{$name}";
    $mtime = filemtime($filename);
    if ($mtime < $expired) {
        if (is_file($filename)) {
            unlink($filename);
        }
        if (is_dir($filename)) {
            Filter_Rmdir::rmdir($filename);
        }
Ejemplo n.º 12
0
function die_if_databases_unhealthy_or_busy()
{
    $database_notes = Database_Notes::getInstance();
    $available = true;
    if (!$database_notes->healthy()) {
        $available = false;
    }
    if (!$database_notes->checksums_healthy()) {
        $available = false;
    }
    if (!$database_notes->available()) {
        $available = false;
    }
    if (!$available) {
        $database_logs = Database_Logs::getInstance();
        $database_logs->log("Notes databases are unhealthy or unavailable", Filter_Roles::TRANSLATOR_LEVEL);
        die;
    }
}
Ejemplo n.º 13
0
 /**
  * handleEmailNew - handles an email received from $from with subject $subject and body $body.
  * Returns true if the mail was processed, else false.
  * The email is considered to have been processed if it created a new Consultation Note.
  */
 public function handleEmailNew($from, $subject, $body)
 {
     // Store the original subject.
     $originalSubject = $subject;
     // Check that the subject indicates that a new consultation note is to be created.
     $pos = strpos(strtolower($subject), "new note");
     if ($pos === false) {
         return false;
     }
     // There is a new note. Remove that bit from the $subject.
     $subject = substr($subject, 0, $pos) . substr($subject, $pos + 8);
     // Clean the subject line.
     $subject = trim($subject);
     $subject = str_replace(".", " ", $subject);
     $subject = str_replace(":", " ", $subject);
     $subject = str_replace("  ", " ", $subject);
     $subject = str_replace("  ", " ", $subject);
     $subject = str_replace("  ", " ", $subject);
     $subject = str_replace("  ", " ", $subject);
     // Check that the $from address of the email belongs to an existing user.
     $from = Filter_Email::extractEmail($from);
     $database_users = Database_Users::getInstance();
     if (!$database_users->emailExists($from)) {
         return false;
     }
     $username = $database_users->getEmailToUser($from);
     // Extract book, chapter, verse, and note summary from the $subject
     $book = NULL;
     $chapter = NULL;
     $verse = NULL;
     $summary = NULL;
     $subject = explode(" ", $subject);
     if (count($subject) > 0) {
         $book = Filter_Books::interpretBook($subject[0]);
     }
     if (count($subject) > 1) {
         $chapter = Filter_Numeric::integer_in_string($subject[1]);
     }
     if (count($subject) > 2) {
         $verse = Filter_Numeric::integer_in_string($subject[2]);
     }
     unset($subject[0]);
     unset($subject[1]);
     unset($subject[2]);
     $summary = implode(" ", $subject);
     unset($subject);
     // Check book, chapter, verse, and summary. Give feedback if there's anything wrong.
     $noteCheck = "";
     if (!(is_numeric($book) && $book > 0)) {
         $noteCheck .= Locale_Translate::_("Unknown book");
     }
     if (!is_numeric($chapter)) {
         $noteCheck .= " " . Locale_Translate::_("Unknown chapter");
     }
     if (!is_numeric($verse)) {
         $noteCheck .= " " . Locale_Translate::_("Unknown verse");
     }
     if ($summary == NULL || $summary == "") {
         $noteCheck .= " " . Locale_Translate::_("Unknown summary");
     }
     // Mail user if the note could not be posted.
     $database_mail = Database_Mail::getInstance();
     if ($noteCheck != "") {
         $subject = Locale_Translate::_("Your new note could not be posted");
         $database_mail->send($username, $subject . ": " . $originalSubject, $noteCheck);
         return false;
     }
     // Clean the email's body.
     $body = Filter_Email::extractBody($body);
     // Post the note.
     $session_logic = Session_Logic::getInstance();
     $sessionuser = $session_logic->currentUser();
     $session_logic->setUsername($username);
     $database_notes = Database_Notes::getInstance();
     $identifier = $database_notes->storeNewNote("", $book, $chapter, $verse, $summary, $body, false);
     $this->handlerNewNote($identifier);
     $session_logic->setUsername($sessionuser);
     // Mail confirmation to the $username.
     $database_config_user = Database_Config_User::getInstance();
     if ($database_config_user->getUserNotifyMeOfMyPosts($username)) {
         $subject = Locale_Translate::_("Your new note was posted");
         $database_mail->send($username, $subject . ": " . $originalSubject, $body);
     }
     // Log operation.
     $database_logs = Database_Logs::getInstance();
     $database_logs->log("New note posted" . ":" . " " . $body);
     // Job done.
     return true;
 }
Ejemplo n.º 14
0
 public static function query($db, $sql)
 {
     // Run the SQL on the database handle.
     $success = $result = $db->query($sql);
     // Check / log errors.
     if ($success === false) {
         $message = $db->errorInfo();
         $message = "Database error: " . $message[0] . " - " . $message[2] . " - Query was: " . $sql;
         if (class_exists("Database_Logs", true)) {
             $database_logs = Database_Logs::getInstance();
             $database_logs->log($message, Filter_Roles::ADMIN_LEVEL);
         } else {
             echo "<p>{$message}</p>";
         }
         if (php_sapi_name() == "cli") {
             echo "{$message}\n";
         }
     }
     // In case of errors, the $result won't be an array.
     // Make it an ampty array so it won't produce further errors down the code.
     if (!$result) {
         $result = array();
     }
     return $result;
 }
Ejemplo n.º 15
0
    public function create()
    {
        $database_logs = Database_Logs::getInstance();
        Database_SQLite::exec($this->db, "PRAGMA temp_store = MEMORY;");
        Database_SQLite::exec($this->db, "PRAGMA synchronous = OFF;");
        Database_SQLite::exec($this->db, "PRAGMA journal_mode = OFF;");
        $sql = <<<'EOD'
CREATE TABLE kjv (
  book integer,
  chapter integer,
  verse integer,
  strong text,
  english text
);
EOD;
        Database_SQLite::exec($this->db, $sql);
        $book = 0;
        $chapter = 0;
        $verse = 0;
        $lemma = "";
        $english = "";
        $xml = new XMLReader();
        $xml->open("../kjv/kjvfull.xml");
        while ($xml->read()) {
            $nodeType = $xml->nodeType;
            $name = $xml->name;
            if ($nodeType == XMLReader::ELEMENT) {
                if ($name == "div") {
                    $type = $xml->getAttribute("type");
                    if ($type == "book") {
                        $book++;
                        $database_logs->log("Importing Strong's data and English glosses for Bible book" . " " . $book);
                        $chapter = 0;
                        $verse = 0;
                    }
                }
                if ($name == "chapter") {
                    $chapter++;
                    $verse = 0;
                }
                if ($name == "verse") {
                    $sID = $xml->getAttribute("sID");
                    if ($sID) {
                        $verse++;
                    }
                }
                if ($name == "w") {
                    $lemma = $xml->getAttribute("lemma");
                    $lemma = trim($lemma);
                }
            }
            if ($nodeType == XMLReader::TEXT) {
                $value = $xml->value;
                $english = trim($value);
            }
            if ($nodeType == XMLReader::END_ELEMENT) {
                if ($name == "w") {
                    $lemma = explode(" ", $lemma);
                    foreach ($lemma as $strong) {
                        if (strpos($strong, "strong") === false) {
                            continue;
                        }
                        $strong = str_replace("strong:", "", $strong);
                        $strong = str_replace("'", "''", $strong);
                        $english = str_replace("'", "''", $english);
                        $sql = "INSERT INTO kjv (book, chapter, verse, strong, english) VALUES ({$book}, {$chapter}, {$verse}, '{$strong}', '{$english}');";
                        Database_SQLite::exec($this->db, $sql);
                    }
                    $lemma = "";
                    $english = "";
                }
            }
        }
        $xml->close();
    }
Ejemplo n.º 16
0
    public function create()
    {
        $database_logs = Database_Logs::getInstance();
        Database_SQLite::exec($this->db, "PRAGMA temp_store = MEMORY;");
        Database_SQLite::exec($this->db, "PRAGMA synchronous = OFF;");
        Database_SQLite::exec($this->db, "PRAGMA journal_mode = OFF;");
        $sql = <<<'EOD'
CREATE TABLE sblgnt (
  book integer,
  chapter integer,
  verse integer,
  greek text
);
EOD;
        Database_SQLite::exec($this->db, $sql);
        $book = 40 - 1;
        $chapter = 0;
        $verse = 0;
        $word = false;
        $greek = "";
        $xml = new XMLReader();
        $xml->open("../sblgnt/sblgnt.xml");
        while ($xml->read()) {
            $nodeType = $xml->nodeType;
            $name = $xml->name;
            if ($nodeType == XMLReader::ELEMENT) {
                if ($name == "book") {
                    $book++;
                    $chapter = 0;
                    $verse = 0;
                    $database_logs->log("Importing Greek data for book {$book}");
                    $type = $xml->getAttribute("type");
                    if ($type == "book") {
                    }
                }
                if ($name == "verse-number") {
                    $id = $xml->getAttribute("id");
                    $id = explode(":", $id);
                    $chapter = substr($id[0], -2, 2);
                    $chapter = intval($chapter);
                    $verse = intval($id[1]);
                }
                if ($name == "w") {
                    $word = true;
                }
            }
            if ($nodeType == XMLReader::TEXT) {
                if ($word) {
                    $greek = $xml->value;
                    $greek = trim($greek);
                    $greek = str_replace("'", "''", $greek);
                    $sql = "INSERT INTO sblgnt (book, chapter, verse, greek) VALUES ({$book}, {$chapter}, {$verse}, '{$greek}');";
                    Database_SQLite::exec($this->db, $sql);
                }
            }
            if ($nodeType == XMLReader::END_ELEMENT) {
                if ($name == "w") {
                    $word = false;
                }
            }
        }
        $xml->close();
    }
Ejemplo n.º 17
0
 public static function syncGitChapter2Bible($git, $bible, $book, $chapter)
 {
     // The databases.
     $database_bibles = Database_Bibles::getInstance();
     $database_books = Database_Books::getInstance();
     $database_logs = Database_Logs::getInstance();
     // Filename for the chapter.
     $bookname = $database_books->getEnglishFromId($book);
     $filename = "{$git}/{$bookname}/{$chapter}/data";
     if (file_exists($filename)) {
         // Store chapter in database.
         $usfm = file_get_contents($filename);
         Bible_Logic::storeChapter($bible, $book, $chapter, $usfm);
         $database_logs->log(Locale_Translate::_("A collaborator updated") . " {$bible} {$bookname} {$chapter}");
     } else {
         // Delete chapter from database.
         Bible_Logic::deleteChapter($bible, $book, $chapter);
         $database_logs->log(Locale_Translate::_("A collaborator deleted chapter") . " {$bible} {$bookname} {$chapter}");
     }
 }