diff options
Diffstat (limited to 'src/mgr')
-rw-r--r-- | src/mgr/Makefile.am | 26 | ||||
-rw-r--r-- | src/mgr/encfiltmgr.cpp | 148 | ||||
-rw-r--r-- | src/mgr/filemgr.cpp | 266 | ||||
-rw-r--r-- | src/mgr/localemgr.cpp | 184 | ||||
-rw-r--r-- | src/mgr/markupfiltmgr.cpp | 236 | ||||
-rw-r--r-- | src/mgr/swcacher.cpp | 43 | ||||
-rw-r--r-- | src/mgr/swconfig.cpp | 163 | ||||
-rw-r--r-- | src/mgr/swfiltermgr.cpp | 90 | ||||
-rw-r--r-- | src/mgr/swlocale.cpp | 140 | ||||
-rw-r--r-- | src/mgr/swmgr.cpp | 1084 |
10 files changed, 2380 insertions, 0 deletions
diff --git a/src/mgr/Makefile.am b/src/mgr/Makefile.am new file mode 100644 index 0000000..c648032 --- /dev/null +++ b/src/mgr/Makefile.am @@ -0,0 +1,26 @@ +mgrdir = $(top_srcdir)/src/mgr + +if CONFDEF +globdef = -DGLOBCONFPATH=\"${globalconfdir}/sword.conf\" +else +globdef = +endif + +if ICU +icudatadir = -DICUDATA=\"${pkglibdir}\" +else +icudatadir = +endif + + +DEFS += $(globdef) $(icudatadir) + +libsword_la_SOURCES += $(mgrdir)/swconfig.cpp +libsword_la_SOURCES += $(mgrdir)/swmgr.cpp +libsword_la_SOURCES += $(mgrdir)/swfiltermgr.cpp +libsword_la_SOURCES += $(mgrdir)/encfiltmgr.cpp +libsword_la_SOURCES += $(mgrdir)/markupfiltmgr.cpp +libsword_la_SOURCES += $(mgrdir)/filemgr.cpp +libsword_la_SOURCES += $(mgrdir)/swlocale.cpp +libsword_la_SOURCES += $(mgrdir)/localemgr.cpp +libsword_la_SOURCES += $(mgrdir)/swcacher.cpp diff --git a/src/mgr/encfiltmgr.cpp b/src/mgr/encfiltmgr.cpp new file mode 100644 index 0000000..ab55de9 --- /dev/null +++ b/src/mgr/encfiltmgr.cpp @@ -0,0 +1,148 @@ +/****************************************************************************** + * swencodingmgr.cpp - implementaion of class EncodingFilterMgr, subclass of + * used to transcode all module text to a requested + * encoding. + * + * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <encfiltmgr.h> + +#include <scsuutf8.h> +#include <latin1utf8.h> + +#include <unicodertf.h> +#include <utf8latin1.h> +#include <utf8utf16.h> +#include <utf8html.h> + +#include <swmgr.h> + +/****************************************************************************** + * EncodingFilterMgr Constructor - initializes instance of EncodingFilterMgr + * + * ENT: + * enc - Encoding format to emit + */ + +EncodingFilterMgr::EncodingFilterMgr (char enc) + : SWFilterMgr() { + + scsuutf8 = new SCSUUTF8(); + latin1utf8 = new Latin1UTF8(); + + encoding = enc; + + switch (encoding) { + case ENC_LATIN1: + targetenc = new UTF8Latin1(); + break; + case ENC_UTF16: + targetenc = new UTF8UTF16(); + break; + case ENC_RTF: + targetenc = new UnicodeRTF(); + break; + case ENC_HTML: + targetenc = new UTF8HTML(); + break; + default: // i.e. case ENC_UTF8 + targetenc = NULL; + } +} + +/****************************************************************************** + * EncodingFilterMgr Destructor - Cleans up instance of EncodingFilterMgr + */ +EncodingFilterMgr::~EncodingFilterMgr() { + if (scsuutf8) + delete scsuutf8; + if (latin1utf8) + delete latin1utf8; + if (targetenc) + delete targetenc; +} + +void EncodingFilterMgr::AddRawFilters(SWModule *module, ConfigEntMap §ion) { + + ConfigEntMap::iterator entry; + + string encoding = ((entry = section.find("Encoding")) != section.end()) ? (*entry).second : (string)""; + if (encoding.empty() || !stricmp(encoding.c_str(), "Latin-1")) { + module->AddRawFilter(latin1utf8); + } + else if (!stricmp(encoding.c_str(), "SCSU")) { + module->AddRawFilter(scsuutf8); + } +} + +void EncodingFilterMgr::AddEncodingFilters(SWModule *module, ConfigEntMap §ion) { + if (targetenc) + module->AddEncodingFilter(targetenc); +} + +/****************************************************************************** + * EncodingFilterMgr::Encoding - sets/gets encoding + * + * ENT: enc - new encoding or 0 to simply get the current encoding + * + * RET: encoding + */ +char EncodingFilterMgr::Encoding(char enc) { + if (enc && enc != encoding) { + encoding = enc; + SWFilter * oldfilter = targetenc; + + switch (encoding) { + case ENC_LATIN1: + targetenc = new UTF8Latin1(); + break; + case ENC_UTF16: + targetenc = new UTF8UTF16(); + break; + case ENC_RTF: + targetenc = new UnicodeRTF(); + break; + case ENC_HTML: + targetenc = new UTF8HTML(); + break; + default: // i.e. case ENC_UTF8 + targetenc = NULL; + } + + ModMap::const_iterator module; + + if (oldfilter != targetenc) { + if (oldfilter) { + if (!targetenc) { + for (module = getParentMgr()->Modules.begin(); module != getParentMgr()->Modules.end(); module++) + module->second->RemoveRenderFilter(oldfilter); + } + else { + for (module = getParentMgr()->Modules.begin(); module != getParentMgr()->Modules.end(); module++) + module->second->ReplaceRenderFilter(oldfilter, targetenc); + } + delete oldfilter; + } + else if (targetenc) { + for (module = getParentMgr()->Modules.begin(); module != getParentMgr()->Modules.end(); module++) + module->second->AddRenderFilter(targetenc); + } + } + + } + return encoding; +} diff --git a/src/mgr/filemgr.cpp b/src/mgr/filemgr.cpp new file mode 100644 index 0000000..0b31576 --- /dev/null +++ b/src/mgr/filemgr.cpp @@ -0,0 +1,266 @@ +/****************************************************************************** + * filemgr.cpp - implementation of class FileMgr used for pooling file + * handles + * + * $Id: filemgr.cpp,v 1.22 2002/07/31 20:26:38 scribe Exp $ + * + * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <filemgr.h> +#include <utilstr.h> + +#include <dirent.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#ifndef __GNUC__ +#include <io.h> +#else +#include <unistd.h> +#endif + +// ---------------- statics ----------------- +FileMgr FileMgr::systemFileMgr; + +// --------------- end statics -------------- + + +FileDesc::FileDesc(FileMgr *parent, char *path, int mode, int perms, bool tryDowngrade) { + this->parent = parent; + this->path = 0; + stdstr(&this->path, path); + this->mode = mode; + this->perms = perms; + this->tryDowngrade = tryDowngrade; + offset = 0; + fd = -77; +} + + +FileDesc::~FileDesc() { + if (fd > 0) + close(fd); + + if (path) + delete [] path; +} + + +int FileDesc::getFd() { + if (fd == -77) + fd = parent->sysOpen(this); + return fd; +} + + +FileMgr::FileMgr(int maxFiles) { + this->maxFiles = maxFiles; // must be at least 2 + files = 0; +} + + +FileMgr::~FileMgr() { + FileDesc *tmp; + + while(files) { + tmp = files->next; + delete files; + files = tmp; + } +} + + +FileDesc *FileMgr::open(char *path, int mode, bool tryDowngrade) { + return open(path, mode, S_IREAD | S_IWRITE, tryDowngrade); +} + +FileDesc *FileMgr::open(char *path, int mode, int perms, bool tryDowngrade) { + FileDesc **tmp, *tmp2; + + for (tmp = &files; *tmp; tmp = &((*tmp)->next)) { + if ((*tmp)->fd < 0) // insert as first non-system_open file + break; + } + + tmp2 = new FileDesc(this, path, mode, perms, tryDowngrade); + tmp2->next = *tmp; + *tmp = tmp2; + + return tmp2; +} + + +void FileMgr::close(FileDesc *file) { + FileDesc **loop; + + for (loop = &files; *loop; loop = &((*loop)->next)) { + if (*loop == file) { + *loop = (*loop)->next; + delete file; + break; + } + } +} + + +// to truncate a file at its current position +// leaving byte at current possition intact +// deleting everything afterward. +signed char FileMgr::trunc(FileDesc *file) { + + static const char *writeTest = "x"; + long size = lseek(file->getFd(), 1, SEEK_CUR); + if (size == 1) // was empty + size = 0; + char nibble [ 32767 ]; + bool writable = write(file->getFd(), writeTest, 1); + int bytes = 0; + + if (writable) { + // get tmpfilename + char *buf = new char [ strlen(file->path) + 10 ]; + int i; + for (i = 0; i < 9999; i++) { + sprintf(buf, "%stmp%.4d", file->path, i); + if (!existsFile(buf)) + break; + } + if (i == 9999) + return -2; + + int fd = ::open(buf, O_CREAT|O_RDWR, S_IREAD|S_IWRITE); + if (fd < 0) + return -3; + + lseek(file->getFd(), 0, SEEK_SET); + while (size > 0) { + bytes = read(file->getFd(), nibble, 32767); + write(fd, nibble, (bytes < size)?bytes:size); + size -= bytes; + } + // zero out the file + ::close(file->fd); + file->fd = ::open(file->path, O_TRUNC, S_IREAD|S_IWRITE); + ::close(file->fd); + file->fd = -77; // force file open by filemgr + // copy tmp file back (dumb, but must preserve file permissions) + lseek(fd, 0, SEEK_SET); + do { + bytes = read(fd, nibble, 32767); + write(file->getFd(), nibble, bytes); + } while (bytes == 32767); + + ::close(fd); + ::close(file->fd); + unlink(buf); // remove our tmp file + file->fd = -77; // causes file to be swapped out forcing open on next call to getFd() + } + else { // put offset back and return failure + lseek(file->getFd(), -1, SEEK_CUR); + return -1; + } + return 0; +} + + +int FileMgr::sysOpen(FileDesc *file) { + FileDesc **loop; + int openCount = 1; // because we are presently opening 1 file, and we need to be sure to close files to accomodate, if necessary + + for (loop = &files; *loop; loop = &((*loop)->next)) { + + if ((*loop)->fd > 0) { + if (++openCount > maxFiles) { + (*loop)->offset = lseek((*loop)->fd, 0, SEEK_CUR); + ::close((*loop)->fd); + (*loop)->fd = -77; + } + } + + if (*loop == file) { + if (*loop != files) { + *loop = (*loop)->next; + file->next = files; + files = file; + } + if ((!access(file->path, 04)) || ((file->mode & O_CREAT) == O_CREAT)) { // check for at least file exists / read access before we try to open + char tries = (((file->mode & O_RDWR) == O_RDWR) && (file->tryDowngrade)) ? 2 : 1; // try read/write if possible + for (int i = 0; i < tries; i++) { + if (i > 0) { + file->mode = (file->mode & ~O_RDWR); // remove write access + file->mode = (file->mode | O_RDONLY);// add read access + } + file->fd = ::open(file->path, file->mode, file->perms); + + if (file->fd >= 0) + break; + } + + if (file->fd >= 0) + lseek(file->fd, file->offset, SEEK_SET); + } + else file->fd = -1; + if (!*loop) + break; + } + } + return file->fd; +} + + +signed char FileMgr::existsFile(const char *ipath, const char *ifileName) +{ + int len = strlen(ipath) + ((ifileName)?strlen(ifileName):0) + 3; + char *ch; + char *path = new char [ len ]; + strcpy(path, ipath); + + if ((path[strlen(path)-1] == '\\') || (path[strlen(path)-1] == '/')) + path[strlen(path)-1] = 0; + + if (ifileName) { + ch = path + strlen(path); + sprintf(ch, "/%s", ifileName); + } + signed char retVal = !access(path, 04); + delete [] path; + return retVal; +} + + +signed char FileMgr::existsDir(const char *ipath, const char *idirName) +{ + char *ch; + int len = strlen(ipath) + ((idirName)?strlen(idirName):0) + 1; + if (idirName) + len += strlen(idirName); + char *path = new char [ len ]; + strcpy(path, ipath); + + if ((path[strlen(path)-1] == '\\') || (path[strlen(path)-1] == '/')) + path[strlen(path)-1] = 0; + + if (idirName) { + ch = path + strlen(path); + sprintf(ch, "/%s", idirName); + } + signed char retVal = !access(path, 04); + delete [] path; + return retVal; +} diff --git a/src/mgr/localemgr.cpp b/src/mgr/localemgr.cpp new file mode 100644 index 0000000..bc12f4c --- /dev/null +++ b/src/mgr/localemgr.cpp @@ -0,0 +1,184 @@ +/****************************************************************************** + * localemgr.cpp - implementation of class LocaleMgr used to interact with + * registered locales for a sword installation + * + * $Id: localemgr.cpp,v 1.12 2002/06/19 09:24:44 scribe Exp $ + * + * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> + +#ifndef __GNUC__ +#include <io.h> +#else +#include <unistd.h> +#include <unixstr.h> +#endif +#include <sys/stat.h> +#include <dirent.h> + +#include <swmgr.h> +#include <utilfuns.h> + +#include <localemgr.h> +#include <filemgr.h> + + +LocaleMgr LocaleMgr::systemLocaleMgr; + + +LocaleMgr::LocaleMgr(const char *iConfigPath) { + char *prefixPath = 0; + char *configPath = 0; + char configType = 0; + string path; + + defaultLocaleName = 0; + + char *lang = getenv ("LANG"); + if (lang) { + if (strlen(lang) > 0) + setDefaultLocaleName(lang); + else setDefaultLocaleName("en_us"); + } + else setDefaultLocaleName("en_us"); + + if (!iConfigPath) + SWMgr::findConfig(&configType, &prefixPath, &configPath); + else configPath = (char *)iConfigPath; + + if (prefixPath) { + switch (configType) { + case 2: + int i; + for (i = strlen(configPath)-1; ((i) && (configPath[i] != '/') && (configPath[i] != '\\')); i--); + configPath[i] = 0; + path = configPath; + path += "/"; + break; + default: + path = prefixPath; + if ((prefixPath[strlen(prefixPath)-1] != '\\') && (prefixPath[strlen(prefixPath)-1] != '/')) + path += "/"; + + break; + } + if (FileMgr::existsDir(path.c_str(), "locales.d")) { + path += "locales.d"; + loadConfigDir(path.c_str()); + } + } + + if (prefixPath) + delete [] prefixPath; + + if (configPath) + delete [] configPath; +} + + +LocaleMgr::~LocaleMgr() { + if (defaultLocaleName) + delete [] defaultLocaleName; + deleteLocales(); +} + + +void LocaleMgr::loadConfigDir(const char *ipath) { + DIR *dir; + struct dirent *ent; + string newmodfile; + LocaleMap::iterator it; + + if ((dir = opendir(ipath))) { + rewinddir(dir); + while ((ent = readdir(dir))) { + if ((strcmp(ent->d_name, ".")) && (strcmp(ent->d_name, ".."))) { + newmodfile = ipath; + if ((ipath[strlen(ipath)-1] != '\\') && (ipath[strlen(ipath)-1] != '/')) + newmodfile += "/"; + newmodfile += ent->d_name; + SWLocale *locale = new SWLocale(newmodfile.c_str()); + if (locale->getName()) { + it = locales.find(locale->getName()); + if (it != locales.end()) { + *((*it).second) += *locale; + delete locale; + } + else locales.insert(LocaleMap::value_type(locale->getName(), locale)); + } + else delete locale; + } + } + closedir(dir); + } +} + + +void LocaleMgr::deleteLocales() { + + LocaleMap::iterator it; + + for (it = locales.begin(); it != locales.end(); it++) + delete (*it).second; + + locales.erase(locales.begin(), locales.end()); +} + + +SWLocale *LocaleMgr::getLocale(const char *name) { + LocaleMap::iterator it; + + it = locales.find(name); + if (it != locales.end()) + return (*it).second; + + return 0; +} + + +list <string> LocaleMgr::getAvailableLocales() { + list <string> retVal; + for (LocaleMap::iterator it = locales.begin(); it != locales.end(); it++) + retVal.push_back((*it).second->getName()); + + return retVal; +} + + +const char *LocaleMgr::translate(const char *text, const char *localeName) { + SWLocale *target; + if (!localeName) { + localeName = getDefaultLocaleName(); + } + target = getLocale(localeName); + if (target) + return target->translate(text); + return text; +} + + +const char *LocaleMgr::getDefaultLocaleName() { + return defaultLocaleName; +} + + +void LocaleMgr::setDefaultLocaleName(const char *name) { + stdstr(&defaultLocaleName, name); +} diff --git a/src/mgr/markupfiltmgr.cpp b/src/mgr/markupfiltmgr.cpp new file mode 100644 index 0000000..8dc68ea --- /dev/null +++ b/src/mgr/markupfiltmgr.cpp @@ -0,0 +1,236 @@ +/****************************************************************************** + * swmarkupmgr.cpp - implementaion of class MarkupFilterMgr, subclass of + * used to transcode all module text to a requested + * markup. + * + * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <thmlplain.h> +#include <gbfplain.h> +#include <thmlgbf.h> +#include <gbfthml.h> +#include <thmlhtml.h> +#include <gbfhtml.h> +#include <plainhtml.h> +#include <thmlhtmlhref.h> +#include <gbfhtmlhref.h> +#include <thmlrtf.h> +#include <gbfrtf.h> +#include <gbfosis.h> +#include <thmlosis.h> + +#include <markupfiltmgr.h> + +#include <swmgr.h> + + +/****************************************************************************** + * MarkupFilterMgr Constructor - initializes instance of MarkupFilterMgr + * + * ENT: + * enc - Encoding format to emit + * mark - Markup format to emit + */ + +MarkupFilterMgr::MarkupFilterMgr (char mark, char enc) + : EncodingFilterMgr(enc) { + + markup = mark; + + CreateFilters(markup); +} + + +/****************************************************************************** + * MarkupFilterMgr Destructor - Cleans up instance of MarkupFilterMgr + */ + +MarkupFilterMgr::~MarkupFilterMgr() { + if (fromthml) + delete (fromthml); + if (fromgbf) + delete (fromgbf); + if (fromplain) + delete (fromplain); + if (fromosis) + delete (fromosis); +} + +/****************************************************************************** + * MarkupFilterMgr::Markup - sets/gets markup + * + * ENT: mark - new encoding or 0 to simply get the current markup + * + * RET: markup + */ +char MarkupFilterMgr::Markup(char mark) { + if (mark && mark != markup) { + markup = mark; + ModMap::const_iterator module; + + SWFilter * oldplain = fromplain; + SWFilter * oldthml = fromthml; + SWFilter * oldgbf = fromgbf; + SWFilter * oldosis = fromosis; + + CreateFilters(markup); + + for (module = getParentMgr()->Modules.begin(); module != getParentMgr()->Modules.end(); module++) + switch (module->second->Markup()) { + case FMT_THML: + if (oldthml != fromthml) { + if (oldthml) { + if (!fromthml) { + module->second->RemoveRenderFilter(oldthml); + } + else { + module->second->ReplaceRenderFilter(oldthml, fromthml); + } + } + else if (fromthml) { + module->second->AddRenderFilter(fromthml); + } + } + break; + case FMT_GBF: + if (oldgbf != fromgbf) { + if (oldgbf) { + if (!fromgbf) { + module->second->RemoveRenderFilter(oldgbf); + } + else { + module->second->ReplaceRenderFilter(oldgbf, fromgbf); + } + } + else if (fromgbf) { + module->second->AddRenderFilter(fromgbf); + } + break; + } + case FMT_PLAIN: + if (oldplain != fromplain) { + if (oldplain) { + if (!fromplain) { + module->second->RemoveRenderFilter(oldplain); + } + else { + module->second->ReplaceRenderFilter(oldplain, fromplain); + } + } + else if (fromplain) { + module->second->AddRenderFilter(fromplain); + } + break; + } + case FMT_OSIS: + if (oldosis != fromosis) { + if (oldosis) { + if (!fromosis) { + module->second->RemoveRenderFilter(oldosis); + } + else { + module->second->ReplaceRenderFilter(oldosis, fromosis); + } + } + else if (fromosis) { + module->second->AddRenderFilter(fromosis); + } + break; + } + } + + if (oldthml) + delete oldthml; + if (oldgbf) + delete oldgbf; + if (oldplain) + delete oldplain; + if (oldosis) + delete oldosis; + } + return markup; +} + +void MarkupFilterMgr::AddRenderFilters(SWModule *module, ConfigEntMap §ion) { + switch (module->Markup()) { + case FMT_THML: + if (fromthml) + module->AddRenderFilter(fromthml); + break; + case FMT_GBF: + if (fromgbf) + module->AddRenderFilter(fromgbf); + break; + case FMT_PLAIN: + if (fromplain) + module->AddRenderFilter(fromplain); + break; + case FMT_OSIS: + if (fromosis) + module->AddRenderFilter(fromosis); + break; + } +} + +void MarkupFilterMgr::CreateFilters(char markup) { + + switch (markup) { + case FMT_PLAIN: + fromplain = NULL; + fromthml = new ThMLPlain(); + fromgbf = new GBFPlain(); + fromosis = NULL; + break; + case FMT_THML: + fromplain = NULL; + fromthml = NULL; + fromgbf = new GBFThML(); + fromosis = NULL; + break; + case FMT_GBF: + fromplain = NULL; + fromthml = new ThMLGBF(); + fromgbf = NULL; + fromosis = NULL; + break; + case FMT_HTML: + fromplain = new PLAINHTML(); + fromthml = new ThMLHTML(); + fromgbf = new GBFHTML(); + fromosis = NULL; + break; + case FMT_HTMLHREF: + fromplain = NULL; + fromthml = new ThMLHTMLHREF(); + fromgbf = new GBFHTMLHREF(); + fromosis = NULL; + break; + case FMT_RTF: + fromplain = NULL; + fromthml = new ThMLRTF(); + fromgbf = new GBFRTF(); + fromosis = NULL; + break; + case FMT_OSIS: + fromplain = NULL; + fromthml = new ThMLOSIS(); + fromgbf = new GBFOSIS(); + fromosis = NULL; + break; + } + +} diff --git a/src/mgr/swcacher.cpp b/src/mgr/swcacher.cpp new file mode 100644 index 0000000..8128a70 --- /dev/null +++ b/src/mgr/swcacher.cpp @@ -0,0 +1,43 @@ +/****************************************************************************** + * swcacher.h - definition of class SWCacher used to provide an interface for + * objects that cache and want a standard interface for cleaning up. + * + * $Id: swcacher.cpp,v 1.1 2002/03/16 01:12:37 scribe Exp $ + * + * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <swcacher.h> + + +SWCacher::SWCacher() { +} + + +SWCacher::~SWCacher() { +} + + +void SWCacher::flush() { +} + +long SWCacher::resourceConsumption() { + return 0; +} + +long SWCacher::lastAccess() { + return 0; +} diff --git a/src/mgr/swconfig.cpp b/src/mgr/swconfig.cpp new file mode 100644 index 0000000..d73d475 --- /dev/null +++ b/src/mgr/swconfig.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** + * swconfig.cpp - implementation of Class SWConfig used for saving and + * retrieval of configuration information + * + * $Id: swconfig.cpp,v 1.9 2002/07/28 01:48:38 scribe Exp $ + * + * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <swconfig.h> +#include <utilfuns.h> + + +SWConfig::SWConfig(const char * ifilename) { + filename = ifilename; + Load(); +} + + +SWConfig::~SWConfig() { +} + + +char SWConfig::getline(FILE *fp, string &line) +{ + char retval = 0; + char buf[255]; + + line = ""; + + while (fgets(buf, 254, fp)) { + while (buf[strlen(buf)-1] == '\n' || buf[strlen(buf)-1] == '\r') + buf[strlen(buf)-1] = 0; + + if (buf[strlen(buf)-1] == '\\') { + buf[strlen(buf)-1] = 0; + line += buf; + continue; + } + line += buf; + + if (strlen(buf) < 253) { + retval = 1; + break; + } + } + return retval; +} + + +void SWConfig::Load() { + FILE *cfile; + char *buf, *data; + string line; + ConfigEntMap cursect; + string sectname; + bool first = true; + + Sections.erase(Sections.begin(), Sections.end()); + + if ((cfile = fopen(filename.c_str(), "r"))) { + while (getline(cfile, line)) { + buf = new char [ line.length() + 1 ]; + strcpy(buf, line.c_str()); + if (*strstrip(buf) == '[') { + if (!first) + Sections.insert(SectionMap::value_type(sectname, cursect)); + else first = false; + + cursect.erase(cursect.begin(), cursect.end()); + + strtok(buf, "]"); + sectname = buf+1; + } + else { + strtok(buf, "="); + if ((*buf) && (*buf != '=')) { + if ((data = strtok(NULL, ""))) + cursect.insert(ConfigEntMap::value_type(buf, strstrip(data))); + else cursect.insert(ConfigEntMap::value_type(buf, "")); + } + } + delete [] buf; + } + if (!first) + Sections.insert(SectionMap::value_type(sectname, cursect)); + + fclose(cfile); + } +} + + +void SWConfig::Save() { + FILE *cfile; + string buf; + SectionMap::iterator sit; + ConfigEntMap::iterator entry; + string sectname; + + if ((cfile = fopen(filename.c_str(), "w"))) { + + for (sit = Sections.begin(); sit != Sections.end(); sit++) { + buf = "\n["; + buf += (*sit).first.c_str(); + buf += "]\n"; + fputs(buf.c_str(), cfile); + for (entry = (*sit).second.begin(); entry != (*sit).second.end(); entry++) { + buf = (*entry).first.c_str(); + buf += "="; + buf += (*entry).second.c_str(); + buf += "\n"; + fputs(buf.c_str(), cfile); + } + } + fputs("\n", cfile); // so getline will find last line + fclose(cfile); + } +} + + +void SWConfig::augment(SWConfig &addFrom) { + + SectionMap::iterator section; + ConfigEntMap::iterator entry, start, end; + + for (section = addFrom.Sections.begin(); section != addFrom.Sections.end(); section++) { + for (entry = (*section).second.begin(); entry != (*section).second.end(); entry++) { + start = Sections[section->first].lower_bound(entry->first); + end = Sections[section->first].upper_bound(entry->first); + if (start != end) { + if (((++start) != end) + || ((++(addFrom.Sections[section->first].lower_bound(entry->first))) != addFrom.Sections[section->first].upper_bound(entry->first))) { + for (--start; start != end; start++) { + if (!strcmp(start->second.c_str(), entry->second.c_str())) + break; + } + if (start == end) + Sections[(*section).first].insert(ConfigEntMap::value_type((*entry).first, (*entry).second)); + } + else Sections[section->first][entry->first.c_str()] = entry->second.c_str(); + } + else Sections[section->first][entry->first.c_str()] = entry->second.c_str(); + } + } +} + + +ConfigEntMap & SWConfig::operator [] (const char *section) { + return Sections[section]; +} diff --git a/src/mgr/swfiltermgr.cpp b/src/mgr/swfiltermgr.cpp new file mode 100644 index 0000000..264b5a6 --- /dev/null +++ b/src/mgr/swfiltermgr.cpp @@ -0,0 +1,90 @@ +/****************************************************************************** + * swfiltermgr.cpp - definition of class SWFilterMgr used as an interface to + * manage filters on a module + * + * $Id: swfiltermgr.cpp,v 1.2 2001/11/30 12:04:34 scribe Exp $ + * + * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <swfiltermgr.h> + + +SWFilterMgr::SWFilterMgr() { +} + + +SWFilterMgr::~SWFilterMgr() { +} + + +void SWFilterMgr::setParentMgr(SWMgr *parentMgr) { + this->parentMgr = parentMgr; +} + + +SWMgr *SWFilterMgr::getParentMgr() { + return parentMgr; +} + + +void SWFilterMgr::AddGlobalOptions(SWModule * module, ConfigEntMap & section, ConfigEntMap::iterator start, ConfigEntMap::iterator end) { +} + + +void SWFilterMgr::AddLocalOptions(SWModule * module, ConfigEntMap & section, ConfigEntMap::iterator start, ConfigEntMap::iterator end) { +} + + +/** +* Adds the encoding filters which are defined in "section" to the SWModule object "module". +* @param module To this module the encoding filter(s) are added +* @param section We use this section to get a list of filters we should apply to the module +*/ + +void SWFilterMgr::AddEncodingFilters(SWModule * module, ConfigEntMap & section) { +} + + +/** +* Adds the render filters which are defined in "section" to the SWModule object "module". +* @param module To this module the render filter(s) are added +* @param section We use this section to get a list of filters we should apply to the module +*/ + +void SWFilterMgr::AddRenderFilters(SWModule * module, ConfigEntMap & section) { +} + + +/** +* Adds the strip filters which are defined in "section" to the SWModule object "module". +* @param module To this module the strip filter(s) are added +* @param section We use this section to get a list of filters we should apply to the module +*/ + +void SWFilterMgr::AddStripFilters(SWModule * module, ConfigEntMap & section) { +} + + +/** +* Adds the raw filters which are defined in "section" to the SWModule object "module". +* @param module To this module the raw filter(s) are added +* @param section We use this section to get a list of filters we should apply to the module +*/ + +void SWFilterMgr::AddRawFilters(SWModule * module, ConfigEntMap & section) { +} + diff --git a/src/mgr/swlocale.cpp b/src/mgr/swlocale.cpp new file mode 100644 index 0000000..d85d1eb --- /dev/null +++ b/src/mgr/swlocale.cpp @@ -0,0 +1,140 @@ +/****************************************************************************** + * swlocale.cpp - implementation of Class SWLocale used for retrieval + * of locale lookups + * + * $Id: swlocale.cpp,v 1.4 2002/07/28 01:48:38 scribe Exp $ + * + * Copyright 2000 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <swlocale.h> +#include <utilfuns.h> + + +SWLocale::SWLocale(const char * ifilename) { + ConfigEntMap::iterator confEntry; + + name = 0; + description = 0; + bookAbbrevs = 0; + BMAX = 0; + books = 0; + localeSource = new SWConfig(ifilename); + + confEntry = localeSource->Sections["Meta"].find("Name"); + if (confEntry != localeSource->Sections["Meta"].end()) + stdstr(&name, (*confEntry).second.c_str()); + + confEntry = localeSource->Sections["Meta"].find("Description"); + if (confEntry != localeSource->Sections["Meta"].end()) + stdstr(&description, (*confEntry).second.c_str()); +} + + +SWLocale::~SWLocale() { + + delete localeSource; + + if (description) + delete [] description; + + if (name) + delete [] name; + + if (bookAbbrevs) + delete [] bookAbbrevs; + + if (BMAX) { + for (int i = 0; i < 2; i++) + delete [] books[i]; + delete [] BMAX; + delete [] books; + } +} + + +const char *SWLocale::translate(const char *text) { + LookupMap::iterator entry; + + entry = lookupTable.find(text); + + if (entry == lookupTable.end()) { + ConfigEntMap::iterator confEntry; + confEntry = localeSource->Sections["Text"].find(text); + if (confEntry == localeSource->Sections["Text"].end()) + lookupTable.insert(LookupMap::value_type(text, text)); + else lookupTable.insert(LookupMap::value_type(text, (*confEntry).second.c_str())); + entry = lookupTable.find(text); + } + return (*entry).second.c_str(); +} + + +const char *SWLocale::getName() { + return name; +} + + +const char *SWLocale::getDescription() { + return description; +} + + +void SWLocale::augment(SWLocale &addFrom) { + *localeSource += *addFrom.localeSource; +} + + +const struct abbrev *SWLocale::getBookAbbrevs() { + static const char *nullstr = ""; + if (!bookAbbrevs) { + ConfigEntMap::iterator it; + int i; + int size = localeSource->Sections["Book Abbrevs"].size(); + bookAbbrevs = new struct abbrev[size + 1]; + for (i = 0, it = localeSource->Sections["Book Abbrevs"].begin(); it != localeSource->Sections["Book Abbrevs"].end(); it++, i++) { + bookAbbrevs[i].ab = (*it).first.c_str(); + bookAbbrevs[i].book = atoi((*it).second.c_str()); + } + bookAbbrevs[i].ab = nullstr; + bookAbbrevs[i].book = -1; + } + + return bookAbbrevs; +} + + +void SWLocale::getBooks(char **iBMAX, struct sbook ***ibooks) { + if (!BMAX) { + BMAX = new char [2]; + BMAX[0] = VerseKey::builtin_BMAX[0]; + BMAX[1] = VerseKey::builtin_BMAX[1]; + + books = new struct sbook *[2]; + books[0] = new struct sbook[BMAX[0]]; + books[1] = new struct sbook[BMAX[1]]; + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < BMAX[i]; j++) { + books[i][j] = VerseKey::builtin_books[i][j]; + books[i][j].name = translate(VerseKey::builtin_books[i][j].name); + } + } + } + + *iBMAX = BMAX; + *ibooks = books; +} diff --git a/src/mgr/swmgr.cpp b/src/mgr/swmgr.cpp new file mode 100644 index 0000000..ff36acc --- /dev/null +++ b/src/mgr/swmgr.cpp @@ -0,0 +1,1084 @@ +/****************************************************************************** + * swmgr.cpp - implementaion of class SWMgr used to interact with an install + * base of sword modules. + * + * $Id: swmgr.cpp,v 1.79 2002/08/09 05:53:48 scribe Exp $ + * + * Copyright 1998 CrossWire Bible Society (http://www.crosswire.org) + * CrossWire Bible Society + * P. O. Box 2528 + * Tempe, AZ 85280-2528 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> + +#ifndef __GNUC__ +#include <io.h> +#else +#include <unistd.h> +#include <unixstr.h> +#endif +#include <sys/stat.h> +#ifndef _MSC_VER +#include <iostream> +#endif +#include <dirent.h> + +#include <swmgr.h> +#include <rawtext.h> +#include <rawgenbook.h> +#include <rawcom.h> +#include <hrefcom.h> +#include <rawld.h> +#include <rawld4.h> +#include <utilfuns.h> +#include <gbfplain.h> +#include <thmlplain.h> +#include <gbfstrongs.h> +#include <gbffootnotes.h> +#include <gbfheadings.h> +#include <gbfmorph.h> +#include <thmlstrongs.h> +#include <thmlfootnotes.h> +#include <thmlheadings.h> +#include <thmlmorph.h> +#include <thmllemma.h> +#include <thmlscripref.h> +#include <cipherfil.h> +#include <rawfiles.h> +#include <ztext.h> +#include <zld.h> +#include <zcom.h> +#include <lzsscomprs.h> +#include <utf8greekaccents.h> +#include <utf8cantillation.h> +#include <utf8hebrewpoints.h> +#include <greeklexattribs.h> +#include <swfiltermgr.h> + + + +#ifdef _ICU_ +#include <utf8transliterator.h> +bool SWMgr::isICU = true; +#else +bool SWMgr::isICU = false; +#endif + +#ifndef EXCLUDEZLIB +#include <zipcomprs.h> +#endif + +bool SWMgr::debug = false; + +#ifdef GLOBCONFPATH +const char *SWMgr::globalConfPath = GLOBCONFPATH; +#else +const char *SWMgr::globalConfPath = "/etc/sword.conf:/usr/local/etc/sword.conf"; +#endif + +void SWMgr::init() { + SWFilter *tmpFilter = 0; + configPath = 0; + prefixPath = 0; + configType = 0; + myconfig = 0; + mysysconfig = 0; + homeConfig = 0; + + + cipherFilters.clear(); + optionFilters.clear(); + cleanupFilters.clear(); + + tmpFilter = new GBFStrongs(); + optionFilters.insert(FilterMap::value_type("GBFStrongs", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new GBFFootnotes(); + optionFilters.insert(FilterMap::value_type("GBFFootnotes", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new GBFMorph(); + optionFilters.insert(FilterMap::value_type("GBFMorph", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new GBFHeadings(); + optionFilters.insert(FilterMap::value_type("GBFHeadings", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new ThMLStrongs(); + optionFilters.insert(FilterMap::value_type("ThMLStrongs", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new ThMLFootnotes(); + optionFilters.insert(FilterMap::value_type("ThMLFootnotes", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new ThMLMorph(); + optionFilters.insert(FilterMap::value_type("ThMLMorph", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new ThMLHeadings(); + optionFilters.insert(FilterMap::value_type("ThMLHeadings", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new ThMLLemma(); + optionFilters.insert(FilterMap::value_type("ThMLLemma", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new ThMLScripref(); + optionFilters.insert(FilterMap::value_type("ThMLScripref", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new UTF8GreekAccents(); + optionFilters.insert(FilterMap::value_type("UTF8GreekAccents", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new UTF8HebrewPoints(); + optionFilters.insert(FilterMap::value_type("UTF8HebrewPoints", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new UTF8Cantillation(); + optionFilters.insert(FilterMap::value_type("UTF8Cantillation", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + + tmpFilter = new GreekLexAttribs(); + optionFilters.insert(FilterMap::value_type("GreekLexAttribs", tmpFilter)); + cleanupFilters.push_back(tmpFilter); + +// UTF8Transliterator needs to be handled differently because it should always available as an option, for all modules +#ifdef _ICU_ + transliterator = new UTF8Transliterator(); + optionFilters.insert(FilterMap::value_type("UTF8Transliterator", transliterator)); + options.push_back(transliterator->getOptionName()); + cleanupFilters.push_back(transliterator); +#endif + + gbfplain = new GBFPlain(); + cleanupFilters.push_back(gbfplain); + + thmlplain = new ThMLPlain(); + cleanupFilters.push_back(thmlplain); +} + + +SWMgr::SWMgr(SWFilterMgr *filterMgr) { + commonInit(0, 0, true, filterMgr); +} + + +SWMgr::SWMgr(SWConfig *iconfig, SWConfig *isysconfig, bool autoload, SWFilterMgr *filterMgr) { + commonInit(iconfig, isysconfig, autoload, filterMgr); +} + + +void SWMgr::commonInit(SWConfig * iconfig, SWConfig * isysconfig, bool autoload, SWFilterMgr *filterMgr) { + this->filterMgr = filterMgr; + if (filterMgr) + filterMgr->setParentMgr(this); + + init(); + + if (iconfig) { + config = iconfig; + myconfig = 0; + } + else config = 0; + if (isysconfig) { + sysconfig = isysconfig; + mysysconfig = 0; + } + else sysconfig = 0; + + if (autoload) + Load(); +} + + +SWMgr::SWMgr(const char *iConfigPath, bool autoload, SWFilterMgr *filterMgr) { + + string path; + + this->filterMgr = filterMgr; + if (filterMgr) + filterMgr->setParentMgr(this); + + init(); + + path = iConfigPath; + if ((iConfigPath[strlen(iConfigPath)-1] != '\\') && (iConfigPath[strlen(iConfigPath)-1] != '/')) + path += "/"; + if (FileMgr::existsFile(path.c_str(), "mods.conf")) { + stdstr(&prefixPath, path.c_str()); + path += "mods.conf"; + stdstr(&configPath, path.c_str()); + } + else { + if (FileMgr::existsDir(path.c_str(), "mods.d")) { + stdstr(&prefixPath, path.c_str()); + path += "mods.d"; + stdstr(&configPath, path.c_str()); + configType = 1; + } + } + + config = 0; + sysconfig = 0; + + if (autoload && configPath) + Load(); +} + + +SWMgr::~SWMgr() { + + DeleteMods(); + + for (FilterList::iterator it = cleanupFilters.begin(); it != cleanupFilters.end(); it++) + delete (*it); + + if (homeConfig) + delete homeConfig; + + if (myconfig) + delete myconfig; + + if (prefixPath) + delete [] prefixPath; + + if (configPath) + delete [] configPath; + + if (filterMgr) + delete filterMgr; +} + + +void SWMgr::findConfig(char *configType, char **prefixPath, char **configPath, list<string> *augPaths) { + string path; + ConfigEntMap::iterator entry; + ConfigEntMap::iterator lastEntry; + + char *envsworddir = getenv ("SWORD_PATH"); + char *envhomedir = getenv ("HOME"); + + *configType = 0; + +#ifndef _MSC_VER + // check working directory +if (debug) + std::cerr << "Checking working directory for mods.conf..."; +#endif + + if (FileMgr::existsFile(".", "mods.conf")) { + +#ifndef _MSC_VER +if (debug) + std::cerr << "found\n"; +#endif + + stdstr(prefixPath, "./"); + stdstr(configPath, "./mods.conf"); + return; + } + +#ifndef _MSC_VER +if (debug) + std::cerr << "\nChecking working directory for mods.d..."; +#endif + + if (FileMgr::existsDir(".", "mods.d")) { + +#ifndef _MSC_VER +if (debug) + std::cerr << "found\n"; +#endif + + stdstr(prefixPath, "./"); + stdstr(configPath, "./mods.d"); + *configType = 1; + return; + } + + + // check environment variable SWORD_PATH +#ifndef _MSC_VER +if (debug) + std::cerr << "\nChecking SWORD_PATH..."; +#endif + + if (envsworddir != NULL) { + +#ifndef _MSC_VER +if (debug) + std::cerr << "found (" << envsworddir << ")\n"; +#endif + + path = envsworddir; + if ((envsworddir[strlen(envsworddir)-1] != '\\') && (envsworddir[strlen(envsworddir)-1] != '/')) + path += "/"; + +#ifndef _MSC_VER +if (debug) + std::cerr << "\nChecking $SWORD_PATH for mods.conf..."; +#endif + + if (FileMgr::existsFile(path.c_str(), "mods.conf")) { + +#ifndef _MSC_VER +if (debug) + std::cerr << "found\n"; +#endif + + stdstr(prefixPath, path.c_str()); + path += "mods.conf"; + stdstr(configPath, path.c_str()); + return; + } + +#ifndef _MSC_VER +if (debug) + std::cerr << "\nChecking $SWORD_PATH for mods.d..."; +#endif + + if (FileMgr::existsDir(path.c_str(), "mods.d")) { + +#ifndef _MSC_VER +if (debug) + std::cerr << "found\n"; +#endif + + stdstr(prefixPath, path.c_str()); + path += "mods.d"; + stdstr(configPath, path.c_str()); + *configType = 1; + return; + } + } + + + // check for systemwide globalConfPath + +#ifndef _MSC_VER +if (debug) + std::cerr << "\nParsing " << globalConfPath << "..."; +#endif + + char *globPaths = 0; + char *gfp; + stdstr(&globPaths, globalConfPath); + for (gfp = strtok(globPaths, ":"); gfp; gfp = strtok(0, ":")) { + + #ifndef _MSC_VER +if (debug) + std::cerr << "\nChecking for " << gfp << "..."; +#endif + + if (FileMgr::existsFile(gfp)) + break; + } + + if (gfp) { + +#ifndef _MSC_VER +if (debug) + std::cerr << "found\n"; +#endif + + SWConfig etcconf(gfp); + if ((entry = etcconf.Sections["Install"].find("DataPath")) != etcconf.Sections["Install"].end()) { + path = (*entry).second; + if (((*entry).second.c_str()[strlen((*entry).second.c_str())-1] != '\\') && ((*entry).second.c_str()[strlen((*entry).second.c_str())-1] != '/')) + path += "/"; + +#ifndef _MSC_VER +if (debug) + std::cerr << "DataPath in " << gfp << " is set to: " << path; +#endif + +#ifndef _MSC_VER +if (debug) + std::cerr << "\nChecking for mods.conf in DataPath "; +#endif + if (FileMgr::existsFile(path.c_str(), "mods.conf")) { + +#ifndef _MSC_VER +if (debug) + std::cerr << "found\n"; +#endif + + stdstr(prefixPath, path.c_str()); + path += "mods.conf"; + stdstr(configPath, path.c_str()); + *configType = 1; + } + +#ifndef _MSC_VER +if (debug) + std::cerr << "\nChecking for mods.d in DataPath "; +#endif + + if (FileMgr::existsDir(path.c_str(), "mods.d")) { + +#ifndef _MSC_VER +if (debug) + std::cerr << "found\n"; +#endif + + stdstr(prefixPath, path.c_str()); + path += "mods.d"; + stdstr(configPath, path.c_str()); + *configType = 1; + } + } + if (augPaths) { + augPaths->clear(); + entry = etcconf.Sections["Install"].lower_bound("AugmentPath"); + lastEntry = etcconf.Sections["Install"].upper_bound("AugmentPath"); + for (;entry != lastEntry; entry++) { + path = entry->second; + if ((entry->second.c_str()[strlen(entry->second.c_str())-1] != '\\') && (entry->second.c_str()[strlen(entry->second.c_str())-1] != '/')) + path += "/"; + augPaths->push_back(path); + } + } + } + + delete [] globPaths; + if (*configType) + return; + + // check ~/.sword/ + +#ifndef _MSC_VER +if (debug) + std::cerr << "\nChecking home directory for ~/.sword/mods.conf" << path; +#endif + + if (envhomedir != NULL) { + path = envhomedir; + if ((envhomedir[strlen(envhomedir)-1] != '\\') && (envhomedir[strlen(envhomedir)-1] != '/')) + path += "/"; + path += ".sword/"; + if (FileMgr::existsFile(path.c_str(), "mods.conf")) { + +#ifndef _MSC_VER +if (debug) + std::cerr << " found\n"; +#endif + + stdstr(prefixPath, path.c_str()); + path += "mods.conf"; + stdstr(configPath, path.c_str()); + return; + } + +#ifndef _MSC_VER +if (debug) + std::cerr << "\nChecking home directory for ~/.sword/mods.d" << path; +#endif + + if (FileMgr::existsDir(path.c_str(), "mods.d")) { + +#ifndef _MSC_VER +if (debug) + std::cerr << "found\n"; +#endif + + stdstr(prefixPath, path.c_str()); + path += "mods.d"; + stdstr(configPath, path.c_str()); + *configType = 2; + return; + } + } +} + + +void SWMgr::loadConfigDir(const char *ipath) +{ + DIR *dir; + struct dirent *ent; + string newmodfile; + + if ((dir = opendir(ipath))) { + rewinddir(dir); + while ((ent = readdir(dir))) { + if ((strcmp(ent->d_name, ".")) && (strcmp(ent->d_name, ".."))) { + newmodfile = ipath; + if ((ipath[strlen(ipath)-1] != '\\') && (ipath[strlen(ipath)-1] != '/')) + newmodfile += "/"; + newmodfile += ent->d_name; + if (config) { + SWConfig tmpConfig(newmodfile.c_str()); + *config += tmpConfig; + } + else config = myconfig = new SWConfig(newmodfile.c_str()); + } + } + closedir(dir); + if (!config) { // if no .conf file exist yet, create a default + newmodfile = ipath; + if ((ipath[strlen(ipath)-1] != '\\') && (ipath[strlen(ipath)-1] != '/')) + newmodfile += "/"; + newmodfile += "globals.conf"; + config = myconfig = new SWConfig(newmodfile.c_str()); + } + } +} + + +void SWMgr::augmentModules(const char *ipath) { + string path = ipath; + if ((ipath[strlen(ipath)-1] != '\\') && (ipath[strlen(ipath)-1] != '/')) + path += "/"; + if (FileMgr::existsDir(path.c_str(), "mods.d")) { + char *savePrefixPath = 0; + char *saveConfigPath = 0; + SWConfig *saveConfig = 0; + stdstr(&savePrefixPath, prefixPath); + stdstr(&prefixPath, path.c_str()); + path += "mods.d"; + stdstr(&saveConfigPath, configPath); + stdstr(&configPath, path.c_str()); + saveConfig = config; + config = myconfig = 0; + loadConfigDir(configPath); + + CreateMods(); + + stdstr(&prefixPath, savePrefixPath); + delete []savePrefixPath; + stdstr(&configPath, saveConfigPath); + delete []saveConfigPath; + (*saveConfig) += *config; + homeConfig = myconfig; + config = myconfig = saveConfig; + } +} + + +/*********************************************************************** + * SWMgr::Load - loads actual modules + * + * RET: status - 0 = ok; -1 no config found; 1 = no modules installed + * + */ + +signed char SWMgr::Load() { + signed char ret = 0; + + if (!config) { // If we weren't passed a config object at construction, find a config file + if (!configPath) // If we weren't passed a config path at construction... + findConfig(&configType, &prefixPath, &configPath, &augPaths); + if (configPath) { + if (configType) + loadConfigDir(configPath); + else config = myconfig = new SWConfig(configPath); + } + } + + if (config) { + SectionMap::iterator Sectloop, Sectend; + ConfigEntMap::iterator Entryloop, Entryend; + + DeleteMods(); + + for (Sectloop = config->Sections.lower_bound("Globals"), Sectend = config->Sections.upper_bound("Globals"); Sectloop != Sectend; Sectloop++) { // scan thru all 'Globals' sections + for (Entryloop = (*Sectloop).second.lower_bound("AutoInstall"), Entryend = (*Sectloop).second.upper_bound("AutoInstall"); Entryloop != Entryend; Entryloop++) // scan thru all AutoInstall entries + InstallScan((*Entryloop).second.c_str()); // Scan AutoInstall entry directory for new modules and install + } + if (configType) { // force reload on config object because we may have installed new modules + delete myconfig; + config = myconfig = 0; + loadConfigDir(configPath); + } + else config->Load(); + + CreateMods(); + + for (list<string>::iterator pathIt = augPaths.begin(); pathIt != augPaths.end(); pathIt++) { + augmentModules(pathIt->c_str()); + } +// augment config with ~/.sword/mods.d if it exists --------------------- + char *envhomedir = getenv ("HOME"); + if (envhomedir != NULL && configType != 2) { // 2 = user only + string path = envhomedir; + if ((envhomedir[strlen(envhomedir)-1] != '\\') && (envhomedir[strlen(envhomedir)-1] != '/')) + path += "/"; + path += ".sword/"; + augmentModules(path.c_str()); + } +// ------------------------------------------------------------------------- + if ( !Modules.size() ) // config exists, but no modules + ret = 1; + + } + else { + SWLog::systemlog->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>"); + ret = -1; + } + + return ret; +} + +SWModule *SWMgr::CreateMod(string name, string driver, ConfigEntMap §ion) +{ + string description, datapath, misc1; + ConfigEntMap::iterator entry; + SWModule *newmod = 0; + string lang, sourceformat, encoding; + signed char direction, enc, markup; + + description = ((entry = section.find("Description")) != section.end()) ? (*entry).second : (string)""; + lang = ((entry = section.find("Lang")) != section.end()) ? (*entry).second : (string)"en"; + sourceformat = ((entry = section.find("SourceType")) != section.end()) ? (*entry).second : (string)""; + encoding = ((entry = section.find("Encoding")) != section.end()) ? (*entry).second : (string)""; + datapath = prefixPath; + if ((prefixPath[strlen(prefixPath)-1] != '\\') && (prefixPath[strlen(prefixPath)-1] != '/')) + datapath += "/"; + misc1 += ((entry = section.find("DataPath")) != section.end()) ? (*entry).second : (string)""; + char *buf = new char [ strlen(misc1.c_str()) + 1 ]; + char *buf2 = buf; + strcpy(buf, misc1.c_str()); +// for (; ((*buf2) && ((*buf2 == '.') || (*buf2 == '/') || (*buf2 == '\\'))); buf2++); + for (; ((*buf2) && ((*buf2 == '/') || (*buf2 == '\\'))); buf2++); + if (*buf2) + datapath += buf2; + delete [] buf; + + section["AbsoluteDataPath"] = datapath; + + if (!stricmp(sourceformat.c_str(), "GBF")) + markup = FMT_GBF; + else if (!stricmp(sourceformat.c_str(), "ThML")) + markup = FMT_THML; + else if (!stricmp(sourceformat.c_str(), "OSIS")) + markup = FMT_OSIS; + else + markup = FMT_PLAIN; + + if (!stricmp(encoding.c_str(), "SCSU")) + enc = ENC_SCSU; + else if (!stricmp(encoding.c_str(), "UTF-8")) { + enc = ENC_UTF8; + } + else enc = ENC_LATIN1; + + if ((entry = section.find("Direction")) == section.end()) { + direction = DIRECTION_LTR; + } + else if (!stricmp((*entry).second.c_str(), "rtol")) { + direction = DIRECTION_RTL; + } + else if (!stricmp((*entry).second.c_str(), "bidi")) { + direction = DIRECTION_BIDI; + } + else { + direction = DIRECTION_LTR; + } + + if ((!stricmp(driver.c_str(), "zText")) || (!stricmp(driver.c_str(), "zCom"))) { + SWCompress *compress = 0; + int blockType = CHAPTERBLOCKS; + misc1 = ((entry = section.find("BlockType")) != section.end()) ? (*entry).second : (string)"CHAPTER"; + if (!stricmp(misc1.c_str(), "VERSE")) + blockType = VERSEBLOCKS; + else if (!stricmp(misc1.c_str(), "CHAPTER")) + blockType = CHAPTERBLOCKS; + else if (!stricmp(misc1.c_str(), "BOOK")) + blockType = BOOKBLOCKS; + + misc1 = ((entry = section.find("CompressType")) != section.end()) ? (*entry).second : (string)"LZSS"; +#ifndef EXCLUDEZLIB + if (!stricmp(misc1.c_str(), "ZIP")) + compress = new ZipCompress(); + else +#endif + if (!stricmp(misc1.c_str(), "LZSS")) + compress = new LZSSCompress(); + + if (compress) { + if (!stricmp(driver.c_str(), "zText")) + newmod = new zText(datapath.c_str(), name.c_str(), description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str()); + else newmod = new zCom(datapath.c_str(), name.c_str(), description.c_str(), blockType, compress, 0, enc, direction, markup, lang.c_str()); + } + } + + if (!stricmp(driver.c_str(), "RawText")) { + newmod = new RawText(datapath.c_str(), name.c_str(), description.c_str(), 0, enc, direction, markup, lang.c_str()); + } + + // backward support old drivers + if (!stricmp(driver.c_str(), "RawGBF")) { + newmod = new RawText(datapath.c_str(), name.c_str(), description.c_str(), 0, enc, direction, markup, lang.c_str()); + } + + if (!stricmp(driver.c_str(), "RawCom")) { + newmod = new RawCom(datapath.c_str(), name.c_str(), description.c_str(), 0, enc, direction, markup, lang.c_str()); + } + + if (!stricmp(driver.c_str(), "RawFiles")) { + newmod = new RawFiles(datapath.c_str(), name.c_str(), description.c_str(), 0, enc, direction, markup, lang.c_str()); + } + + if (!stricmp(driver.c_str(), "HREFCom")) { + misc1 = ((entry = section.find("Prefix")) != section.end()) ? (*entry).second : (string)""; + newmod = new HREFCom(datapath.c_str(), misc1.c_str(), name.c_str(), description.c_str()); + } + + if (!stricmp(driver.c_str(), "RawLD")) + newmod = new RawLD(datapath.c_str(), name.c_str(), description.c_str(), 0, enc, direction, markup, lang.c_str()); + + if (!stricmp(driver.c_str(), "RawLD4")) + newmod = new RawLD4(datapath.c_str(), name.c_str(), description.c_str(), 0, enc, direction, markup, lang.c_str()); + + if (!stricmp(driver.c_str(), "zLD")) { + SWCompress *compress = 0; + int blockCount; + misc1 = ((entry = section.find("BlockCount")) != section.end()) ? (*entry).second : (string)"200"; + blockCount = atoi(misc1.c_str()); + blockCount = (blockCount) ? blockCount : 200; + + misc1 = ((entry = section.find("CompressType")) != section.end()) ? (*entry).second : (string)"LZSS"; +#ifndef EXCLUDEZLIB + if (!stricmp(misc1.c_str(), "ZIP")) + compress = new ZipCompress(); + else +#endif + if (!stricmp(misc1.c_str(), "LZSS")) + compress = new LZSSCompress(); + + if (compress) { + newmod = new zLD(datapath.c_str(), name.c_str(), description.c_str(), blockCount, compress, 0, enc, direction, markup, lang.c_str()); + } + } + + if (!stricmp(driver.c_str(), "RawGenBook")) { + newmod = new RawGenBook(datapath.c_str(), name.c_str(), description.c_str(), 0, enc, direction, markup, lang.c_str()); + } + // if a specific module type is set in the config, use this + if ((entry = section.find("Type")) != section.end()) + newmod->Type(entry->second.c_str()); + + newmod->setConfig(§ion); + return newmod; +} + + +void SWMgr::AddGlobalOptions(SWModule *module, ConfigEntMap §ion, ConfigEntMap::iterator start, ConfigEntMap::iterator end) { + for (;start != end; start++) { + FilterMap::iterator it; + it = optionFilters.find((*start).second); + if (it != optionFilters.end()) { + module->AddOptionFilter((*it).second); // add filter to module and option as a valid option + OptionsList::iterator loop; + for (loop = options.begin(); loop != options.end(); loop++) { + if (!strcmp((*loop).c_str(), (*it).second->getOptionName())) + break; + } + if (loop == options.end()) // if we have not yet included the option + options.push_back((*it).second->getOptionName()); + } + } + if (filterMgr) + filterMgr->AddGlobalOptions(module, section, start, end); +#ifdef _ICU_ + module->AddOptionFilter(transliterator); +#endif +} + + +void SWMgr::AddLocalOptions(SWModule *module, ConfigEntMap §ion, ConfigEntMap::iterator start, ConfigEntMap::iterator end) +{ + for (;start != end; start++) { + FilterMap::iterator it; + it = optionFilters.find((*start).second); + if (it != optionFilters.end()) { + module->AddOptionFilter((*it).second); // add filter to module + } + } + + if (filterMgr) + filterMgr->AddLocalOptions(module, section, start, end); +} + + +void SWMgr::AddRawFilters(SWModule *module, ConfigEntMap §ion) { + string sourceformat, cipherKey; + ConfigEntMap::iterator entry; + + cipherKey = ((entry = section.find("CipherKey")) != section.end()) ? (*entry).second : (string)""; + if (!cipherKey.empty()) { + SWFilter *cipherFilter = new CipherFilter(cipherKey.c_str()); + cipherFilters.insert(FilterMap::value_type(module->Name(), cipherFilter)); + cleanupFilters.push_back(cipherFilter); + module->AddRawFilter(cipherFilter); + } + + if (filterMgr) + filterMgr->AddRawFilters(module, section); +} + + +void SWMgr::AddEncodingFilters(SWModule *module, ConfigEntMap §ion) { + + if (filterMgr) + filterMgr->AddEncodingFilters(module, section); +} + + +void SWMgr::AddRenderFilters(SWModule *module, ConfigEntMap §ion) { + string sourceformat; + ConfigEntMap::iterator entry; + + sourceformat = ((entry = section.find("SourceType")) != section.end()) ? (*entry).second : (string)""; + + // Temporary: To support old module types + // TODO: Remove at 1.6.0 release? + if (sourceformat.empty()) { + sourceformat = ((entry = section.find("ModDrv")) != section.end()) ? (*entry).second : (string)""; + if (!stricmp(sourceformat.c_str(), "RawGBF")) + sourceformat = "GBF"; + else sourceformat = ""; + } + +// process module - eg. follows +// if (!stricmp(sourceformat.c_str(), "GBF")) { +// module->AddRenderFilter(gbftortf); +// } + + if (filterMgr) + filterMgr->AddRenderFilters(module, section); + +} + + +void SWMgr::AddStripFilters(SWModule *module, ConfigEntMap §ion) +{ + string sourceformat; + ConfigEntMap::iterator entry; + + sourceformat = ((entry = section.find("SourceType")) != section.end()) ? (*entry).second : (string)""; + // Temporary: To support old module types + if (sourceformat.empty()) { + sourceformat = ((entry = section.find("ModDrv")) != section.end()) ? (*entry).second : (string)""; + if (!stricmp(sourceformat.c_str(), "RawGBF")) + sourceformat = "GBF"; + else sourceformat = ""; + } + + if (!stricmp(sourceformat.c_str(), "GBF")) { + module->AddStripFilter(gbfplain); + } + else if (!stricmp(sourceformat.c_str(), "ThML")) { + module->AddStripFilter(thmlplain); + } + + if (filterMgr) + filterMgr->AddStripFilters(module, section); + +} + + +void SWMgr::CreateMods() { + SectionMap::iterator it; + ConfigEntMap::iterator start; + ConfigEntMap::iterator end; + ConfigEntMap::iterator entry; + SWModule *newmod; + string driver, misc1; + for (it = config->Sections.begin(); it != config->Sections.end(); it++) { + ConfigEntMap §ion = (*it).second; + newmod = 0; + + driver = ((entry = section.find("ModDrv")) != section.end()) ? (*entry).second : (string)""; + if (!driver.empty()) { + newmod = CreateMod((*it).first, driver, section); + if (newmod) { + start = (*it).second.lower_bound("GlobalOptionFilter"); + end = (*it).second.upper_bound("GlobalOptionFilter"); + AddGlobalOptions(newmod, section, start, end); + + start = (*it).second.lower_bound("LocalOptionFilter"); + end = (*it).second.upper_bound("LocalOptionFilter"); + AddLocalOptions(newmod, section, start, end); + + AddRawFilters(newmod, section); + AddStripFilters(newmod, section); + AddRenderFilters(newmod, section); + AddEncodingFilters(newmod, section); + + Modules.insert(ModMap::value_type(newmod->Name(), newmod)); + } + } + } +} + + +void SWMgr::DeleteMods() { + + ModMap::iterator it; + + for (it = Modules.begin(); it != Modules.end(); it++) + delete (*it).second; + + Modules.clear(); +} + + +void SWMgr::InstallScan(const char *dirname) +{ + DIR *dir; + struct dirent *ent; + int conffd = 0; + string newmodfile; + string targetName; + + if (!access(dirname, 04)) { + if ((dir = opendir(dirname))) { + rewinddir(dir); + while ((ent = readdir(dir))) { + if ((strcmp(ent->d_name, ".")) && (strcmp(ent->d_name, ".."))) { + newmodfile = dirname; + if ((dirname[strlen(dirname)-1] != '\\') && (dirname[strlen(dirname)-1] != '/')) + newmodfile += "/"; + newmodfile += ent->d_name; + if (configType) { + if (config > 0) + close(conffd); + targetName = configPath; + if ((configPath[strlen(configPath)-1] != '\\') && (configPath[strlen(configPath)-1] != '/')) + targetName += "/"; + targetName += ent->d_name; + conffd = open(targetName.c_str(), O_WRONLY|O_CREAT, S_IREAD|S_IWRITE); + } + else { + if (conffd < 1) { + conffd = open(config->filename.c_str(), O_WRONLY|O_APPEND); + if (conffd > 0) + lseek(conffd, 0L, SEEK_END); + } + } + AddModToConfig(conffd, newmodfile.c_str()); + unlink(newmodfile.c_str()); + } + } + if (conffd > 0) + close(conffd); + closedir(dir); + } + } +} + + +char SWMgr::AddModToConfig(int conffd, const char *fname) +{ + int modfd; + char ch; + + SWLog::systemlog->LogTimedInformation("Found new module [%s]. Installing...", fname); + modfd = open(fname, O_RDONLY); + ch = '\n'; + write(conffd, &ch, 1); + while (read(modfd, &ch, 1) == 1) + write(conffd, &ch, 1); + ch = '\n'; + write(conffd, &ch, 1); + close(modfd); + return 0; +} + + +void SWMgr::setGlobalOption(const char *option, const char *value) +{ + for (FilterMap::iterator it = optionFilters.begin(); it != optionFilters.end(); it++) { + if ((*it).second->getOptionName()) { + if (!stricmp(option, (*it).second->getOptionName())) + (*it).second->setOptionValue(value); + } + } +} + + +const char *SWMgr::getGlobalOption(const char *option) +{ + for (FilterMap::iterator it = optionFilters.begin(); it != optionFilters.end(); it++) { + if ((*it).second->getOptionName()) { + if (!stricmp(option, (*it).second->getOptionName())) + return (*it).second->getOptionValue(); + } + } + return 0; +} + + +const char *SWMgr::getGlobalOptionTip(const char *option) +{ + for (FilterMap::iterator it = optionFilters.begin(); it != optionFilters.end(); it++) { + if ((*it).second->getOptionName()) { + if (!stricmp(option, (*it).second->getOptionName())) + return (*it).second->getOptionTip(); + } + } + return 0; +} + + +OptionsList SWMgr::getGlobalOptions() +{ + return options; +} + + +OptionsList SWMgr::getGlobalOptionValues(const char *option) +{ + OptionsList options; + for (FilterMap::iterator it = optionFilters.begin(); it != optionFilters.end(); it++) { + if ((*it).second->getOptionName()) { + if (!stricmp(option, (*it).second->getOptionName())) { + options = (*it).second->getOptionValues(); + break; // just find the first one. All option filters with the same option name should expect the same values + } + } + } + return options; +} + + +signed char SWMgr::setCipherKey(const char *modName, const char *key) { + FilterMap::iterator it; + ModMap::iterator it2; + + // check for filter that already exists + it = cipherFilters.find(modName); + if (it != cipherFilters.end()) { + ((CipherFilter *)(*it).second)->getCipher()->setCipherKey(key); + return 0; + } + // check if module exists + else { + it2 = Modules.find(modName); + if (it2 != Modules.end()) { + SWFilter *cipherFilter = new CipherFilter(key); + cipherFilters.insert(FilterMap::value_type(modName, cipherFilter)); + cleanupFilters.push_back(cipherFilter); + (*it2).second->AddRawFilter(cipherFilter); + return 0; + } + } + return -1; +} |