string filter_passage_link_for_opening_editor_at (int book, int chapter, string verse) { string display = filter_passage_display (book, chapter, verse); Passage passage = Passage ("", book, chapter, verse); string numeric = convert_to_string (filter_passage_to_integer (passage)); string link = "<a class=\"starteditor\" href=\"" + numeric + "\">" + display + "</a> <span></span>"; return link; }
// This converts the $integer, created above, to a passage. Passage filter_integer_to_passage (int integer) { int book = round (integer / 1000000); integer -= book * 1000000; int chapter = round (integer / 1000); integer -= chapter * 1000; string verse = convert_to_string (integer); return Passage ("", book, chapter, verse); }
string checks_suppress (void * webserver_request) { Webserver_Request * request = (Webserver_Request *) webserver_request; Database_Check database_check; string page; page = Assets_Page::header (translate ("Suppressed check results"), webserver_request); Assets_View view; if (request->query.count ("release")) { int release = convert_to_int (request->query["release"]); database_check.release (release); view.set_variable ("success", translate("The check result is no longer suppressed.")); } // Get the Bibles the user has write-access to. vector <string> bibles; { vector <string> all_bibles = request->database_bibles()->getBibles (); for (auto bible : all_bibles) { if (access_bible_write (webserver_request, bible)) { bibles.push_back (bible); } } } string block; vector <Database_Check_Hit> suppressions = database_check.getSuppressions (); for (auto suppression : suppressions) { string bible = suppression.bible; // Only display entries for Bibles the user has write access to. if (in_array (bible, bibles)) { int id = suppression.rowid; bible = filter_string_sanitize_html (bible); string passage = filter_passage_display_inline ({Passage ("", suppression.book, suppression.chapter, convert_to_string (suppression.verse))}); string result = filter_string_sanitize_html (suppression.data); result.insert (0, bible + " " + passage + " "); block.append ("<p style=\"color:grey;\">\n"); block.append ("<a href=\"suppress?release=" + convert_to_string (id) + "\">\n"); block.append (emoji_wastebasket () + "\n"); block.append ("</a>\n"); block.append (result + "\n"); block.append ("</p>\n"); } } view.set_variable ("block", block); page += view.render ("checks", "suppress"); page += Assets_Page::footer (); return page; }
Passage Navigation_Passage::getPreviousVerse (void * webserver_request, string bible, int book, int chapter, int verse) { verse--; if (bible != "") { Webserver_Request * request = (Webserver_Request *) webserver_request; vector <int> verses = usfm_get_verse_numbers (request->database_bibles()->getChapter (bible, book, chapter)); if (find (verses.begin(), verses.end(), verse) == verses.end()) { if (!verses.empty ()) verse = verses [0]; } } Passage passage = Passage ("", book, chapter, convert_to_string (verse)); return passage; }
Passage Navigation_Passage::getPreviousChapter (void * webserver_request, string bible, int book, int chapter) { chapter--; if (bible != "") { Webserver_Request * request = (Webserver_Request *) webserver_request; vector <int> chapters = request->database_bibles ()->getChapters (bible, book); if (find (chapters.begin(), chapters.end(), chapter) == chapters.end()) { if (!chapters.empty ()) chapter = chapters [0]; } } Passage passage = Passage ("", book, chapter, "1"); return passage; }
string xrefs_next (void * webserver_request) { Webserver_Request * request = (Webserver_Request *) webserver_request; string bible = request->database_config_user()->getTargetXrefBible (); int currentBook = Ipc_Focus::getBook (webserver_request); int currentChapter = Ipc_Focus::getChapter (webserver_request); Passage currentPassage = Passage ("", currentBook, currentChapter, "1"); int currentLocation = filter_passage_to_integer (currentPassage); vector <int> books = request->database_bibles()->getBooks (bible); for (auto book : books) { vector <int> chapters = request->database_bibles()->getChapters (bible, book); for (auto chapter : chapters) { if (chapter == 0) continue; Passage passage = Passage ("", book, chapter, "1"); int location = filter_passage_to_integer (passage); if (location > currentLocation) { string usfm = request->database_bibles()->getChapter (bible, book, chapter); auto xrefs = usfm_extract_notes (usfm, {"x"}); if (xrefs.empty ()) { Ipc_Focus::set (webserver_request, book, chapter, 1); redirect_browser (request, xrefs_index_url ()); return ""; } } } } redirect_browser (request, xrefs_index_url ()); return ""; }
// Searches the text of the Bibles. // Returns an array with matching passages. // $search: Contains the text to search for. // $bibles: Array of Bible names to search in. vector <Passage> search_logic_search_text (string search, vector <string> bibles) { vector <Passage> passages; if (search == "") return passages; search = unicode_string_casefold (search); search = filter_string_str_replace (",", "", search); Database_Bibles database_bibles; for (auto bible : bibles) { vector <int> books = database_bibles.getBooks (bible); for (auto book : books) { vector <int> chapters = database_bibles.getChapters (bible, book); for (auto chapter : chapters) { string path = search_logic_chapter_file (bible, book, chapter); string index = filter_url_file_get_contents (path); if (index.find (search) != string::npos) { vector <string> lines = filter_string_explode (index, '\n'); int index_verse = 0; bool read_index_verse = false; int index_item = 0; for (auto & line : lines) { if (read_index_verse) { index_verse = convert_to_int (line); read_index_verse = false; } else if (line == search_logic_verse_separator ()) { read_index_verse = true; index_item = 0; } else if (line == search_logic_index_separator ()) { index_item++; } else if (index_item == PLAIN_LOWER) { if (line.find (search) != string::npos) { passages.push_back (Passage (bible, book, chapter, convert_to_string (index_verse))); } } } } } } } return passages; }
void Navigation_Passage::setPassage (void * webserver_request, string bible, string passage) { int currentBook = Ipc_Focus::getBook (webserver_request); int currentChapter = Ipc_Focus::getChapter (webserver_request); int currentVerse = Ipc_Focus::getVerse (webserver_request); passage = filter_string_trim (passage); Passage passage_to_set; if ((passage == "") || (passage == "+")) { passage_to_set = Navigation_Passage::getNextVerse (webserver_request, bible, currentBook, currentChapter, currentVerse); } else if (passage == "-") { passage_to_set = Navigation_Passage::getPreviousVerse (webserver_request, bible, currentBook, currentChapter, currentVerse); } else { Passage inputpassage = Passage ("", currentBook, currentChapter, convert_to_string (currentVerse)); passage_to_set = filter_passage_interpret_passage (inputpassage, passage); } if (passage_to_set.book != 0) { Ipc_Focus::set (webserver_request, passage_to_set.book, passage_to_set.chapter, convert_to_int (passage_to_set.verse)); Navigation_Passage::recordHistory (webserver_request, passage_to_set.book, passage_to_set.chapter, convert_to_int (passage_to_set.verse)); } }
// Get all passages that contain a strong's number. vector <Passage> Database_Kjv::searchStrong (string strong) { int strongid = get_id ("strong", strong); SqliteDatabase sql = SqliteDatabase (filename ()); sql.add ("SELECT DISTINCT book, chapter, verse FROM kjv2 WHERE strong ="); sql.add (strongid); sql.add ("ORDER BY rowid;"); vector <Passage> hits; map <string, vector <string> > result = sql.query (); vector <string> books = result ["book"]; vector <string> chapters = result ["chapter"]; vector <string> verses = result ["verse"]; for (unsigned int i = 0; i < books.size (); i++) { Passage passage = Passage (); passage.book = convert_to_int (books [i]); passage.chapter = convert_to_int (chapters [i]); passage.verse = verses [i]; hits.push_back (passage); } return hits; }
// Get array of book / chapter / verse of all passages that contain a $hebrew word. vector <Passage> Database_MorphHb::searchHebrew (string hebrew) { int word_id = get_id ("word", hebrew); SqliteDatabase sql = SqliteDatabase (filename ()); sql.add ("SELECT DISTINCT book, chapter, verse FROM morphhb WHERE word ="); sql.add (word_id); sql.add ("ORDER BY rowid;"); vector <Passage> hits; map <string, vector <string> > result = sql.query (); vector <string> books = result ["book"]; vector <string> chapters = result ["chapter"]; vector <string> verses = result ["verse"]; for (unsigned int i = 0; i < books.size (); i++) { Passage passage = Passage (); passage.book = convert_to_int (books [i]); passage.chapter = convert_to_int (chapters [i]); passage.verse = verses [i]; hits.push_back (passage); } return hits; }
// Performs a case-sensitive search of the USFM of one $bible. // Returns an array with the rowid's of matching verses. // $search: Contains the text to search for. vector <Passage> search_logic_search_bible_usfm_case_sensitive (string bible, string search) { vector <Passage> passages; if (search == "") return passages; Database_Bibles database_bibles; vector <int> books = database_bibles.getBooks (bible); for (auto book : books) { vector <int> chapters = database_bibles.getChapters (bible, book); for (auto chapter : chapters) { string path = search_logic_chapter_file (bible, book, chapter); string index = filter_url_file_get_contents (path); if (index.find (search) != string::npos) { vector <string> lines = filter_string_explode (index, '\n'); int index_verse = 0; bool read_index_verse = false; int index_item = 0; for (auto & line : lines) { if (read_index_verse) { index_verse = convert_to_int (line); read_index_verse = false; } else if (line == search_logic_verse_separator ()) { read_index_verse = true; index_item = 0; } else if (line == search_logic_index_separator ()) { index_item++; } else if (index_item == USFM_RAW) { if (line.find (search) != string::npos) { passages.push_back (Passage (bible, book, chapter, convert_to_string (index_verse))); } } } } } } return passages; }
// Returns the books, chapters, verses for the given versification system. vector <Passage> Database_Versifications::getBooksChaptersVerses (const string& name) { vector <Passage> data; int id = getID (name); SqliteSQL sql = SqliteSQL (); sql.add ("SELECT book, chapter, verse FROM data WHERE system ="); sql.add (id); sql.add ("ORDER BY book, chapter, verse ASC;"); sqlite3 * db = connect (); map <string, vector <string> > result = database_sqlite_query (db, sql.sql); database_sqlite_disconnect (db); vector <string> books = result ["book"]; vector <string> chapters = result ["chapter"]; vector <string> verses = result ["verse"]; for (unsigned int i = 0; i < books.size (); i++) { Passage passage = Passage (); passage.book = convert_to_int (books [i]); passage.chapter = convert_to_int (chapters [i]); passage.verse = verses [i]; data.push_back (passage); } return data; }
string resource_logic_get_html (void * webserver_request, string resource, int book, int chapter, int verse, bool add_verse_numbers) { Webserver_Request * request = (Webserver_Request *) webserver_request; string html; Database_UsfmResources database_usfmresources; Database_ImageResources database_imageresources; Database_Mappings database_mappings; // Lists of the various types of resources. vector <string> bibles = request->database_bibles()->getBibles (); vector <string> usfms; if (config_logic_client_prepared ()) { usfms = client_logic_usfm_resources_get (); // As from February 2016 a client no longer automatically downloads USFM resources off the server. // But a client takes in account existing USFM resources it has downloaded before. vector <string> old_usfms = database_usfmresources.getResources (); usfms.insert (usfms.end (), old_usfms.begin (), old_usfms.end ()); } else { usfms = database_usfmresources.getResources (); } vector <string> externals = resource_external_names (); vector <string> images = database_imageresources.names (); vector <string> lexicons = lexicon_logic_resource_names (); // Possible SWORD details. string sword_module = sword_logic_get_remote_module (resource); string sword_source = sword_logic_get_source (resource); // Determine the type of the current resource. bool isBible = in_array (resource, bibles); bool isUsfm = in_array (resource, usfms); bool isExternal = in_array (resource, externals); bool isImage = in_array (resource, images); bool isLexicon = in_array (resource, lexicons); bool isSword = (!sword_source.empty () && !sword_module.empty ()); // Retrieve versification system of the active Bible. string bible = request->database_config_user ()->getBible (); string bible_versification = Database_Config_Bible::getVersificationSystem (bible); // Determine the versification system of the current resource. string resource_versification; if (isBible || isUsfm) { resource_versification = Database_Config_Bible::getVersificationSystem (bible); } else if (isExternal) { resource_versification = resource_external_mapping (resource); } else if (isImage) { } else if (isLexicon) { resource_versification = database_mappings.original (); if (resource == KJV_LEXICON_NAME) resource_versification = "English"; } else if (isSword) { resource_versification = "English"; } else { } // If the resource versification system differs from the Bible's versification system, // map the focused verse of the Bible to a verse in the Resource. // There are resources without versification system: Do nothing about them. vector <Passage> passages; if ((bible_versification != resource_versification) && !resource_versification.empty ()) { passages = database_mappings.translate (bible_versification, resource_versification, book, chapter, verse); } else { passages.push_back (Passage ("", book, chapter, convert_to_string (verse))); } // If there's been a mapping, the resource should include the verse number for clarity. if (passages.size () != 1) add_verse_numbers = true; for (auto passage : passages) { if (verse != convert_to_int (passage.verse)) { add_verse_numbers = true; } } for (auto passage : passages) { int book = passage.book; int chapter = passage.chapter; int verse = convert_to_int (passage.verse); string possible_included_verse; if (add_verse_numbers) possible_included_verse = convert_to_string (verse) + " "; if (isImage) possible_included_verse.clear (); html.append (resource_logic_get_verse (webserver_request, resource, book, chapter, verse)); } return html; }
string resource_img (void * webserver_request) { Webserver_Request * request = (Webserver_Request *) webserver_request; Database_ImageResources database_imageresources; string page; Assets_Header header = Assets_Header (translate("Image resources"), request); page = header.run (); Assets_View view; string error, success; int book1, chapter1, verse1, book2, chapter2, verse2; string name = request->query ["name"]; view.set_variable ("name", name); string image = request->query ["image"]; view.set_variable ("image", image); int userid = filter_string_user_identifier (webserver_request); if (request->post.count ("submit")) { vector <string> errors; string book = request->post ["book1"]; book1 = filter_passage_interpret_book (book); if (book1 == 0) errors.push_back (translate ("Unknown starting book.")); chapter1 = convert_to_int (request->post ["chapter1"]); if (chapter1 < 0) errors.push_back (translate ("Negative starting chapter.")); if (chapter1 > 200) errors.push_back (translate ("High starting chapter.")); verse1 = convert_to_int (request->post ["verse1"]); if (chapter1 < 0) errors.push_back (translate ("Negative starting verse.")); if (chapter1 > 200) errors.push_back (translate ("High starting verse.")); book = request->post ["book2"]; book2 = filter_passage_interpret_book (book); if (book2 == 0) errors.push_back (translate ("Unknown ending book.")); chapter2 = convert_to_int (request->post ["chapter2"]); if (chapter2 < 0) errors.push_back (translate ("Negative ending chapter.")); if (chapter2 > 200) errors.push_back (translate ("High ending chapter.")); verse2 = convert_to_int (request->post ["verse2"]); if (chapter2 < 0) errors.push_back (translate ("Negative ending verse.")); if (chapter2 > 200) errors.push_back (translate ("High ending verse.")); int start = filter_passage_to_integer (Passage ("", book1, chapter1, convert_to_string (verse1))); int end = filter_passage_to_integer (Passage ("", book2, chapter2, convert_to_string (verse2))); if (start > end) { errors.push_back (translate ("The starting passage is beyond the ending passage.")); } database_imageresources.assign (name, image, book1, chapter1, verse1, book2, chapter2, verse2); Database_Volatile::setValue (userid, "imageresources", convert_to_string (end)); error = filter_string_implode (errors, " "); if (errors.empty ()) { redirect_browser (request, filter_url_build_http_query (resource_image_url (), "name", name)); return ""; } } // Retrieve passage range for this image. database_imageresources.get (name, image, book1, chapter1, verse1, book2, chapter2, verse2); if ((book1 == 0) || (book2 == 0)) { string end = Database_Volatile::getValue (userid, "imageresources"); Passage passage = filter_integer_to_passage (convert_to_int (end)); book1 = book2 = passage.book; chapter1 = chapter2 = passage.chapter; verse1 = verse2 = convert_to_int (passage.verse); if (book1 == 0) book1 = 1; if (book2 == 0) book2 = 1; } view.set_variable ("book1", Database_Books::getEnglishFromId (book1)); view.set_variable ("chapter1", convert_to_string (chapter1)); view.set_variable ("verse1", convert_to_string (verse1)); view.set_variable ("book2", Database_Books::getEnglishFromId (book2)); view.set_variable ("chapter2", convert_to_string (chapter2)); view.set_variable ("verse2", convert_to_string (verse2)); view.set_variable ("success", success); view.set_variable ("error", error); page += view.render ("resource", "img"); page += Assets_Page::footer (); return page; }
string Consistency_Logic::response () { // The request. Webserver_Request * request = (Webserver_Request *) webserver_request; // The resources to display in the Consistency tool. vector <string> resources = request->database_config_user()->getConsistencyResources (); string bible = access_bible_clamp (webserver_request, request->database_config_user()->getBible ()); resources.insert (resources.begin (), bible); // The passages entered in the Consistency tool. string s_passages = Database_Volatile::getValue (id, "passages"); s_passages = filter_string_trim (s_passages); vector <string> passages = filter_string_explode (s_passages, '\n'); // The translations entered in the Consistency tool. string s_translations = Database_Volatile::getValue (id, "translations"); s_translations = filter_string_trim (s_translations); vector <string> translations = filter_string_explode (s_translations, '\n'); // Contains the response to display. vector <string> response; // Go through the passages interpreting them. Passage previousPassage = Passage ("", 1, 1, "1"); for (auto line : passages) { // Clean line. line = filter_string_trim (line); // Skip empty line. if (line.empty ()) continue; // Remove verse text remaining with the passage(s) only. line = omit_verse_text (line); vector <string> range_sequence = filter_passage_handle_sequences_ranges (line); for (auto line : range_sequence) { Passage passage = filter_passage_interpret_passage (previousPassage, line); if (passage.book != 0) { int book = passage.book; int chapter = passage.chapter; string verse = passage.verse; line = filter_passage_link_for_opening_editor_at (book, chapter, verse); line += " "; // Check whether the chapter identifier has changed for this reference. // If so, set a flag so the data can be re-assembled for this verse. // If there was no change, then the data can be fetched from the volatile database. bool redoPassage = false; string passageKey = convert_to_string (book) + "." + convert_to_string (chapter) + "." + verse; int currentChapterId = request->database_bibles()->getChapterId (resources [0], book, chapter); int storedChapterId = convert_to_int (Database_Volatile::getValue (id, passageKey + ".id")); if (currentChapterId != storedChapterId) { Database_Volatile::setValue (id, passageKey + ".id", convert_to_string (currentChapterId)); redoPassage = true; } // Go through each resource. for (auto resource : resources) { // Produce new verse text if the passage is to be redone, or else fetch the existing text. string text; if (redoPassage) { text = verseText (resource, book, chapter, convert_to_int (verse)); if (!translations.empty ()) { text = filter_string_markup_words (translations, text); } Database_Volatile::setValue (id, passageKey + "." + resource, text); } else { text = Database_Volatile::getValue (id, passageKey + "." + resource); } // Formatting. if (resources.size () > 1) { line += "<br>"; } line += text; } response.push_back (line); previousPassage = passage; } else { response.push_back ("<span class=\"error\">" + translate("Unknown passage") + " " + line + "</span>"); } } } string output; for (auto line : response) { output += "<div>" + line + "</div>\n"; } return output; }