Esempio n. 1
0
string manage_indexing (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;

  string page;

  page = Assets_Page::header (translate ("Indexing"), webserver_request, "");

  Assets_View view = Assets_View ();

  string refresh = request->query ["refresh"];
  
  if (refresh == "bibles") {
    tasks_logic_queue (REINDEXBIBLES);
    redirect_browser (request, journal_index_url ());
    return "";
  }
  
  if (refresh == "notes") {
    tasks_logic_queue (REINDEXNOTES);
    redirect_browser (request, journal_index_url ());
    return "";
  }

  page += view.render ("manage", "indexing");

  page += Assets_Page::footer ();

  return page;
}
Esempio n. 2
0
// Schedule export to web.
// $bible: Bible.
void Export_Logic::scheduleWeb (string bible, bool log)
{
  Database_Bibles database_bibles;
  vector <int> books = database_bibles.getBooks (bible);
  for (auto book : books) {
    tasks_logic_queue (EXPORTWEBMAIN, {bible, convert_to_string (book), convert_to_string (log)});
  }
}
Esempio n. 3
0
// Schedule a Bible book for export to text and basic USFM format.
// $bible: Bible.
// $book: book.
void Export_Logic::scheduleTextAndBasicUsfm (string bible, bool log)
{
  Database_Bibles database_bibles;
  vector <int> books = database_bibles.getBooks (bible);
  for (auto book : books) {
    tasks_logic_queue (EXPORTTEXTUSFM, {bible, convert_to_string (book), convert_to_string (log)});
  }
}
Esempio n. 4
0
// Queues Paratext sync.
void sendreceive_queue_paratext ()
{
  if (config_logic_paratext_enabled ()) {
    if (sendreceive_paratext_queued ()) {
      Database_Logs::log ("Still synchronizing with Paratext");
    } else {
      tasks_logic_queue (SYNCPARATEXT);
    }
  }
}
Esempio n. 5
0
// If $minute is negative, it syncs.
// If $minute >=0, it determines from the settings whether to sync.
void sendreceive_queue_sync (int minute)
{
  // Deal with a numerical minute to find out whether it's time to automatically sync.
  if (minute >= 0) {
    int repeat = Database_Config_General::getRepeatSendReceive ();
    // Sync every hour.
    if (repeat == 1) {
      minute = minute % 60;
      if (minute == 0) minute = -1;
    }
    // Sync every five minutes.
    if (repeat == 2) {
      minute = minute % 5;
      if (minute == 0) minute = -1;
    }
  }
  
  // Send and receive: It is time now, or it is manual.
  // Only queue a sync task if it is not running at the moment.
  if (minute < 0) {
    
    // Send / receive only works in Client mode.
    if (client_logic_client_enabled ()) {
      
      if (tasks_logic_queued (SYNCBIBLES)) {
        Database_Logs::log ("Still synchronizing Bibles");
      } else {
        tasks_logic_queue (SYNCBIBLES);
      }
      if (tasks_logic_queued (SYNCNOTES)) {
        Database_Logs::log ("Still synchronizing Notes");
      } else {
        tasks_logic_queue (SYNCNOTES);
      }
      if (tasks_logic_queued (SYNCSETTINGS)) {
        Database_Logs::log ("Still synchronizing Settings");
      } else {
        tasks_logic_queue (SYNCSETTINGS);
      }
      if (tasks_logic_queued (SYNCCHANGES)) {
        Database_Logs::log ("Still synchronizing Changes");
      } else {
        tasks_logic_queue (SYNCCHANGES);
      }
      if (tasks_logic_queued (SYNCFILES)) {
        Database_Logs::log ("Still synchronizing Files");
      } else {
        tasks_logic_queue (SYNCFILES);
      }
      // Sync resources always, because it checks on its own whether to do something.
      tasks_logic_queue (SYNCRESOURCES);
    }
    
    // Store the most recent time that the sync action ran.
    Database_Config_General::setLastSendReceive (filter_date_seconds_since_epoch ());
  }
}
Esempio n. 6
0
// Schedule SWORD module installation.
void sword_logic_install_module_schedule (string source, string module)
{
  // No source: Done.
  if (source.empty ()) return;
  
  // No module: Done.
  // There have been cases with more than 6000 scheduled SWORD module installation tasks,
  // all trying to install an empty $module.
  // So it's important to check on that.
  if (module.empty ()) return;
  
  // Check whether the module installation has been scheduled already.
  if (tasks_logic_queued (INSTALLSWORDMODULE, {source, module})) return;
  
  // Schedule it.
  tasks_logic_queue (INSTALLSWORDMODULE, {source, module});
}
Esempio n. 7
0
// Schedule creation info documents.
// $bible: Bible.
void Export_Logic::scheduleInfo (string bible, bool log)
{
  tasks_logic_queue (EXPORTINFO, {bible, convert_to_string (log)});
}
Esempio n. 8
0
string bible_import (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;
  
  string page;
  
  Assets_Header header = Assets_Header (translate("Import"), webserver_request);
  header.setNavigator ();
  header.addBreadCrumb (menu_logic_settings_menu (), menu_logic_settings_text ());
  header.addBreadCrumb (bible_manage_url (), menu_logic_bible_manage_text ());
  page = header.run ();
  
  Assets_View view;
  
  string success_message;
  string error_message;
  
  // The name of the Bible.
  string bible = access_bible_clamp (request, request->query["bible"]);
  view.set_variable ("bible", filter_string_sanitize_html (bible));
  
  int book = Ipc_Focus::getBook (webserver_request);
  int chapter = Ipc_Focus::getChapter (webserver_request);

  // Whether the user has write access to this Bible.
  bool write_access = access_bible_write (request, bible);
  if (write_access) view.enable_zone ("write_access");

  // USFM data submission.
  if (request->post.count ("submit")) {
    // Submission may take long if there's a lot of data or the network is slow.
    string data = request->post ["data"];
    data = filter_url_tag_to_plus (data);
    data = filter_string_trim (data);
    if (data != "") {
      if (unicode_string_is_valid (data)) {
        string datafile = filter_url_tempfile ();
        filter_url_file_put_contents (datafile, data);
        success_message = translate("Import has started. See Journal for progress.");
        tasks_logic_queue (IMPORTBIBLE, { datafile, bible, convert_to_string (book), convert_to_string (chapter) });
      } else {
        error_message = translate("Please supply valid Unicode UTF-8 text.");
      }
    } else {
      success_message = translate("Nothing was imported.");
    }
    // User imported something into this Bible: Set it as the default Bible.
    request->database_config_user()->setBible (bible);
  }

  // File upload.
  if (request->post.count ("upload")) {
    string datafile = filter_url_tempfile () + request->post ["filename"];
    string data = request->post ["data"];
    if (!data.empty ()) {
      filter_url_file_put_contents (datafile, data);
      success_message = translate("Import has started. See Journal for progress.");
      tasks_logic_queue (IMPORTBIBLE, { datafile, bible, convert_to_string (book), convert_to_string (chapter) });
    } else {
      error_message = translate ("Nothing was uploaded");
    }
    // User imported something into this Bible: Set it as the default Bible.
    request->database_config_user()->setBible (bible);
  }
  
#ifdef HAVE_UPLOAD
  view.enable_zone ("enable_upload");
#else
  view.enable_zone ("disable_upload");
#endif
  
  view.set_variable ("success_message", success_message);
  view.set_variable ("error_message", error_message);
  
  page += view.render ("bible", "import");
  
  page += Assets_Page::footer ();
  
  return page;
}
Esempio n. 9
0
// Schedule a Bible for export to USFM format.
void Export_Logic::scheduleUsfm (string bible, bool log)
{
  tasks_logic_queue (EXPORTUSFM, {bible, convert_to_string (log)});
}
Esempio n. 10
0
void Export_Logic::scheduleQuickBible (string bible, bool log)
{
  tasks_logic_queue (EXPORTQUICKBIBLE, {bible, convert_to_string (log)});
}
Esempio n. 11
0
// Schedule all Bibles for exports.
void Export_Logic::scheduleAll ()
{
  tasks_logic_queue (EXPORTALL);
}
Esempio n. 12
0
void Export_Logic::scheduleOnlineBible (string bible, bool log)
{
  tasks_logic_queue (EXPORTONLINEBIBLE, {bible, convert_to_string (log)});
}
Esempio n. 13
0
void Export_Logic::scheduleESword (string bible, bool log)
{
  tasks_logic_queue (EXPORTESWORD, {bible, convert_to_string (log)});
}
Esempio n. 14
0
string bible_import_usfm (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;
  
  string page;
  
  page = Assets_Page::header (translate ("Import USFM"), webserver_request, "");
  
  Assets_View view = Assets_View ();
  
  string success_message;
  string error_message;
  
  // The name of the Bible.
  string bible = access_bible_clamp (request, request->query["bible"]);
  view.set_variable ("bible", filter_string_sanitize_html (bible));
  
  // Whether the user has write access to this Bible.
  bool write_access = access_bible_write (request, bible);
  if (write_access) view.enable_zone ("write_access");

  // USFM data submission.
  if (request->post.count ("submit")) {
    // Submission may take long if there's a lot of data or the network is slow.
    string data = request->post ["data"];
    data = filter_url_tag_to_plus (data);
    data = filter_string_trim (data);
    if (data != "") {
      if (unicode_string_is_valid (data)) {
        string datafile = filter_url_tempfile ();
        filter_url_file_put_contents (datafile, data);
        success_message = translate("Import has started. See Journal for progress.");
        tasks_logic_queue (IMPORTUSFM, { datafile, bible });
      } else {
        error_message = translate("Please supply valid Unicode UTF-8 text.");
      }
    } else {
      success_message = translate("Nothing was imported.");
    }
  }

  // File upload.
  if (request->post.count ("upload")) {
    string datafile = filter_url_tempfile () + request->post ["filename"];
    string data = request->post ["data"];
    if (!data.empty ()) {
      filter_url_file_put_contents (datafile, data);
      success_message = translate("Import has started. See Journal for progress.");
      tasks_logic_queue (IMPORTUSFM, { datafile, bible });
    } else {
      error_message = translate ("Nothing was uploaded");
    }
  }
  
  view.set_variable ("success_message", success_message);
  view.set_variable ("error_message", error_message);
  
  page += view.render ("bible", "import_usfm");
  
  page += Assets_Page::footer ();
  
  return page;
}
Esempio n. 15
0
// Schedule export to web index.
// $bible: Bible.
void Export_Logic::scheduleWebIndex (string bible, bool log)
{
  tasks_logic_queue (EXPORTWEBINDEX, {bible, convert_to_string (log)});
}
Esempio n. 16
0
string developer_index (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;
  
  if (request->query.count ("log")) {
    string message = request->query ["log"];
    Database_Logs::log (message);
    return "";
  }
  
  string page;

  Assets_Header header = Assets_Header ("Bibledit", webserver_request);
  header.notifItOn ();
  page = header.run ();

  Assets_View view;

  string code;
  
  string debug = request->query ["debug"];
  
  // It is cleaner and easier to move the following task to the binary ./generate.
  if (debug == "etcbc4download") {
    // sources_etcbc4_download ();
    view.set_variable ("success", "Task disabled");
  }
  
  // It is cleaner and easier to move the following task to the binary ./generate.
  if (debug == "etcbc4parse") {
    //sources_etcbc4_parse ();
    view.set_variable ("success", "Task disabled");
  }
  
  // It is cleaner and easier to move the following task to the binary ./generate.
  if (debug == "parsekjv") {
    //sources_kjv_parse ();
    view.set_variable ("success", "Task disabled");
  }
  
  // It is cleaner and easier to move the following task to the binary ./generate.
  if (debug == "parsemorphgnt") {
    // sources_morphgnt_parse ();
    view.set_variable ("success", "Task disabled");
  }

  // It is cleaner and easier to move the following task to the binary ./generate.
  if (debug == "parsehebrewlexicon") {
    // sources_hebrewlexicon_parse ();
    view.set_variable ("success", "Task disabled");
  }

  // It is cleaner and easier to move the following task to the binary ./generate.
  if (debug == "studylightcommentaries") {
    // code = resource_external_studylight_code ();
    view.set_variable ("success", "Task disabled");
  }

  if (debug == "crash") {
    // int *foo = (int*)-1; // make a bad pointer
    // printf ("%d\n", *foo); // cause segmentation fault
    view.set_variable ("success", "Task disabled");
  }
  
  if (debug == "receive") {
    tasks_logic_queue (RECEIVEEMAIL);
    view.set_variable ("success", "Receiving email and running tasks that send mail");
  }

  if (debug == "ipv6") {
    view.set_variable ("success", "Fetching data via IPv6");
    string error;
    string response = filter_url_http_request_mbed ("http://ipv6.google.com", error, {}, "", true);
    page.append (response);
    view.set_variable ("error", error);
  }
  
  if (debug == "ipv6s") {
    view.set_variable ("success", "Securely fetching data via IPv6");
    string error;
    string response = filter_url_http_request_mbed ("https://ipv6.google.com", error, {}, "", true);
    page.append (response);
    view.set_variable ("error", error);
  }
  
  view.set_variable ("code", code);

  page += view.render ("developer", "index");
  page += Assets_Page::footer ();

  return page;
}
Esempio n. 17
0
void sendreceive_resources ()
{
  if (sendreceive_resources_watchdog) {
    int time = filter_date_seconds_since_epoch ();
    if (time < (sendreceive_resources_watchdog + 900)) {
      return;
    }
    Database_Logs::log ("Resources: " + translate("Watchdog timeout"), Filter_Roles::translator ());
    sendreceive_resources_done ();
  }

  // If any of the prioritized synchronization tasks run, postpone the current task and do not start it.
  if (sendreceive_logic_prioritized_task_is_active ()) {
    sendreceive_resources_done ();
    this_thread::sleep_for (chrono::seconds (5));
    tasks_logic_queue (SYNCRESOURCES);
    return;
  }

  sendreceive_resources_interrupt = false;

  // If there's nothing to cache, bail out.
  vector <string> resources = Database_Config_General::getResourcesToCache ();
  if (resources.empty ()) return;
  
  sendreceive_resources_kick_watchdog ();

  // Error counter.
  int error_count = 0;
  
  // Resource to cache.
  string resource = resources [0];
  
  // Erase the two older storage locations that were used to cache resources in earlier versions of Bibledit.
  {
    Database_OfflineResources database_offlineresources;
    Database_UsfmResources database_usfmresources;
    database_offlineresources.erase (resource);
    database_usfmresources.deleteResource (resource);
  }

  Database_Logs::log ("Starting to install resource:" " " + resource, Filter_Roles::consultant ());
  
  Database_Versifications database_versifications;
  
  vector <int> books = database_versifications.getMaximumBooks ();
  for (auto & book : books) {
    sendreceive_resources_delay_during_prioritized_tasks ();
    if (sendreceive_resources_interrupt) continue;
    
    // Database layout is per book: Create a database for this book.
    Database_Cache::create (resource, book);

    // Last downloaded passage in a previous download operation.
    int last_downloaded_passage = 0;
    {
      pair <int, int> progress = Database_Cache::progress (resource, book);
      int chapter = progress.first;
      int verse = progress.second;
      Passage passage ("", book, chapter, convert_to_string (verse));
      last_downloaded_passage = filter_passage_to_integer (passage);
    }
    
    // List of passages recorded in the database that had errors on a previous download operation.
    vector <int> previous_errors;
    {
      vector <pair <int, int> > errors = Database_Cache::errors (resource, book);
      for (auto & element : errors) {
        int chapter = element.first;
        int verse = element.second;
        Passage passage ("", book, chapter, convert_to_string (verse));
        int numeric_error = filter_passage_to_integer (passage);
        previous_errors.push_back (numeric_error);
      }
    }
    
    string bookName = Database_Books::getEnglishFromId (book);
    
    vector <int> chapters = database_versifications.getMaximumChapters (book);
    for (auto & chapter : chapters) {
      sendreceive_resources_delay_during_prioritized_tasks ();
      if (sendreceive_resources_interrupt) continue;
      bool downloaded = false;
      string message = resource + ": " + bookName + " chapter " + convert_to_string (chapter);
      vector <int> verses = database_versifications.getMaximumVerses (book, chapter);
      for (auto & verse : verses) {
        sendreceive_resources_delay_during_prioritized_tasks ();
        if (sendreceive_resources_interrupt) continue;
        // Numeric representation of passage to deal with.
        Passage passage ("", book, chapter, convert_to_string (verse));
        int numeric_passage = filter_passage_to_integer (passage);
        // Conditions to download this verse:
        // 1. The passage is past the last downloaded passage.
        bool download_verse_past = numeric_passage > last_downloaded_passage;
        // 2. The passage was recorded as an error in a previous download operation.
        bool download_verse_error = in_array (numeric_passage, previous_errors);
        // Whether to download the verse.
        if (download_verse_past || download_verse_error) {
          // Fetch the text for the passage.
          bool server_is_installing_module = false;
          int wait_iterations = 0;
          string html, error;
          do {
            // Fetch this resource from the server.
            string address = Database_Config_General::getServerAddress ();
            int port = Database_Config_General::getServerPort ();
            // If the client has not been connected to a cloud instance,
            // fetch the resource from the Bibledit Cloud demo.
            if (!client_logic_client_enabled ()) {
              address = demo_address ();
              port = demo_port ();
            }
            string url = client_logic_url (address, port, sync_resources_url ());
            url = filter_url_build_http_query (url, "r", filter_url_urlencode (resource));
            url = filter_url_build_http_query (url, "b", convert_to_string (book));
            url = filter_url_build_http_query (url, "c", convert_to_string (chapter));
            url = filter_url_build_http_query (url, "v", convert_to_string (verse));
            error.clear ();
            html = filter_url_http_get (url, error);
            server_is_installing_module = (html == sword_logic_installing_module_text ());
            if (server_is_installing_module) {
              Database_Logs::log ("Waiting while Bibledit Cloud installs the requested SWORD module");
              this_thread::sleep_for (chrono::seconds (60));
              wait_iterations++;
            }
          } while (server_is_installing_module && (wait_iterations < 5));
          // Record the passage as having been done in case it was a regular download,
          // rather than one to retry a previous download error.
          if (download_verse_past) Database_Cache::progress (resource, book, chapter, verse);
          // Clear the registered error in case the verse download corrects it.
          if (download_verse_error) Database_Cache::error (resource, book, chapter, verse, false);
          if (error.empty ()) {
            // Cache the verse data.
            if (!Database_Cache::exists (resource, book)) Database_Cache::create (resource, book);
            Database_Cache::cache (resource, book, chapter, verse, html);
          } else {
            // Record an error.
            Database_Cache::error (resource, book, chapter, verse, true);
            if (message.find (error) == string::npos) {
              message.append ("; " + error);
            }
            error_count++;
            this_thread::sleep_for (chrono::seconds (1));
          }
          downloaded = true;
        }
        sendreceive_resources_kick_watchdog ();
      }
      message += "; done";
      if (downloaded) Database_Logs::log (message, Filter_Roles::manager ());
    }
  }
  
  // Done.
  if (error_count) {
    string msg = "Error count while downloading resource: " + convert_to_string (error_count);
    Database_Logs::log (msg, Filter_Roles::consultant ());
  }
  Database_Logs::log ("Completed installing resource:" " " + resource, Filter_Roles::consultant ());
  // In case of too many errors, schedule the resource download again.
  bool re_schedule_download = false;
  if (error_count) {
    if (!sendreceive_resources_interrupt) {
      re_schedule_download = true;
      Database_Logs::log ("Errors: Re-scheduling resource installation", Filter_Roles::consultant ());
    }
  }
  // Store new download schedule.
  resources = Database_Config_General::getResourcesToCache ();
  resources = filter_string_array_diff (resources, {resource});
  if (re_schedule_download) {
    resources.push_back (resource);
  }
  Database_Config_General::setResourcesToCache (resources);

  sendreceive_resources_done ();
  
  sendreceive_resources_interrupt = false;

  // If there's another resource waiting to be cached, schedule it for caching.
  if (!resources.empty ()) tasks_logic_queue (SYNCRESOURCES);
}
Esempio n. 18
0
string resource_download (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;
  Database_UsfmResources database_usfmresources;
  
  
  string page;
  Assets_Header header = Assets_Header (translate("Download resource"), request);
  header.addBreadCrumb (menu_logic_settings_menu (), menu_logic_settings_text ());
  header.addBreadCrumb (resource_cache_url (), menu_logic_resources_text ());
  page = header.run ();
  Assets_View view;

  
  string name = request->query["name"];
  view.set_variable ("name", name);
  
  
  
  bool old = request->query.count ("old");
  if (old) view.enable_zone ("old");
  else view.enable_zone ("current");
                        
                      
  if (request->query.count ("clear")) {
    // The client clears the two older storage locations just to be sure they are gone.
    database_usfmresources.deleteResource (name);
    // The client clears the installed resource.
    Database_Cache::remove (name);
  }
  if (request->query.count ("clearold")) {
    // The client clears the two older storage locations just to be sure they are gone.
    database_usfmresources.deleteResource (name);
    redirect_browser (request, resource_cache_url ());
    return "";
  }
  
  
  if (request->query.count ("download")) {
    // Trigger caching the resource.
    // Add the resource to the general configuration to be cached, if it is not already there.
    vector <string> resources = Database_Config_General::getResourcesToCache ();
    if (!in_array (name, resources)) {
      resources.push_back (name);
      Database_Config_General::setResourcesToCache (resources);
    }
    tasks_logic_queue (SYNCRESOURCES);
    redirect_browser (request, journal_index_url ());
    return "";
  }
  
  
  int count = 0;
  if (count == 0) {
    vector <int> books = database_usfmresources.getBooks (name);
    for (auto book : books) {
      vector <int> chapters = database_usfmresources.getChapters (name, book);
      // Rough average of 20 verses per chapter.
      count += (20 * chapters.size());
    }
  }
  if (count == 0) count = Database_Cache::count (name);
  view.set_variable ("count", convert_to_string (count));
                      
                      
  page += view.render ("resource", "download");
  page += Assets_Page::footer ();
  return page;
}
Esempio n. 19
0
string resource_organize (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;

  
  string checkbox = request->post ["checkbox"];
  bool checked = convert_to_bool (request->post ["checked"]);

  
  if (request->query.count ("add") || request->post.count ("add")) {
    string add = request->query["add"];
    if (add.empty ()) add = request->post ["add"];
    vector <string> resources = request->database_config_user()->getActiveResources ();
    resources.push_back (add);
    request->database_config_user()->setActiveResources (resources);
    request->database_config_user()->addUpdatedSetting (Sync_Logic::settings_send_resources_organization);
  }
  
  
  if (request->query.count ("remove")) {
    size_t remove = convert_to_int (request->query["remove"]);
    vector <string> resources = request->database_config_user()->getActiveResources ();
    if (remove < resources.size ()) {
      resources.erase (resources.begin () + remove);
    }
    request->database_config_user()->setActiveResources (resources);
    request->database_config_user()->addUpdatedSetting (Sync_Logic::settings_send_resources_organization);
  }

  
  if (request->query.count ("moveup")) {
    size_t moveup = convert_to_int (request->query["moveup"]);
    vector <string> resources = request->database_config_user()->getActiveResources ();
    array_move_up_down (resources, moveup, true);
    request->database_config_user()->setActiveResources (resources);
    request->database_config_user()->addUpdatedSetting (Sync_Logic::settings_send_resources_organization);
  }

  
  if (request->query.count ("movedown")) {
    size_t movedown = convert_to_int (request->query["movedown"]);
    vector <string> resources = request->database_config_user()->getActiveResources ();
    array_move_up_down (resources, movedown, false);
    request->database_config_user()->setActiveResources (resources);
    request->database_config_user()->addUpdatedSetting (Sync_Logic::settings_send_resources_organization);
  }
  
  
  string page;
  Assets_Header header = Assets_Header (translate("Resources"), request);
  page = header.run ();
  Assets_View view;

  
  // Active resources.
  vector <string> active_resources = request->database_config_user()->getActiveResources ();
  string activesblock;
  for (size_t i = 0; i < active_resources.size (); i++) {
    activesblock.append ("<p>");
    activesblock.append ("<a href=\"?remove=" + convert_to_string (i) + "\">");
    activesblock.append (emoji_wastebasket ());
    activesblock.append ("</a>");
    activesblock.append (" ");
    activesblock.append ("<a href=\"?moveup=" + convert_to_string (i) + "\">");
    activesblock.append (unicode_black_up_pointing_triangle ());
    activesblock.append ("</a>");
    activesblock.append ("<a href=\"?movedown=" + convert_to_string (i) + "\">");
    activesblock.append (unicode_black_down_pointing_triangle ());
    activesblock.append ("</a>");
    activesblock.append (" ");
    activesblock.append (active_resources [i]);
    activesblock.append ("</p>");
    activesblock.append ("\n");
  }
  view.set_variable ("activesblock", activesblock);
  
  
  // Context before.
  if (request->query.count ("before")) {
    Dialog_Entry dialog_entry = Dialog_Entry ("organize", translate("Please enter the number of verses"), convert_to_string (request->database_config_user ()->getResourceVersesBefore ()), "before", translate ("How many verses of context to display before the focused verse."));
    page += dialog_entry.run ();
    return page;
  }
  if (request->post.count ("before")) {
    int value = convert_to_int (request->post["entry"]);
    if ((value >= 0) && (value <= 100)) {
      request->database_config_user ()->setResourceVersesBefore (value);
    }
  }
  view.set_variable ("before", convert_to_string (request->database_config_user ()->getResourceVersesBefore ()));

  
  // Context after.
  if (request->query.count ("after")) {
    Dialog_Entry dialog_entry = Dialog_Entry ("organize", translate("Please enter the number of verses"), convert_to_string (request->database_config_user ()->getResourceVersesAfter ()), "after", translate ("How many verses of context to display after the focused verse."));
    page += dialog_entry.run ();
    return page;
  }
  if (request->post.count ("after")) {
    int value = convert_to_int (request->post["entry"]);
    if ((value >= 0) && (value <= 100)) {
      request->database_config_user ()->setResourceVersesAfter (value);
    }
  }
  view.set_variable ("after", convert_to_string (request->database_config_user ()->getResourceVersesAfter ()));

  
  if (checkbox == "related") {
    request->database_config_user ()->setIncludeRelatedPassages (checked);
    return "";
  }
  view.set_variable ("related", get_checkbox_status (request->database_config_user ()->getIncludeRelatedPassages ()));

  
  if (request->query.count ("install")) {
    vector <string> usfm_resources = client_logic_usfm_resources_get ();
    vector <string> original_language_resources = resource_external_get_original_language_resources ();
    vector <string> bible_resources = resource_external_get_bibles ();
    vector <string> commentary_resources = resource_external_get_commentaries ();
    vector <string> general_resources = resource_external_get_general_resources ();
    vector <string> sword_resources = sword_logic_get_available ();
    vector <string> installable_resources;
    installable_resources.insert (installable_resources.end (), usfm_resources.begin (), usfm_resources.end ());
    installable_resources.insert (installable_resources.end (), original_language_resources.begin (), original_language_resources.end ());
    installable_resources.insert (installable_resources.end (), bible_resources.begin (), bible_resources.end ());
    installable_resources.insert (installable_resources.end (), commentary_resources.begin (), commentary_resources.end ());
    installable_resources.insert (installable_resources.end (), general_resources.begin (), general_resources.end ());
    installable_resources.insert (installable_resources.end (), sword_resources.begin (), sword_resources.end ());
    vector <string> installing_resources = Database_Config_General::getResourcesToCache ();
    vector <string> active_resources = request->database_config_user()->getActiveResources ();
    for (auto & resource : active_resources) {
      if (in_array (resource, installable_resources)) {
        if (!in_array (resource, installing_resources)) {
          installing_resources.push_back (resource);
          Database_Config_General::setResourcesToCache (installing_resources);
        }
      }
    }
    tasks_logic_queue (SYNCRESOURCES);
    view.set_variable ("success", translate ("Will install the resources.") + " " + translate ("The journal displays the progress."));
  }

  
#ifdef HAVE_CLIENT
  view.enable_zone ("client");
#endif

  
  page += view.render ("resource", "organize");
  page += Assets_Page::footer ();
  return page;
}
Esempio n. 20
0
string resource_manage (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;

  
  string page;
  Assets_Header header = Assets_Header (translate("USFM Resources"), request);
  header.addBreadCrumb (menu_logic_settings_menu (), menu_logic_settings_text ());
  page = header.run ();
  Assets_View view;
  
  
  Database_UsfmResources database_usfmresources = Database_UsfmResources ();

  
  // Delete resource.
  string remove = request->query ["delete"];
  if (remove != "") {
    string confirm = request->query ["confirm"];
    if (confirm == "") {
      Dialog_Yes dialog_yes = Dialog_Yes ("manage", translate("Would you like to delete this resource?"));
      dialog_yes.add_query ("delete", remove);
      page += dialog_yes.run ();
      return page;
    } if (confirm == "yes") {
      if (access_bible_write (request, remove)) {
        database_usfmresources.deleteResource (remove);
        // The Cloud updates the list of available USFM resources for the clients.
        tasks_logic_queue (LISTUSFMRESOURCES);
      } else {
        view.set_variable ("error", translate("You do not have write access to this resource"));
      }
    }
  }
  
  
  // Convert resource.
  string convert = request->query ["convert"];
  if (convert != "") {
    string confirm = request->query ["confirm"];
    if (confirm == "") {
      Dialog_Yes dialog_yes = Dialog_Yes ("manage", translate("Would you like to convert this resource to a Bible?"));
      dialog_yes.add_query ("convert", convert);
      page += dialog_yes.run ();
      return page;
    } if (confirm == "yes") {
      if (access_bible_write (request, convert)) {
        tasks_logic_queue (CONVERTRESOURCE2BIBLE, {convert});
        redirect_browser (request, journal_index_url ());
        return "";
      } else {
        view.set_variable ("error", translate("Insufficient privileges"));
      }
    }
  }
  
  
  vector <string> resources = database_usfmresources.getResources ();
  vector <string> resourceblock;
  for (auto & resource : resources) {
    resourceblock.push_back ("<p>");
    resourceblock.push_back ("<a href=\"?delete=" + resource + "\" class=\"deleteresource\" title=\"" + translate("Remove") + "\">");
    resourceblock.push_back (emoji_wastebasket ());
    resourceblock.push_back ("</a>");
    resourceblock.push_back ("<a href=\"?convert=" + resource + "\" class=\"convertresource\" title=\"" + translate("Convert") + "\">");
    resourceblock.push_back ("♻");
    resourceblock.push_back ("</a>");
    resourceblock.push_back (resource);
    resourceblock.push_back ("</p>");
  }
  view.set_variable ("resourceblock", filter_string_implode (resourceblock, "\n"));

  
  page += view.render ("resource", "manage");
  page += Assets_Page::footer ();
  return page;
}
Esempio n. 21
0
string manage_index (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;

  string page;

  Assets_Header header = Assets_Header (translate("Manage"), webserver_request);
  header.addBreadCrumb (menu_logic_settings_menu (), menu_logic_settings_text ());
  page = header.run ();

  Assets_View view;
  string success;
  string error;
  
  
  // Force re-index Bibles.
  if (request->query ["reindex"] == "bibles") {
    Database_Config_General::setIndexBibles (true);
    tasks_logic_queue (REINDEXBIBLES, {"1"});
    redirect_browser (request, journal_index_url ());
    return "";
  }
  
  
  // Re-index consultation notes.
  if (request->query ["reindex"] == "notes") {
    Database_Config_General::setIndexNotes (true);
    tasks_logic_queue (REINDEXNOTES);
    redirect_browser (request, journal_index_url ());
    return "";
  }

  
  // Delete a font.
  string deletefont = request->query ["deletefont"];
  if (!deletefont.empty ()) {
    string font = filter_url_basename (deletefont);
    bool font_in_use = false;
    vector <string> bibles = request->database_bibles ()->getBibles ();
    for (auto & bible : bibles) {
      if (font == Fonts_Logic::getTextFont (bible)) font_in_use = true;
    }
    if (!font_in_use) {
      // Only delete a font when it is not in use.
      Fonts_Logic::erase (font);
    } else {
      error = translate("The font could not be deleted because it is in use");
    }
  }
  
  
  // Upload a font.
  if (request->post.count ("uploadfont")) {
    string filename = request->post ["filename"];
    string path = filter_url_create_root_path ("fonts", filename);
    string fontdata = request->post ["fontdata"];
    filter_url_file_put_contents (path, fontdata);
    success = translate("The font has been uploaded.");
  }
  

  // Assemble the font block html.
  vector <string> fonts = Fonts_Logic::getFonts ();
  vector <string> fontsblock;
  for (auto & font : fonts) {
    fontsblock.push_back ("<p>");
#ifndef CLIENT_PREPARED
    fontsblock.push_back ("<a href=\"?deletefont=" + font+ "\" title=\"" + translate("Delete font") + "\"> ✗ </a>");
#endif
    fontsblock.push_back (font);
    fontsblock.push_back ("</p>");
  }
  view.set_variable ("fontsblock", filter_string_implode (fontsblock, "\n"));

  
#ifdef CLIENT_PREPARED
  view.enable_zone ("client");
  view.set_variable ("cloudlink", client_logic_link_to_cloud (manage_index_url (), ""));
#else
  view.enable_zone ("server");
#endif
  
  
  view.set_variable ("success", success);
  view.set_variable ("error", error);
  page += view.render ("manage", "index");

  page += Assets_Page::footer ();
  
  return page;
}
Esempio n. 22
0
string resource_sword (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;

  
  if (request->query.count ("refresh")) {
    tasks_logic_queue (REFRESHSWORDMODULES);
    redirect_browser (request, journal_index_url ());
  }

  
  if (request->query.count ("update")) {
    tasks_logic_queue (UPDATESWORDMODULES, {});
    redirect_browser (request, journal_index_url ());
  }
  
  
  /*
   It used to be possible to manually install or uninstall SWORD modules.
   However it was observed that on the open Bibledit demo, 
   there were bursts of installed SWORD modules.
   That made Bibledit unresponsive or just get stuck.
   Likely the web crawlers of the search engines click all links to install all modules.
   The answer to this problem was to remove manual install or uninstall of SWORD modules.
   */
  
  
  string page;
  Assets_Header header = Assets_Header (translate("Resources"), request);
  header.addBreadCrumb (menu_logic_settings_menu (), menu_logic_settings_text ());
  page = header.run ();
  Assets_View view;

  
  map <string, string> installed_modules;
  {
    vector <string> modules = sword_logic_get_installed ();
    for (auto module : modules) {
      string name = sword_logic_get_installed_module (module);
      string version = sword_logic_get_version (module);
      installed_modules [name] = version;
    }
  }
  
  vector <string> available_modules = sword_logic_get_available ();
  string moduleblock;
  for (auto & available_module : available_modules) {
    string source = sword_logic_get_source (available_module);
    string module = sword_logic_get_remote_module (available_module);
    moduleblock.append ("<p>");
    moduleblock.append (available_module);
    if (!installed_modules [module].empty ()) {
      moduleblock.append (" (" + translate ("installed") + ") ");
      string version = sword_logic_get_version (available_module);
      if (version != installed_modules[module]) {
        moduleblock.append (" (" + translate ("to be updated") + ")");
      }
    }
    moduleblock.append ("</p>\n");
  }
  view.set_variable ("moduleblock", moduleblock);

  
#ifdef HAVE_CLIENT
  view.enable_zone ("client");
#else
  view.enable_zone ("server");
#endif
  
  
  page += view.render ("resource", "sword");
  page += Assets_Page::footer ();
  return page;
}
Esempio n. 23
0
void timer_index ()
{
  bool client = client_logic_client_enabled ();
  int previous_second = -1;
  int previous_minute = -1;
  int previous_fraction = -1;
  while (config_globals_running) {

    try {

      // Wait shortly.
      this_thread::sleep_for (chrono::milliseconds (100));
      
      // Wait tilll the data structures have been initialized.
      if (!config_globals_data_initialized) continue;
      
      // The current time, localized.
      int seconds_since_epoch = filter_date_seconds_since_epoch ();
      int local_seconds = filter_date_local_seconds (seconds_since_epoch);
      int second = filter_date_numerical_second (local_seconds);
      int minute = filter_date_numerical_minute (local_seconds);
      int hour = filter_date_numerical_hour (local_seconds);
      int weekday = filter_date_numerical_week_day (local_seconds);
      
      // Run once per second.
      if (second == previous_second) continue;
      previous_second = second;

      // Every second: Deal with queued and/or active tasks.
      tasks_run_check ();
      
      // Run the part below every so many seconds.
      int fraction = second / 5;
      if (fraction != previous_fraction) {
        previous_fraction = fraction;
      }
      
      // Run the part below once per minute.
      if (minute == previous_minute) continue;
      previous_minute = minute;
      
      // Every minute send out queued email, except in client mode.
      if (!client) tasks_logic_queue (SENDEMAIL);

      // Check for new mail every five minutes.
      // Do not check more often with gmail else the account may be shut down.
      if ((!client) && ((minute % 5) == 0)) {
        tasks_logic_queue (RECEIVEEMAIL);
      }

      // At the nineth minute after every full hour rotate the journal.
      // The nine is chosen, because the journal rotation will summarize the send/receive messages.
      // In case send/receive happens every five minutes, it is expected that under normal circumstances
      // the whole process of sending/receivning will be over, so summarization can then be done.
      if (minute == 9) tasks_logic_queue (ROTATEJOURNAL);
      
      // Client sends/receives Bibles and Consultation.
      sendreceive_queue_sync (minute);
      
      // Sending and receiving Bibles to and from the git repository.
      // On a production website running on an inexpensive virtual private server
      // with 512 Mbyte of memory and a fast network connection,
      // sending and receiving two Bibles takes more than 15 minutes when there are many changes.
      bool sendreceive = ((hour == 0) && (minute == 5));
      bool repeat = ((minute % 5) == 0);
      if (sendreceive || repeat) {
        sendreceive_queue_all (sendreceive);
      }
      
      // Deal with the changes in the Bible made per user.
      // Deal with notifications for the daily changes in the Bibles.
      // This takes a few minutes on a production machine with two Bibles and changes in several chapters.
      // It runs in a server configuration, not on a client.
      if (!client) {
        if ((hour == 0) && (minute == 20)) {
          changes_logic_start ();
        }
      }

      // Run the checks on the Bibles.
      // This takes 15 minutes on a production machine with two Bibles.
      if (!client) {
        if ((hour == 0) && (minute == 30)) {
          checks_logic_start_all ();
        }
      }
      
      // Database maintenance and trimming.
      // It takes a few minutes on a production machine.
      if ((hour == 0) && (minute == 50)) {
        tasks_logic_queue (MAINTAINDATABASE);
      }
      
      // Export the Bibles to the various output formats.
      // This may take an hour on a production machine.
      // This hour was in PHP. In C++ it is much faster.
      if (!client) {
        if ((hour == 1) && (minute == 10)) {
          Export_Logic::scheduleAll ();
        }
      }
      
      // Delete temporal files older than a few days.
      if ((hour == 2) && (minute == 0)) {
        tasks_logic_queue (CLEANTMPFILES);
      }
      
      // Re-index Bibles and notes.
      // Only update missing indexes.
      if ((hour == 2) && (minute == 0)) {
        Database_State::create ();
        Database_Config_General::setIndexBibles (true);
        tasks_logic_queue (REINDEXBIBLES);
        Database_Config_General::setIndexNotes (true);
        tasks_logic_queue (REINDEXNOTES);
      }
      
      // Actions for a demo installation.
      if (minute == 10) {
        if (config_logic_demo_enabled ()) {
          tasks_logic_queue (CLEANDEMO);
        }
      }
      
      // Sprint burndown.
      // It runs every hour in the Cloud.
      // The script itself determines what to do at which hour of the day or day of the week or day of the month.
      if (!client) {
        if (minute == 5) {
          tasks_logic_queue (SPRINTBURNDOWN);
        }
      }

      // Quit at midnight if flag is set.
      if (config_globals_quit_at_midnight) {
        if (hour == 0) {
          if (minute == 1) {
            if (!Database_Config_General::getJustStarted ()) {
              if (tasks_run_active_count ()) {
                Database_Logs::log ("Server is due to restart itself but does not because of active jobs");
              } else {
                Database_Logs::log ("Server restarts itself");
                exit (0);
              }
            }
          }
          // Clear flag in preparation of restart next minute.
          // This flag also has the purpose of ensuring the server restarts once during that minute,
          // rather than restarting repeatedly many times during that minute.
          if (minute == 0) {
            Database_Config_General::setJustStarted (false);
          }
        }
      }
      
      // Email notes statistics to the users.
      if (!client) {
        if ((hour == 3) && (minute == 0)) {
          tasks_logic_queue (NOTESSTATISTICS);
        }
      }

      // Update SWORD stuff once a week.
      if (weekday == 1) {
        // Refresh module list.
        if ((!client) && (hour == 3) && (minute == 5)) {
          tasks_logic_queue (REFRESHSWORDMODULES);
        }
        // Update installed SWORD modules, shortly after the module list has been refreshed.
        if ((!client) && (hour == 3) && (minute == 15)) {
          tasks_logic_queue (UPDATESWORDMODULES);
        }
      }
      
      // The Cloud updates the list of USFM resources once a week.
      if (weekday == 1) {
        if ((!client) && (hour == 3) && (minute == 10)) {
          tasks_logic_queue (LISTUSFMRESOURCES);
        }
      }
      

    } catch (exception & e) {
      Database_Logs::log (e.what ());
    } catch (exception * e) {
      Database_Logs::log (e->what ());
    } catch (...) {
      Database_Logs::log ("A general internal error occurred in the timers");
    }

  }
}
Esempio n. 24
0
void sendreceive_queue_bible (string bible)
{
  tasks_logic_queue (SENDRECEIVEBIBLES, {bible});
}