The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
swmgr.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * swmgr.cpp - used to interact with an install base of sword modules
4  *
5  * $Id: swmgr.cpp 3822 2020-11-03 18:54:47Z scribe $
6  *
7  * Copyright 1998-2014 CrossWire Bible Society (http://www.crosswire.org)
8  * CrossWire Bible Society
9  * P. O. Box 2528
10  * Tempe, AZ 85280-2528
11  *
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by the
14  * Free Software Foundation version 2.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <fcntl.h>
26 
27 #include <sys/stat.h>
28 #ifndef _MSC_VER
29 #include <iostream>
30 #endif
31 #include <dirent.h>
32 
33 #include <swmgr.h>
34 #include <rawtext.h>
35 #include <rawtext4.h>
36 #include <filemgr.h>
37 #include <rawgenbook.h>
38 #include <rawcom.h>
39 #include <rawcom4.h>
40 #include <hrefcom.h>
41 #include <rawld.h>
42 #include <rawld4.h>
43 #include <utilstr.h>
44 #include <gbfplain.h>
45 #include <thmlplain.h>
46 #include <osisplain.h>
47 #include <teiplain.h>
48 #include <papyriplain.h>
49 #include <gbfstrongs.h>
50 #include <gbffootnotes.h>
51 #include <gbfheadings.h>
52 #include <gbfredletterwords.h>
53 #include <gbfmorph.h>
54 #include <osisenum.h>
55 #include <osisglosses.h>
56 #include <osisheadings.h>
57 #include <osisfootnotes.h>
58 #include <osisstrongs.h>
59 #include <osismorph.h>
60 #include <osislemma.h>
61 #include <osisredletterwords.h>
62 #include <osismorphsegmentation.h>
63 #include <osisscripref.h>
64 #include <osisvariants.h>
65 #include <osisxlit.h>
66 #include <osisreferencelinks.h>
67 #include <thmlstrongs.h>
68 #include <thmlfootnotes.h>
69 #include <thmlheadings.h>
70 #include <thmlmorph.h>
71 #include <thmlvariants.h>
72 #include <thmllemma.h>
73 #include <thmlscripref.h>
74 #include <cipherfil.h>
75 #include <rawfiles.h>
76 #include <ztext.h>
77 #include <ztext4.h>
78 #include <zld.h>
79 #include <zcom.h>
80 #include <zcom4.h>
81 #include <lzsscomprs.h>
82 #include <utf8greekaccents.h>
83 #include <utf8cantillation.h>
84 #include <utf8hebrewpoints.h>
85 #include <utf8arabicpoints.h>
86 #include <greeklexattribs.h>
87 #include <swfiltermgr.h>
88 #include <swcipher.h>
89 #include <swoptfilter.h>
90 #include <rtfhtml.h>
91 
92 #include <swlog.h>
93 
94 #include <iterator>
95 
96 #ifndef EXCLUDEZLIB
97 #include "zipcomprs.h"
98 #endif
99 #ifndef EXCLUDEBZIP2
100 #include "bz2comprs.h"
101 #endif
102 #ifndef EXCLUDEXZ
103 #include "xzcomprs.h"
104 #endif
105 
106 
107 #ifdef _ICU_
108 #include <utf8transliterator.h>
109 #endif
110 
111 
113 
114 
115 #ifdef _ICU_
116 bool SWMgr::isICU = true;
117 #else
118 bool SWMgr::isICU = false;
119 #endif
120 
121 
122 #ifdef GLOBCONFPATH
123 const char *SWMgr::globalConfPath = GLOBCONFPATH;
124 #else
125 const char *SWMgr::globalConfPath = "/etc/sword.conf:/usr/local/etc/sword.conf";
126 #endif
127 
128 
129 const char *SWMgr::MODTYPE_BIBLES = "Biblical Texts";
130 const char *SWMgr::MODTYPE_COMMENTARIES = "Commentaries";
131 const char *SWMgr::MODTYPE_LEXDICTS = "Lexicons / Dictionaries";
132 const char *SWMgr::MODTYPE_GENBOOKS = "Generic Books";
133 const char *SWMgr::MODTYPE_DAILYDEVOS = "Daily Devotional";
134 
135 namespace {
136  void setSystemLogLevel(SWConfig *sysConf, const char *logLevel = 0) {
137  SWBuf logLevelString = logLevel;
138  // kindof cheese. we should probably pass this in.
139  SWBuf logLocation = (sysConf ? "[SWORD] section of sword.conf" : "SWORD_LOGLEVEL");
140  if (sysConf) {
141  ConfigEntMap::iterator entry;
142  if ((entry = sysConf->getSection("SWORD").find("LogLevel")) != sysConf->getSection("SWORD").end()) {
143  logLevelString = entry->second;
144  }
145  }
146  if (logLevelString.length()) {
147  int logLevel =
148  logLevelString == "ERROR" ? SWLog::LOG_ERROR:
149  logLevelString == "WARN" ? SWLog::LOG_WARN:
150  logLevelString == "INFO" ? SWLog::LOG_INFO:
151  logLevelString == "TIMEDINFO" ? SWLog::LOG_TIMEDINFO:
152  logLevelString == "DEBUG" ? SWLog::LOG_DEBUG:
153  -1;
154  if (logLevel < 0) SWLog::getSystemLog()->logError("Invalid LogLevel found in %s: LogLevel: %s", logLocation.c_str(), logLevelString.c_str());
155  else {
156  SWLog::getSystemLog()->setLogLevel(logLevel);
157  SWLOGTI("Setting log level from %s to %s", logLocation.c_str(), logLevelString.c_str());
158  }
159  }
160  }
161 }
162 
163 void SWMgr::init() {
164  SWOptionFilter *tmpFilter = 0;
165  configPath = 0;
166  prefixPath = 0;
167  configType = 0;
168  myconfig = 0;
169  mysysconfig = 0;
170  homeConfig = 0;
171  augmentHome = true;
172 
173  cipherFilters.clear();
174  optionFilters.clear();
175  cleanupFilters.clear();
176  extraFilters.clear();
177  tmpFilter = new ThMLVariants();
178  optionFilters.insert(OptionFilterMap::value_type("ThMLVariants", tmpFilter));
179  cleanupFilters.push_back(tmpFilter);
180 
181  tmpFilter = new GBFStrongs();
182  optionFilters.insert(OptionFilterMap::value_type("GBFStrongs", tmpFilter));
183  cleanupFilters.push_back(tmpFilter);
184 
185  tmpFilter = new GBFFootnotes();
186  optionFilters.insert(OptionFilterMap::value_type("GBFFootnotes", tmpFilter));
187  cleanupFilters.push_back(tmpFilter);
188 
189  tmpFilter = new GBFRedLetterWords();
190  optionFilters.insert(OptionFilterMap::value_type("GBFRedLetterWords", tmpFilter));
191  cleanupFilters.push_back(tmpFilter);
192 
193  tmpFilter = new GBFMorph();
194  optionFilters.insert(OptionFilterMap::value_type("GBFMorph", tmpFilter));
195  cleanupFilters.push_back(tmpFilter);
196 
197  tmpFilter = new GBFHeadings();
198  optionFilters.insert(OptionFilterMap::value_type("GBFHeadings", tmpFilter));
199  cleanupFilters.push_back(tmpFilter);
200 
201  tmpFilter = new OSISHeadings();
202  optionFilters.insert(OptionFilterMap::value_type("OSISHeadings", tmpFilter));
203  cleanupFilters.push_back(tmpFilter);
204 
205  tmpFilter = new OSISStrongs();
206  optionFilters.insert(OptionFilterMap::value_type("OSISStrongs", tmpFilter));
207  cleanupFilters.push_back(tmpFilter);
208 
209  tmpFilter = new OSISMorph();
210  optionFilters.insert(OptionFilterMap::value_type("OSISMorph", tmpFilter));
211  cleanupFilters.push_back(tmpFilter);
212 
213  tmpFilter = new OSISLemma();
214  optionFilters.insert(OptionFilterMap::value_type("OSISLemma", tmpFilter));
215  cleanupFilters.push_back(tmpFilter);
216 
217  tmpFilter = new OSISFootnotes();
218  optionFilters.insert(OptionFilterMap::value_type("OSISFootnotes", tmpFilter));
219  cleanupFilters.push_back(tmpFilter);
220 
221  tmpFilter = new OSISScripref();
222  optionFilters.insert(OptionFilterMap::value_type("OSISScripref", tmpFilter));
223  cleanupFilters.push_back(tmpFilter);
224 
225  tmpFilter = new OSISRedLetterWords();
226  optionFilters.insert(OptionFilterMap::value_type("OSISRedLetterWords", tmpFilter));
227  cleanupFilters.push_back(tmpFilter);
228 
229  tmpFilter = new OSISMorphSegmentation();
230  optionFilters.insert(OptionFilterMap::value_type("OSISMorphSegmentation", tmpFilter));
231  cleanupFilters.push_back(tmpFilter);
232 
233  tmpFilter = new OSISGlosses();
234  optionFilters.insert(OptionFilterMap::value_type("OSISGlosses", tmpFilter));
235  optionFilters.insert(OptionFilterMap::value_type("OSISRuby", tmpFilter));
236  cleanupFilters.push_back(tmpFilter);
237 
238  tmpFilter = new OSISXlit();
239  optionFilters.insert(OptionFilterMap::value_type("OSISXlit", tmpFilter));
240  cleanupFilters.push_back(tmpFilter);
241 
242  tmpFilter = new OSISEnum();
243  optionFilters.insert(OptionFilterMap::value_type("OSISEnum", tmpFilter));
244  cleanupFilters.push_back(tmpFilter);
245 
246  tmpFilter = new OSISVariants();
247  optionFilters.insert(OptionFilterMap::value_type("OSISVariants", tmpFilter));
248  cleanupFilters.push_back(tmpFilter);
249 
250  tmpFilter = new ThMLStrongs();
251  optionFilters.insert(OptionFilterMap::value_type("ThMLStrongs", tmpFilter));
252  cleanupFilters.push_back(tmpFilter);
253 
254  tmpFilter = new ThMLFootnotes();
255  optionFilters.insert(OptionFilterMap::value_type("ThMLFootnotes", tmpFilter));
256  cleanupFilters.push_back(tmpFilter);
257 
258  tmpFilter = new ThMLMorph();
259  optionFilters.insert(OptionFilterMap::value_type("ThMLMorph", tmpFilter));
260  cleanupFilters.push_back(tmpFilter);
261 
262  tmpFilter = new ThMLHeadings();
263  optionFilters.insert(OptionFilterMap::value_type("ThMLHeadings", tmpFilter));
264  cleanupFilters.push_back(tmpFilter);
265 
266  tmpFilter = new ThMLLemma();
267  optionFilters.insert(OptionFilterMap::value_type("ThMLLemma", tmpFilter));
268  cleanupFilters.push_back(tmpFilter);
269 
270  tmpFilter = new ThMLScripref();
271  optionFilters.insert(OptionFilterMap::value_type("ThMLScripref", tmpFilter));
272  cleanupFilters.push_back(tmpFilter);
273 
274  tmpFilter = new UTF8GreekAccents();
275  optionFilters.insert(OptionFilterMap::value_type("UTF8GreekAccents", tmpFilter));
276  cleanupFilters.push_back(tmpFilter);
277 
278  tmpFilter = new UTF8HebrewPoints();
279  optionFilters.insert(OptionFilterMap::value_type("UTF8HebrewPoints", tmpFilter));
280  cleanupFilters.push_back(tmpFilter);
281 
282  tmpFilter = new UTF8ArabicPoints();
283  optionFilters.insert(OptionFilterMap::value_type("UTF8ArabicPoints", tmpFilter));
284  cleanupFilters.push_back(tmpFilter);
285 
286  tmpFilter = new UTF8Cantillation();
287  optionFilters.insert(OptionFilterMap::value_type("UTF8Cantillation", tmpFilter));
288  cleanupFilters.push_back(tmpFilter);
289 
290  tmpFilter = new GreekLexAttribs();
291  optionFilters.insert(OptionFilterMap::value_type("GreekLexAttribs", tmpFilter));
292  cleanupFilters.push_back(tmpFilter);
293 
294  tmpFilter = new PapyriPlain();
295  optionFilters.insert(OptionFilterMap::value_type("PapyriPlain", tmpFilter));
296  cleanupFilters.push_back(tmpFilter);
297 
298 // UTF8Transliterator needs to be handled differently because it should always available as an option, for all modules
299 #ifdef _ICU_
301  optionFilters.insert(OptionFilterMap::value_type("UTF8Transliterator", transliterator));
302  options.push_back(transliterator->getOptionName());
303  cleanupFilters.push_back(transliterator);
304 #endif
305 
306  gbfplain = new GBFPlain();
307  cleanupFilters.push_back(gbfplain);
308  extraFilters.insert(FilterMap::value_type("GBFPlain", gbfplain));
309 
310  thmlplain = new ThMLPlain();
311  cleanupFilters.push_back(thmlplain);
312  extraFilters.insert(FilterMap::value_type("ThMLPlain", thmlplain));
313 
314  osisplain = new OSISPlain();
315  cleanupFilters.push_back(osisplain);
316  extraFilters.insert(FilterMap::value_type("OSISPlain", osisplain));
317 
318  teiplain = new TEIPlain();
319  cleanupFilters.push_back(teiplain);
320  extraFilters.insert(FilterMap::value_type("TEIPlain", teiplain));
321 
322  // filters which aren't really used anywhere but which we want available for a "FilterName" -> filter mapping (e.g., filterText)
323  SWFilter *f = new RTFHTML();
324  extraFilters.insert(FilterMap::value_type("RTFHTML", f));
325  cleanupFilters.push_back(f);
326 
327 }
328 
329 
330 // TODO: because we're still calling deprecated virtual Load. Removed in 2.0
331 #if defined(__GNUC__)
332 #pragma GCC diagnostic push
333 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
334 #endif
335 void SWMgr::commonInit(SWConfig *iconfig, SWConfig *isysconfig, bool autoload, SWFilterMgr *filterMgr, bool multiMod) {
336 
337  init();
338 
339  mgrModeMultiMod = multiMod;
340  this->filterMgr = filterMgr;
341  if (filterMgr)
342  filterMgr->setParentMgr(this);
343 
344  if (iconfig) {
345  config = iconfig;
346  myconfig = 0;
347  }
348  else config = 0;
349  if (isysconfig) {
350  sysConfig = isysconfig;
351  mysysconfig = 0;
352  }
353  else sysConfig = 0;
354 
355  if (autoload)
356  Load();
357 }
358 #if defined(__GNUC__)
359 #pragma GCC diagnostic pop
360 #endif
361 
362 
363 SWMgr::SWMgr(SWFilterMgr *filterMgr, bool multiMod) {
364  commonInit(0, 0, true, filterMgr, multiMod);
365 }
366 
367 
368 SWMgr::SWMgr(SWConfig *iconfig, SWConfig *isysconfig, bool autoload, SWFilterMgr *filterMgr, bool multiMod) {
369  commonInit(iconfig, isysconfig, autoload, filterMgr, multiMod);
370 }
371 
372 
373 #if defined(__GNUC__)
374 #pragma GCC diagnostic push
375 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
376 #endif
377 SWMgr::SWMgr(const char *iConfigPath, bool autoload, SWFilterMgr *filterMgr, bool multiMod, bool augmentHome) {
378 
379  init();
380 
381  mgrModeMultiMod = multiMod;
382  SWBuf path;
383 
384  this->filterMgr = filterMgr;
385  if (filterMgr)
386  filterMgr->setParentMgr(this);
387 
388  this->augmentHome = augmentHome;
389 
390  path = iConfigPath;
391  int len = (int)path.length();
392  if ((len < 1) || ((iConfigPath[len-1] != '\\') && (iConfigPath[len-1] != '/')))
393  path += "/";
394  SWLOGTI("Checking at provided path: %s...", path.c_str());
395  if (FileMgr::existsFile(path.c_str(), "mods.conf")) {
396  stdstr(&prefixPath, path.c_str());
397  path += "mods.conf";
398  stdstr(&configPath, path.c_str());
399  }
400  else if (FileMgr::existsDir(path.c_str(), "mods.d")) {
401  SWLOGTI("Found mods.d/");
402  stdstr(&prefixPath, path.c_str());
403  path += "mods.d";
404  stdstr(&configPath, path.c_str());
405  configType = 1;
406  }
407  else {
408  SWLOGTI("Config not found at provided path.");
409  }
410 
411  config = 0;
412  sysConfig = 0;
413 
414  if (autoload && configPath)
415  Load();
416 }
417 #if defined(__GNUC__)
418 #pragma GCC diagnostic pop
419 #endif
420 
421 
423 
425 
426  for (FilterList::iterator it = cleanupFilters.begin(); it != cleanupFilters.end(); it++)
427  delete (*it);
428 
429  if (homeConfig)
430  delete homeConfig;
431 
432  if (mysysconfig)
433  delete mysysconfig;
434 
435  if (myconfig)
436  delete myconfig;
437 
438  if (prefixPath)
439  delete [] prefixPath;
440 
441  if (configPath)
442  delete [] configPath;
443 
444  if (filterMgr)
445  delete filterMgr;
446 }
447 
448 
449 void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, std::list<SWBuf> *augPaths, SWConfig **providedSysConf) {
450  static bool setLogLevel = false;
451  SWBuf path;
452  SWBuf sysConfPath;
453  ConfigEntMap::iterator entry;
454  ConfigEntMap::iterator lastEntry;
455 
456  if (!setLogLevel) {
457  SWBuf envLogLevel = FileMgr::getEnvValue("SWORD_LOGLEVEL");
458  if (envLogLevel.length()) {
459  setSystemLogLevel(0, envLogLevel);
460  setLogLevel = true;
461  }
462  }
463 
464  SWConfig *sysConf = 0;
465  SWBuf sysConfDataPath = "";
466 
467  *configType = 0;
468 
470 
471  // check for a sysConf passed in to us
472  SWLOGTI("Checking for provided SWConfig(\"sword.conf\")...");
473  if (providedSysConf && *providedSysConf) {
474  sysConf = *providedSysConf;
475  SWLOGTI("found.");
476  if (!setLogLevel) { setSystemLogLevel(sysConf); setLogLevel = true; }
477  }
478 
479  // if we haven't been given our datapath in a sysconf, we need to track it down
480  if (!sysConf) {
481  // check working directory
482  SWLOGTI("Checking working directory for sword.conf...");
483  if (FileMgr::existsFile(".", "sword.conf")) {
484  SWLOGTI("Overriding any systemwide or ~/.sword/ sword.conf with one found in current directory.");
485  sysConfPath = "./sword.conf";
486  sysConf = new SWConfig(sysConfPath);
487  if ((entry = sysConf->getSection("Install").find("DataPath")) != sysConf->getSection("Install").end()) {
488  sysConfDataPath = (*entry).second;
489  }
490  if (!setLogLevel) { setSystemLogLevel(sysConf); setLogLevel = true; }
491  if (providedSysConf) {
492  *providedSysConf = sysConf;
493  }
494  else {
495  delete sysConf;
496  sysConf = 0;
497  }
498  }
499  if (!sysConfDataPath.size()) {
500  SWLOGTI("Checking working directory for mods.conf...");
501  if (FileMgr::existsFile(".", "mods.conf")) {
502  SWLOGTI("found.");
503  stdstr(prefixPath, "./");
504  stdstr(configPath, "./mods.conf");
505  return;
506  }
507 
508  SWLOGTI("Checking working directory for mods.d...");
509  if (FileMgr::existsDir(".", "mods.d")) {
510  SWLOGTI("found.");
511  stdstr(prefixPath, "./");
512  stdstr(configPath, "./mods.d");
513  *configType = 1;
514  return;
515  }
516 
517  // check working directory ../library/
518  SWLOGTI("Checking working directory ../library/ for mods.d...");
519  if (FileMgr::existsDir("../library", "mods.d")) {
520  SWLOGTI("found.");
521  stdstr(prefixPath, "../library/");
522  stdstr(configPath, "../library/mods.d");
523  *configType = 1;
524  return;
525  }
526 
527  // check environment variable SWORD_PATH
528  SWLOGTI("Checking $SWORD_PATH...");
529 
530  SWBuf envsworddir = FileMgr::getEnvValue("SWORD_PATH");
531  if (envsworddir.length()) {
532 
533  SWLOGTI("found (%s).", envsworddir.c_str());
534  path = envsworddir;
535  if ((envsworddir[envsworddir.length()-1] != '\\') && (envsworddir[envsworddir.length()-1] != '/'))
536  path += "/";
537 
538  SWLOGTI("Checking $SWORD_PATH for mods.conf...");
539  if (FileMgr::existsFile(path.c_str(), "mods.conf")) {
540  SWLOGTI("found.");
541  stdstr(prefixPath, path.c_str());
542  path += "mods.conf";
543  stdstr(configPath, path.c_str());
544  return;
545  }
546 
547  SWLOGTI("Checking $SWORD_PATH for mods.d...");
548  if (FileMgr::existsDir(path.c_str(), "mods.d")) {
549  SWLOGTI("found.");
550  stdstr(prefixPath, path.c_str());
551  path += "mods.d";
552  stdstr(configPath, path.c_str());
553  *configType = 1;
554  return;
555  }
556  }
557 
558 
559  // check for systemwide globalConfPath
560 
561  SWLOGTI("Parsing %s...", globalConfPath);
562  char *globPaths = 0;
563  char *gfp;
564  stdstr(&globPaths, globalConfPath);
565  for (gfp = strtok(globPaths, ":"); gfp; gfp = strtok(0, ":")) {
566  SWLOGTI("Checking for %s...", gfp);
567  if (FileMgr::existsFile(gfp)) {
568  SWLOGTI("found.");
569  break;
570  }
571  }
572  if (gfp)
573  sysConfPath = gfp;
574  delete [] globPaths;
575 
576  if (homeDir.length()) {
577  SWBuf tryPath = homeDir;
578  tryPath += ".sword/sword.conf";
579  if (FileMgr::existsFile(tryPath)) {
580  SWLOGTI("Overriding any systemwide sword.conf with one found in users home directory (%s)", tryPath.c_str());
581  sysConfPath = tryPath;
582  }
583  else {
584  SWBuf tryPath = homeDir;
585  tryPath += "sword/sword.conf";
586  if (FileMgr::existsFile(tryPath)) {
587  SWLOGTI("Overriding any systemwide sword.conf with one found in users home directory (%s)", tryPath.c_str());
588  sysConfPath = tryPath;
589  }
590  }
591  }
592  }
593  }
594 
595  if (!sysConf && sysConfPath.size()) {
596  sysConf = new SWConfig(sysConfPath);
597  }
598 
599  if (sysConf) {
600  if (!setLogLevel) { setSystemLogLevel(sysConf); setLogLevel = true; }
601  if ((entry = sysConf->getSection("Install").find("DataPath")) != sysConf->getSection("Install").end()) {
602  sysConfDataPath = (*entry).second;
603  }
604  if (sysConfDataPath.size()) {
605  if ((!sysConfDataPath.endsWith("\\")) && (!sysConfDataPath.endsWith("/")))
606  sysConfDataPath += "/";
607 
608  path = sysConfDataPath;
609  SWLOGTI("DataPath in %s is set to %s.", sysConfPath.c_str(), path.c_str());
610  SWLOGTI("Checking for mods.conf in DataPath...");
611 
612  if (FileMgr::existsFile(path.c_str(), "mods.conf")) {
613  SWLOGTI("found.");
614  stdstr(prefixPath, path.c_str());
615  path += "mods.conf";
616  stdstr(configPath, path.c_str());
617  *configType = 1;
618  }
619 
620  SWLOGTI("Checking for mods.d in DataPath...");
621 
622  if (FileMgr::existsDir(path.c_str(), "mods.d")) {
623  SWLOGTI("found.");
624  stdstr(prefixPath, path.c_str());
625  path += "mods.d";
626  stdstr(configPath, path.c_str());
627  *configType = 1;
628  }
629  }
630  }
631 
632  // do some extra processing of sysConf if we have one
633  if (sysConf) {
634  if (!setLogLevel) { setSystemLogLevel(sysConf); setLogLevel = true; }
635  if (augPaths) {
636  augPaths->clear();
637  entry = sysConf->getSection("Install").lower_bound("AugmentPath");
638  lastEntry = sysConf->getSection("Install").upper_bound("AugmentPath");
639  for (;entry != lastEntry; entry++) {
640  path = entry->second;
641  if ((entry->second.c_str()[strlen(entry->second.c_str())-1] != '\\') && (entry->second.c_str()[strlen(entry->second.c_str())-1] != '/'))
642  path += "/";
643  augPaths->push_back(path);
644  }
645  }
646  if (providedSysConf) {
647  *providedSysConf = sysConf;
648  }
649  else delete sysConf;
650  }
651 
652  if (*configType)
653  return;
654 
655  // WE STILL HAVEN'T FOUND A CONFIGURATION. LET'S LOOK IN SOME OS SPECIFIC
656  // LOCATIONS
657  //
658  // for various flavors of windoze...
659  // check %ALLUSERSPROFILE%/Application Data/sword/
660 
661  SWLOGTI("Checking $ALLUSERSPROFILE/Application Data/sword/...");
662 
663  SWBuf envallusersdir = FileMgr::getEnvValue("ALLUSERSPROFILE");
664  if (envallusersdir.length()) {
665  SWLOGTI("found (%s).", envallusersdir.c_str());
666  path = envallusersdir;
667  if ((!path.endsWith("\\")) && (!path.endsWith("/")))
668  path += "/";
669 
670  path += "Application Data/sword/";
671  SWLOGTI("Checking %s for mods.d...", path.c_str());
672  if (FileMgr::existsDir(path.c_str(), "mods.d")) {
673  SWLOGTI("found.");
674  stdstr(prefixPath, path.c_str());
675  path += "mods.d";
676  stdstr(configPath, path.c_str());
677  *configType = 1;
678  return;
679  }
680  }
681 
682  // for Mac OSX...
683  // check $HOME/Library/Application Support/Sword/
684 
685  SWLOGTI("Checking $HOME/Library/Application Support/Sword/...");
686 
687  SWBuf pathCheck = FileMgr::getSystemFileMgr()->getHomeDir();
688  if (pathCheck.length()) {
689  SWLOGTI("found (%s).", pathCheck.c_str());
690  path = pathCheck;
691  if ((!path.endsWith("\\")) && (!path.endsWith("/")))
692  path += "/";
693 
694  SWLOGTI("Checking %s for mods.d...", path.c_str());
695  if (FileMgr::existsDir(path.c_str(), "mods.d")) {
696  SWLOGTI("found.");
697  stdstr(prefixPath, path.c_str());
698  path += "mods.d";
699  stdstr(configPath, path.c_str());
700  *configType = 1;
701  return;
702  }
703  }
704 
705  // FINALLY CHECK PERSONAL HOME DIRECTORY LOCATIONS
706  // check ~/.sword/
707 
708  SWLOGTI("Checking home directory for ~/.sword...");
709 
710  if (homeDir.length()) {
711  path = homeDir;
712  path += ".sword/";
713  SWLOGTI(" Checking for %smods.conf...", path.c_str());
714  if (FileMgr::existsFile(path.c_str(), "mods.conf")) {
715  SWLOGTI("found.");
716  stdstr(prefixPath, path.c_str());
717  path += "mods.conf";
718  stdstr(configPath, path.c_str());
719  return;
720  }
721 
722  SWLOGTI(" Checking for %smods.d...", path.c_str());
723  if (FileMgr::existsDir(path.c_str(), "mods.d")) {
724  SWLOGTI("found.");
725  stdstr(prefixPath, path.c_str());
726  path += "mods.d";
727  stdstr(configPath, path.c_str());
728  *configType = 2;
729  return;
730  }
731 
732  path = homeDir;
733  path += "sword/";
734  SWLOGTI(" Checking for %smods.d...", path.c_str());
735  if (FileMgr::existsDir(path.c_str(), "mods.d")) {
736  SWLOGTI("found.");
737  stdstr(prefixPath, path.c_str());
738  path += "mods.d";
739  stdstr(configPath, path.c_str());
740  *configType = 2;
741  return;
742  }
743  }
744 }
745 
746 
747 void SWMgr::loadConfigDir(const char *ipath)
748 {
749  SWBuf basePath = ipath;
750  if (!basePath.endsWith("/") && !basePath.endsWith("\\")) basePath += "/";
751 
752  SWBuf newModFile;
753 
754  std::vector<DirEntry> dirList = FileMgr::getDirList(ipath);
755  for (unsigned int i = 0; i < dirList.size(); ++i) {
756  //check whether it ends with .conf, if it doesn't skip it!
757  if (!dirList[i].name.endsWith(".conf")) {
758  continue;
759  }
760 
761  newModFile = basePath + dirList[i].name;
762  if (config) {
763  SWConfig tmpConfig(newModFile);
764  config->augment(tmpConfig);
765  }
766  else config = myconfig = new SWConfig(newModFile);
767  }
768 
769  if (!config) { // if no .conf file exist yet, create a default
770  newModFile = basePath + "globals.conf";
771  config = myconfig = new SWConfig(newModFile);
772  }
773 }
774 
775 
776 void SWMgr::augmentModules(const char *ipath, bool multiMod) {
777  SWBuf path = ipath;
778  if (!path.endsWith("/") && !path.endsWith("\\")) path += "/";
779  if (FileMgr::existsDir(path.c_str(), "mods.d")) {
780  char *savePrefixPath = 0;
781  char *saveConfigPath = 0;
782  SWConfig *saveConfig = 0;
783  stdstr(&savePrefixPath, prefixPath);
784  stdstr(&prefixPath, path.c_str());
785  path += "mods.d";
786  stdstr(&saveConfigPath, configPath);
787  stdstr(&configPath, path.c_str());
788  saveConfig = config;
789  config = myconfig = 0;
791 
792  if (multiMod) {
793  // fix config's Section names to rename modules which are available more than once
794  // find out which sections are in both config objects
795  // inserting all configs first is not good because that overwrites old keys and new modules would share the same config
796  for (SectionMap::iterator it = config->getSections().begin(); it != config->getSections().end();) {
797  if (saveConfig->getSections().find((*it).first) != saveConfig->getSections().end()) { //if the new section is already present rename it
798  ConfigEntMap entMap((*it).second);
799 
800  SWBuf name;
801  int i = 1;
802  do { //module name already used?
803  name.setFormatted("%s_%d", (*it).first.c_str(), i);
804  i++;
805  } while (config->getSections().find(name) != config->getSections().end());
806 
807  config->getSections().insert(SectionMap::value_type(name, entMap) );
808  SectionMap::iterator toErase = it++;
809  config->getSections().erase(toErase);
810  }
811  else ++it;
812  }
813  }
814 
815  createAllModules(multiMod);
816 
817  stdstr(&prefixPath, savePrefixPath);
818  delete []savePrefixPath;
819  stdstr(&configPath, saveConfigPath);
820  delete []saveConfigPath;
821 
822  (*saveConfig) += *config;
823 
825  config = myconfig = saveConfig;
826  }
827 }
828 
829 
830 /***********************************************************************
831  * SWMgr::load - loads actual modules
832  *
833  * RET: status - 0 = ok; -1 no config found; 1 = no modules installed
834  *
835  */
836 
837 signed char SWMgr::load() {
838  signed char ret = 0;
839 
840  if (!config) { // If we weren't passed a config object at construction, find a config file
841  if (!configPath) { // If we weren't passed a config path at construction...
842  SWLOGTI("LOOKING UP MODULE CONFIGURATION...");
843  SWConfig *externalSysConf = sysConfig; // if we have a sysConf before findConfig, then we were provided one from an external source.
845  if (!externalSysConf) mysysconfig = sysConfig; // remind us to delete our own sysConfig in d-tor
846  SWLOGTI("LOOKING UP MODULE CONFIGURATION COMPLETE.");
847  }
848  if (configPath) {
849  SWLOGTI("LOADING MODULE CONFIGURATIONS...");
850  if (configType)
852  else config = myconfig = new SWConfig(configPath);
853  SWLOGTI("LOADING MODULE CONFIGURATIONS COMPLETE.");
854  }
855  }
856 
857  if (config) {
858 
859  SWLOGTI("LOADING MODULE LIBRARY...");
860 
861  SectionMap::iterator Sectloop, Sectend;
862  ConfigEntMap::iterator Entryloop, Entryend;
863 
865 
866  for (Sectloop = config->getSections().lower_bound("Globals"), Sectend = config->getSections().upper_bound("Globals"); Sectloop != Sectend; Sectloop++) { // scan thru all 'Globals' sections
867  for (Entryloop = (*Sectloop).second.lower_bound("AutoInstall"), Entryend = (*Sectloop).second.upper_bound("AutoInstall"); Entryloop != Entryend; Entryloop++) // scan thru all AutoInstall entries
868  InstallScan((*Entryloop).second.c_str()); // Scan AutoInstall entry directory for new modules and install
869  }
870  if (configType) { // force reload on config object because we may have installed new modules
871  delete myconfig;
872  config = myconfig = 0;
874  }
875  else config->load();
876 
878 
879  for (std::list<SWBuf>::iterator pathIt = augPaths.begin(); pathIt != augPaths.end(); pathIt++) {
880  augmentModules(pathIt->c_str(), mgrModeMultiMod);
881  }
882  if (augmentHome) {
883  // augment config with ~/.sword/mods.d if it exists ---------------------
885  if (homeDir.length() && configType != 2) { // 2 = user only
886  SWBuf path = homeDir;
887  path += ".sword/";
889  path = homeDir;
890  path += "sword/";
891  augmentModules(path.c_str(), mgrModeMultiMod);
892  }
893  }
894 // -------------------------------------------------------------------------
895  if (!getModules().size()) // config exists, but no modules
896  ret = 1;
897 
898  SWLOGTI("LOADING MODULE LIBRARY COMPLETE.");
899  }
900  else {
901  SWLog::getSystemLog()->logError("SWMgr: Can't find 'mods.conf' or 'mods.d'. Try setting:\n\tSWORD_PATH=<directory containing mods.conf>\n\tOr see the README file for a full description of setup options (%s)", (configPath) ? configPath : "<configPath is null>");
902  ret = -1;
903  }
904 
905  return ret;
906 }
907 
908 
909 SWModule *SWMgr::createModule(const char *name, const char *driver, ConfigEntMap &section)
910 {
911  SWBuf description, datapath, misc1;
912  ConfigEntMap::iterator entry;
913  SWModule *newmod = 0;
914  SWBuf lang, sourceformat, encoding;
915  signed char direction, enc, markup;
916 
917  description = ((entry = section.find("Description")) != section.end()) ? (*entry).second : (SWBuf)"";
918  lang = ((entry = section.find("Lang")) != section.end()) ? (*entry).second : (SWBuf)"en";
919  sourceformat = ((entry = section.find("SourceType")) != section.end()) ? (*entry).second : (SWBuf)"";
920  encoding = ((entry = section.find("Encoding")) != section.end()) ? (*entry).second : (SWBuf)"";
921  datapath = prefixPath;
922  if ((prefixPath[strlen(prefixPath)-1] != '\\') && (prefixPath[strlen(prefixPath)-1] != '/'))
923  datapath += "/";
924 
925  SWBuf versification = ((entry = section.find("Versification")) != section.end()) ? (*entry).second : (SWBuf)"KJV";
926 
927  // DataPath - relative path to data used by module driver. May be a directory, may be a File.
928  // Typically not useful by outside world. See AbsoluteDataPath, PrefixPath, and RelativePrefixPath
929  // below.
930  misc1 += ((entry = section.find("DataPath")) != section.end()) ? (*entry).second : (SWBuf)"";
931  char *buf = new char [ strlen(misc1.c_str()) + 1 ];
932  char *buf2 = buf;
933  strcpy(buf, misc1.c_str());
934 // for (; ((*buf2) && ((*buf2 == '.') || (*buf2 == '/') || (*buf2 == '\\'))); buf2++);
935  for (; ((*buf2) && ((*buf2 == '/') || (*buf2 == '\\'))); buf2++);
936  if (!strncmp(buf2, "./", 2)) { //remove the leading ./ in the module data path to make it look better
937  buf2 += 2;
938  }
939  // PrefixPath - absolute directory path to the repository in which this module was found
940  section["PrefixPath"] = datapath;
941  if (*buf2)
942  datapath += buf2;
943  delete [] buf;
944 
945  section["AbsoluteDataPath"] = datapath;
946 
947  if (!stricmp(sourceformat.c_str(), "GBF"))
948  markup = FMT_GBF;
949  else if (!stricmp(sourceformat.c_str(), "ThML"))
950  markup = FMT_THML;
951  else if (!stricmp(sourceformat.c_str(), "OSIS"))
952  markup = FMT_OSIS;
953  else if (!stricmp(sourceformat.c_str(), "TEI"))
954  markup = FMT_TEI;
955  else
956  markup = FMT_GBF;
957 
958  if (!stricmp(encoding.c_str(), "UTF-8")) {
959  enc = ENC_UTF8;
960  }
961  else if (!stricmp(encoding.c_str(), "SCSU")) {
962  enc = ENC_SCSU;
963  }
964  else if (!stricmp(encoding.c_str(), "UTF-16")) {
965  enc = ENC_UTF16;
966  }
967  else enc = ENC_LATIN1;
968 
969  if ((entry = section.find("Direction")) == section.end()) {
970  direction = DIRECTION_LTR;
971  }
972  else if (!stricmp((*entry).second.c_str(), "rtol")) {
973  direction = DIRECTION_RTL;
974  }
975  else if (!stricmp((*entry).second.c_str(), "bidi")) {
976  direction = DIRECTION_BIDI;
977  }
978  else {
979  direction = DIRECTION_LTR;
980  }
981 
982  if ((!stricmp(driver, "zText")) || (!stricmp(driver, "zCom")) || (!stricmp(driver, "zText4")) || (!stricmp(driver, "zCom4"))) {
983  SWCompress *compress = 0;
984  int blockType = CHAPTERBLOCKS;
985  misc1 = ((entry = section.find("BlockType")) != section.end()) ? (*entry).second : (SWBuf)"CHAPTER";
986  if (!stricmp(misc1.c_str(), "VERSE"))
987  blockType = VERSEBLOCKS;
988  else if (!stricmp(misc1.c_str(), "CHAPTER"))
989  blockType = CHAPTERBLOCKS;
990  else if (!stricmp(misc1.c_str(), "BOOK"))
991  blockType = BOOKBLOCKS;
992 
993  misc1 = ((entry = section.find("CompressType")) != section.end()) ? (*entry).second : (SWBuf)"LZSS";
994 #ifndef EXCLUDEZLIB
995  if (!stricmp(misc1.c_str(), "ZIP"))
996  compress = new ZipCompress();
997  else
998 #endif
999 #ifndef EXCLUDEBZIP2
1000  if (!stricmp(misc1.c_str(), "BZIP2"))
1001  compress = new Bzip2Compress();
1002  else
1003 #endif
1004 #ifndef EXCLUDEXZ
1005  if (!stricmp(misc1.c_str(), "XZ"))
1006  compress = new XzCompress();
1007  else
1008 #endif
1009  if (!stricmp(misc1.c_str(), "LZSS"))
1010  compress = new LZSSCompress();
1011 
1012  if (compress) {
1013  if (!stricmp(driver, "zText"))
1014  newmod = new zText(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification);
1015  else if (!stricmp(driver, "zText4"))
1016  newmod = new zText4(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification);
1017  else if (!stricmp(driver, "zCom4"))
1018  newmod = new zCom4(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification);
1019  else
1020  newmod = new zCom(datapath.c_str(), name, description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str(), versification);
1021  }
1022  }
1023 
1024  if (!stricmp(driver, "RawText")) {
1025  newmod = new RawText(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), versification);
1026  }
1027 
1028  if (!stricmp(driver, "RawText4")) {
1029  newmod = new RawText4(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), versification);
1030  }
1031 
1032  // backward support old drivers
1033  if (!stricmp(driver, "RawGBF")) {
1034  newmod = new RawText(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str());
1035  }
1036 
1037  if (!stricmp(driver, "RawCom")) {
1038  newmod = new RawCom(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), versification);
1039  }
1040 
1041  if (!stricmp(driver, "RawCom4")) {
1042  newmod = new RawCom4(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), versification);
1043  }
1044 
1045  if (!stricmp(driver, "RawFiles")) {
1046  newmod = new RawFiles(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str());
1047  }
1048 
1049  if (!stricmp(driver, "HREFCom")) {
1050  misc1 = ((entry = section.find("Prefix")) != section.end()) ? (*entry).second : (SWBuf)"";
1051  newmod = new HREFCom(datapath.c_str(), misc1.c_str(), name, description.c_str());
1052  }
1053 
1054  int pos = 0; //used for position of final / in AbsoluteDataPath, but also set to 1 for modules types that need to strip module name
1055  if (!stricmp(driver, "RawLD")) {
1056  bool caseSensitive = ((entry = section.find("CaseSensitiveKeys")) != section.end()) ? (*entry).second == "true": false;
1057  bool strongsPadding = ((entry = section.find("StrongsPadding")) != section.end()) ? (*entry).second == "true": true;
1058  newmod = new RawLD(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), caseSensitive, strongsPadding);
1059  pos = 1;
1060  }
1061 
1062  if (!stricmp(driver, "RawLD4")) {
1063  bool caseSensitive = ((entry = section.find("CaseSensitiveKeys")) != section.end()) ? (*entry).second == "true": false;
1064  bool strongsPadding = ((entry = section.find("StrongsPadding")) != section.end()) ? (*entry).second == "true": true;
1065  newmod = new RawLD4(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), caseSensitive, strongsPadding);
1066  pos = 1;
1067  }
1068 
1069  if (!stricmp(driver, "zLD")) {
1070  SWCompress *compress = 0;
1071  int blockCount;
1072  bool caseSensitive = ((entry = section.find("CaseSensitiveKeys")) != section.end()) ? (*entry).second == "true": false;
1073  bool strongsPadding = ((entry = section.find("StrongsPadding")) != section.end()) ? (*entry).second == "true": true;
1074  misc1 = ((entry = section.find("BlockCount")) != section.end()) ? (*entry).second : (SWBuf)"200";
1075  blockCount = atoi(misc1.c_str());
1076  blockCount = (blockCount) ? blockCount : 200;
1077 
1078  misc1 = ((entry = section.find("CompressType")) != section.end()) ? (*entry).second : (SWBuf)"LZSS";
1079 #ifndef EXCLUDEZLIB
1080  if (!stricmp(misc1.c_str(), "ZIP"))
1081  compress = new ZipCompress();
1082  else
1083 #endif
1084 #ifndef EXCLUDEBZIP2
1085  if (!stricmp(misc1.c_str(), "BZIP2"))
1086  compress = new Bzip2Compress();
1087  else
1088 #endif
1089 #ifndef EXCLUDEXZ
1090  if (!stricmp(misc1.c_str(), "XZ"))
1091  compress = new XzCompress();
1092  else
1093 #endif
1094  if (!stricmp(misc1.c_str(), "LZSS"))
1095  compress = new LZSSCompress();
1096 
1097  if (compress) {
1098  newmod = new zLD(datapath.c_str(), name, description.c_str(), blockCount, compress, 0, enc, direction, markup, lang.c_str(), caseSensitive, strongsPadding);
1099  }
1100  pos = 1;
1101  }
1102 
1103  if (!stricmp(driver, "RawGenBook")) {
1104  misc1 = ((entry = section.find("KeyType")) != section.end()) ? (*entry).second : (SWBuf)"TreeKey";
1105  newmod = new RawGenBook(datapath.c_str(), name, description.c_str(), 0, enc, direction, markup, lang.c_str(), misc1.c_str());
1106  pos = 1;
1107  }
1108 
1109  if (pos == 1) {
1110  SWBuf &dp = section["AbsoluteDataPath"];
1111  for (int i = (int)dp.length() - 1; i; i--) {
1112  if (dp[i] == '/') {
1113  dp.setSize(i);
1114  break;
1115  }
1116  }
1117 /*
1118  SWBuf &rdp = section["RelativeDataPath"];
1119  for (int i = rdp.length() - 1; i; i--) {
1120  if (rdp[i] == '/') {
1121  rdp.setSize(i);
1122  break;
1123  }
1124  }
1125 */
1126  }
1127 
1128  if (newmod) {
1129  // if a specific module type is set in the config, use this
1130  if ((entry = section.find("Type")) != section.end())
1131  newmod->setType(entry->second.c_str());
1132 
1133  newmod->setConfig(&section);
1134  }
1135 
1136  return newmod;
1137 }
1138 
1139 
1141 
1142  ConfigEntMap::iterator start = section.lower_bound("GlobalOptionFilter");
1143  ConfigEntMap::iterator end = section.upper_bound("GlobalOptionFilter");
1144 
1145  for (;start != end; ++start) {
1146  OptionFilterMap::iterator it;
1147  SWBuf filterName = start->second;
1148 
1149 
1150  // special cases for filters with parameters
1151 
1152  if (filterName.startsWith("OSISReferenceLinks")) {
1153  SWBuf params = filterName;
1154  filterName = params.stripPrefix('|', true);
1155  SWBuf optionName = params.stripPrefix('|', true);
1156  SWBuf optionTip = params.stripPrefix('|', true);
1157  SWBuf optionType = params.stripPrefix('|', true);
1158  SWBuf optionSubType = params.stripPrefix('|', true);
1159  SWBuf optionDefaultValue = params.stripPrefix('|', true);
1160  // we'll key off of type and subtype.
1161  filterName = filterName + "." + optionType + "." + optionSubType;
1162 
1163  it = optionFilters.find(filterName);
1164  if (it == optionFilters.end()) {
1165  SWOptionFilter *tmpFilter = new OSISReferenceLinks(optionName, optionTip, optionType, optionSubType, optionDefaultValue);
1166  optionFilters.insert(OptionFilterMap::value_type(filterName, tmpFilter));
1167  cleanupFilters.push_back(tmpFilter);
1168  }
1169  }
1170 
1171 
1172  it = optionFilters.find(filterName);
1173  if (it != optionFilters.end()) {
1174  module->addOptionFilter((*it).second); // add filter to module and option as a valid option
1175  StringList::iterator loop;
1176  for (loop = options.begin(); loop != options.end(); loop++) {
1177  if (!strcmp((*loop).c_str(), (*it).second->getOptionName()))
1178  break;
1179  }
1180  if (loop == options.end()) // if we have not yet included the option
1181  options.push_back((*it).second->getOptionName());
1182  }
1183  }
1184  if (filterMgr)
1185  filterMgr->addGlobalOptions(module, section, start, end);
1186 #ifdef _ICU_
1188 #endif
1189 }
1190 
1191 
1192 char SWMgr::filterText(const char *filterName, SWBuf &text, const SWKey *key, const SWModule *module) {
1193  signed char retVal = -1;
1194  // why didn't we use find here?
1195  for (OptionFilterMap::iterator it = optionFilters.begin(); it != optionFilters.end(); it++) {
1196  if ((*it).second->getOptionName()) {
1197  if (!stricmp(filterName, (*it).second->getOptionName())) {
1198  retVal = it->second->processText(text, key, module);
1199  break;
1200  }
1201  }
1202  }
1203 
1204  if (retVal == -1) {
1205  FilterMap::iterator it = extraFilters.find(filterName);
1206  if (it != extraFilters.end()) {
1207  retVal = it->second->processText(text, key, module);
1208  }
1209  }
1210 
1211  return retVal;
1212 }
1213 
1214 
1216 
1217  ConfigEntMap::iterator start = section.lower_bound("LocalOptionFilter");
1218  ConfigEntMap::iterator end = section.upper_bound("LocalOptionFilter");
1219 
1220  for (;start != end; start++) {
1221  OptionFilterMap::iterator it;
1222  it = optionFilters.find((*start).second);
1223  if (it != optionFilters.end()) {
1224  module->addOptionFilter((*it).second); // add filter to module
1225  }
1226  }
1227 
1228  if (filterMgr)
1229  filterMgr->addLocalOptions(module, section, start, end);
1230 }
1231 
1232 
1233 // manually specified StripFilters for special cases, like Papyri marks and such
1235 
1236  ConfigEntMap::iterator start = section.lower_bound("LocalStripFilter");
1237  ConfigEntMap::iterator end = section.upper_bound("LocalStripFilter");
1238 
1239  for (;start != end; start++) {
1240  OptionFilterMap::iterator it;
1241  it = optionFilters.find((*start).second);
1242  if (it != optionFilters.end()) {
1243  module->addStripFilter((*it).second); // add filter to module
1244  }
1245  }
1246 }
1247 
1248 
1250  SWBuf sourceformat, cipherKey;
1251  ConfigEntMap::iterator entry;
1252 
1253  cipherKey = ((entry = section.find("CipherKey")) != section.end()) ? (*entry).second : (SWBuf)"";
1254  if (cipherKey.length()) {
1255  SWFilter *cipherFilter = new CipherFilter(cipherKey.c_str());
1256  cipherFilters.insert(FilterMap::value_type(module->getName(), cipherFilter));
1257  cleanupFilters.push_back(cipherFilter);
1258  module->addRawFilter(cipherFilter);
1259  }
1260 
1261  if (filterMgr)
1262  filterMgr->addRawFilters(module, section);
1263 }
1264 
1265 
1267  if (filterMgr)
1268  filterMgr->addEncodingFilters(module, section);
1269 }
1270 
1271 
1273  SWBuf sourceformat;
1274  ConfigEntMap::iterator entry;
1275 
1276  sourceformat = ((entry = section.find("SourceType")) != section.end()) ? (*entry).second : (SWBuf)"";
1277 
1278  // Temporary: To support old module types
1279  // TODO: Remove at 1.6.0 release?
1280  if (!sourceformat.length()) {
1281  sourceformat = ((entry = section.find("ModDrv")) != section.end()) ? (*entry).second : (SWBuf)"";
1282  if (!stricmp(sourceformat.c_str(), "RawGBF"))
1283  sourceformat = "GBF";
1284  else sourceformat = "";
1285  }
1286 
1287 // process module - eg. follows
1288 // if (!stricmp(sourceformat.c_str(), "GBF")) {
1289 // module->AddRenderFilter(gbftortf);
1290 // }
1291 
1292  if (filterMgr)
1293  filterMgr->addRenderFilters(module, section);
1294 
1295 }
1296 
1297 
1299 {
1300  SWBuf sourceformat;
1301  ConfigEntMap::iterator entry;
1302 
1303  sourceformat = ((entry = section.find("SourceType")) != section.end()) ? (*entry).second : (SWBuf)"";
1304  // Temporary: To support old module types
1305  if (!sourceformat.length()) {
1306  sourceformat = ((entry = section.find("ModDrv")) != section.end()) ? (*entry).second : (SWBuf)"";
1307  if (!stricmp(sourceformat.c_str(), "RawGBF"))
1308  sourceformat = "GBF";
1309  else sourceformat = "";
1310  }
1311 
1312  if (!stricmp(sourceformat.c_str(), "GBF")) {
1313  module->addStripFilter(gbfplain);
1314  }
1315  else if (!stricmp(sourceformat.c_str(), "ThML")) {
1316  module->addStripFilter(thmlplain);
1317  }
1318  else if (!stricmp(sourceformat.c_str(), "OSIS")) {
1319  module->addStripFilter(osisplain);
1320  }
1321  else if (!stricmp(sourceformat.c_str(), "TEI")) {
1322  module->addStripFilter(teiplain);
1323  }
1324 
1325  if (filterMgr)
1326  filterMgr->addStripFilters(module, section);
1327 
1328 }
1329 
1330 
1331 void SWMgr::InstallScan(const char *dirname)
1332 {
1333  FileDesc *conffd = 0;
1334  SWBuf newModFile;
1335  SWBuf targetName;
1336  SWBuf basePath = dirname;
1337  if (!basePath.endsWith("/") && !basePath.endsWith("\\")) basePath += "/";
1338 
1339  std::vector<DirEntry> dirList = FileMgr::getDirList(dirname);
1340  for (unsigned int i = 0; i < dirList.size(); ++i) {
1341  newModFile = basePath + dirList[i].name;
1342 
1343  // mods.d
1344  if (configType) {
1345  if (conffd)
1346  FileMgr::getSystemFileMgr()->close(conffd);
1347  targetName = configPath;
1348  if ((configPath[strlen(configPath)-1] != '\\') && (configPath[strlen(configPath)-1] != '/'))
1349  targetName += "/";
1350  targetName += dirList[i].name;
1352  }
1353 
1354  // mods.conf
1355  else {
1356  if (!conffd) {
1358  if (conffd && conffd->getFd() >= 0)
1359  conffd->seek(0L, SEEK_END);
1360  else {
1361  FileMgr::getSystemFileMgr()->close(conffd);
1362  conffd = 0;
1363  }
1364  }
1365  }
1366  addModToConfig(conffd, newModFile.c_str());
1367  FileMgr::removeFile(newModFile.c_str());
1368  }
1369  if (conffd)
1370  FileMgr::getSystemFileMgr()->close(conffd);
1371 }
1372 
1373 
1374 char SWMgr::addModToConfig(FileDesc *conffd, const char *fname)
1375 {
1376  FileDesc *modfd;
1377  char ch;
1378 
1379  SWLOGTI("Found new module [%s]. Installing...", fname);
1380  modfd = FileMgr::getSystemFileMgr()->open(fname, FileMgr::RDONLY);
1381  ch = '\n';
1382  conffd->write(&ch, 1);
1383  while (modfd->read(&ch, 1) == 1)
1384  conffd->write(&ch, 1);
1385  ch = '\n';
1386  conffd->write(&ch, 1);
1387  FileMgr::getSystemFileMgr()->close(modfd);
1388  return 0;
1389 }
1390 
1391 
1392 void SWMgr::setGlobalOption(const char *option, const char *value)
1393 {
1394  for (OptionFilterMap::iterator it = optionFilters.begin(); it != optionFilters.end(); it++) {
1395  if ((*it).second->getOptionName()) {
1396  if (!stricmp(option, (*it).second->getOptionName()))
1397  (*it).second->setOptionValue(value);
1398  }
1399  }
1400 }
1401 
1402 
1403 const char *SWMgr::getGlobalOption(const char *option)
1404 {
1405  for (OptionFilterMap::iterator it = optionFilters.begin(); it != optionFilters.end(); it++) {
1406  if ((*it).second->getOptionName()) {
1407  if (!stricmp(option, (*it).second->getOptionName()))
1408  return (*it).second->getOptionValue();
1409  }
1410  }
1411  return 0;
1412 }
1413 
1414 
1415 const char *SWMgr::getGlobalOptionTip(const char *option)
1416 {
1417  for (OptionFilterMap::iterator it = optionFilters.begin(); it != optionFilters.end(); it++) {
1418  if ((*it).second->getOptionName()) {
1419  if (!stricmp(option, (*it).second->getOptionName()))
1420  return (*it).second->getOptionTip();
1421  }
1422  }
1423  return 0;
1424 }
1425 
1426 
1428 {
1429  return options;
1430 }
1431 
1432 
1434 {
1436  for (OptionFilterMap::iterator it = optionFilters.begin(); it != optionFilters.end(); it++) {
1437  if ((*it).second->getOptionName()) {
1438  if (!stricmp(option, (*it).second->getOptionName())) {
1439  options = (*it).second->getOptionValues();
1440  break; // just find the first one. All option filters with the same option name should expect the same values
1441  }
1442  }
1443  }
1444  return options;
1445 }
1446 
1447 #if defined(__GNUC__)
1448 #pragma GCC diagnostic push
1449 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1450 #endif
1451 
1452 // TODO: use deprecated public 'Modules' property for now until we remove deprecation
1453 // and store in private property
1454 // also old deprecated virtuals so client overrides still are called
1455 
1456 void SWMgr::createAllModules(bool multiMod) {
1457 SWLOGD("libsword: SWMgr::createAllModules");
1458  SectionMap::iterator it;
1459  ConfigEntMap::iterator entry;
1460  SWModule *newmod;
1461  SWBuf driver, misc1;
1462  for (it = config->getSections().begin(); it != config->getSections().end(); it++) {
1463  ConfigEntMap &section = (*it).second;
1464  newmod = 0;
1465 
1466  driver = ((entry = section.find("ModDrv")) != section.end()) ? (*entry).second : (SWBuf)"";
1467  if (driver.length()) {
1468  newmod = createModule((*it).first, driver, section);
1469  if (newmod) {
1470  // Filters to add for this module and globally announce as an option to the user
1471  // e.g. translit, strongs, redletterwords, etc, so users can turn these on and off globally
1472  // TODO: addGlobalOptionFilters(newmod, section);
1473  AddGlobalOptions(newmod, section, section.lower_bound("GlobalOptionFilter"), section.upper_bound("GlobalOptionFilter"));
1474 
1475  // Only add the option to the module, don't announce it's availability
1476  // These are useful for like: filters that parse special entryAttribs in a text
1477  // or whatever you might want to happen on entry lookup
1478  // TODO: addLocalOptionFilters(newmod, section);
1479  AddLocalOptions(newmod, section, section.lower_bound("LocalOptionFilter"), section.upper_bound("LocalOptionFilter"));
1480 
1481  //STRIP FILTERS
1482 
1483  // add all basic strip filters for for the modtype
1484  // TODO: addStripFilters(newmod, section);
1485  addStripFilters(newmod, section);
1486 
1487  // Any module-specific processing specified in module config
1488  // as entries LocalStripFilter=
1489  // e.g. for papyri, removed all [](). notation
1490  // TODO: addLocalStripFilters(newmod, section);
1491  AddStripFilters(newmod, section, section.lower_bound("LocalStripFilter"), section.upper_bound("LocalStripFilter"));
1492 
1493  // TODO: addRawFilters(newmod, section);
1494  addRawFilters(newmod, section);
1495  // TODO: addRenderFilters(newmod, section);
1496  addRenderFilters(newmod, section);
1497  // TODO: addEncodingFilters(newmod, section);
1498  addEncodingFilters(newmod, section);
1499 
1500  // place our module in module container, removing first if one
1501  // already exists by our same name
1502  SWModule *oldmod = getModule(newmod->getName());
1503  if (oldmod) {
1504  delete oldmod;
1505  }
1506 
1507  // if it's not a utility module save it to Modules
1508  if ( SWBuf("Utility") != newmod->getType() &&
1509  SWBuf("Utility") != newmod->getConfigEntry("Category")) {
1510  Modules[newmod->getName()] = newmod;
1511  }
1512  else utilModules[newmod->getName()] = newmod;
1513  }
1514  }
1515  }
1516 }
1517 
1518 
1520 
1521  ModMap::iterator it;
1522 
1523  for (it = getModules().begin(); it != getModules().end(); ++it) {
1524  delete (*it).second;
1525  }
1526  for (it = getUtilModules().begin(); it != getUtilModules().end(); ++it) {
1527  delete (*it).second;
1528  }
1529 
1530  Modules.clear();
1531  utilModules.clear();
1532 }
1533 
1534 
1535 void SWMgr::deleteModule(const char *modName) {
1536  ModMap::iterator it = Modules.find(modName);
1537  if (it != Modules.end()) {
1538  delete (*it).second;
1539  Modules.erase(it);
1540  }
1541  else {
1542  it = utilModules.find(modName);
1543  if (it != utilModules.end()) {
1544  delete (*it).second;
1545  utilModules.erase(it);
1546  }
1547  }
1548 }
1549 
1550 signed char SWMgr::setCipherKey(const char *modName, const char *key) {
1551  FilterMap::iterator it;
1552 
1553  // check for filter that already exists
1554  it = cipherFilters.find(modName);
1555  if (it != cipherFilters.end()) {
1556  ((CipherFilter *)(*it).second)->getCipher()->setCipherKey(key);
1557  return 0;
1558  }
1559  // check if module exists
1560  else {
1561  SWModule *mod = getModule(modName);
1562  if (mod) {
1563  SWFilter *cipherFilter = new CipherFilter(key);
1564  cipherFilters.insert(FilterMap::value_type(modName, cipherFilter));
1565  cleanupFilters.push_back(cipherFilter);
1566  mod->addRawFilter(cipherFilter);
1567  return 0;
1568  }
1569  }
1570  return -1;
1571 }
1572 
1573 
1576 
1578 
1579 #if defined(__GNUC__)
1580 #pragma GCC diagnostic pop
1581 #endif
1582 
1584 
static signed char existsFile(const char *ipath, const char *ifileName=0)
Definition: filemgr.cpp:337
const char * getName() const
Definition: swmodule.cpp:204
Definition: zcom4.h:33
SWOptionFilter * transliterator
Definition: swmgr.h:120
#define SWORD_NAMESPACE_START
Definition: defs.h:39
long seek(long offset, int whence)
Definition: filemgr.cpp:143
virtual void deleteAllModules()
Definition: swmgr.cpp:1519
virtual void InstallScan(const char *dir)
Definition: swmgr.cpp:1331
virtual const char * getOptionName()
Definition: swoptfilter.h:72
virtual void load()
Definition: swconfig.cpp:55
FileDesc * open(const char *path, int mode, bool tryDowngrade)
Definition: filemgr.cpp:175
Definition: swbuf.h:47
unsigned long length() const
Definition: swbuf.h:197
virtual const char * getGlobalOption(const char *option)
Definition: swmgr.cpp:1403
virtual const char * getGlobalOptionTip(const char *option)
Definition: swmgr.cpp:1415
Definition: rawcom.h:34
Definition: rawld4.h:35
virtual void setGlobalOption(const char *option, const char *value)
Definition: swmgr.cpp:1392
virtual SectionMap & getSections()
Definition: swconfig.cpp:186
Definition: zld.h:34
int pos
Definition: regex.c:5534
static const char * MODTYPE_GENBOOKS
Definition: swmgr.h:276
virtual char filterText(const char *filterName, SWBuf &text, const SWKey *key=0, const SWModule *module=0)
Definition: swmgr.cpp:1192
Definition: ztext4.h:39
const char * getType() const
Definition: swmodule.cpp:232
static signed char existsDir(const char *ipath, const char *idirName=0)
Definition: filemgr.cpp:357
static unsigned int RDONLY
Definition: filemgr.h:75
static SWBuf getEnvValue(const char *variableName)
Definition: filemgr.cpp:316
char configType
Definition: swmgr.h:113
virtual const char * getConfigEntry(const char *key) const
Definition: swmodule.cpp:1159
virtual signed char load()
Definition: swmgr.cpp:837
static SWLog * getSystemLog()
Definition: swlog.cpp:53
static bool isICU
Definition: swmgr.h:280
virtual SWModule * createModule(const char *name, const char *driver, ConfigEntMap &section)
Definition: swmgr.cpp:909
ModMap Modules
Definition: swmgr.h:322
virtual void addRawFilters(SWModule *module, ConfigEntMap &section)
Definition: swfiltermgr.cpp:92
#define VERSEBLOCKS
Definition: zverse.h:58
#define SEEK_END
Definition: zconf.h:246
void commonInit(SWConfig *iconfig, SWConfig *isysconfig, bool autoload, SWFilterMgr *filterMgr, bool multiMod=false)
Definition: swmgr.cpp:335
virtual StringList getGlobalOptionValues(const char *option)
Definition: swmgr.cpp:1433
SWText * module
Definition: osis2mod.cpp:105
static const char * MODTYPE_LEXDICTS
Definition: swmgr.h:275
char * prefixPath
Definition: swmgr.h:312
virtual SWDEPRECATED void AddStripFilters(SWModule *module, ConfigEntMap &section)
Definition: swmgr.h:224
ModMap & getModules()
Definition: swmgr.cpp:1574
ModMap & getUtilModules()
Definition: swmgr.cpp:1575
bool startsWith(const SWBuf &prefix) const
Definition: swbuf.h:486
SWFilter * gbfplain
Definition: swmgr.h:116
SWCompress * compress
Definition: step2vpl.cpp:140
SWBuf getFileName() const
Definition: swconfig.cpp:191
virtual StringList getGlobalOptions()
Definition: swmgr.cpp:1427
int getFd()
Definition: filemgr.h:231
ModMap utilModules
Definition: swmgr.h:95
FilterMap extraFilters
Definition: swmgr.h:122
Definition: rawld.h:35
#define CHAPTERBLOCKS
Definition: zverse.h:59
bool endsWith(const SWBuf &postfix) const
Definition: swbuf.h:501
int stricmp(const char *s1, const char *s2)
Definition: utilstr.cpp:194
virtual void augmentModules(const char *path, bool multiMod=false)
Definition: swmgr.cpp:776
virtual void addStripFilters(SWModule *module, ConfigEntMap &section)
Definition: swfiltermgr.cpp:82
long write(const void *buf, long count)
Definition: filemgr.cpp:153
virtual SWDEPRECATED signed char Load()
Definition: swmgr.h:426
static const char * MODTYPE_BIBLES
Definition: swmgr.h:273
SWModule * getModule(const char *modName)
Definition: swmgr.h:360
SWORD_NAMESPACE_START char * stdstr(char **ipstr, const char *istr, unsigned int memPadFactor=1)
Definition: utilstr.h:44
SWConfig * config
Definition: swmgr.h:302
ConfigEntMap & getSection(const char *section)
Definition: swconfig.h:76
OptionFilterMap optionFilters
Definition: swmgr.h:114
Definition: zcom.h:33
void close(FileDesc *file)
Definition: filemgr.cpp:196
SWMgr(SWConfig *iconfig=0, SWConfig *isysconfig=0, bool autoload=true, SWFilterMgr *filterMgr=0, bool multiMod=false)
Definition: swmgr.cpp:368
virtual void addGlobalOptions(SWModule *module, ConfigEntMap &section, ConfigEntMap::iterator start, ConfigEntMap::iterator end)
Definition: swfiltermgr.cpp:48
virtual void augment(const SWConfig &addFrom)
Definition: swconfig.cpp:148
const char * c_str() const
Definition: swbuf.h:158
std::list< SWBuf > StringList
Definition: swmodule.cpp:91
static int removeFile(const char *fName)
Definition: filemgr.cpp:517
virtual SWDEPRECATED void AddLocalOptions(SWModule *module, ConfigEntMap &section, ConfigEntMap::iterator start, ConfigEntMap::iterator end)
Definition: swmgr.h:181
FilterMap cipherFilters
Definition: swmgr.h:115
static SWDEPRECATED SWBuf getHomeDir()
Definition: swmgr.cpp:1577
static unsigned int APPEND
Definition: filemgr.h:73
static const char * MODTYPE_COMMENTARIES
Definition: swmgr.h:274
virtual ~SWMgr()
Definition: swmgr.cpp:422
bool mgrModeMultiMod
Definition: swmgr.h:96
StringList augPaths
Definition: swmgr.h:266
virtual void addRenderFilters(SWModule *module, ConfigEntMap &section)
Definition: swmgr.cpp:1272
virtual SWModule & addOptionFilter(SWOptionFilter *newFilter)
Definition: swmodule.h:727
virtual void init()
Definition: swmgr.cpp:163
virtual void addEncodingFilters(SWModule *module, ConfigEntMap &section)
Definition: swfiltermgr.cpp:62
FilterList cleanupFilters
Definition: swmgr.h:121
virtual SWModule & addRawFilter(SWFilter *newFilter)
Definition: swmodule.h:694
virtual SWModule & addStripFilter(SWFilter *newFilter)
Definition: swmodule.h:681
std::map< SWBuf, SWModule *, std::less< SWBuf > > ModMap
Definition: swmgr.h:74
SWConfig * myconfig
Definition: swmgr.h:102
virtual void addRenderFilters(SWModule *module, ConfigEntMap &section)
Definition: swfiltermgr.cpp:72
SWConfig * sysConfig
Definition: swmgr.h:308
unsigned long size() const
Definition: swbuf.h:185
const char * stripPrefix(char separator, bool endOfStringAsSeparator=false)
Definition: swbuf.h:457
StringList options
Definition: swmgr.h:123
static const char * MODTYPE_DAILYDEVOS
Definition: swmgr.h:277
static const char LOG_WARN
Definition: swlog.h:43
virtual void addLocalStripFilters(SWModule *module, ConfigEntMap &section)
Definition: swmgr.cpp:1234
static std::vector< struct DirEntry > getDirList(const char *dirPath, bool includeSize=false, bool includeIsDirectory=true)
Definition: filemgr.cpp:379
SWFilter * osisplain
Definition: swmgr.h:118
SWFilter * teiplain
Definition: swmgr.h:119
virtual void addEncodingFilters(SWModule *module, ConfigEntMap &section)
Definition: swmgr.cpp:1266
virtual void setParentMgr(SWMgr *parentMgr)
Definition: swfiltermgr.cpp:38
virtual void setConfig(ConfigEntMap *config)
Definition: swmodule.cpp:1165
SWORD_NAMESPACE_START typedef multimapwithdefault< SWBuf, SWBuf, std::less< SWBuf > > ConfigEntMap
Definition: swconfig.h:35
static unsigned int CREAT
Definition: filemgr.h:72
static void findConfig(char *configType, char **prefixPath, char **configPath, StringList *augPaths=0, SWConfig **providedSysConf=0)
Definition: swmgr.cpp:449
void logError(const char *fmt,...) const
Definition: swlog.cpp:87
void setLogLevel(char level)
Definition: swlog.h:54
#define SWLOGTI(...)
Definition: defs.h:194
virtual void addRawFilters(SWModule *module, ConfigEntMap &section)
Definition: swmgr.cpp:1249
reg_syntax_t ret
Definition: regex.c:1351
virtual void addGlobalOptionFilters(SWModule *module, ConfigEntMap &section)
Definition: swmgr.cpp:1140
virtual void loadConfigDir(const char *ipath)
Definition: swmgr.cpp:747
static unsigned int IWRITE
Definition: filemgr.h:79
SWConfig * mysysconfig
Definition: swmgr.h:103
static unsigned int WRONLY
Definition: filemgr.h:77
virtual void createAllModules(bool multiMod=false)
Definition: swmgr.cpp:1456
long read(void *buf, long count)
Definition: filemgr.cpp:148
bool augmentHome
Definition: swmgr.h:97
void deleteModule(const char *)
Definition: swmgr.cpp:1535
static unsigned int IREAD
Definition: filemgr.h:78
SWConfig * homeConfig
Definition: swmgr.h:104
virtual void addStripFilters(SWModule *module, ConfigEntMap &section)
Definition: swmgr.cpp:1298
static const char LOG_INFO
Definition: swlog.h:44
#define SWORD_NAMESPACE_END
Definition: defs.h:40
virtual char addModToConfig(FileDesc *conffd, const char *fname)
Definition: swmgr.cpp:1374
#define SWLOGD(...)
Definition: defs.h:187
virtual void addLocalOptions(SWModule *module, ConfigEntMap &section, ConfigEntMap::iterator start, ConfigEntMap::iterator end)
Definition: swfiltermgr.cpp:52
void setType(const char *imodtype)
Definition: swmodule.h:397
SWBuf & setFormatted(const char *format,...)
Definition: swbuf.cpp:50
Definition: swkey.h:77
SWBuf getHomeDir()
Definition: filemgr.cpp:681
#define BOOKBLOCKS
Definition: zverse.h:60
static const char LOG_ERROR
Definition: swlog.h:42
virtual SWDEPRECATED void AddGlobalOptions(SWModule *module, ConfigEntMap &section, ConfigEntMap::iterator start, ConfigEntMap::iterator end)
Definition: swmgr.h:160
SWFilter * thmlplain
Definition: swmgr.h:117
static const char * globalConfPath
Definition: swmgr.h:281
char * configPath
Definition: swmgr.h:316
SWFilterMgr * filterMgr
Definition: swmgr.h:101
virtual signed char setCipherKey(const char *modName, const char *key)
Definition: swmgr.cpp:1550
static const char LOG_TIMEDINFO
Definition: swlog.h:45
void setSize(unsigned long len)
Definition: swbuf.h:255
virtual void addLocalOptionFilters(SWModule *module, ConfigEntMap &section)
Definition: swmgr.cpp:1215
Definition: ztext.h:39
static const char LOG_DEBUG
Definition: swlog.h:46
static FileMgr * getSystemFileMgr()
Definition: filemgr.cpp:101