예제 #1
0
string public_create (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;
  Database_Notes database_notes (webserver_request);
  Notes_Logic notes_logic = Notes_Logic (webserver_request);
  
  
  string page;
  Assets_Header header = Assets_Header (translate("Create note"), request);
  page += header.run ();
  Assets_View view;

  
  string bible = request->database_config_user()->getBible ();
  int book = Ipc_Focus::getBook (webserver_request);
  int chapter = Ipc_Focus::getChapter (webserver_request);
  int verse = Ipc_Focus::getVerse (webserver_request);

  
  string chapter_usfm = request->database_bibles()->getChapter (bible, book, chapter);
  string verse_usfm = usfm_get_verse_text (chapter_usfm, verse);
  string stylesheet = Database_Config_Bible::getExportStylesheet (bible);
  Filter_Text filter_text = Filter_Text (bible);
  filter_text.html_text_standard = new Html_Text (bible);
  filter_text.addUsfmCode (verse_usfm);
  filter_text.run (stylesheet);
  string versetext = filter_text.html_text_standard->getInnerHtml ();
  view.set_variable ("versetext", versetext);

 
  if (request->post.count ("submit")) {
    string summary = filter_string_trim (request->post["summary"]);
    if (summary.empty ()) summary = translate ("Feedback");
    string contents = "<p>" + versetext + "</p>" + filter_string_trim (request->post["contents"]);
    int identifier = notes_logic.createNote (bible, book, chapter, verse, summary, contents, false);
    // A note created by a public user is made public to all.
    database_notes.setPublic (identifier, true);
    // Subscribe the user to the note.
    // Then the user receives email about any updates made on this note.
    database_notes.subscribe (identifier);
    // Go to the main public notes page.
    redirect_browser (request, public_index_url ());
    return "";
  }

  
  if (request->post.count ("cancel")) {
    redirect_browser (request, public_index_url ());
    return "";
  }
  
  
  string passage = filter_passage_display (book, chapter, convert_to_string (verse));
  view.set_variable ("passage", passage);
                                                                                                      
  
  page += view.render ("public", "create");
  page += Assets_Page::footer ();
  return page;
}
예제 #2
0
파일: usfm.cpp 프로젝트: alerque/bibledit
// This imports USFM $input.
// It takes raw $input,
// and returns a vector with objects with book_number, chapter_number, chapter_data.
vector <BookChapterData> usfm_import (string input, string stylesheet)
{
  vector <BookChapterData> result;

  int book_number = 0;
  int chapter_number = 0;
  string chapter_data = "";

  input = usfm_one_string (input);
  vector <string> markers_and_text = usfm_get_markers_and_text (input);
  bool retrieve_book_number_on_next_iteration = false;
  bool retrieve_chapter_number_on_next_iteration = false;

  for (string marker_or_text : markers_and_text) {
    if (retrieve_book_number_on_next_iteration) {
      book_number = Database_Books::getIdFromUsfm (marker_or_text.substr (0, 3));
      chapter_number = 0;
      retrieve_book_number_on_next_iteration = false;
    }
    if (retrieve_chapter_number_on_next_iteration) {
      retrieve_chapter_number_on_next_iteration = false;
      chapter_number = convert_to_int (marker_or_text);
    }
    string marker = usfm_get_marker (marker_or_text);
    if (marker != "") {
      // USFM marker found.
      bool store_chapter_data = false;
      if (marker == "id") {
        retrieve_book_number_on_next_iteration = true;
        store_chapter_data = true;
      }
      if (marker == "c") {
        retrieve_chapter_number_on_next_iteration = true;
        store_chapter_data = true;
      }
      if (store_chapter_data) {
        chapter_data = filter_string_trim (chapter_data);
        if (chapter_data != "") result.push_back ( { book_number, chapter_number, chapter_data } );
        chapter_number = 0;
        chapter_data = "";
        store_chapter_data = false;
      }
      Database_Styles database_styles;
      Database_Styles_Item marker_data = database_styles.getMarkerData (stylesheet, marker);
      int type = marker_data.type;
      int subtype = marker_data.subtype;
      if (styles_logic_starts_new_line_in_usfm (type, subtype)) {
        chapter_data += "\n";
      }
    }
    chapter_data += marker_or_text;
  }
  chapter_data = filter_string_trim (chapter_data);
  if (chapter_data != "") result.push_back (BookChapterData (book_number, chapter_number, chapter_data));
  return result;
}
예제 #3
0
파일: http.cpp 프로젝트: githubber/bibledit
// Takes data POSTed from the browser, and parses it.
void http_parse_post (string content, Webserver_Request * request)
{
  // Read and parse the POST data.
  try {
    if (!content.empty ()) {
      // Standard parse.
      bool urlencoded = request->content_type.find ("urlencoded") != string::npos;
      ParseWebData::WebDataMap dataMap;
      ParseWebData::parse_post_data (content, request->content_type, dataMap);
      for (ParseWebData::WebDataMap::const_iterator iter = dataMap.begin(); iter != dataMap.end(); ++iter) {
        string value;
        if (urlencoded) value = filter_url_urldecode ((*iter).second.value);
        else value = (*iter).second.value;
        request->post [(*iter).first] = value;
      }
      // Special case: Extract the filename in case of a file upload.
      if (content.length () > 1000) content.resize (1000);
      if (content.find ("filename=") != string::npos) {
        vector <string> lines = filter_string_explode (content, '\n');
        for (auto & line : lines) {
          if (line.find ("Content-Disposition") == string::npos) continue;
          size_t pos = line.find ("filename=");
          if (pos == string::npos) continue;
          line = line.substr (pos + 10);
          line = filter_string_trim (line);
          line.pop_back ();
          request->post ["filename"] = line;
        }
      }
    }
  } catch (...) {
  }
}
예제 #4
0
파일: logs.cpp 프로젝트: alerque/bibledit
void Database_Logs::log (string description, int level)
{
  // No new lines.
  description = filter_string_str_replace ("\n", " ", description);
  // Discard empty line.
  if (filter_string_trim (description).empty()) return;
  // Truncate long entry.
  int length = description.length ();
  if (length > 1000) {
    description.erase (1000);
    description.append ("... This entry was too large and has been truncated: " + convert_to_string (length) + " bytes");
  }
  // Save this logbook entry to a filename with seconds and microseconds.
  string seconds = convert_to_string (filter_date_seconds_since_epoch ());
  string time = seconds + filter_string_fill (convert_to_string (filter_date_numerical_microseconds ()), 8, '0');
  string file = filter_url_create_path (folder (), time);
  // The microseconds granularity depends on the platform.
  // On Windows it is lower than on Linux.
  // There may be the rare case of more than one entry per file.
  // Append the data so it won't overwrite an earlier entry.
  if (file_exists (file)) {
    description.insert (0, " | ");
  } else {
    description.insert (0, convert_to_string (level) + " " + seconds + " ");
  }
  filter_url_file_put_contents_append (file, description);
  // Delay to cover for lower usec granularity on Windows.
  if (config_logic_windows ()) {
    this_thread::sleep_for (chrono::milliseconds (1));
  }
}
예제 #5
0
string filter_passage_clean_passage (string text)
{
  // Trim text.
  text = filter_string_trim (text);
  // As references could be, e.g.: Genesis 10.2, or Genesis 10:2,
  // it needs to convert a the full stop and the colon to a space.
  text = filter_string_str_replace (".", " ", text);
  text = filter_string_str_replace (":", " ", text);
  // Change double spaces into single ones.
  text = filter_string_str_replace ("  ", " ", text);
  text = filter_string_str_replace ("  ", " ", text);
  // Trim again.
  text = filter_string_trim (text);
  // Result.
  return text;
}
예제 #6
0
파일: usfm.cpp 프로젝트: alerque/bibledit
// Returns the verse number in the $usfm code.
string usfm_peek_verse_number (string usfm)
{
  // Make it robust, even handling cases like \v 1-2“Moi - No space after verse number.
  string verseNumber = "";
  size_t usfmStringLength = usfm.length ();
  unsigned int i = 0;
  for (i = 0; i < usfmStringLength; i++) {
    string character = usfm.substr (i, 1);
    if (character == "0") continue;
    if (character == "1") continue;
    if (character == "2") continue;
    if (character == "3") continue;
    if (character == "4") continue;
    if (character == "5") continue;
    if (character == "6") continue;
    if (character == "7") continue;
    if (character == "8") continue;
    if (character == "9") continue;
    if (character == ",") continue;
    if (character == "-") continue;
    if (character == "a") continue;
    if (character == "b") continue;
    break;
  }
  verseNumber = usfm.substr (0, i);
  verseNumber = filter_string_trim (verseNumber);
  return verseNumber;
}
예제 #7
0
// This function reads the $data for the Bible book abbreviations.
// It then transforms that data into pairs of <book identifier, abbreviation>.
// It returns them as a vector.
vector <pair <int, string> > filter_abbreviations_read (string data)
{
  vector <pair <int, string> > output;
  vector <string> v_data = filter_string_explode (data, '\n');
  for (string & entry : v_data) {
    if (entry.empty ()) continue;
    entry = filter_string_trim (entry);
    vector <string> v_entry = filter_string_explode (entry, '=');
    if (v_entry.size() != 2) continue;
    string sbook = filter_string_trim (v_entry [0]);
    int book = Database_Books::getIdFromEnglish (sbook);
    if (book == 0) continue;
    string abbrev = filter_string_trim (v_entry [1]);
    if (abbrev == "") continue;
    output.push_back (make_pair (book, abbrev));
  }
  return output;
}
예제 #8
0
void Editor_Html2Usfm::flushLine ()
{
  if (!currentLine.empty ()) {
    // Trim so that '\p ' becomes '\p', for example.
    currentLine = filter_string_trim (currentLine);
    output.push_back (currentLine);
    currentLine.clear ();
  }
}
예제 #9
0
// Returns how many emails are waiting in the mail storage host's POP3 email inbox.
int email_receive_count (string& error, bool verbose)
{
#ifdef CLIENT_PREPARED
  error = "Not implemented with embedded http library";
  if (verbose) {}
  return 0;
#else
  CURL *curl;
  CURLcode res = CURLE_OK;

  struct cstring s;
  init_string (&s);

  curl = curl_easy_init ();

  curl_easy_setopt (curl, CURLOPT_USERNAME, Database_Config_General::getMailStorageUsername ().c_str());
  curl_easy_setopt (curl, CURLOPT_PASSWORD, Database_Config_General::getMailStoragePassword ().c_str());

  curl_easy_setopt (curl, CURLOPT_URL, url ().c_str());

  curl_easy_setopt (curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
  curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0); 
  curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0); 

  curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, writefunc);

  curl_easy_setopt (curl, CURLOPT_WRITEDATA, &s);

  if (verbose) {
    curl_easy_setopt (curl, CURLOPT_DEBUGFUNCTION, filter_url_curl_debug_callback);
    curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L);
  }

  // Some servers need this validation.
  curl_easy_setopt (curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");

  filter_url_curl_set_timeout (curl);
  
  res = curl_easy_perform (curl);

  int mailcount = 0;
  
  if (res == CURLE_OK) {
    string response = (char *) s.ptr;
    response = filter_string_trim (response);
    mailcount = filter_string_explode (response, '\n').size();
  } else {
    error = curl_easy_strerror (res);
  }

  if (s.ptr) free (s.ptr);

  curl_easy_cleanup (curl);

  return mailcount;
#endif
}
예제 #10
0
// Gets the human-readable name of a $line like this:
// [CrossWire] *[Shona] (1.1) - Shona Bible
string sword_logic_get_name (string line)
{
  vector <string> bits = filter_string_explode (line, '-');
  if (bits.size () >= 2) {
    bits.erase (bits.begin ());
  }
  line = filter_string_implode (bits, "-");
  line = filter_string_trim (line);
  return line;
}
예제 #11
0
// Gets the module name of the $line like this:
// [Shona]  (1.1)  - Shona Bible
string sword_logic_get_installed_module (string line)
{
  line = filter_string_trim (line);
  if (line.length () > 10) {
    line.erase (0, 1);
    size_t pos = line.find ("]");
    if (pos != string::npos) line.erase (pos);
  }
  return line;
}
예제 #12
0
// This deals with sequences and ranges of verses, like the following:
// Exod. 37:4-5, 14-15, 27-28
// It puts each verse on a separate line.
vector <string> filter_passage_handle_sequences_ranges (const string& passage)
{
  // A passage like Exod. 37:4-5, 14-15, 27-28 will be cut at the comma.
  // The resulting array contains the following:
  // Exod. 37:4-5
  // 14-15
  // 27-28
  // It implies that the first sequence has book and chapter.
  vector <string> sequences = filter_string_explode (passage, ',');
  for (string & line : sequences) line = filter_string_trim (line);


  // Store output lines.
  vector <string> output;

  // Cut the passages at the hyphen.
  for (unsigned int offset = 0; offset < sequences.size(); offset++) {
    string sequence = sequences [offset];
    vector <string> range = filter_string_explode (sequence, '-');
    if (range.size () == 1) {
      output.push_back (filter_string_trim (range [0]));
    } else {
      string start = filter_string_trim (range [0]);
      output.push_back (start);
      if (offset == 0) {
        // Since the first bit contains book / chapter / verse,
        // extract the verse number.
        start = string (start.rbegin(), start.rend());
        start = convert_to_string (convert_to_int (start));
        start = string (start.rbegin(), start.rend());
      }
      unsigned int end = convert_to_int (filter_string_trim (range [1]));
      for (size_t i = convert_to_int (start) + 1; i <= end; i++) {
        output.push_back (convert_to_string (i));
      }
    }
  }

  // Result.
  return output;
}
예제 #13
0
// Return the network port configured for the server.
string config_logic_http_network_port ()
{
  // Read the port number from file.
  string path = filter_url_create_root_path (config_logic_config_folder (), "network-port");
  string port = filter_url_file_get_contents (path);
  // Remove white-space, e.g. a new line, that easily makes its way into the configuration file.
  port = filter_string_trim (port);
  // Default value.
  if (port.empty ()) port = "8080";
  // Done.
  return port;
}
예제 #14
0
파일: load.cpp 프로젝트: alerque/bibledit
string editverse_load (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;
  
  string bible = request->query ["bible"];
  int book = convert_to_int (request->query ["book"]);
  int chapter = convert_to_int (request->query ["chapter"]);
  int verse = convert_to_int (request->query ["verse"]);
  
  string usfm = request->database_bibles()->getChapter (bible, book, chapter);
  usfm = usfm_get_verse_text (usfm, verse);
  
  usfm = filter_string_str_replace ("\n", "<br>", usfm);
  string chapter_verse_text;
  string needle = "\\c";
  if (verse) needle = "\\v";
  size_t pos = usfm.find (needle);
  if (pos != string::npos) {
    if (pos < 2) {
      usfm.erase (0, pos + 2);
      usfm = filter_string_trim (usfm);
      chapter_verse_text = usfm_peek_verse_number (usfm);
      usfm.erase (0, chapter_verse_text.length ());
      usfm = filter_string_trim (usfm);
    }
  }
  usfm.insert (0, "<span contenteditable=\"true\">");
  usfm.append ("</span>");
  if (!chapter_verse_text.empty ()) {
    string spacer;
    if (verse) spacer = " ";
    usfm.insert (0, "<span " + filter_css_grey_background () + ">" + needle + " " + chapter_verse_text + spacer + "</span>");
  }
  
  string user = request->session_logic ()->currentUser ();
  bool write = access_bible_book_write (webserver_request, user, bible, book);
  
  return Checksum_Logic::send (usfm, write);
}
예제 #15
0
void sword_logic_log (string message)
{
  // Remove less comely stuff, warnings, confusing information.
  message = filter_string_str_replace ("-=+*", "", message);
  message = filter_string_str_replace ("WARNING", "", message);
  message = filter_string_str_replace ("*+=-", "", message);
  message = filter_string_str_replace ("enable?", "", message);
  message = filter_string_str_replace ("[no]", "", message);
  // Clean message up.
  message = filter_string_trim (message);
  // Record in the journal.
  Database_Logs::log (message);
}
예제 #16
0
// Gets the version number of a module of the $line like this:
// [Shona]  (1.1)  - Shona Bible
string sword_logic_get_version (string line)
{
  line = filter_string_trim (line);
  if (line.length () > 10) {
    line.erase (0, 3);
  }
  if (line.length () > 10) {
    size_t pos = line.find ("(");
    if (pos != string::npos) line.erase (0, pos + 1);
    pos = line.find (")");
    if (pos != string::npos) line.erase (pos);
  }
  return line;
}
예제 #17
0
string bible_abbreviations (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;
  
  string page;
  
  Assets_Header header = Assets_Header (translate("Abbreviations"), webserver_request);
  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));
  
  // Data submission.
  if (request->post.count ("submit")) {
    string data = request->post ["data"];
    data = filter_string_trim (data);
    if (data != "") {
      if (unicode_string_is_valid (data)) {
        Database_Config_Bible::setBookAbbreviations (bible, data);
        success_message = translate("The abbreviations were saved.");
      } else {
        error_message = translate("Please supply valid Unicode UTF-8 text.");
      }
    } else {
      success_message = translate("Nothing was saved.");
    }
  }

  string data = Database_Config_Bible::getBookAbbreviations (bible);
  data = filter_abbreviations_display (data);
  view.set_variable ("data", data);
  
  view.set_variable ("success_message", success_message);
  view.set_variable ("error_message", error_message);
  
  page += view.render ("bible", "abbreviations");
  
  page += Assets_Page::footer ();
  
  return page;
}
예제 #18
0
// Get installed SWORD modules.
vector <string> sword_logic_get_installed ()
{
  vector <string> modules;
  string out_err;
  string sword_path = sword_logic_get_path ();
  filter_shell_run ("cd " + sword_path + "; installmgr -l", out_err);
  vector <string> lines = filter_string_explode (out_err, '\n');
  for (auto line : lines) {
    line = filter_string_trim (line);
    if (line.empty ()) continue;
    if (line.find ("[") == string::npos) continue;
    modules.push_back (line);
  }
  return modules;
}
예제 #19
0
파일: info.cpp 프로젝트: alerque/bibledit
void export_info (string bible)
{
  // Create folders for the information.
  string directory = filter_url_create_path (Export_Logic::bibleDirectory (bible), "info");
  if (!file_exists (directory)) filter_url_mkdir (directory);
  
  
  // Filenames for the various types of OpenDocument files.
  string informationdFilename = filter_url_create_path (directory, "information.html");
  string falloutFilename = filter_url_create_path (directory, "fallout.html");
  
  
  Database_Bibles database_bibles;
  
  
  string stylesheet = Database_Config_Bible::getExportStylesheet (bible);
  
  
  Filter_Text filter_text = Filter_Text (bible);
  
  
  vector <int> books = database_bibles.getBooks (bible);
  for (auto book : books) {
    vector <int> chapters = database_bibles.getChapters (bible, book);
    for (auto chapter : chapters) {
      string usfm = database_bibles.getChapter (bible, book, chapter);
      usfm = filter_string_trim (usfm);
      // Use small chunks of USFM at a time for much better performance.
      filter_text.addUsfmCode (usfm);
    }
  }
  
  
  // Go through USFM to find the info and fallout.
  filter_text.run (stylesheet);
  
  
  // Save files.
  filter_text.produceInfoDocument (informationdFilename);
  filter_text.produceFalloutDocument (falloutFilename);
  
  
  // Clear the flag for this export.
  Database_State::clearExport (bible, 0, Export_Logic::export_info);

  
  Database_Logs::log (translate("Documents with information and fallout were created") + " " + bible, Filter_Roles::translator ());
}
예제 #20
0
// This returns the filtered value of file userfacingurl.conf.
string config_logic_manual_user_facing_url ()
{
#ifdef HAVE_CLIENT
  return "";
#else
  // Read the configuration file.
  string path = filter_url_create_root_path (config_logic_config_folder (), "userfacingurl.conf");
  string url = filter_url_file_get_contents (path);
  // Remove white space.
  url = filter_string_trim (url);
  // The previous file contained dummy text by default. Remove that.
  if (url.length () <= 6) url.clear ();
  // Ensure it ends with a slash.
  if (url.find_last_of ("/") != url.length () - 1) url.append ("/");
  // Done.
  return url;
#endif
}
예제 #21
0
string public_comment (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;
  Database_Notes database_notes (webserver_request);
  Notes_Logic notes_logic = Notes_Logic (webserver_request);

  
  string page;
  Assets_Header header = Assets_Header (translate("Feedback"), request);
  page += header.run();
  Assets_View view;
  
  
  int id = convert_to_int (request->query ["id"]);
  view.set_variable ("id", convert_to_string (id));
  
  
  if (request->post.count ("submit")) {
    string comment = filter_string_trim (request->post ["comment"]);
    notes_logic.addComment (id, comment);
    redirect_browser (request, public_note_url () + "?id=" + convert_to_string (id));
    return "";
  }
  
  
  if (request->post.count ("cancel")) {
    redirect_browser (request, public_note_url () + "?id=" + convert_to_string (id));
    return "";
  }
  
  
  string summary = database_notes.getSummary (id);
  view.set_variable ("summary", summary);
  
  
  string content = database_notes.getContents (id);
  view.set_variable ("content", content);
  
  
  page += view.render ("public", "comment");
  page += Assets_Page::footer ();
  return page;
}
예제 #22
0
파일: usfm.cpp 프로젝트: alerque/bibledit
// Returns the string $usfm as one long string.
// $usfm may contain new lines, but the resulting long string won't.
string usfm_one_string (string usfm)
{
  string long_string = "";
  vector <string> usfm_lines = filter_string_explode (usfm, '\n');
  for (string & line : usfm_lines) {
    line = filter_string_trim (line);
    // Skip empty line.
    if (line != "") {
      // The line will be appended to the output line.
      // If it does not start with a backslash (\), a space is inserted first.
      size_t pos = line.find ("\\");
      if (pos != 0) {
        if (long_string != "") long_string += " ";
      }
      long_string += line;
    }
  }
  return long_string;
}
예제 #23
0
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));
  }
}
예제 #24
0
파일: usfm.cpp 프로젝트: alerque/bibledit
// Returns the string $code as an array alternating between marker and text.
// Example, input is:   \id GEN
//                      \c 10
//             ...
// Output would be:     array ("\id ", "GEN", "\c ", "10", ...)
// If $code does not start with a marker, this becomes visible in the output too.
vector <string> usfm_get_markers_and_text (string code)
{
  vector <string> markers_and_text;
  code = filter_string_str_replace ("\n\\", "\\", code); // New line followed by backslash: leave new line out.
  code = filter_string_str_replace ("\n", " ", code); // New line only: change to space, according to the USFM specification.
  // No removal of double spaces, because it would remove an opening marker (which already has its own space), followed by a space.
  code = filter_string_trim (code);
  while (!code.empty ()) {
    size_t pos = code.find ("\\");
    if (pos == 0) {
      // Marker found.
      // The marker ends
      // - after the first space, or
      // - after the first asterisk (*), or
      // - at the first backslash (\), or
      // - at the end of the string,
      // whichever comes first.
      vector <size_t> positions;
      pos = code.find (" ");
      if (pos != string::npos) positions.push_back (pos + 1);
      pos = code.find ("*");
      if (pos != string::npos) positions.push_back (pos + 1);
      pos = code.find ("\\", 1);
      if (pos != string::npos) positions.push_back (pos);
      positions.push_back (code.length());
      sort (positions.begin (), positions.end());
      pos = positions[0];
      string marker = code.substr (0, pos);
      markers_and_text.push_back (marker);
      code = code.substr (pos);
    } else {
      // Text found. It ends at the next backslash or at the end of the string.
      pos = code.find ("\\");
      if (pos == string::npos) pos = code.length();
      string text = code.substr (0, pos);
      markers_and_text.push_back (text);
      code = code.substr (pos);
    }
  }
  return markers_and_text;
}
예제 #25
0
// Import data.
void Database_Versifications::input (const string& contents, const string& name)
{
  // Delete old system if it is there, and create new one.
  erase (name);
  int id = createSystem (name);

  sqlite3 * db = connect ();
  database_sqlite_exec (db, "PRAGMA temp_store = MEMORY;");
  database_sqlite_exec (db, "PRAGMA synchronous = OFF;");
  database_sqlite_exec (db, "PRAGMA journal_mode = OFF;");
  database_sqlite_exec (db, "BEGIN;");
  
  vector <string> lines = filter_string_explode (contents, '\n');
  for (auto line : lines) {
    line = filter_string_trim (line);
    if (line.empty ()) continue;
    Passage passage = filter_passage_explode_passage (line);
    if ((passage.book == 0)
     || (passage.chapter == 0)
     || (passage.verse.empty ())) {
      Database_Logs::log ("Malformed versification entry: " + line);
      continue;
    }
    SqliteSQL sql = SqliteSQL ();
    sql.add ("INSERT INTO data (system, book, chapter, verse) VALUES (");
    sql.add (id);
    sql.add (",");
    sql.add (passage.book);
    sql.add (",");
    sql.add (passage.chapter);
    sql.add (",");
    sql.add (convert_to_int (passage.verse));
    sql.add (");");
    database_sqlite_exec (db, sql.sql);
  }
  
  database_sqlite_exec (db, "COMMIT;");
  database_sqlite_disconnect (db);
}
예제 #26
0
// This function takes the html from an editor that edits one verse,
// and converts it to USFM.
// It properly deals with cases when a verse does not start a new paragraph.
string editor_export_verse (string stylesheet, string html)
{
  // When the $html starts with a paragraph without a style,
  // put a recognizable style there.
  string style = "oneversestyle";
  size_t pos = html.find ("<p>");
  if (pos == 0) {
    html.insert (2, " class=\"" + style + "\"");
  }

  // Convert html to USFM.
  Editor_Html2Usfm editor_export;
  editor_export.load (html);
  editor_export.stylesheet (stylesheet);
  editor_export.run ();
  string usfm = editor_export.get ();

  // Remove that recognizable style converted to USFM.
  usfm = filter_string_str_replace ("\\" + style, "", usfm);
  usfm = filter_string_trim (usfm);
  
  return usfm;
}
예제 #27
0
파일: logic.cpp 프로젝트: alerque/bibledit
// 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.
bool Notes_Logic::handleEmailNew (string from, string subject, string body)
{
  // Webserver request.
  Webserver_Request * request = (Webserver_Request *) webserver_request;
  // Store the original subject.
  string originalSubject = subject;
  // Check that the subject indicates that a new consultation note is to be created.
  size_t pos = unicode_string_casefold (subject).find ("new note");
  if (pos == string::npos) return false;
  // There is a new note. Remove that bit from the subject.
  if (pos > 0) subject.erase (0, pos + 8);
  // Clean the subject line.
  subject = filter_string_trim (subject);
  subject = filter_string_str_replace (".", " ", subject);
  subject = filter_string_str_replace (":", " ", subject);
  subject = filter_string_str_replace ("   ", " ", subject);
  subject = filter_string_str_replace ("  ", " ", subject);
  // Check that the from address of the email belongs to an existing user.
  from = filter_string_extract_email (from);
  if (!request->database_users()->emailExists (from)) return false;
  string username = request->database_users()->getEmailToUser (from);
  // Extract book, chapter, verse, and note summary from the subject
  int book = -1;
  int chapter = -1;
  int verse = -1;
  string summary;
  vector <string> subjectlines = filter_string_explode (subject, ' ');
  if (!subjectlines.empty()) {
    book = filter_passage_interpret_book (subjectlines[0]);
    subjectlines.erase (subjectlines.begin());
  }
  if (!subjectlines.empty()) {
    chapter = convert_to_int (subjectlines[0]);
    subjectlines.erase (subjectlines.begin());
  }
  if (!subjectlines.empty()) {
    verse = convert_to_int (subjectlines[0]);
    subjectlines.erase (subjectlines.begin());
  }
  summary = filter_string_implode (subjectlines, " ");
  // Check book, chapter, verse, and summary. Give feedback if there's anything wrong.
  string noteCheck;
  if (book <= 0) noteCheck.append (translate("Unknown book"));
  if (chapter < 0) {
    noteCheck.append (" ");
    noteCheck.append (translate("Unknown chapter"));
  }
  if (verse < 0) {
    noteCheck.append (" ");
    noteCheck.append (translate("Unknown verse"));
  }
  if (summary.empty ()) {
    noteCheck.append (" ");
    noteCheck.append (translate("Unknown summary"));
  }
  // Mail user if the note could not be posted.
  Database_Mail database_mail = Database_Mail (webserver_request);
  if (noteCheck != "") {
    subject = translate("Your new note could not be posted");
    database_mail.send (username, subject  + ": " + originalSubject, noteCheck);
    return false;
  }
  // Clean the email's body.
  body = filter_string_extract_body (body);
  // Post the note.
  string sessionuser = request->session_logic()->currentUser ();
  request->session_logic()->setUsername (username);
  Database_Notes database_notes = Database_Notes(webserver_request);
  string bible = request->database_config_user()->getBible ();
  int identifier = database_notes.storeNewNote (bible, book, chapter, verse, summary, body, false);
  handlerNewNote (identifier);
  request->session_logic()->setUsername (sessionuser);
  // Mail confirmation to the username.
  if (request->database_config_user()->getUserNotifyMeOfMyPosts (username)) {
    subject = translate("Your new note was posted");
    database_mail.send (username, subject + ": " + originalSubject, body);
  }
  // Log operation.
  Database_Logs::log ("New note posted : " + body);
  // Job done.
  return true;
}
예제 #28
0
string styles_indexm (void * webserver_request)
{
  Webserver_Request * request = (Webserver_Request *) webserver_request;
  
  string page;
  
  Assets_Header header = Assets_Header (translate("Styles"), webserver_request);
  header.addBreadCrumb (menu_logic_settings_menu (), menu_logic_settings_text ());
  header.addBreadCrumb (menu_logic_settings_styles_menu (), menu_logic_styles_text ());
  page = header.run ();
  
  Assets_View view;
  
  Database_Styles database_styles;
  
  string username = request->session_logic ()->currentUser ();
  int userlevel = request->session_logic ()->currentLevel ();
  
  if (request->post.count ("new")) {
    string name = request->post["entry"];
    // Remove spaces at the ends of the name for the new stylesheet.
    // Because predictive keyboards can add a space to the name,
    // and the stylesheet system is not built for whitespace at the start / end of the name of the stylesheet.
    name = filter_string_trim (name);
    vector <string> existing = database_styles.getSheets ();
    if (find (existing.begin(), existing.end (), name) != existing.end ()) {
      page += Assets_Page::error (translate("This stylesheet already exists"));
    } else {
      database_styles.createSheet (name);
      database_styles.grantWriteAccess (username, name);
      styles_sheets_create_all ();
      page += Assets_Page::success (translate("The stylesheet has been created"));
    }
  }
  if (request->query.count ("new")) {
    Dialog_Entry dialog_entry = Dialog_Entry ("indexm", translate("Please enter the name for the new stylesheet"), "", "new", "");
    page += dialog_entry.run();
    return page;
  }
  
  if (request->query.count ("delete")) {
    string del = request->query ["delete"];
    if (del != "") {
      string confirm = request->query ["confirm"];
      if (confirm == "yes") {
        bool write = database_styles.hasWriteAccess (username, del);
        if (userlevel >= Filter_Roles::admin ()) write = true;
        if (write) {
          database_styles.deleteSheet (del);
          database_styles.revokeWriteAccess ("", del);
          page += Assets_Page::success (translate("The stylesheet has been deleted"));
        }
      } if (confirm == "") {
        Dialog_Yes dialog_yes = Dialog_Yes ("indexm", translate("Would you like to delete this stylesheet?"));
        dialog_yes.add_query ("delete", del);
        page += dialog_yes.run ();
        return page;
      }
    }
  
  }
  // Delete empty sheet that may have been there.
  database_styles.deleteSheet ("");

  vector <string> sheets = database_styles.getSheets();
  vector <string> sheetblock;
  for (auto & sheet : sheets) {
    sheetblock.push_back ("<p>");
    sheetblock.push_back (sheet);
    bool editable = database_styles.hasWriteAccess (username, sheet);
    if (userlevel >= Filter_Roles::admin ()) editable = true;
    // Cannot edit the Standard stylesheet.
    if (sheet == styles_logic_standard_sheet ()) editable = false;
    if (editable) {
      sheetblock.push_back ("<a href=\"sheetm?name=" + sheet + "\">[" + translate("edit") + "]</a>");
    }
    sheetblock.push_back ("</p>");
  }
  
  view.set_variable ("sheetblock", filter_string_implode (sheetblock, "\n"));

  page += view.render ("styles", "indexm");
  
  page += Assets_Page::footer ();
  
  return page;
}
예제 #29
0
void export_bibledropbox (string user, string bible)
{
  Webserver_Request request;
  Database_Bibles database_bibles;
  Database_Users database_users;
  Database_Mail database_mail = Database_Mail (&request);

  
  string tag = translate ("Submit to the Bible Drop Box") + ": ";
  Database_Logs::log (tag + bible, Filter_Roles::translator ());

  
  // Temporal USFM directory.
  string directory = filter_url_tempfile ();
  filter_url_mkdir (directory);
  

  // Take the USFM from the Bible database.
  // Generate one USFM file per book.
  vector <int> books = database_bibles.getBooks (bible);
  for (auto book : books) {
    
    
    // The USFM data of the current book.
    string bookdata;
    
    
    // Collect the USFM for all chapters in this book.
    vector <int> chapters = database_bibles.getChapters (bible, book);
    for (auto chapter : chapters) {
      // Get the USFM code for the current chapter.
      string usfm = database_bibles.getChapter (bible, book, chapter);
      usfm = filter_string_trim (usfm);
      // Add the chapter USFM code to the book's USFM code.
      bookdata.append (usfm);
      bookdata.append ("\n");
    }
    
    
    // The filename for the USFM for this book.
    string filename = Export_Logic::baseBookFileName (book);
    string path = filter_url_create_path (directory, filename + ".usfm");
    
    
    // Save.
    filter_url_file_put_contents (path, bookdata);
  }
  
  
  // Compress USFM files into one zip file.
  string zipfile = filter_url_create_path (directory, Export_Logic::baseBookFileName (0) + ".zip");
  
  string archive = filter_archive_zip_folder (directory);
  filter_url_rename (archive, zipfile);
  
  /*
  <form action="SubmitAction.phtml" method="post" enctype="multipart/form-data">
  <p>Your name: <input type="text" name="nameLine" size="40" /> </p>
  <p>Your email address: <input type="text" name="emailLine" size="50" /></p>
  <p>Language/Project name: <input type="text" name="projectLine" size="35" /></p>
  <p>I have the authority to submit this data: <input type="checkbox" name="permission" value="Yes">
  What is your main goal here (optional): <input type="text" name="goalLine" size="80" />
  <input type="checkbox" name="photoBible" value="Yes">
  OpenDocument <input type="checkbox" name="odfs" value="Yes">
  PDF <input type="checkbox" name="pdfs" value="Yes">
  Zip file containing your Bible file(s) <input type="file" name="uploadedZipFile" size="50" />
  <input type="hidden" name="MAX_FILE_SIZE" value="5000000" />
  <input type="file" name="uploadedMetadataFile" size="50" />
  <input type="submit" name="submit" value="Submit" />
  </form>
  */
  
  
  // Bible Drop Box submission URL.
  string url = "http://freely-given.org/Software/BibleDropBox/SubmitAction.phtml";
  
  
  // Form values to POST.
  map <string, string> post;
  post ["nameLine"] = user;
  post ["emailLine"] = database_users.getUserToEmail (user);
  post ["projectLine"] = bible;
  post ["permission"] = "Yes";
  post ["goalLine"] = "Bible translation through Bibledit";
  // Just one request: Is it possible to make the Bibledit submission system default to turning off the three check-boxes for the tasks that take heavy processing on The Bible Drop Box: PhotoBible, ODFs using the Python interface to LibreOffice (which is slow compared to the Pathway method of creating the XML files directly), and PDF exports (via TeX). If the user is only after, say a Sword module, it's quite a heavy cost to wastefully produce these other exports.
  //post ["photoBible"] = "Yes";
  //post ["odfs"] = "Yes";
  //post ["pdfs"] = "Yes";
  post ["submit"] = "Submit";
  
  // Submission and response.
  string error;
  string response = filter_url_http_upload (url, post, zipfile, error);
  if (!error.empty ()) {
    Database_Logs::log (tag + error, Filter_Roles::translator ());
    database_mail.send (user, "Error submitting to the Bible Drop Box", error);
  }
  size_t pos = response.find ("<head>");
  if (pos != string::npos) {
    response.insert (pos + 6, "<base href=\"http://freely-given.org/Software/BibleDropBox/\">");
  }
  database_mail.send (user, "Result of your submission to the Bible Drop Box", response);

  
  // Done.
  Database_Logs::log (tag + translate("Ready"), Filter_Roles::translator ());
}
예제 #30
0
파일: save.cpp 프로젝트: alerque/bibledit
string editusfm_save (void * webserver_request)
{
    Webserver_Request * request = (Webserver_Request *) webserver_request;


    string bible = request->post["bible"];
    int book = convert_to_int (request->post["book"]);
    int chapter = convert_to_int (request->post["chapter"]);
    string usfm = request->post["usfm"];
    string checksum = request->post["checksum"];


    if (request->post.count ("bible") && request->post.count ("book") && request->post.count ("chapter") && request->post.count ("usfm")) {
        if (Checksum_Logic::get (usfm) == checksum) {
            usfm = filter_url_tag_to_plus (usfm);
            usfm = filter_string_trim (usfm);
            if (usfm != "") {
                if (unicode_string_is_valid (usfm)) {
                    string stylesheet = request->database_config_user()->getStylesheet();
                    vector <BookChapterData> book_chapter_text = usfm_import (usfm, stylesheet);
                    for (BookChapterData & data : book_chapter_text) {
                        int book_number = data.book;
                        int chapter_number = data.chapter;
                        string chapter_data_to_save = data.data;
                        if (((book_number == book) || (book_number == 0)) && (chapter_number == chapter)) {
                            string ancestor_usfm = getLoadedUsfm (webserver_request, bible, book, chapter, "editusfm");
                            // Collect some data about the changes for this user.
                            string username = request->session_logic()->currentUser ();
                            int oldID = request->database_bibles()->getChapterId (bible, book, chapter);
                            string oldText = ancestor_usfm;
                            string newText = chapter_data_to_save;
                            // Merge if the ancestor is there and differs from what's in the database.
                            if (!ancestor_usfm.empty ()) {
                                string server_usfm = request->database_bibles ()->getChapter (bible, book, chapter);
                                if (server_usfm != ancestor_usfm) {
                                    // Prioritize the USFM to save.
                                    chapter_data_to_save = filter_merge_run (ancestor_usfm, server_usfm, chapter_data_to_save);
                                    Database_Logs::log (translate ("Merging and saving chapter."));
                                }
                            }
                            // Check on write access.
                            if (access_bible_book_write (request, "", bible, book)) {
                                // Safely store the chapter.
                                string message = usfm_safely_store_chapter (request, bible, book, chapter, chapter_data_to_save);
                                if (message.empty()) {
#ifndef CLIENT_PREPARED
                                    // Server configuration: Store details for the user's changes.
                                    int newID = request->database_bibles()->getChapterId (bible, book, chapter);
                                    Database_Modifications database_modifications;
                                    database_modifications.recordUserSave (username, bible, book, chapter, oldID, oldText, newID, newText);
                                    Database_Git::store_chapter (username, bible, book, chapter, oldText, newText);
#endif
                                    // Store a copy of the USFM loaded in the editor for later reference.
                                    storeLoadedUsfm (webserver_request, bible, book, chapter, "editusfm");
                                    return locale_logic_text_saved ();
                                }
                                return message;
                            } else {
                                return translate("No write access");
                            }
                        } else {
                            Database_Logs::log ("The following data could not be saved and was discarded: " + chapter_data_to_save);
                            return translate("Passage mismatch");
                        }
                    }
                } else {
                    Database_Logs::log ("The text was not valid Unicode UTF-8. The chapter could not saved and has been reverted to the last good version.");
                    return translate("Needs Unicode");
                }
            } else {
                Database_Logs::log ("There was no text. Nothing was saved. The original text of the chapter was reloaded.");
                return translate("Nothing to save");
            }
        } else {
            request->response_code = 409;
            return translate("Checksum error");
        }
    } else {
        return translate("Nothing to save");
    }
    return translate ("Confusing data");
}