summaryrefslogtreecommitdiffstats
path: root/lib/libsi18n
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /lib/libsi18n
downloadds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.gz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.xz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'lib/libsi18n')
-rw-r--r--lib/libsi18n/Makefile155
-rw-r--r--lib/libsi18n/acclanglist.c187
-rw-r--r--lib/libsi18n/coreres.c113
-rw-r--r--lib/libsi18n/coreres.h15
-rw-r--r--lib/libsi18n/getlang.c294
-rw-r--r--lib/libsi18n/getstrmem.c123
-rw-r--r--lib/libsi18n/getstrmem.h1156
-rw-r--r--lib/libsi18n/getstrprop.c137
-rw-r--r--lib/libsi18n/gsslapd.h37
-rw-r--r--lib/libsi18n/makstrdb.c221
-rw-r--r--lib/libsi18n/propset.c404
-rw-r--r--lib/libsi18n/propset.h43
-rw-r--r--lib/libsi18n/reshash.c264
-rw-r--r--lib/libsi18n/reshash.h54
-rw-r--r--lib/libsi18n/txtfile.c130
-rw-r--r--lib/libsi18n/txtfile.h45
16 files changed, 3378 insertions, 0 deletions
diff --git a/lib/libsi18n/Makefile b/lib/libsi18n/Makefile
new file mode 100644
index 00000000..9b1c9c2e
--- /dev/null
+++ b/lib/libsi18n/Makefile
@@ -0,0 +1,155 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+# The libsi18n library support for getting strings from the
+# string database.
+
+MCOM_ROOT=../../..
+MODULE=LibsI18N
+include ../../nsdefs.mk
+
+NSDEFS_PRODUCT = $(NS_PRODUCT)
+
+OBJDEST=$(OBJDIR)/lib/libsi18n
+
+L10NDIR = $(MCOM_ROOT)/ldapserver/l10n
+
+ifeq ($(ARCH), WINNT)
+CCOUT0= /Fo
+CCOUT1= /Fe
+LIBS=$(OBJDIR)/lib/libsi18n.lib
+ifeq ($(BSCINFO), yes)
+BSCS=$(OBJDIR)/lib/libsi18n.bsc
+endif
+else
+LIBS=$(OBJDIR)/lib/libsi18n.a
+CCOUT0= -o
+CCOUT1= -o
+endif
+
+ifeq ($(ARCH), IRIX)
+ ifeq ($(USE_N32), 1)
+ MYLDFLAG = -n32
+ else
+ MYLDFLAG =
+ endif
+else
+ MYLDFLAG =
+endif
+
+ifeq ($(USE_64), 1)
+ifeq ($(ARCH), HPUX)
+ MYLDFLAG = +DA2.0W
+endif
+ifeq ($(ARCH), SOLARIS)
+ MYLDFLAG = -xarch=v9
+endif
+endif
+ifeq ($(BUILD_MODULE), HTTP_ENTERPRISE)
+StringDatabase = ns-httpd.db
+L10N_SERVER = httpd
+DBTheaders = \
+ ../../httpd/src/dbthttpd.h \
+ ../../include/base/dbtbase.h \
+ ../../include/frame/dbtframe.h \
+ ../../include/httpdaemon/dbthttpdaemon.h \
+ ../../include/libaccess/dbtlibaccess.h \
+ ../../include/libadmin/dbtlibadmin.h \
+ ../../include/libir/dbtlibir.h \
+ gshttpd.h
+endif
+
+ifeq ($(BUILD_MODULE), DIRECTORY)
+ StringDatabase = ns-slapd.properties
+ DBTheaders = \
+ ../../httpd/src/dbthttpd.h \
+ ../../include/base/dbtbase.h \
+ ../../include/frame/dbtframe.h \
+ ../../include/httpdaemon/dbthttpdaemon.h \
+ ../../include/libaccess/dbtlibaccess.h \
+ ../../include/libadmin/dbtlibadmin.h \
+ ../../include/libir/dbtlibir.h \
+ ../../ldap/clients/dsgw/dbtdsgw.h \
+ gsslapd.h
+ endif
+
+
+ifeq ($(BUILD_MODULE), HTTP_PERSONAL)
+StringDatabase = ns-httpd.db
+L10N_SERVER = httpd
+DBTheaders = \
+ ../../httpd/src/dbthttpd.h \
+ ../../include/base/dbtbase.h \
+ ../../include/frame/dbtframe.h \
+ ../../include/httpdaemon/dbthttpdaemon.h \
+ ../../include/libaccess/dbtlibaccess.h \
+ ../../include/libadmin/dbtlibadmin.h \
+ gshttpd.h
+endif
+
+ifeq ($(BUILD_MODULE), HTTP_PROXY)
+StringDatabase = ns-proxy.db
+DBTheaders = \
+ ../../httpd/src/dbthttpd.h \
+ ../../include/base/dbtbase.h \
+ ../../include/frame/dbtframe.h \
+ ../../include/httpdaemon/dbthttpdaemon.h \
+ ../../include/libaccess/dbtlibaccess.h \
+ ../../include/libadmin/dbtlibadmin.h \
+ gsproxy.h
+endif
+
+ifeq ($(BUILD_MODULE), HTTP_ADMIN)
+StringDatabase = ns-admin.db
+L10N_SERVER = admserv
+DBTheaders = \
+ ../../admserv/src/dbtadmserv.h \
+ ../../admserv/cgi-src/dbtcgiadmin.h \
+ ../../admserv/user-forms/src/dbtuserforms.h \
+ ../../include/base/dbtbase.h \
+ ../../include/frame/dbtframe.h \
+ ../../include/httpdaemon/dbthttpdaemon.h \
+ ../../include/libaccess/dbtlibaccess.h \
+ ../../include/libadmin/dbtlibadmin.h \
+ ../../include/libir/dbtlibir.h \
+ gsadmserv.h
+endif
+
+include ../../nsconfig.mk
+
+MCC_INCLUDE += $(ADMINUTIL_INCLUDE)
+
+all: $(OBJDEST) $(LIBS) $(BSCS) $(OBJDEST)/$(StringDatabase)
+
+$(OBJDEST)/$(StringDatabase): makstrdb.c ../../include/i18n.h $(DBTheaders)
+ @echo "Building String Database for $(BUILD_MODULE) in"
+ @echo "$(OBJDEST)/$(StringDatabase)"
+ $(CC) -g $(CFLAGS) $(MCC_INCLUDE) -c makstrdb.c \
+ $(CCOUT0)$(OBJDEST)/makstrdb.o
+ $(CC) $(MYLDFLAG) -g $(OBJDEST)/makstrdb.o \
+ $(CCOUT1)$(OBJDEST)/makstrdb.exe
+ cd $(OBJDEST); ./makstrdb.exe
+ rm $(OBJDEST)/makstrdb.exe
+
+$(OBJDEST):
+ mkdir -p $(OBJDEST)
+
+OBJS = \
+ $(OBJDEST)/acclanglist.o \
+ $(OBJDEST)/getstrprop.o \
+ $(OBJDEST)/getlang.o \
+ $(OBJDEST)/coreres.o \
+ $(OBJDEST)/txtfile.o \
+ $(OBJDEST)/propset.o \
+ $(OBJDEST)/reshash.o
+
+
+
+$(LIBS): $(OBJS)
+ rm -f $@
+ $(AR) $(OBJS)
+ $(RANLIB) $@
diff --git a/lib/libsi18n/acclanglist.c b/lib/libsi18n/acclanglist.c
new file mode 100644
index 00000000..cc985cde
--- /dev/null
+++ b/lib/libsi18n/acclanglist.c
@@ -0,0 +1,187 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "i18n.h"
+
+
+/*
+ * Accept-Language = "Accept-Language" ":"
+ * 1#( language-range [ ";" "q" "=" qvalue ] )
+ * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
+ *
+ * NLS_AccLangList() assumes that "Accept-Language:" has already
+ * been stripped off. It takes as input
+ *
+ * 1#( ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) [ ";" "q" "=" qvalue ] )
+ *
+ * and returns a list of languages, ordered by qvalues, in
+ * the array NLS_ACCEPT_LANGUAGE_LIST.
+ *
+ * If there are to many languages (>NLS_MAX_ACCEPT_LANGUAGE) the excess
+ * is ignored. If the language-range is too long (>NLS_MAX_ACCEPT_LENGTH),
+ * the language-range is ignored. In these cases, NLS_AccLangList()
+ * will quietly return, perhaps with numLang = 0. numLang is
+ * returned by the function.
+ */
+
+
+static size_t
+AcceptLangList(const char* AcceptLanguage,
+ ACCEPT_LANGUAGE_LIST AcceptLanguageList)
+{
+ char* input;
+ char* cPtr;
+ char* cPtr1;
+ char* cPtr2;
+ int i;
+ int j;
+ int countLang = 0;
+
+ input = strdup(AcceptLanguage);
+ if (input == (char*)NULL){
+ return 0;
+ }
+
+ cPtr1 = input-1;
+ cPtr2 = input;
+
+ /* put in standard form */
+ while (*(++cPtr1)) {
+ if (isalpha(*cPtr1)) *cPtr2++ = tolower(*cPtr1); /* force lower case */
+ else if (isspace(*cPtr1)); /* ignore any space */
+ else if (*cPtr1=='-') *cPtr2++ = '_'; /* "-" -> "_" */
+ else if (*cPtr1=='*'); /* ignore "*" */
+ else *cPtr2++ = *cPtr1; /* else unchanged */
+ }
+ *cPtr2 = '\0';
+
+ countLang = 0;
+
+ if (strchr(input,';')) {
+ /* deal with the quality values */
+
+ float qvalue[MAX_ACCEPT_LANGUAGE];
+ float qSwap;
+ float bias = 0.0f;
+ char* ptrLanguage[MAX_ACCEPT_LANGUAGE];
+ char* ptrSwap;
+
+ cPtr = strtok(input,",");
+ while (cPtr) {
+ qvalue[countLang] = 1.0f;
+ if (cPtr1 = strchr(cPtr,';')) {
+ sscanf(cPtr1,";q=%f",&qvalue[countLang]);
+ *cPtr1 = '\0';
+ }
+ if (strlen(cPtr)<MAX_ACCEPT_LENGTH) { /* ignore if too long */
+ qvalue[countLang] -= (bias += 0.0001f); /* to insure original order */
+ ptrLanguage[countLang++] = cPtr;
+ if (countLang>=MAX_ACCEPT_LANGUAGE) break; /* quit if too many */
+ }
+ cPtr = strtok(NULL,",");
+ }
+
+ /* sort according to decending qvalue */
+ /* not a very good algorithm, but count is not likely large */
+ for ( i=0 ; i<countLang-1 ; i++ ) {
+ for ( j=i+1 ; j<countLang ; j++ ) {
+ if (qvalue[i]<qvalue[j]) {
+ qSwap = qvalue[i];
+ qvalue[i] = qvalue[j];
+ qvalue[j] = qSwap;
+ ptrSwap = ptrLanguage[i];
+ ptrLanguage[i] = ptrLanguage[j];
+ ptrLanguage[j] = ptrSwap;
+ }
+ }
+ }
+ for ( i=0 ; i<countLang ; i++ ) {
+ strcpy(AcceptLanguageList[i],ptrLanguage[i]);
+ }
+
+ } else {
+ /* simple case: no quality values */
+
+ cPtr = strtok(input,",");
+ while (cPtr) {
+ if (strlen(cPtr)<MAX_ACCEPT_LENGTH) { /* ignore if too long */
+ strcpy(AcceptLanguageList[countLang++],cPtr);
+ if (countLang>=MAX_ACCEPT_LANGUAGE) break; /* quit if too many */
+ }
+ cPtr = strtok(NULL,",");
+ }
+ }
+
+ free(input);
+
+ return countLang;
+}
+
+/*
+ * Get prioritized locale list from NLS_AcceptLangList
+ *
+ * Add additonal language to the list for fallback if locale
+ * name is language_region
+ *
+ */
+
+
+int
+XP_AccLangList(char* AcceptLanguage,
+ ACCEPT_LANGUAGE_LIST AcceptLanguageList)
+{
+ int i;
+ int n;
+ char *defaultLanguage = "en";
+ ACCEPT_LANGUAGE_LIST curLanguageList;
+ int index = 0;
+ char lang[3];
+ int k;
+
+ n = AcceptLangList(AcceptLanguage, curLanguageList);
+
+ if (n == 0)
+ return 0;
+
+ memset(lang, 0, 3);
+ for (i = 0; i < n; i++) {
+ if (*lang && (strncmp(lang, curLanguageList[i], 2) != 0)) {
+ /* add lang if current language is the last occurence in the list */
+ for (k = i+1; (k < n) && strncmp(curLanguageList[k],lang,2); k++);
+
+ if (k == n) {
+ strcpy(AcceptLanguageList[index++], lang);
+ *lang = '\0';
+ }
+ }
+
+ strcpy(AcceptLanguageList[index++], curLanguageList[i]);
+
+ /* Add current language for future appending.,make sure it's not on list */
+ if ((strlen(curLanguageList[i]) > 2) && (curLanguageList[i][2] == '_')) {
+ strncpy(lang, curLanguageList[i], 2);
+ for (k = 0; (k < index) && strcmp(AcceptLanguageList[k], lang); k++);
+
+ if (k != index) lang[0] = '\0';
+ }
+ }
+
+ if (lang[0] != '\0')
+ strcpy(AcceptLanguageList[index++], lang); /* add new lang */
+
+ /* Append defaultLanguage if it's not in the list */
+ for (i = 0; (i < index) && strcmp(AcceptLanguageList[i], defaultLanguage); i++);
+
+ if (i == index)
+ strcpy(AcceptLanguageList[index++], defaultLanguage);
+
+ return index;
+}
diff --git a/lib/libsi18n/coreres.c b/lib/libsi18n/coreres.c
new file mode 100644
index 00000000..5e438069
--- /dev/null
+++ b/lib/libsi18n/coreres.c
@@ -0,0 +1,113 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "i18n.h"
+
+#include "libadminutil/resource.h"
+#include "propset.h"
+
+#include "coreres.h"
+#if 0
+typedef struct ResourceS
+{
+ char *path;
+ char *package;
+ PropertiesSet *propset;
+} Resource;
+#endif
+
+Resource* core_res_init_resource(const char* path, const char* package)
+{
+ PropertiesSet *propset;
+ char *directory;
+ char *filename;
+ char *file_path;
+ char *p, *q;
+ char *filep;
+ Resource *hres;
+
+ /*********************
+ Create full path information
+ eg. ./es40/admin and cgi.bin.start ==>
+ ./es40/admin/cgi/bin/start.properties
+ **********************/
+ file_path = (char *) malloc (strlen(path) + strlen(package) + 20);
+
+
+ strcpy(file_path, path);
+ if (path[strlen(path)-1] != '/')
+ strcat(file_path, "/");
+
+ p = file_path + strlen(file_path);
+ q = (char *) package;
+
+ filep = p - 1;
+
+ /* Append package to file_path
+ p: end positon of path + 1
+ q: start position of package
+ */
+ while (q && *q) {
+ if (*q == '.') {
+ filep = q;
+ *p ++ = '/';
+ }
+ else
+ *p ++ = *q ++;
+
+ }
+ *p = '\0';
+
+ *filep = '\0';
+ filename = filep + 1;
+ directory = file_path;
+
+ propset = PropertiesInit (directory, filename);
+
+ if (propset == NULL)
+ return NULL;
+
+ hres = (Resource *) malloc(sizeof(Resource));
+ memset(hres, 0, sizeof(Resource));
+
+ hres->path = strdup(file_path);
+ hres->propset = propset;
+
+ if (file_path)
+ free (file_path);
+
+ return hres;
+}
+
+const char *core_res_getstring(Resource *hres, char *key, ACCEPT_LANGUAGE_LIST lang)
+{
+
+ if (key == NULL)
+ return NULL;
+
+ if (hres) {
+ return PropertiesGetString(hres->propset, key, lang);
+ }
+
+ return NULL;
+}
+
+void core_res_destroy_resource(Resource *hres)
+{
+ if (hres) {
+ if (hres->path)
+ free(hres->path);
+ if (hres->package)
+ free(hres->package);
+ PropertiesDestroy(hres->propset);
+
+ free(hres);
+ }
+}
+
diff --git a/lib/libsi18n/coreres.h b/lib/libsi18n/coreres.h
new file mode 100644
index 00000000..9d27060a
--- /dev/null
+++ b/lib/libsi18n/coreres.h
@@ -0,0 +1,15 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#ifndef CORERES_H
+#define CORERES_H
+
+#include "libadminutil/resource.h"
+
+Resource* core_res_init_resource(const char* path, const char* package);
+const char *core_res_getstring(Resource *hres, char *key, ACCEPT_LANGUAGE_LIST lang);
+void core_res_destroy_resource(Resource *hres);
+
+#endif
diff --git a/lib/libsi18n/getlang.c b/lib/libsi18n/getlang.c
new file mode 100644
index 00000000..5aa24d04
--- /dev/null
+++ b/lib/libsi18n/getlang.c
@@ -0,0 +1,294 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "libadmin/libadmin.h"
+#include "frame/conf.h" /* get access on global language setting */
+
+
+#include "i18n.h"
+
+/*********************************************************************
+ strReplace replaces the first instance of from in target with to.
+ from can be "": to is inserted at start of target.
+ to can be "": from is removed from target.
+ if from is not found, 0 is returned; else 1 is returned.
+ *********************************************************************/
+
+static int
+strReplace(char* target,char* from,char* to)
+{
+ /* replace /from/to/ in target */
+
+ char* pFrom;
+ char* pOldTail;
+ int lenTo;
+
+ pFrom = strstr(target,from);
+ if (pFrom) {
+ pOldTail = pFrom+strlen(from);
+ lenTo = strlen(to);
+ memmove(pFrom+lenTo,pOldTail,strlen(pOldTail)+1);
+ memcpy(pFrom,to,lenTo);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*********************************************************************
+ statFileDir is a wrapper to stat() that strips trailing slashes
+ because stat() on Windows seems to return -1 otherwise.
+*********************************************************************/
+
+int
+statFileDir(const char *path, struct stat *info) {
+ int ret, pathlen;
+ char *newpath = strdup(path);
+
+ if(newpath == NULL)
+ return -1;
+
+ for (pathlen = (strlen(newpath) - 1); pathlen >= 0; pathlen--) {
+ if (newpath[pathlen] == '/' || newpath[pathlen] == '\\') {
+ newpath[pathlen] = '\0';
+ } else {
+ break;
+ }
+ }
+
+ ret = stat(newpath, info);
+
+ if (newpath)
+ free(newpath);
+
+ return ret;
+}
+
+/*********************************************************************
+ GetLanguage is reserved for future use. These APIs are not belong
+ to this file. It needs to be moved to somewhere which knows what's
+ the current language setting.
+ *********************************************************************/
+
+static char emptyString[] = "";
+
+static char client_language[128] = "en";
+static char admin_language[128] = "en";
+static char default_language[128] = "en";
+
+void
+SetLanguage(int type, char *language)
+{
+ switch(type) {
+ case CLIENT_LANGUAGE:
+ if (language)
+ strcpy(client_language, language);
+ break;
+ case ADMIN_LANGUAGE:
+ if (language)
+ strcpy(admin_language, language);
+ break;
+ case DEFAULT_LANGUAGE:
+ if (language)
+ strcpy(default_language, language);
+ break;
+ }
+ return ;
+}
+
+
+
+char*
+GetClientLanguage(void)
+{
+ if (client_language)
+ return client_language;
+ else
+ return emptyString;
+}
+
+char*
+GetAdminLanguage(void)
+{
+ if (admin_language)
+ return admin_language;
+ else
+ return emptyString;
+}
+
+char*
+GetDefaultLanguage(void)
+{
+ if (default_language)
+ return default_language;
+ else
+ return "en";
+}
+
+/*********************************************************************
+ GetFileForLanguage looks for a file in the appropriate language.
+ *********************************************************************/
+
+NSAPI_PUBLIC
+int
+GetFileForLanguage(char* filePath,char* language,char* existingFilePath)
+{
+ /* Input: filePath,language
+ * filePath is of the form "/xxx/xxx/$$LANGDIR/xxx/xxx/filename"
+ * or of the form "/xxx/xxx/xxx/xxx/filename".
+ * filename may or may not have an extension.
+ * language is an Accept-Language list; each language-range will be
+ * tried as a subdirectory name and possibly as a filename modifier.
+ * "*" is ignored - default always provided if needed.
+ * "-" is replaced by "_".
+ * $$LANGDIR is a special string replaced by language. It is optional.
+ * For the default case, $$LANGDIR/ is replaced by nothing
+ * (so // is not created).
+ *
+ * Returned: existingPath
+ * existingFilePath is the path of a satisfactory, existing file.
+ * if no file is found, an empty string "" is returned.
+ *
+ * int returned: -1 if no file found (existingFilePath = "")
+ * 0 if default file is returned
+ * 1 if language file is returned (any in list)
+ *
+ * Example:
+ * filePath = "/path/$$LANGDIR/filename.ext"
+ * language = "language"
+ * GetDefaultLanguage() --> "default"
+ * LANG_DELIMIT = "_"
+ *
+ * 1. Try: "/path/language/filename.ext"
+ * 2. Try: "/path/filename_language.ext"
+ * 3. Try: "/path/default/filename.ext"
+ * 4. Try: "/path/filename_default.ext"
+ * 5. Try: "/path/filename.ext"
+ * else: ""
+ *
+ * Example:
+ * language = "en-us;q=0.6,ja;q=0.8,en-ca"
+ *
+ * 1. Try: "/path/en-ca/filename.ext"
+ * 2. Try: "/path/filename_en_ca.ext"
+ * 3. Try: "/path/ja/filename.ext"
+ * 4. Try: "/path/filename_ja.ext"
+ * 5. Try: "/path/en_us/filename.ext"
+ * 6. Try: "/path/filename_en_us.ext"
+ * 7. Try: "/path/default/filename.ext"
+ * 8. Try: "/path/filename_default.ext"
+ * 9. Try: "/path/filename.ext"
+ * else: ""
+ *
+ */
+
+#define LANG_DELIMIT '_'
+
+ int pattern;
+ char* pDot;
+ char* pSlash;
+
+ /* PRFileInfo info; */
+ struct stat info;
+
+ char lang_modifier[MAX_ACCEPT_LENGTH+1];
+
+ ACCEPT_LANGUAGE_LIST acceptLanguageList;
+ int numLang;
+ int iLang;
+ int iCase;
+
+
+ /* escape in case XP_InitStringDatabase has not been called */
+ if (filePath==NULL) {
+ *existingFilePath = '\0';
+ return -1;
+ }
+
+ pattern = (strstr(filePath,"$$LANGDIR/")!=NULL);
+
+ for ( iCase=1 ; iCase>=0 ; iCase-- ) {
+ if (iCase==1) { /* iCase=1 tries requested language */
+ numLang = XP_AccLangList(language,acceptLanguageList);
+ } else { /* iCase=0 tries default language */
+ numLang = XP_AccLangList(GetDefaultLanguage(),acceptLanguageList);
+ }
+
+ for ( iLang=0 ; iLang<numLang ; iLang++ ) {
+
+ /* Try: /path/language/filename.ext */
+ if (pattern) {
+ strcpy(existingFilePath,filePath);
+ strReplace(existingFilePath,"$$LANGDIR",acceptLanguageList[iLang]);
+
+ if (statFileDir(existingFilePath,&info)==0) {
+ return iCase;
+ }
+
+ /*
+ if (PR_GetFileInfo(existingFilePath,&info)==PR_SUCCESS) {
+ return iCase;
+ }
+ */
+ }
+
+ /* Try: /path/filename_language.ext */
+ {
+ strcpy(existingFilePath,filePath);
+ strReplace(existingFilePath,"$$LANGDIR/",emptyString);
+ pDot = strrchr(existingFilePath,'.');
+ pSlash = strrchr(existingFilePath,'/');
+ if (pSlash>=pDot) {
+ pDot = strchr(existingFilePath,'\0');
+ }
+ sprintf(lang_modifier,"%c%s",LANG_DELIMIT,acceptLanguageList[iLang]);
+ strReplace(pDot,emptyString,lang_modifier);
+
+ if (statFileDir(existingFilePath,&info)==0) {
+ return iCase;
+ }
+
+ /*
+ if (PR_GetFileInfo(existingFilePath,&info)==PR_SUCCESS) {
+ return iCase;
+ }
+ */
+ }
+ }
+ }
+
+ /* Try: /path/filename.ext */
+ {
+ strcpy(existingFilePath,filePath);
+ strReplace(existingFilePath,"$$LANGDIR/",emptyString);
+
+ if (statFileDir(existingFilePath,&info)==0) {
+ return 0;
+ }
+
+ /*
+ if (PR_GetFileInfo(existingFilePath,&info)==PR_SUCCESS) {
+ return 0;
+ }
+ */
+ }
+
+ /* Else: */
+ *existingFilePath = '\0';
+ return -1;
+}
+
+
+
+
+
+
diff --git a/lib/libsi18n/getstrmem.c b/lib/libsi18n/getstrmem.c
new file mode 100644
index 00000000..b49b4cc6
--- /dev/null
+++ b/lib/libsi18n/getstrmem.c
@@ -0,0 +1,123 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include <stdio.h>
+#include <string.h>
+
+#define COMPILE_STRINGS_IN_MEMORY
+
+static char emptyString[] = "";
+
+#ifdef COMPILE_STRINGS_IN_MEMORY
+
+typedef struct DATABIN {
+ char* pLibraryName;
+ char** pArrayOfLibraryStrings;
+ unsigned numberOfStringsInLibrary;
+ } DATABIN;
+
+#include "getstrmem.h"
+
+#endif
+
+#if 0 /* Example of getstrmem.h */
+ /* It is intended that this header file be generated by program dblink */
+
+ #define NUM_BUCKETS 2 /* must be power of 2 */
+
+ /* strings in library libalpha */
+ static char* libalpha[] = {
+ "",
+ "libalpha string 1",
+ "libalpha string 2",
+ "libalpha string 3",
+ "libalpha string 4",
+ emptyString };
+
+ /* strings in library libbeta */
+ static char* libbeta[] = {
+ "",
+ "libbeta string 1",
+ "libbeta string 2",
+ emptyString };
+
+ /* libraries in bucket for hashKey==0 */
+ static struct DATABIN bucket0[] = {
+ {emptyString, NULL, 0}};
+
+ /* libraries in bucket for hashKey==1 */
+ static struct DATABIN bucket1[] = {
+ {"libalpha", libalpha, 5},
+ {"libbeta", libbeta, 3},
+ {emptyString, NULL, 0}};
+
+ /* array of buckets */
+ static struct DATABIN* buckets[NUM_BUCKETS] = {
+ bucket0,
+ bucket1 };
+
+#endif /* end of example getstrmem.h */
+
+#define BUCKET_MASK NUM_BUCKETS-1
+
+char*
+XP_GetStringFromMemory(char* strLibraryName,int iToken)
+{
+ /*
+ * In memory model called by XP_GetStringFromDatabase
+ * does not use database (nsres, et al.).
+ *
+ * This function uses hash table for library lookup
+ * and direct lookup for string.
+ *
+ * This function is thread safe.
+ */
+
+#ifdef COMPILE_STRINGS_IN_MEMORY
+
+ unsigned hashKey;
+ int found = 0;
+ unsigned uToken = iToken;
+ char* cPtr;
+ DATABIN* pBucket;
+
+ /* calculate hash key */
+ hashKey = 0;
+ cPtr = strLibraryName;
+ while (*cPtr) {
+ hashKey += *(cPtr++);
+ }
+ hashKey &= BUCKET_MASK;
+
+ /* get bucket for this hash key */
+ pBucket = buckets[hashKey];
+
+ /* search overflow buckets */
+ while (*(pBucket->pLibraryName)!='\0') {
+ if (strcmp(pBucket->pLibraryName,strLibraryName)==0) {
+ found = 1;
+ break;
+ }
+ pBucket++;
+ }
+
+ if (!found) {
+ return emptyString;
+ }
+
+ if (uToken<=pBucket->numberOfStringsInLibrary) {
+ return pBucket->pArrayOfLibraryStrings[uToken];
+ } else {
+ /* string token out of range */
+ return emptyString;
+ }
+
+#else
+
+ return emptyString;
+
+#endif
+}
diff --git a/lib/libsi18n/getstrmem.h b/lib/libsi18n/getstrmem.h
new file mode 100644
index 00000000..edb6d754
--- /dev/null
+++ b/lib/libsi18n/getstrmem.h
@@ -0,0 +1,1156 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#define BUCKET_MASK NUM_BUCKETS-1
+typedef struct DATABIN {
+ char* pLibraryName;
+ char** pArrayOfLibraryStrings;
+ unsigned numberOfStringsInLibrary;
+ } DATABIN;
+
+/* It is intended that this header file be generated by program dblink */
+static char emptyString[] = "";
+
+#define NUM_BUCKETS 32 /* must be a power of 2 */
+
+/* strings in library libadmin */
+static char* libadminid[] = {"$DBT: libadmin in memory v1 $"};
+static char* libadmin[] = {
+ "",
+ " Help ",
+ " OK ",
+ " Reset ",
+ " Done ",
+ " Cancel ",
+ emptyString };
+
+/* libraries in bucket for hashKey==0 */
+static struct DATABIN bucket0[] = {
+ {"libadmin",libadmin,5},
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==1 */
+static struct DATABIN bucket1[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==2 */
+static struct DATABIN bucket2[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==3 */
+static struct DATABIN bucket3[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==4 */
+static struct DATABIN bucket4[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==5 */
+static struct DATABIN bucket5[] = {
+ {emptyString,NULL,0} };
+
+/* strings in library userforms */
+static char* userformsid[] = {"$DBT: userforms in memory v1 $"};
+static char* userforms[] = {
+ "",
+ "Error: could not open servers list file.<p>\n",
+ "Error: could not open %s server list file.<p>\n",
+ "Netscape Server Account",
+ "Server Account Management for %s",
+ "Server Account Management",
+ emptyString };
+
+/* libraries in bucket for hashKey==6 */
+static struct DATABIN bucket6[] = {
+ {"userforms",userforms,5},
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==7 */
+static struct DATABIN bucket7[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==8 */
+static struct DATABIN bucket8[] = {
+ {emptyString,NULL,0} };
+
+/* strings in library libaccess */
+static char* libaccessid[] = {"$DBT: libaccess in memory v1 $"};
+static char* libaccess[] = {
+ "",
+ "basic-ncsa",
+ "cannot open database %s",
+ "basic-ncsa",
+ "user %s password did not match database %s",
+ "basic-ncsa",
+ "cannot open connection to LDAP server on %s:%d",
+ "basic-ncsa",
+ "user %s password did not match LDAP on %s:%d",
+ "acl-state",
+ "missing realm",
+ "Unable to allocate ACL List Hash\n",
+ "ACLEvalBuildContext unable to PERM_MALLOC cache structure\n",
+ "ACLEvalBuildContext unable to create hash table\n",
+ "ACLEvalBuildContext unable to allocate ACE Entry\n",
+ "ACLEvalBuildContext unable to allocate ACE entry\n",
+ "ACLEvalBuildContext unable to allocate Boundary Entry\n",
+ "ACLEvalBuildContext failed.\n",
+ "ACL_EvalTestRights: an interim, absolute non-allow value was encountered. right=%s, value=%d\n",
+ "LASDnsBuild unable to allocate hash table header\n",
+ "LASDnsBuild unable to add key %s\n",
+ "LASDnsBuild unable to add key %s\n",
+ "LASDnsBuild unable to add key %s\n",
+ "LASDnsBuild unable to add key %s\n",
+ "LASDnsBuild unable to add key %s\n",
+ "LAS DNS build received request for attribute %s\n",
+ "LASDnsEval - illegal comparator %s\n",
+ "LASDnsEval unable to allocate Context struct\n\n",
+ "LASDnsEval unable to get session address %d\n",
+ "LASDnsEval unable to get DNS - error=%s\n",
+ "LAS Group Eval received request for attribute %s\n",
+ "LASGroupEval - illegal comparator %s\n",
+ "LASGroupEval - ran out of memory\n",
+ "LASGroupEval unable to get session address %d\n",
+ "LASGroupEval unable to get session address %d\n",
+ "LASGroupEval - couldn't locate getter for auth-user\n",
+ "LASGroupEval - Attribute getter for auth-user failed\n",
+ "LASGroupEval - Attribute getter didn't set auth-user\n",
+ "Check group membership of user \"%s\" for group \"%s\"\n",
+ "LDAPU_SUCCESS for group \"%s\"\n",
+ "LDAPU_FAILED for group \"%s\"\n",
+ "LAS_EVAL_FALSE\n",
+ "LAS_EVAL_TRUE\n",
+ "LASIpTreeAlloc - no memory\n",
+ "IP LAS unable to allocate tree node\n",
+ "IP LAS unable to allocate tree node\n",
+ "LAS IP build received request for attribute %s\n",
+ "LASIpEval - illegal comparator %s\n",
+ "LASIpEval unable to get session address - error=%s\n",
+ "LASIpEval unable to allocate Context struct\n\n",
+ "LASIpEval - reach 32 bits without conclusion value=%s",
+ "LAS Program Eval received request for attribute %s\n",
+ "LASProgramEval - illegal comparator %s\n",
+ "LASProgram unable to get session address %d\n",
+ "bin",
+ "LASProgramEval: request not of type admin or bin, passing.\n",
+ "LASProgramEval: check if program %s matches pattern %s.\n",
+ "LASProgramEval: Invalid wildcard expression %s.\n",
+ "LAS_EVAL_FALSE\n",
+ "LAS_EVAL_TRUE\n",
+ "Unexpected attribute in dayOfWeek - %s\n",
+ "Illegal comparator for dayOfWeek - %s\n",
+ "Unexpected attribute in timeOfDay - %s\n",
+ "LAS User Eval received request for attribute %s\n",
+ "LASUserEval - illegal comparator %s\n",
+ "LASUserEval - ran out of memory\n",
+ "LASUserEval unable to get session address %d\n",
+ "LASUserEval unable to get session address %d\n",
+ "LASGroupEval - couldn't locate getter for auth-user\n",
+ "LASGroupEval - Attribute getter for auth-user failed\n",
+ "LASGroupEval - Attribute getter didn't set auth-user\n",
+ "Check if uid == user (i.e. check \"%s\" == \"%s)\"\n",
+ "SUCCESS for user \"%s\"\n",
+ "FAILED for user \"%s\"\n",
+ "LAS_EVAL_FALSE\n",
+ "LAS_EVAL_TRUE\n",
+ "",
+ "LASProgram unable to get request address - error=%s",
+ "LASProgram rejecting request for program %s from pattern %s",
+ "ACL_CacheFlush: unable to parse file \"%s\"\n",
+ "ACL_CacheFlush: unable to concatenate ACL list \"%s\"\n",
+ "ACL_CacheFlush: unable to open and process the magnus file \"%s\"\n",
+ "Illegal comparator for timeOfDay - %s\n",
+ "ACL_EvalBuildContext unable to create hash table\n",
+ "ACL_EvalBuildContext unable to PERM_CALLOC cache structure\n",
+ "ACL_EvalBuildContext unable to allocate ACE entry\n",
+ "ACL_EvalBuildContext unable to allocate auth pointer array\n",
+ "ACL_EvalBuildContext unable to allocate auth plist\n",
+ "ACL_EvalTestRights: an interim, absolute non-allow value was encountered. right=%s, value=%s\n",
+ "ACL_INTEvalTestRights: call to ACL_EvalBuildContext returned failure status\n",
+ "ACL_ModuleRegister: module name is missing\n",
+ "ACL_ModuleRegister: call to module init function returned a failed status\n",
+ "ACL_GetAttribute: couldn't determine method for %s\n",
+ "ACL_GetAttribute: couldn't locate getter for %s",
+ "ACL_GetAttribute: attr getter failed to get %s",
+ "ACL_GetAttribute: attr getter failed to get %s",
+ "ACL_GetAttribute: All attribute getters declined for attr %s",
+ "ACL_DatabaseRegister: dbtype for database \"%s\" is not defined yet!",
+ "ACL_DatabaseRegister: database name is missing",
+ "Error reading the DB Map File: %s. Reason: %s",
+ "URL is missing for database %s",
+ "Invalid property value pair for database %s",
+ "\"default\" database must be an LDAP database",
+ "Multiple \"default\" databases are being registered",
+ "\"default\" LDAP database must be registered",
+ "LASGroupEval unable to get database name - error= %s",
+ "received invalid program expression %s",
+ "parse_ldap_url: database url is missing",
+ "parse_ldap_url: database name is missing",
+ "parse_ldap_url: error in parsing ldap url. Reason: %s",
+ "ldap password check: unable to get database name - error=%s",
+ "ldap password check: unable to get parsed database %s",
+ "ldap password check: couldn't initialize connection to LDAP. Reason: %s",
+ "ldap password check: LDAP error: \"%s\"",
+ "get_user_ismember_ldap unable to get database name - error=%s",
+ "get_user_ismember_ldap unable to get parsed database %s",
+ "ldap password check: couldn't initialize connection to LDAP. Reason: %s",
+ "get_user_ismember_ldap: group %s does not exist",
+ "get_user_ismember_ldap: LDAP error: \"%s\"",
+ "ACL_LDAPDatabaseHandle: %s is not a registered database",
+ "ACL_LDAPDatabaseHandle: %s is not an LDAP database",
+ "ACL_LDAPDatabaseHandle: out of memory",
+ "ACL_LDAPDatabaseHandle: couldn't initialize connection to LDAP. Reason: %s",
+ "ACL_LDAPDatabaseHandle: couldn't bind to LDAP server. Reason: %s",
+ "insufficient dynamic memory",
+ "error opening file, %s: %s",
+ "duplicate definition of %s",
+ "file %s, line %s: duplicate definition of %s",
+ "file %s, line %s: syntax error",
+ "file %s, line %s: %s is undefined",
+ "in acl %s, %s %s is undefined",
+ "database %s: error accessing %s",
+ "%s",
+ "file %s, line %s: invalid syntax",
+ "file %s, line %s: syntax error at \"%s\"",
+ "realm %s is not defined",
+ "error code = %d",
+ "internal ACL error",
+ "invalid argument",
+ "ACL_DatabaseRegister: dbtype for database \"%s\" is not defined yet!",
+ "couldn't determine dbtype from: %s",
+ "Failed to register database %s",
+ "ACL call returned failed status",
+ "file %s: ACL IO error - %s",
+ "acl_user_exists: out of memory",
+ "acl_user_exists: user doesn't exist anymore",
+ "acl_user_exists: plist error",
+ emptyString };
+
+/* libraries in bucket for hashKey==9 */
+static struct DATABIN bucket9[] = {
+ {"libaccess",libaccess,146},
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==10 */
+static struct DATABIN bucket10[] = {
+ {emptyString,NULL,0} };
+
+/* strings in library frame */
+static char* frameid[] = {"$DBT: frame in memory v1 $"};
+static char* frame[] = {
+ "",
+ "<TITLE>Not Found</TITLE><H1>Not Found</H1> The requested object does not exist on this server. The link you followed is either outdated, inaccurate, or the server has been instructed not to let you have it. ",
+ "Please inform the site administrator of the <A HREF=\"%s\">referring page</A>.",
+ "Your browser sent a request that this proxy could not understand.",
+ "Proper authorization is required for the administration of this proxy.\nEither your browser does not perform authorization, or your authorization\nhas failed.",
+ "Username authentication is required for using this proxy.\nEither your browser does not perform proxy authorization, or your\nauthorization has failed.",
+ "The proxy's access control configuration denies access to\nthe requested object through this proxy.",
+ "The proxy has encountered an internal error which prevents it from\nfulfilling your request. The most likely cause is a misconfiguration.\nPlease ask the administrator to look for messages in the proxy's error log.",
+ "This proxy server does not implement the requested method.",
+ "An error has occurred on the proxy server.",
+ "Your browser sent a query this server could not understand.",
+ "Proper authorization is required for this area. Either your browser does not perform authorization, or your authorization has failed.",
+ "Your client is not allowed to access the requested object.",
+ "This server has encountered an internal error which prevents it from fulfilling your request. The most likely cause is a misconfiguration. Please ask the administrator to look for messages in the server's error log.",
+ "This server does not implement the requested method.",
+ "An error has occurred.",
+ "Your browser sent a message this server could not understand.",
+ "<HTML><HEAD><TITLE>%s</TITLE></HEAD><BODY><H1>%s</H1>\nThis document has moved to a new <a href=\"%s\">location</a>. Please update your documents and hotlists accordingly.</BODY></HTML>",
+ "<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n<BODY><H1>%s</H1>\n%s\n</BODY></HTML>",
+ "process-uri-objects",
+ "cannot find template %s",
+ "process-uri-objects",
+ "no partial path after object processing",
+ "find-service",
+ "invalid shexp %s",
+ "find-service",
+ "invalid shexp %s",
+ "handle-processed",
+ "no way to service request for %s",
+ "finish-socks-request",
+ "close failed (%s), csd=%d",
+ "This beta software has expired.\n",
+ "mr_accept(%d)",
+ "Error issuing read on accept socket",
+ "acb_accept_connection(%d)",
+ "Error getting accept socket (%d)",
+ "Error in accept! (%d, %s)",
+ "Error creating new accept request",
+ "accepted connection: %d (NSPR %d)",
+ "Error creating new session structure",
+ "accel_read_request()",
+ "Error allocating request read buffer",
+ "Error issuing async read request",
+ "acb_read_request(%d, bytes %d)",
+ "acb_read_req(1 session = %d)",
+ "Error reading request (%d, %s)",
+ "Client aborted connection",
+ "Error reading request",
+ "Error creating new request",
+ "error occurred, closing %d, io was for %d",
+ "accel_async_scan_headers()",
+ "out of memory: accel_async_scan_headers",
+ "out of memory: accel_async_scan_headers",
+ "Error during async read (%d, %s)",
+ "scan-headers reports: line too long",
+ "scan-headers reports: too many headers",
+ "Error reading headers",
+ "scan-headers reports: header missing terminator (an empty line)",
+ "scan-headers reports: header was empty",
+ "name without value: got line \"%s\"",
+ "accel_send_plain_file()",
+ "accel_send_plain_file() - found request %d",
+ "Parse headers lost the URI!",
+ "accel_send_plain_file() - found uri %s",
+ "accel_send_plain_file() - found in cache?",
+ "malloc died!",
+ "Error writing back file\n",
+ "acb_send_plain_file(%d)",
+ "Error writing in acb_send_plain_file (%d, %s)",
+ "acb_close_connection(%d)",
+ "Errored IO in acb_close_connection (%d, %s)",
+ "Unable to close socket %d",
+ "accel-cache-insert: Error allocating entry",
+ "cache-init: server cache disabled",
+ "accel_file_cache: Error initializing file cache",
+ "accel_file_cache: Error creating cache",
+ "accel_file_cache_init: CacheHashSize < %d, using %d",
+ "accel_file_cache_init: CacheHashSize > %d, using %d",
+ "accel_file_cache_init: MaxNumberOfCachedFiles < %d, using %d",
+ "accel_file_cache_init: MaxNumberOfCachedFiles > %d, using %d",
+ "accel_file_cache_init: MaxNumberOfOpenCachedFiles < %d, using %d",
+ "accel_file_cache_init: MaxNumberOfOpenCachedFiles > %d, using %d",
+ "accel_file_cache: Error initializing file cache",
+ "file-cache: enabled = %s ",
+ "on",
+ "off",
+ "file-cache: MaxNumberOfCachedFiles %d (0x%x)",
+ "file-cache: CacheHashSize %d (0x%x)",
+ "file-cache: MaxNumberOfOpenCachedFiles %d (0x%x)",
+ "accel-cache-insert: Error allocating entry",
+ "file-cache-cleanup: munmap failed (%s)",
+ "file-cache-cleanup: found mmapped file \non system without mmap",
+ "file_cache_init: MaxTotalCachedFileSize < %d, using %d",
+ "file_cache_init: MaxTotalCachedFileSize > %d, using %d",
+ "file cache using mmap flags 0x%x",
+ "file cache using mmap prots 0x%x",
+ "file-cache-init: could not create lock",
+ "file-cache: unable to create temporary directory %s.\n",
+ "file-cache: unable to create temporary directory %s.\n",
+ "file-cache: GetTempPath() Cannot find temp directory to store file!",
+ "file-cache-init: set max cached file size to %d",
+ "file-cache-init: could not create lock",
+ "file_cache_destroy()",
+ "file-cache: Unable to get temp file name. Error %s",
+ "file-cache: Unable to get temp file name. Error %s",
+ "file-cache-insert: Error allocating entry",
+ "file-cache-create: Error opening file %s (%s)",
+ "file-cache-create: Error stat()ing file %s (%s)",
+ "file-cache-create: Error mmap()ing file %s (%s)",
+ "file-cache-create: malloc failure",
+ "file-cache-create: error case failed to munmap(%d, %d) (%s)",
+ "file-cache-valid: cannot stat %s",
+ "dir change: invalidating %s (%d)",
+ "file-cache: asynchronous file change notification failed.",
+ "dir change: offset %d, action %d, len %d, name %s",
+ "unable to check async file status",
+ "ReadDirectoryChangesW failure- unable to continue watching %s. Error is %s",
+ "file-cache-add-watch failure- unable to open directory %s. Error %s",
+ "ReadDirectoryChangesW failure- unable to start watching %s. Error %s",
+ "func_exec",
+ "no handler function given for directive",
+ "func_exec",
+ "cannot find function named %s",
+ "handle-request",
+ "method without URI",
+ "http-parse-request",
+ "while scanning HTTP headers, %s",
+ "handle-request",
+ "read from %s failed, error is %s",
+ "handle-request",
+ "request too long",
+ "start-http-response",
+ "write failed (%s)",
+ "start-http-response",
+ "write failed (%s)",
+ "http-status",
+ "%d is not a valid HTTP status code",
+ "finish-request",
+ "close failed (%s)",
+ "Unable to close socket for writing",
+ "os has %d objects",
+ "obj %d has no hash table at %d",
+ "obj %d has no param",
+ "obj %d name %s value %s",
+ ".....directives %d.......",
+ ".....directive %d",
+ ".......instance %d",
+ "...........param name %s value %s",
+ "ClearConfigurationParameters:RegCreateKey %s",
+ "ClearConfigurationParameters:RegEnumKey %s failed",
+ "obj.conf line %d: error in filter file \"%s\" at line %d: %s",
+ "obj.conf line %d: error in filter file \"%s\" at line %d: %s",
+ "Unable to allocate Subject property list.\n",
+ "Unable to set session ptr in Subject property list - error=%d\n",
+ "Unable to set request ptr in Subject property list - error=%d\n",
+ "file-cache-valid: cannot stat %s",
+ "file-cache-create: Error stat()ing file %s (%s)",
+ emptyString };
+
+/* libraries in bucket for hashKey==11 */
+static struct DATABIN bucket11[] = {
+ {"frame",frame,156},
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==12 */
+static struct DATABIN bucket12[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==13 */
+static struct DATABIN bucket13[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==14 */
+static struct DATABIN bucket14[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==15 */
+static struct DATABIN bucket15[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==16 */
+static struct DATABIN bucket16[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==17 */
+static struct DATABIN bucket17[] = {
+ {emptyString,NULL,0} };
+
+/* strings in library admserv */
+static char* admservid[] = {"$DBT: admserv in memory v1 $"};
+static char* admserv[] = {
+ "",
+ "Unauthorized host",
+ "Invalid URL",
+ "no filename extension",
+ "unrecognized type",
+ "<title>Internal Error</title>\n<h1>Internal Error</h1>\nThe administration server was unable to fulfill your request.<p>\n",
+ "Reason:",
+ emptyString };
+
+/* strings in library libir */
+static char* libirid[] = {"$DBT: libadmin in memory v1 $"};
+static char* libir[] = {
+ "",
+ "An I/O error occurred before all form data could be read.",
+ emptyString };
+
+/* libraries in bucket for hashKey==18 */
+static struct DATABIN bucket18[] = {
+ {"admserv",admserv,6},
+ {"libir",libir,1},
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==19 */
+static struct DATABIN bucket19[] = {
+ {emptyString,NULL,0} };
+
+/* strings in library httpdaemon */
+static char* httpdaemonid[] = {"$DBT: httpdaemon in memory v1 $"};
+static char* httpdaemon[] = {
+ "",
+ "Error in ConvertThreadToFiber",
+ "Error in ConvertThreadToFiber",
+ "Error in md_start_system",
+ "Error in CreateFiber - idlefiber",
+ "Error in GetQueuedCompletionStatus",
+ "Error creating completion port",
+ "Could not SetHandleNonInheritable (%s)",
+ "Error accept/read new conn",
+ "Error in Respond()",
+ "Error in RespondCompleted()",
+ "daemon: unable to fork new process (%s)\n",
+ "daemon: setsid failed (%s)\n",
+ "daemon: can't log pid to %s (%s)\n",
+ "warning: could not set group id to %d (%s)\n",
+ "warning: could not set user id to %d (%s)\n",
+ "warning: daemon is running as super-user\n",
+ "could not determine current user name\n",
+ "error: chroot to %s failed (%s)\n",
+ "WARNING! Netscape executable and library have different versions.\n",
+ "startup: listening to %s://%s, port %d as %s\n",
+ "startup: listening to %s://%s, port %d as %s\n",
+ "seminit failed (%s)\n",
+ "Using single threaded accepts.",
+ "Using multi threaded accepts.",
+ "Using partial single threaded accepts.",
+ "This machine has %d processors.",
+ "Error calling thr_seconcurrency(%d)- (%s)",
+ "Set conncurrency to %d.",
+ "can't fork new process (%s)",
+ "This beta software has expired.\n",
+ "can't create IPC pipe (%s)",
+ "write to wakeup pipe failed (%s)",
+ "select thread miss",
+ "startup failure: could not bind to port %d (%s)\n",
+ "startup failure: could not bind to port %d, IP address %s (%s)\n",
+ emptyString };
+
+/* libraries in bucket for hashKey==20 */
+static struct DATABIN bucket20[] = {
+ {"httpdaemon",httpdaemon,35},
+ {emptyString,NULL,0} };
+
+/* strings in library dsgw */
+static char* dsgwid[] = {"$DBT: dsgw in memory v1 $"};
+static char* dsgw[] = {
+ "",
+ "Unknown HTTP request method",
+ "Invalid or incomplete HTML form data",
+ "Out of memory",
+ "Required query/form input is missing",
+ "Illegal character in file path",
+ "Bad or missing configuration file",
+ "Unable to initialize LDAP",
+ "An error occurred while contacting the LDAP server",
+ "Unknown search object type",
+ "Unknown attribute label",
+ "Unknown match prompt",
+ "No search filters for object type",
+ "Unable to open HTML template file",
+ "Unknown search mode - use \"smart\", \"complex\", \"pattern\", or \"auth\"",
+ "Distinguished Name missing in URL",
+ "Unknown scope in URL (should be base, sub, or one)",
+ "Unrecognized URL or unknown error",
+ "Bad URL format",
+ "Internal error",
+ "Unable to write template index file",
+ "Unable to open template index file",
+ "Unable to read directory",
+ "LDAP SSL initialization failed (check the security path)",
+ "For the Users and Groups forms to work over SSL with the Administration Server, you must at least temporarily activate SSL through the <B>Admin Preferences|Encryption On/Off</B> form",
+ "Authentication credentials not found in authentication database",
+ "Error retrieving data from the authentication database",
+ "Your authentication credentials have expired",
+ "Unable to create authentication credentials",
+ "No distinguished name was provided when retrieving credentials",
+ "Cannot open authentication database",
+ "Could not append data to the authentication database",
+ "No Directory Manager is defined",
+ "No search string was provided. Please try again",
+ "Too many arguments on one line in the config. file",
+ "Failed to initialize Windows Sockets",
+ "Authentication credentials could not be obtained from the Administration Server",
+ "Distinguished Name missing in ldapdb:// URL",
+ "Unrecognized URL or unknown error",
+ "Bad URL format",
+ "An error occurred while initializing the local LDAP database",
+ "Unknown directory service type - use \"local\" or \"remote\"",
+ "An error occurred while reading the db configuration file",
+ "NSHOME/userdb path was NULL",
+ "The directory service configuration could not be updated.",
+ "The entry could not be read from the directory.",
+ "The LDAP database could not be erased.",
+ "You may not change entries besides your own.",
+ "Problem",
+ "Authentication Problem",
+ ".\n<P>You must re-authenticate before continuing.\n",
+ ".\n<P>You must re-authenticate before continuing.\n",
+ "unknown error",
+ "The operation was successful.",
+ "An internal error occurred in the server. This usually\nindicates a serious malfunction in the server and should be\nbrought to the attention of your server administrator.",
+ "The server could not understand the request which was sent to\nit by the gateway.",
+ "A time limit was exceeded in responding to your request. If\nyou are searching for entries, you may achieve better results\nif you are more specific in your search.",
+ "A size limit was exceeded in responding to your request. If\nyou are searching for entries, you may achieve better results\nif you are more specific in your search, because too many entries\nmatched your search criteria.",
+ "The gateway attempted to authenticate to the server using\na method the server does not understand.",
+ "The gateway attempted to authenticate to the server using an\nauthentication method which the server does not support. ",
+ "Your request could not be fulfilled, probably because the server\nthat was contacted does not contain the data you are looking\nfor. It is possible that a referral to another server was\nreturned but could not be followed. If you were trying to make\nchanges to the directory, it may be that the server that holds\nthe master copy of the data is not available.",
+ "Your request exceeded an administrative limit in the server.",
+ "A critical extension that the gateway requested is not available in this server.",
+ "The server was unable to process the request, because the\nrequest referred to an attribute which does not exist in the\nentry.",
+ "The server was unable to fulfill your request, because the\nrequest violates a database constraint.",
+ "The server could not add a value to the entry, because that\nvalue is already contained in the entry.",
+ "The server could not locate the entry. If adding a new entry,\nbe sure that the parent of the entry you are trying to add exists.\nIf you received this error while searching or viewing an entry, it indicates that the\nentry which was being searched for does not exist.",
+ "A distinguished name was not in the proper format. ",
+ "The entry you attempted to authenticate as does not have a\npassword set, or is missing other required authentication\ncredentials. You cannot authenticate as that entry until the\nappropriate attributes have been added by the directory manager. ",
+ "The password (or other authentication credentials) you supplied\nis incorrect. If you just changed your password, you might try exiting your browser and connecting again.",
+ "You do not have sufficient privileges to perform the operation. ",
+ "The server is too busy to service your request. Try again\nin a few minutes.",
+ "The LDAP server could not be contacted.",
+ "The server was unwilliing to process your request. Usually,\nthis indicates that serving your request would put a heavy load\non the server. It may also indicate that the server is not\nconfigured to process your request. If searching, you may wish\nto limit the scope of your search.",
+ "The directory server could not honor your request because it\nviolates the schema requirements. Typically, this means that you\nhave not provided a value for a required field. It could also mean\nthat the schema in the directory server needs to be updated.",
+ "The directory server will not allow you to delete or rename\nan entry if that entry has children. If you wish to do this, you\nmust first delete all the child entries.",
+ "The server was unable to add a new entry, or rename an existing\nentry, because an entry by that name already exists.",
+ "Your request would affect several directory servers.",
+ "The directory server could not be contacted. Contact your\ndirectory server administrator for assistance.",
+ "An error occured while sending data to the server.",
+ "An error occured while reading data from the server.",
+ "The server did not respond to the request. \nThe request timed out.",
+ "The server does not support the authentication method used\nby the gateway.",
+ "The search filter constructed by the gateway was in error.",
+ "The operation was cancelled at your request.",
+ "An internal error occurred in the library - a parameter was\nincorrect.",
+ "A connection to the directory server could not be opened. Contact your\ndirectory server administrator for assistance.",
+ "An unknown error was encountered.",
+ "Entry Already Exists",
+ "An entry named ",
+ "onMouseOver=\"window.status='Click here to view this entry'; return true\"",
+ " already exists.<P>Please choose another name and/or location.\n<P>\n",
+ "Parent entry does not exist",
+ "You cannot add an entry by the name:<P><B>%s</B>,<P>\nbecause the parent of that entry does not exist.<P>\nBefore you can add this entry, you must first add\n",
+ "its parent.\n",
+ "an entry named:<P><B>%s</B>.\n",
+ "Warning: no authentication (continuing)...\n",
+ "%s Directory Entry",
+ "<PRE>Entry DN: %s</PRE><P>\n",
+ "Changes to <B>%s</B> have been saved.",
+ "<B>%s</B> has been added.",
+ "<B>%s</B> has been deleted.",
+ "Renamed <B>%s</B> to <B>%s</B>.",
+ "<P><B>Note:</B> because you %s the entry you were \nauthenticated as, it was necessary to discard your \nauthentication credentials. You will need to authenticate \nagain to make additional changes.\n",
+ "deleted",
+ "renamed",
+ "changed the password of",
+ "Attribute %s was changed<BR>\n",
+ " NOT ASCII (%ld bytes)\n",
+ "No values were entered. Please try again.\n",
+ "No changes were made.\n",
+ "<P>Sending %s to the directory server...\n",
+ "information",
+ "changes",
+ "<P>Successfully added entry.\n",
+ "<P>Successfully edited entry. Your changes have been saved.\n",
+ "<P>Successfully deleted entry.\n",
+ "<PRE>The new name for the entry is: %s\n</PRE><HR>\n",
+ "<P>Successfully renamed entry.\n",
+ "You must provide the old password.",
+ "You must provide a new password. Please try again",
+ "The new and confirming passwords do not match. Please try again",
+ "<BR>The %s <B>%s</B> is already in use. Please choose a different one.<BR>\n",
+ "missing form data element \"%.100s\"",
+ "Initializing config info",
+ "Cannot open file.",
+ "Malformed dbconf file.",
+ "Missing property name in dbconf file.",
+ "Out of memory.",
+ "Missing directive in dbconf file.",
+ "Cannot open config file \"%s\"",
+ "Missing argument for \"authlifetime\" directive\n",
+ "Missing argument for \"dirmgr\" directive\n",
+ "Missing argument for \"baseurl\" directive\n",
+ "Bad URL provided for \"baseurl\" directive - the base DN is missing\n",
+ "parsing baseurl directive",
+ "Bad URL provided for \"baseurl\" directive - not an \"ldap://\" URL\n",
+ "\"ldaps://\" URLs are not yet supported\n",
+ "Missing arguments for \"template\" directive\n",
+ "Missing argument for \"sslrequired\" directive\n",
+ "Unknown argument to \"sslrequired\" directive (should be \"never\", \"whenauthenticated\", \"always\")\n",
+ "Missing argument for \"securitypath\" directive\n",
+ "Missing argument for \"location-suffix\" directive\n",
+ "Three arguments are required for the \"location\" directive\n",
+ "At least two arguments are required for the \"newtype\" directive\n",
+ "Unknown location in \"newtype\" directive\n",
+ "Three or four arguments are required for the \"tmplset\" directive\n",
+ "Four arguments are required for the \"attrvset\" directive\n",
+ "Missing argument for \"charset\" directive\n",
+ "Missing argument for \"ClientLanguage\" directive\n",
+ "Missing argument for \"AdminLanguage\" directive\n",
+ "Missing argument for \"DefaultLanguage\" directive\n",
+ "Missing filename for \"include\" directive\n",
+ "Unknown directive in config file\n",
+ "<= erase_db could not open lcache.conf file \"%s\"\n",
+ "<FONT SIZE=\"+1\">\n<P>The database has been deleted. Creating new database... \n</FONT>\n ",
+ "<FONT SIZE=\"+1\">\n<P>The database could not be deleted \n</FONT>\n ",
+ "<= app_suffix could not open ldif file \"%s\"\n",
+ "<= app_suffix could not open tmp file \"%s\"\n",
+ "Unable to rename %s to %s",
+ "null pointer returned by dbconf_read_default_dbinfo().",
+ "Bad \"ldapdb\" URL - the base DN is missing\n",
+ "Bad \"ldapdb\" URL\n",
+ "Bad URL provided for \"baseurl\" directive - the base DN is missing\n",
+ "parsing baseurl directive",
+ "Bad URL provided for \"baseurl\" directive - not an \"ldap:// or ldapdb://\" URL\n",
+ "\"ldaps://\" URLs are not yet supported\n",
+ "No value given for binddn",
+ "No value given for bindpw",
+ "There is no default directory service defined in the dbswitch.conf file",
+ "Cannot open config file \"%s\" for writing",
+ "Unable to rename %s to %s",
+ "config file %s: ",
+ "config file %s: line %d: ",
+ "max %d",
+ " OK ",
+ "Close Window",
+ "Go Back",
+ "{crypt}LOCKED [%s GMT]",
+ "Return to Main",
+ "Return to Main",
+ " Help ",
+ "Help",
+ " Help ",
+ "Help is not yet available.",
+ "Help",
+ "Close Window",
+ "Close Window",
+ "missing ?template",
+ "Authenticate...",
+ "Discard authentication credentials (log out)?",
+ "You did not supply a search string",
+ "The first step in authenticating to the directory is identifying\nyourself.<br>Please type your name:",
+ "Continue",
+ "Continue",
+ "Cancel",
+ "Authenticate as directory manager\"> &nbsp(only available to Directory Administrators)\n",
+ "Authenticate...",
+ "Discard authentication credentials?",
+ "Password for <b>%s</b>: ",
+ "Continue",
+ "Continue",
+ "Cancel",
+ "Authenticate (log in) to the directory",
+ "You are about to authenticate to the directory as \n",
+ "To complete the authentication process, you should\ntype your password.\n",
+ "Before you can edit or add entries, you must authenticate\n(log in) to the directory. This window will guide\nyou through the steps of the authentication\nprocess.\n",
+ "From this screen you may authenticate, or log in, \nto the directory. You will need to authenticate\nbefore you can modify directory entries. If you\nattempt to modify an entry without authenticating,\nyou will be asked to log in.\n",
+ "Authentication Status",
+ "<form>\nYou are currently authenticated to the directory as ",
+ ".\nIf you wish to discard your authentication credentials and log out of the directory, click on the button below.",
+ "Discard Authentication Credentials (log out)",
+ "Your authentication credentials for ",
+ "have expired.\n<HR>\n",
+ "Currently, you are not authenticated to the directory.<HR>\n",
+ "missing \"%s=\"",
+ "unknown \"%s=%s\"",
+ "unknown option %s",
+ "unknown syntax=%s\n",
+ "** HTML type \"%s\" not supported **<BR>\n",
+ "no entries",
+ "1 entry",
+ "%d entries",
+ "where the ",
+ "Edit",
+ "Save Changes",
+ "modify",
+ "add",
+ "Delete",
+ "Delete this entry?",
+ "Rename",
+ "Enter a new name for this entry:",
+ "Edit As",
+ "missing %s=",
+ "Close Window",
+ "Edit...",
+ "missing \"%s=\"\n",
+ "unknown set \"%s\"\n",
+ "unknown syntax \"%s\"\n",
+ "Re-Authenticate",
+ "Close Window",
+ "Do you really want to ",
+ "?",
+ " OK ",
+ " OK ",
+ " Reset ",
+ " Done ",
+ " Cancel ",
+ "found another IF (nested IFs are not supported)",
+ "found ELSE but didn't see an IF",
+ "found ELSE after ELSE (expecting ENDIF)",
+ "found ELIF but didn't see an IF",
+ "found ELIF after ELSE (expecting ENDIF)",
+ "found ENDIF but didn't see an IF",
+ "<BR><B>template error:</B> %s<BR>\n",
+ "ldap_init/lcache_init attempted before config file read",
+ "not running under the administration server",
+ "Could not initialize permissions",
+ "Could not map username to a DN (error from admin server)",
+ "Could not get current username",
+ "Could not get current user password",
+ "Error: %s",
+ "Note: there is no display template for this type of entry available, so it is\ndisplayed below using a default method.",
+ "Invalid user id or NULL LDAP handle",
+ "no match for user id",
+ "more than one match for user id",
+ "the entire directory",
+ "Two arguments are required for the \"includeset\" directive\n",
+ "An error occurred while trying to access the database",
+ "All references to entry could not be changed",
+ "<P>Successfully removed all references to deleted entry.",
+ "<P>Successfully updated all references to renamed entry.",
+ "<P>Removing references to <B>%s</B>...",
+ "<P>Updating references to <B>%s</B>...",
+ "<P>removing %s from %s \n",
+ "The directory server could not be contacted. One common configuration error when using LDAP over SSL is that the certificate used by the directory server must be marked as trusted. Contact your directory server administrator for further assistance.",
+ "A connection to the directory server could not be opened. One common configuration error when using LDAP over SSL is that the certificate used by the directory server must be marked as trusted. Contact your directory server administrator for further assistance.",
+ "Editing",
+ "Adding",
+ "Deleting",
+ "Renaming",
+ "Servers are not configured for CAL",
+ "Cannot update config file \"%s\"\n",
+ "Missing argument for \"locationurl\" directive\n",
+ "Invalid location url\n",
+ "<= app_suffix could not parse LDIF \"%s\"\n",
+ emptyString };
+
+/* libraries in bucket for hashKey==21 */
+static struct DATABIN bucket21[] = {
+ {"dsgw",dsgw,285},
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==22 */
+static struct DATABIN bucket22[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==23 */
+static struct DATABIN bucket23[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==24 */
+static struct DATABIN bucket24[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==25 */
+static struct DATABIN bucket25[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==26 */
+static struct DATABIN bucket26[] = {
+ {emptyString,NULL,0} };
+
+/* strings in library base */
+static char* baseid[] = {"$DBT: base in memory v1 $"};
+static char* base[] = {
+ "",
+ "insufficient memory to create hash table",
+ "insufficient memory to create hash table",
+ "cache_destroy: cache tables appear corrupt.",
+ "unable to allocate hash entry",
+ "cache_insert: unable to create cache entry",
+ "HTTP/1.0 200 OK\nContent-type: text/html\n\n",
+ "<H2>Netscape cache status report</H2>\n",
+ "No caches on system<P>",
+ "<H2>%s cache</H2>\n",
+ "Cache hit ratio: %d/%d (%f)</P>\n</P>\n",
+ "Cache size: %d/%d</P>\n</P>\n",
+ "Hash table size: %d</P>\n</P>\n",
+ "mru : %d</P>\nlru : %d</P>\n",
+ "<UL><TABLE BORDER=4> <TH>Bucket</TH> <TH>Address</TH> <TH>Key</TH> <TH>Access Count</TH> <TH>Delete</TH> <TH>Next</TH> <TH>LRU</TH> <TH>MRU</TH> <TH>Data</TH>\n",
+ "munmap failed (%s)",
+ "munmap failed (%s)",
+ "close failed (%s)",
+ "daemon: unable to fork new process (%s)\n",
+ "daemon: setsid failed (%s)\n",
+ "daemon: can't log pid to %s (%s)\n",
+ "warning: could not set group id to %d (%s)\n",
+ "warning: could not set user id to %d (%s)\n",
+ "warning: daemon is running as super-user\n",
+ "could not determine current user name\n",
+ "error: chroot to %s failed (%s)\n",
+ "",
+ ", address %s",
+ "warning: statistics disabled (%s)\n",
+ "security handshake timed out for pid %d",
+ "warning: statistics disabled (%s)\n",
+ "secure handshake failed (code %d)\n",
+ "accept failed (%s)",
+ "warning: statistics disabled (%s)\n",
+ "select thread miss",
+ "keepalive worker awoken with no work to do",
+ "could not create new thread: %d (%s)",
+ "wait for sema succeeded, but nothing to dequeue",
+ "queue-sema creation failure",
+ "error getting processor info for processor %d",
+ "Error binding to processor %d",
+ "bound process %d to processor %d",
+ "Netscape server is not explicitly binding to any processors.",
+ "cache monitor exited",
+ "cache batch update daemon exited",
+ "Using single threaded accepts.",
+ "Using multi threaded accepts.",
+ "Using partial single threaded accepts.",
+ "This machine has %d processors.",
+ "Error calling thr_seconcurrency(%d)- (%s)",
+ "Set conncurrency to %d.",
+ "WARNING! Netscape executable and library have different versions.\n",
+ "",
+ "",
+ "seminit failed (%s)\n",
+ "This beta software has expired.\n",
+ "Cache monitor respawned",
+ "Cache batch update daemon respawned",
+ "can't find empty statistics slot",
+ "can't fork new process (%s)",
+ "assert failed! %s\n",
+ "mr_table_init()",
+ "malloc failed",
+ "malloc failed!",
+ "mr_add_io(%d, type %d, file %d)",
+ "mr_add_io - stage 1",
+ "mr_add_io - stage 2",
+ "mr_add_io found invalid IO type %d",
+ "mr_add_io - adding timeout",
+ "Out of memory!\n",
+ "done with mr_add_io",
+ "mr_del_io(%d, type %d, file %d)",
+ "mr_del_io found invalid IO type %d",
+ "mr_lookup_io(%d)",
+ "mr_async_io(%d, %d bytes, file %d)",
+ "malloc failure adding async IO",
+ "Error adding async io!",
+ "Cannot seek for read!",
+ "read failure! (%d, %s)",
+ "do_read read %d bytes for file %d",
+ "Cannot seek for write!",
+ "writev failure! (%d, %s)",
+ "write failure! (%d, %s)",
+ "do_write wrote %d bytes for file %d",
+ "do_timeout(mrp %d)",
+ "do_timeout: found IO (timer=%d, time=%d)",
+ "error deleting io",
+ "timeout callback failure for %d\n",
+ "mr_get_event(%d) - outstanding io %d",
+ "mr_get_event: Waiting for reads on FD:",
+ "mr_get_event: Waiting for writes on FD:",
+ " %d",
+ " %d",
+ "mr_get_event set no timeout",
+ "mr_get_event set timeout to: %d.%d sec",
+ "error in select (%d, %s)",
+ "mr_get_event() - select found %d",
+ "error looking up IO fd %d",
+ "read failed for fd %d",
+ "error deleting io",
+ "callback failure for %d\n",
+ "error looking up IO fd %d",
+ "writing: header len %d, writelen %d, total %d",
+ "write failed for fd %d",
+ "error deleting io",
+ "callback failure for %d\n",
+ "Error creating dns cache",
+ "dns_cache_init: hash_size <= 0, using %d",
+ "dns_cache_init: cache-size <= %d, using %d",
+ "dns_cache_init: cache-size is %d is too large, using %d.",
+ "dns_cache_init: expire_time <= 0, using %d",
+ "dns_cache_init: expire is %d is too large, using %d seconds.",
+ "Error creating dns cache",
+ "dns-cache-insert: Error allocating entry",
+ "dns-cache-insert: malloc failure",
+ "successful server startup",
+ "%s B%s",
+ "Netscape executable and shared library have different versions",
+ " executable version is %s",
+ " shared library version is %s",
+ "error reporting shutting down",
+ "warning",
+ "config",
+ "security",
+ "failure",
+ "catastrophe",
+ "info",
+ "verbose",
+ "event_handler:Failed to wait on events %s",
+ "could not wait on resume event event (%s)",
+ "dlopen of %s failed (%s)",
+ "dlopen of %s failed (%s)",
+ "The server is terminating due to an error. Check the event viewer for the error message. SERVER EXITING!",
+ "Terminating the server %s",
+ "kill_server:cannot open server event %s",
+ "kill_server:cannot set server event %s",
+ "error: could not get socket (%s)\n",
+ "error: could not set socket option (%s)\n",
+ "Terminating Service:error: could not bind to address %s port %d (%s)\n",
+ "Terminating Service:error: could not bind to port %d (%s)\n",
+ "SetHandleNonInheritable: could not duplicate socket (%s)",
+ "SetHandleNonInheritable: closing the original socket failed (%s)",
+ "Could not SetHandleInformation (%s)",
+ "Terminating Service:Failure: Could not open statistics file (%s)\n",
+ "Could not set Thread Local Storage Value for thread at slot %d",
+ "secure handshake failed (code %d)\n",
+ "accept failed %d (%s)",
+ "Failed to pulse Event %d %s",
+ "Failed to send MobGrowth Event to parent %s",
+ "Pulsing MobRespawn Event %d",
+ "respawn thread pool to %d (%d)",
+ "Could not open event to signal rotate application. Could not create the MoveLog event:%s",
+ "Failed to send MoveLog Event to rotate app %s",
+ "growing thread pool from %d to %d",
+ "Could not open the ServiceControlManager, Error %d",
+ "StartNetsiteService:Could not open the service %s: Error %d",
+ "StartNetsiteService:Could not start the service %s",
+ "Service Startup: Could not allocate security descriptor",
+ "Service Startup: Could not init security descriptor",
+ "Service Startup: Could not set the security Dacl",
+ "Terminating Service:WinSock init failed: %s",
+ "Httpd Server Startup failed: %s",
+ "can't find empty statistics slot",
+ "NT daemon: could not create new thread %d",
+ "Service Startup Failure. Terminating Service:Could not create event %d:%s",
+ "Service Startup Error. Could not create the MoveLog event:%s",
+ "Failed to wait on Event objects %s",
+ "Failed to wait on Event objects %s",
+ "pipebuf_buf2sd: pipebuf_grab IO_ERROR %d",
+ "pool-init: memory pools disabled",
+ "pool-init: free_size <= 0, using %d",
+ "pool-create-block: out of memory",
+ "pool-create: out of memory",
+ "pool-create: out of memory",
+ "pool-malloc: out of memory",
+ "FREE() used where PERM_FREE() should have been used- problem corrected and supressing further warnings.",
+ "regex error: %s (regex: '%s')",
+ "can't create IPC pipe (%s)",
+ "write to wakeup pipe failed (%s)",
+ "flushing %d connections; current %d; tot %d",
+ "accept failed (%s)",
+ "Error creating time cache",
+ "time-cache: cache disabled",
+ "time_cache_init: hash_size < %d, using default, %d",
+ "time_cache_init: hash_size > %d, using default, %d",
+ "time_cache_init: cache_size < %d, using default, %d",
+ "time_cache_init: cache_size > %d, using default, %d",
+ "Error allocating memory for time_cache",
+ "Error allocating memory for time_cache entry",
+ "Error allocating memory for time_cache entry",
+ "Error inserting new time_cache entry",
+ "Error allocating memory for time_cache",
+ "cs-terminate failure (%s)",
+ "cs-init failure (%s)",
+ "cs-wait failure (%s)",
+ "cs-post failure (%s)",
+ "Unable to create nonblocking socket (%s)",
+ "error: could not set keepalive (%s)\n",
+ "error: could not set recv timeout (%s)\n",
+ "error: could not set send timeout (%s)\n",
+ "Unable to create nonblocking socket (%s)",
+ "sem_grab failed (%s)",
+ "sem_release failed (%s)",
+ "sem_release failed (%s)",
+ "Could not remove temporary directory %s, Error %d",
+ "Could not remove temporary directory %s, Error %d",
+ emptyString };
+
+/* libraries in bucket for hashKey==27 */
+static struct DATABIN bucket27[] = {
+ {"base",base,205},
+ {emptyString,NULL,0} };
+
+/* strings in library cgiadmin */
+static char* cgiadminid[] = {"$DBT: cgiadmin in memory v1 $"};
+static char* cgiadmin[] = {
+ "",
+ "Missing REQUEST_METHOD",
+ "This should only be invoked as CGI program",
+ "Missing ADMSERV_ROOT",
+ "This should only be invoked as CGI program",
+ "Unrecognized request type.",
+ "Startup",
+ "Failed to initialize WinSock",
+ "Bad file",
+ "Expected servers.lst",
+ "Cluster: merge product.lst from %s",
+ "<i>Obtaining product information from %s://%s:%d</i><br>\n",
+ "Updated %s<BR>\n",
+ "Bad file",
+ "Expected servers-instance.lst",
+ "Warning: %s already exists, information not added<BR>\n",
+ "Error: failed to create file %s<BR>\n",
+ "Warning: directory %s will be removed because of above error<BR>\n",
+ "",
+ "Error: %s %s (errno = %d)<BR>\n",
+ "Error: %s %s, %s<BR>\n",
+ "ALLOW ALL OPERATIONS",
+ "ALLOW GET OPERATIONS",
+ "ALLOW SET OPERATIONS",
+ "You accessed this form with an invalid query string.",
+ "community has been removed.",
+ "Community Strings",
+ "Edit a Community",
+ "Add Another Community",
+ "",
+ "Edit",
+ "Remove",
+ "Do you really want to remove this entry?",
+ "<b>Community:</b> %s\n",
+ "<br><b>Operation:</b> %s\n",
+ "No communities exist.",
+ "You should enter a community string.",
+ "You should enter operation you want for this community.",
+ "the community entry has been changed",
+ "%s has been added",
+ "fails to start up master agent",
+ "Please refer to documents to start it",
+ "master agent start up",
+ "can't open config file",
+ "open temp file fails",
+ "open CONFIG fails",
+ "open CONFIG fails",
+ "No permission to start master agent",
+ "You must be running as super user. Please refer to documents",
+ "can't get tcp protocol entry\n",
+ "can't create a sockect",
+ "Please refer to documents for its configuration",
+ "a smux master agent is running or the smux port is not free yet",
+ "Please refer to documents for its configuration",
+ "can't get udp protocol entry\n",
+ "can't create a socket",
+ "Please refer to documents for its configuration",
+ "a snmpd is running or snmp port is not free yet",
+ "Please refer to documents for its configuration",
+ "can't get udp protocol entry\n",
+ "can't create a socket",
+ "Please refer to documents for its configuration",
+ "Fail to start",
+ "Please refer to documents for its configuration",
+ emptyString };
+
+/* libraries in bucket for hashKey==28 */
+static struct DATABIN bucket28[] = {
+ {"cgiadmin",cgiadmin,63},
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==29 */
+static struct DATABIN bucket29[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==30 */
+static struct DATABIN bucket30[] = {
+ {emptyString,NULL,0} };
+
+/* libraries in bucket for hashKey==31 */
+static struct DATABIN bucket31[] = {
+ {emptyString,NULL,0} };
+
+/* array of bucket pointers */
+static struct DATABIN* buckets[32] = {
+ bucket0,
+ bucket1,
+ bucket2,
+ bucket3,
+ bucket4,
+ bucket5,
+ bucket6,
+ bucket7,
+ bucket8,
+ bucket9,
+ bucket10,
+ bucket11,
+ bucket12,
+ bucket13,
+ bucket14,
+ bucket15,
+ bucket16,
+ bucket17,
+ bucket18,
+ bucket19,
+ bucket20,
+ bucket21,
+ bucket22,
+ bucket23,
+ bucket24,
+ bucket25,
+ bucket26,
+ bucket27,
+ bucket28,
+ bucket29,
+ bucket30,
+ bucket31 };
diff --git a/lib/libsi18n/getstrprop.c b/lib/libsi18n/getstrprop.c
new file mode 100644
index 00000000..6b21fdd5
--- /dev/null
+++ b/lib/libsi18n/getstrprop.c
@@ -0,0 +1,137 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "i18n.h"
+
+#include "getstrmem.h"
+
+#include "libadminutil/resource.h"
+#include "coreres.h"
+
+Resource *hResource = NULL;
+char empty_string[] = "";
+
+char*
+XP_GetStringFromMemory(char* strLibraryName,int iToken);
+
+
+
+void
+XP_InitStringDatabase(char* pathCWD, char* databaseName)
+{
+ hResource = core_res_init_resource (pathCWD, databaseName);
+}
+
+char *XP_GetPropertyString(char* strLibraryName,int iToken, ACCEPT_LANGUAGE_LIST lang)
+{
+ char *key_name;
+ char *result = NULL;
+
+ if (hResource == NULL)
+ return NULL;
+
+ /*creating the key*/
+ key_name=(char*)malloc(strlen(strLibraryName) + 10);
+ sprintf(key_name, "%s-%d", strLibraryName, iToken);
+ if(key_name == NULL)
+ return NULL;
+
+ result = (char *) core_res_getstring(hResource, key_name, lang) ;
+
+ if (key_name)
+ free (key_name);
+
+ if (result == NULL)
+ return empty_string;
+ else
+ return result ;
+}
+
+char*
+XP_GetStringFromDatabase(char* strLibraryName,
+ char* strLanguage,
+ int key)
+{
+ char *result = NULL;
+ ACCEPT_LANGUAGE_LIST alanglist;
+ int n;
+
+ /*
+ * display first choice language if available, otherwise
+ * use default which is english in most case
+ */
+ if (hResource) {
+ n = XP_AccLangList (strLanguage, alanglist);
+ if (n >= MAX_ACCEPT_LANGUAGE)
+ alanglist[MAX_ACCEPT_LANGUAGE-1][0] = '\0';
+ else
+ alanglist[n][0] = '\0';
+ result = XP_GetPropertyString(strLibraryName, key, alanglist);
+ }
+
+ /* we should never come here. */
+ if (result == NULL)
+ result = XP_GetStringFromMemory(strLibraryName,key);
+ return result;
+}
+
+
+char*
+XP_GetStringFromMemory(char* strLibraryName,int iToken)
+{
+ /*
+ * In memory model called by XP_GetStringFromDatabase
+ * does not use database (nsres, et al.).
+ *
+ * This function uses hash table for library lookup
+ * and direct lookup for string.
+ *
+ * This function is thread safe.
+ */
+
+
+ unsigned hashKey;
+ int found = 0;
+ unsigned uToken = iToken;
+ char* cPtr;
+ DATABIN* pBucket;
+
+ /* calculate hash key */
+ hashKey = 0;
+ cPtr = strLibraryName;
+ while (*cPtr) {
+ hashKey += *(cPtr++);
+ }
+ hashKey &= BUCKET_MASK;
+
+ /* get bucket for this hash key */
+ pBucket = buckets[hashKey];
+
+ /* search overflow buckets */
+ while (*(pBucket->pLibraryName)!='\0') {
+ if (strcmp(pBucket->pLibraryName,strLibraryName)==0) {
+ found = 1;
+ break;
+ }
+ pBucket++;
+ }
+
+ if (!found) {
+ return emptyString;
+ }
+
+ if (uToken<=pBucket->numberOfStringsInLibrary) {
+ return pBucket->pArrayOfLibraryStrings[uToken];
+ } else {
+ /* string token out of range */
+ return emptyString;
+ }
+
+}
diff --git a/lib/libsi18n/gsslapd.h b/lib/libsi18n/gsslapd.h
new file mode 100644
index 00000000..bbb44454
--- /dev/null
+++ b/lib/libsi18n/gsslapd.h
@@ -0,0 +1,37 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#define DATABASE_NAME "ns-slapd"
+
+#ifdef RESOURCE_STR
+
+#undef LIBRARY_NAME
+#include "base/dbtbase.h"
+#undef LIBRARY_NAME
+#include "frame/dbtframe.h"
+#undef LIBRARY_NAME
+#include "httpdaemon/dbthttpdaemon.h"
+#undef LIBRARY_NAME
+#include "libaccess/dbtlibaccess.h"
+#undef LIBRARY_NAME
+#include "libadmin/dbtlibadmin.h"
+#undef LIBRARY_NAME
+#include "libir/dbtlibir.h"
+#undef LIBRARY_NAME
+#include "../ldap/clients/dsgw/dbtdsgw.h"
+
+static RESOURCE_GLOBAL allxpstr[] = {
+ base,
+ frame,
+ httpdaemon,
+ libaccess,
+ libadmin,
+ libir,
+ dsgw,
+ 0
+};
+
+#endif /* ifdef RESOURCE_STR */
diff --git a/lib/libsi18n/makstrdb.c b/lib/libsi18n/makstrdb.c
new file mode 100644
index 00000000..6f8b78dd
--- /dev/null
+++ b/lib/libsi18n/makstrdb.c
@@ -0,0 +1,221 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "netsite.h"
+#ifdef BERKELEY_DB_RESOURCE
+#include "mcom_db.h"
+#include "nsres.h"
+#endif
+
+#define RESOURCE_STR
+
+/********************************************/
+/* Begin: Application dependent information */
+/********************************************/
+
+#ifdef MCC_ADMSERV
+#include "gsadmserv.h"
+#define GSXXX_H_INCLUDED
+#endif
+
+#ifdef NS_ENTERPRISE
+#include "gshttpd.h"
+#define GSXXX_H_INCLUDED
+#endif
+
+#ifdef NS_DS
+#include "gsslapd.h"
+#define GSXXX_H_INCLUDED
+#endif
+
+#ifdef NS_PERSONAL
+#include "gshttpd.h"
+#define GSXXX_H_INCLUDED
+#endif
+
+#ifdef MCC_PROXY
+#include "gsproxy.h"
+#define GSXXX_H_INCLUDED
+#endif
+
+#ifdef buildAnotherServer
+#include "gsanother.h"
+#define GSXXX_H_INCLUDED
+#endif
+
+/********************************************/
+/* End: Application dependent information */
+/********************************************/
+
+/**********************************************/
+/* Begin: Check that BUILD_MODULE is handled */
+/* and a gs*.h file has been included */
+/**********************************************/
+
+#ifndef GSXXX_H_INCLUDED
+#error Error in makstrdb.c: BUILD_MODULE not handled; gs*.h not included.
+#endif
+
+/********************************************/
+/* End: Check that BUILD_MODULE is handled */
+/* and a gs*.h file has been included */
+/********************************************/
+
+/*******************************************************************************/
+
+#ifdef XP_DEBUG
+
+void
+XP_PrintStringDatabase(void) /* debug routine */
+{
+ int i;
+ int j;
+ char* LibraryName;
+ RESOURCE_TABLE* table;
+
+ j = 0;
+ while (table=allxpstr[j++].restable) {
+ LibraryName = table->str;
+ printf("Library %d: %s\n",j,LibraryName);
+ i = 1;
+ table++;
+ while (table->str) {
+ printf("%d: %s %d \"%s\"\n",i,LibraryName,table->id,table->str);
+ i++;
+ table++;
+ }
+ }
+}
+
+#endif /* XP_DEBUG */
+
+#ifdef BERKELEY_DB_RESOURCE
+/*******************************************************************************/
+
+int
+XP_MakeStringDatabase(void)
+{
+ int j;
+ char* LibraryName;
+ char* cptr;
+ RESOURCE_TABLE* table;
+ NSRESHANDLE hresdb;
+ char DBTlibraryName[128];
+
+ /* Creating database */
+ hresdb = NSResCreateTable(DATABASE_NAME, NULL);
+ if (hresdb==0) {
+ printf("Error creating database %s\n",DATABASE_NAME);
+ return 1;
+ }
+
+ j = 0;
+ while (table=allxpstr[j++].restable) {
+ LibraryName = table->str;
+ printf("Add Library %d: %s\n",j,LibraryName);
+ table++;
+ while (table->str) {
+ if (table->id==-1 && strstr(table->str,"$DBT: ")) {
+ cptr = strstr(table->str,"referenced");
+ if (cptr) {
+ strncpy(cptr,"in DB file",10);
+ }
+ }
+ NSResAddString(hresdb,LibraryName,table->id,table->str,0);
+ table++;
+ }
+ }
+
+ NSResCloseTable(hresdb);
+ return 0;
+}
+#endif
+
+/*******************************************************************************/
+
+int
+XP_MakeStringProperties(void)
+{
+ int j;
+ char* LibraryName;
+ char* cptr;
+ RESOURCE_TABLE* table;
+ FILE *hresfile;
+ char buffer[2000];
+ char *src, *dest;
+ char *dbfile;
+
+ /* Creating database */
+ dbfile = (char *) malloc (strlen(DATABASE_NAME) + 20);
+ strcpy(dbfile, DATABASE_NAME);
+ strcat(dbfile, ".properties");
+
+ hresfile = fopen(dbfile, "w");
+
+ if (hresfile==NULL) {
+ printf("Error creating properties file %s\n",DATABASE_NAME);
+ return 1;
+ }
+
+ j = 0;
+ while (table=allxpstr[j++].restable) {
+ LibraryName = table->str;
+ fprintf(hresfile, "\n");
+ fprintf(hresfile, "#######################################\n");
+ fprintf(hresfile, "############### %s ###############\n", LibraryName);
+ printf("Add Library %d: %s\n",j,LibraryName);
+ table++;
+ while (table->str) {
+ /*
+ Change special char to \uXXXX
+ */
+ src = table->str;
+ dest = buffer;
+ while (*src) {
+ if (*src < 0x20) {
+ strcpy(dest,"\\u00");
+ dest += 4;
+ sprintf(dest, "%02x", *src);
+ dest += 1;
+ }
+ else {
+ *dest = *src;
+ }
+ src ++;
+ dest ++;
+ }
+ *dest = '\0';
+
+ if (table->id > 0) {
+ fprintf(hresfile, "%s-%d =%s\n", LibraryName, table->id, buffer);
+ }
+ table++;
+ }
+ }
+
+ fclose(hresfile);
+ return 0;
+}
+
+
+
+
+/*******************************************************************************/
+
+int main()
+{
+#if 0
+ return XP_MakeStringDatabase();
+#else
+ return XP_MakeStringProperties();
+#endif
+}
+
+/*******************************************************************************/
diff --git a/lib/libsi18n/propset.c b/lib/libsi18n/propset.c
new file mode 100644
index 00000000..350bbe67
--- /dev/null
+++ b/lib/libsi18n/propset.c
@@ -0,0 +1,404 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "i18n.h"
+
+#include "txtfile.h"
+#include "reshash.h"
+#include "propset.h"
+
+int PropertiesLoadFileToHash(PropertiesSet *propset, char *language);
+char *GetProertiesFilename(char *directory, char *file, char *language);
+int PropertiesLanguageStatus(PropertiesSet *propset, char *language);
+int PropertiesSetLangStatus(LanguageStatus *langstatus, char *language, int status);
+int unicode_to_UTF8(unsigned int wch, char *utf8);
+char *decode_ascii(char *src);
+
+
+PropertiesSet * PropertiesInit(char *directory, char *file)
+{
+ struct stat buf;
+ char * file_path;
+ PropertiesSet *propset = NULL;
+ PropertiesSet *result = NULL;
+ ResHash *reshash;
+
+ file_path = (char *) malloc (strlen(directory) + strlen(file) + 20);
+
+ strcpy(file_path, directory);
+ strcat(file_path, "/");
+ strcat(file_path, file);
+ strcat(file_path, ".properties");
+
+ if (stat(file_path, &buf) == 0) {
+ propset = (PropertiesSet *) malloc(sizeof(PropertiesSet));
+ memset(propset, 0, sizeof(PropertiesSet));
+ reshash = (ResHash *) ResHashCreate(file);
+
+ if (reshash) {
+ propset->langlist = (LanguageStatus *) malloc(sizeof(LanguageStatus));
+ memset(propset->langlist, 0, sizeof(LanguageStatus));
+
+ propset->res = reshash;
+ propset->directory = strdup(directory);
+ propset->filename = strdup(file);
+ PropertiesLoadFileToHash(propset, NULL);
+ result = propset;
+ }
+ }
+
+ if (file_path)
+ free (file_path);
+
+ return result;
+}
+
+
+char *GetProertiesFilename(char *directory, char *file, char *language)
+{
+ char *filepath;
+
+ if (language && *language == '\0')
+ filepath = (char *) malloc(strlen(directory) + strlen(file) + strlen(language) + 20);
+ else
+ filepath = (char *) malloc(strlen(directory) + strlen(file) + 20);
+
+ strcpy(filepath, directory);
+ if (filepath[strlen(filepath) - 1] != '/')
+ strcat(filepath, "/");
+ strcat(filepath, file);
+ if (language && *language != '\0') {
+ strcat(filepath, "_");
+ strcat(filepath, language);
+ }
+ strcat(filepath, ".properties");
+
+ return filepath;
+}
+
+/*
+ PropertiesLoadToHash
+
+ Opens property file and save data to hash table
+
+ Input
+ propfile: handle
+ file: full path with file extension
+
+ return:
+ 0: SUCCESS
+ 1: FAIL
+*/
+
+int PropertiesLoadFileToHash(PropertiesSet *propset, char *language)
+{
+ TEXTFILE *hfile;
+ char *filepath;
+ char *p, *q;
+ int n;
+ char linebuf[1000];
+ int st;
+
+ st = PropertiesLanguageStatus(propset, language);
+ if (st == LANGUAGE_INVALID)
+ return 1;
+ else if (st == LANGUAGE_LOAD)
+ return 0;
+
+ filepath = GetProertiesFilename(propset->directory, propset->filename, language);
+
+ if ((hfile = OpenTextFile (filepath, TEXT_OPEN_FOR_READ)) == NULL) {
+ PropertiesSetLangStatus(propset->langlist, language, LANGUAGE_INVALID);
+ return 1;
+ }
+
+ while ((n = ReadTextLine(hfile, linebuf)) >= 0) {
+ if (n == 0)
+ continue;
+
+ p = linebuf;
+ /* strip leading spaces */
+ while (*p == ' ' || *p == '\t')
+ p ++;
+ /* skip comment line */
+ if (*p == '\0' || *p == '#' || *p == '=')
+ continue;
+
+ q = strchr (linebuf, '=');
+ if (q) {
+ char *key, *value, *newvalue;
+
+ *q = '\0';
+ key = p;
+ value = q + 1;
+ /* strip trailing space for key */
+ p = key + strlen(key) - 1;
+ while (*p == ' ' || *p == '\t') {
+ *p = '\0';
+ p --;
+ }
+
+ /* decode Unicode escape value */
+ newvalue = decode_ascii(value);
+
+ if (newvalue) {
+ ResHashAdd(propset->res, key, newvalue, language);
+ free(newvalue);
+ }
+ else
+ ResHashAdd(propset->res, key, value, language);
+ }
+ }
+ PropertiesSetLangStatus(propset->langlist, language, LANGUAGE_LOAD);
+ return 0;
+}
+
+/*
+ PropertiesIsLoaded
+
+ Test if current properties associated with language
+ is loaded or not.
+
+ return:
+ 1: SUCCESS
+ 0: FAIL
+ */
+
+int PropertiesLanguageStatus(PropertiesSet *propset, char *language)
+{
+ LanguageStatus *plang;
+
+ plang = propset->langlist;
+ if (language == NULL || *language == '\0') {
+ return plang->status;
+ }
+
+ plang = plang->next;
+
+ while (plang) {
+ if (strcmp(plang->language, language) == 0) {
+ return plang->status;
+ }
+ plang = plang->next;
+ }
+ return LANGUAGE_NONE;
+}
+
+int PropertiesSetLangStatus(LanguageStatus *langlist, char *language, int status)
+{
+ LanguageStatus *plang, *prev;
+ LanguageStatus *langstatus;
+
+ if (language == NULL || *language == '\0') {
+ langlist->status = status;
+ return 0;
+ }
+
+ prev = plang = langlist;
+ plang = plang->next;
+
+ while (plang) {
+ if (strcmp(plang->language, language) == 0) {
+ plang->status = status;
+ return 0;
+ }
+ prev = plang;
+ plang = plang->next;
+ }
+
+ langstatus = (LanguageStatus *) malloc(sizeof(LanguageStatus));
+ memset (langstatus, 0, sizeof(LanguageStatus));
+ langstatus->language = strdup(language);
+ langstatus->status = status;
+ prev->next = langstatus;
+
+ return 0;
+}
+
+
+/***
+ PropertiesOpenFile
+
+ return 0: loaded
+ 1: fail to load file associated with the language
+
+
+ */
+int PropertiesOpenFile(PropertiesSet *propset, char *language)
+{
+ int status;
+ status = PropertiesLanguageStatus(propset, language);
+
+ if (status == LANGUAGE_NONE)
+ return PropertiesLoadFileToHash (propset, language);
+ else if (status == LANGUAGE_INVALID)
+ return 1;
+ else
+ return 0;
+}
+
+const char *PropertiesGetString(PropertiesSet *propset, char *key, ACCEPT_LANGUAGE_LIST acceptlangauge)
+{
+ int i;
+ char *language = NULL;
+
+ i = 0;
+ while (acceptlangauge[i][0]) {
+ if (PropertiesOpenFile(propset, acceptlangauge[i]) == 0) {
+ language = acceptlangauge[i];
+ break;
+ }
+ i ++;
+ }
+
+ return ResHashSearch(propset->res, key, language);
+}
+void PropertiesDestroy(PropertiesSet *propset)
+{
+ LanguageStatus *langattrib, *next;
+
+ if (propset) {
+ if (propset->path)
+ free(propset->path);
+ if (propset->directory)
+ free(propset->directory);
+ if (propset->filename)
+ free(propset->filename);
+
+ ResHashDestroy(propset->res);
+
+ langattrib = propset->langlist;
+ while (langattrib) {
+ next = langattrib->next;
+ if (langattrib->language)
+ free(langattrib->language);
+ free(langattrib);
+ langattrib = next;
+ }
+ }
+}
+
+
+char *decode_ascii(char *src)
+{
+ int i;
+ char utf8[10];
+ int state = 0;
+ int digit = 0;
+ int digit_count = 0;
+ char *result, *p, *q;
+
+ if (src == NULL || *src == '\0')
+ return NULL;
+
+ if (strchr(src, '\\') == NULL)
+ return NULL;
+
+ result = (char *) malloc(strlen(src) + 1);
+
+ p = src;
+ q = result;
+
+ for (;*p; p++) {
+ char ch;
+ int n;
+ if (state == BACKSLASH_U) {
+ ch = toupper(*p);
+ if (ch >= '0' && ch <= '9') {
+ digit = digit * 16 + (ch - '0');
+ digit_count ++;
+ }
+ else if (ch >= 'A' && ch <= 'F') {
+ digit = digit * 16 + (ch - 'A' + 10);
+ digit_count ++;
+ }
+ else {
+ n = unicode_to_UTF8(digit, utf8);
+ for (i = 0; i < n; i++)
+ *q ++ = utf8[i];
+ *q ++ = *p;
+ state = 0;
+ digit_count = 0;
+ }
+
+ if (digit_count == 4) {
+ n = unicode_to_UTF8(digit, utf8);
+ for (i = 0; i < n; i++)
+ *q ++ = utf8[i];
+ state = 0;
+ }
+ }
+ else if (state == BACKSLASH) {
+ if (*p == 'u') {
+ state = BACKSLASH_U;
+ digit = 0;
+ digit_count = 0;
+ continue;
+ }
+ else if (*p == 'n') {
+ *q++ = '\n';
+ state = 0;
+ }
+ else if (*p == 'r') {
+ *q++ = '\r';
+ state = 0;
+ }
+ else {
+ *q++ = '\\';
+ *q++ = *p;
+ state = 0;
+ }
+ }
+ else if (*p == '\\') {
+ state = BACKSLASH;
+ continue;
+ }
+ else {
+ *q++ = *p;
+ state = 0;
+ }
+ }
+ *q = '\0';
+ return result;
+}
+
+
+int unicode_to_UTF8(unsigned int wch, char *utf8)
+{
+ unsigned char hibyte, lobyte, mibyte;
+
+ if (wch <= 0x7F) {
+ /* 0000 007F ==> 0xxxxxxx */
+ utf8[0] = (unsigned char) wch ;
+ utf8[1] = '\0';
+ return 1;
+ }
+ else if (wch <= 0x7FF) {
+ /* 0000 07FF ==> 110xxxxx 10xxxxxx */
+ lobyte = wch & 0x3F;
+ hibyte = (wch >> 6) & 0x1F;
+
+ utf8[0] = 0xC0 | hibyte;
+ utf8[1] = 0x80 | lobyte;
+ utf8[2] = '\0';
+ return 2;
+ }
+ else {
+ /* FFFF ==> 1110xxxx 10xxxxxx 10xxxxxx */
+ lobyte = wch & 0x3F;
+ mibyte = (wch >> 6) & 0x3F;
+ hibyte = (wch >> 12) & 0xF;
+
+ utf8[0] = 0xE0 | hibyte;
+ utf8[1] = 0x80 | mibyte;
+ utf8[2] = 0x80 | lobyte;
+ utf8[3] = '\0';
+ return 3;
+ }
+}
diff --git a/lib/libsi18n/propset.h b/lib/libsi18n/propset.h
new file mode 100644
index 00000000..f7322669
--- /dev/null
+++ b/lib/libsi18n/propset.h
@@ -0,0 +1,43 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#ifndef PROPSET_H
+#define PROPSET_H
+
+#include "reshash.h"
+
+
+enum {
+ LANGUAGE_NONE = 0,
+ LANGUAGE_LOAD,
+ LANGUAGE_INVALID
+} ;
+
+enum {
+ BACKSLASH = 1,
+ BACKSLASH_U
+};
+
+
+typedef struct LanguageStatusS {
+ char *language;
+ int status;
+ struct LanguageStatusS *next;
+} LanguageStatus;
+
+typedef struct PropertiesSet {
+ char *path;
+ char *directory;
+ char *filename;
+ LanguageStatus *langlist;
+ ResHash *res;
+} PropertiesSet;
+
+
+PropertiesSet * PropertiesInit(char *directory, char *file);
+const char *PropertiesGetString(PropertiesSet *propset, char *key, ACCEPT_LANGUAGE_LIST acceptlangauge);
+void PropertiesDestroy(PropertiesSet *propfile);
+
+#endif
diff --git a/lib/libsi18n/reshash.c b/lib/libsi18n/reshash.c
new file mode 100644
index 00000000..55740e19
--- /dev/null
+++ b/lib/libsi18n/reshash.c
@@ -0,0 +1,264 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "reshash.h"
+
+/* ======================== Value with Language list ==================== */
+int ValueAddLanguageItem(ValueNode *node, char *value, char *language)
+{
+ ValueNode *prev, *pvalue;
+
+ if (node == NULL)
+ return 0;
+ if (language == NULL || *language == '\0') {
+ /* should be added to default value */
+ return 0;
+ }
+
+ prev = pvalue = node;
+ while (pvalue != NULL) {
+ if ((pvalue->language == NULL) ||
+ (strcmp(pvalue->language,language) == 0)) {
+ /* if value for the language is already there
+ replace it with latest one.
+ */
+ if (pvalue->language == NULL)
+ pvalue->language = strdup(language);
+ if (pvalue->value)
+ free(pvalue->value);
+ pvalue->value = strdup(value);
+ return 0;
+ }
+ prev = pvalue;
+ pvalue = pvalue->next;
+ }
+ pvalue = (ValueNode *) malloc(sizeof(ValueNode));
+ memset(pvalue, 0, sizeof(ValueNode));
+
+ prev->next = pvalue;
+
+ pvalue->language = strdup(language);
+ pvalue->value = strdup(value);
+ return 0;
+}
+
+const char *ValueSearchItem(ValueNode *node, char *language)
+{
+ ValueNode *pvalue;
+
+ if (node == NULL)
+ return NULL;
+
+ pvalue = node;
+ while (pvalue && pvalue->language) {
+ if (strcmp(pvalue->language,language) == 0) {
+ return pvalue->value;
+ }
+ pvalue = pvalue->next;
+ }
+ return NULL;
+}
+
+void ValueDestroy(ValueNode *node)
+{
+ ValueNode *p, *current;
+ p = node;
+ /* free itself and go next */
+ while (p) {
+ current = p;
+ p = p->next;
+ if (current->language)
+ free (current->language);
+ if (current->value)
+ free (current->value);
+ }
+}
+
+/* ======================== End of Value with Language list ==================== */
+
+
+
+/* ======================== Tree List Implementation============================ */
+
+const char * TreeSearchItem(TreeNode *res, char *key, char *language)
+{
+ int k;
+ const char *result;
+
+ if (res == NULL || res->key == NULL)
+ return NULL;
+
+ k = strcmp(key, res->key);
+
+ if (k > 0) {
+ return TreeSearchItem(res->right, key, language);
+ }
+ else if (k < 0) {
+ return TreeSearchItem(res->left, key, language);
+ }
+ else {
+ /* Add to the current node; */
+ if (language == NULL || *language == '\0')
+ return res->value;
+
+ result = ValueSearchItem(res->vlist, language);
+ if (result)
+ return result;
+ else /* fallback to default value if there is any */
+ return res->value;
+ }
+}
+
+/*
+ TreeAddItem
+ Add value for specific language to the resource tree
+
+ Using binary tree now --> Balanced tree later
+ */
+int TreeAddItem(TreeNode *res, char *key, char *value, char *language)
+{
+ TreeNode *node;
+ ValueNode *vnode;
+ int k;
+
+ if (res->key == NULL) {
+ res->key = strdup(key);
+ k = 0;
+ }
+ else {
+ k = strcmp(key, res->key);
+ }
+
+ if (k > 0) {
+ if (res->right == NULL) {
+ /* Create node and it's value sub list
+ */
+ node = (TreeNode *) malloc (sizeof(TreeNode));
+ memset(node, 0, sizeof(TreeNode));
+ vnode = (ValueNode *) malloc(sizeof(ValueNode));
+ memset(vnode, 0, sizeof(ValueNode));
+ node->vlist = vnode;
+
+ res->right = node;
+
+ /* assign value to node */
+ node->key = strdup(key);
+ if (language == NULL)
+ node->value = strdup(value);
+ else
+ ValueAddLanguageItem(node->vlist, value, language);
+ }
+ else {
+ return TreeAddItem(res->right, key, value, language);
+ }
+ }
+ else if (k < 0) {
+ if (res->left == NULL) {
+ node = (TreeNode *) malloc (sizeof(TreeNode));
+ memset(node, 0, sizeof(TreeNode));
+ vnode = (ValueNode *) malloc(sizeof(ValueNode));
+ memset(vnode, 0, sizeof(ValueNode));
+ node->vlist = vnode;
+
+ res->left = node;
+
+ /* assign value to node */
+ node->key = strdup(key);
+ if (language == NULL)
+ node->value = strdup(value);
+ else
+ return ValueAddLanguageItem(node->vlist, value, language);
+ }
+ else {
+ return TreeAddItem(res->left, key, value, language);
+ }
+ }
+ else {
+ /* Add to the current node; */
+ if (language == NULL)
+ res->value = strdup(value);
+ else
+ return ValueAddLanguageItem(res->vlist, value, language);
+ }
+ return 0;
+}
+
+void TreeDestroy(TreeNode *tree)
+{
+ if (tree == NULL)
+ return;
+ if (tree->vlist)
+ ValueDestroy(tree->vlist);
+ if (tree->key)
+ free(tree->key);
+ if (tree->value)
+ free(tree->value);
+ if (tree->left)
+ TreeDestroy(tree->left);
+ if (tree->right)
+ TreeDestroy(tree->right);
+}
+
+/* ====================== End of Tree implementation ================= */
+
+
+/* ====================== Tree controller (hash ?) ================ */
+ResHash * ResHashCreate(char * name)
+{
+ ResHash *pResHash;
+
+ /* Create hash table */
+ pResHash = (ResHash *) malloc (sizeof(ResHash));
+ if (pResHash == NULL)
+ return NULL;
+
+ memset(pResHash, 0, sizeof(ResHash));
+
+ if (name)
+ pResHash->name = strdup(name);
+
+ /* Create initial tree item and it's valuelist to hash table */
+ pResHash->treelist = (TreeNode *) malloc(sizeof(TreeNode));
+ if (pResHash->treelist)
+ memset(pResHash->treelist, 0, sizeof(TreeNode));
+ pResHash->treelist->vlist = (ValueNode *) malloc(sizeof(ValueNode));
+ memset(pResHash->treelist->vlist, 0, sizeof(ValueNode));
+
+ return pResHash;
+}
+
+int ResHashAdd(ResHash *res, char *key, char *value, char *language)
+{
+#if 0
+ hash = get hash value from key
+ tree = find the tree associated with hash value
+#endif
+ return TreeAddItem(res->treelist, key, value, language);
+}
+
+const char *ResHashSearch(ResHash *res, char *key, char *language)
+{
+#if 0
+ hash = get hash value from key
+ tree = find the tree associated with hash value
+#endif
+ return TreeSearchItem(res->treelist, key, language);
+}
+
+void ResHashDestroy(ResHash *res)
+{
+ if (res == NULL)
+ return;
+ if (res->name)
+ free(res->name);
+ if (res->treelist)
+ TreeDestroy(res->treelist);
+}
+
+/* ========================= End of Tree controller ====================== */
diff --git a/lib/libsi18n/reshash.h b/lib/libsi18n/reshash.h
new file mode 100644
index 00000000..b2b7d797
--- /dev/null
+++ b/lib/libsi18n/reshash.h
@@ -0,0 +1,54 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#ifndef RESHASH_H
+#define RESHASH_H
+/**********************************************************************
+ Hash --> Tree --> ValueList
+
+ ValueList: language per item, each list associated with one key
+ Tree: contains multiple keys
+ Hash: Based on hash to decide withc tree to use for lookup
+
+***********************************************************************/
+
+/*
+ Valuelist, each item contains
+ language: ISO two or four letters
+ value: UTF-8 encoding strings
+ */
+typedef struct ValueNode {
+ char *language;
+ char *value;
+ struct ValueNode *next;
+} ValueNode;
+
+
+/*
+ Current: BINARY TREE
+ Future: balanced tree for high search performance
+ */
+typedef struct TreeNodeStruct {
+ ValueNode *vlist;
+ char *key;
+ char *value;
+ struct TreeNodeStruct *left;
+ struct TreeNodeStruct *right;
+} TreeNode;
+
+
+typedef struct ResHash {
+ char *name; /* name of hash table */
+ TreeNode *treelist;
+} ResHash;
+
+
+ResHash * ResHashCreate(char * name);
+int ResHashAdd(ResHash *res, char *key, char *value, char *language);
+const char *ResHashSearch(ResHash *res, char *key, char *language);
+void ResHashDestroy(ResHash *res);
+
+#endif
+
diff --git a/lib/libsi18n/txtfile.c b/lib/libsi18n/txtfile.c
new file mode 100644
index 00000000..a88d1672
--- /dev/null
+++ b/lib/libsi18n/txtfile.c
@@ -0,0 +1,130 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#include "txtfile.h"
+
+
+
+#if 0
+char fileBuffer[FILE_BUFFER_SIZE + 1];
+char *fbCurrent;
+int fbSize;
+int fbStatus;
+#endif
+
+
+TEXTFILE * OpenTextFile(char *filename, int access)
+{
+ TEXTFILE *txtfile;
+ FILE *file;
+ int status;
+
+ if (access == TEXT_OPEN_FOR_WRITE) {
+ status = TEXT_FILE_WRITING;
+ file = fopen(filename, "w+");
+ }
+ else {
+ status = TEXT_FILE_READING;
+ file = fopen(filename, "r");
+ }
+
+ if (file == NULL)
+ return NULL;
+
+ txtfile = (TEXTFILE *) malloc (sizeof(TEXTFILE));
+ memset(txtfile, 0, sizeof(TEXTFILE));
+
+ txtfile->file = file;
+ txtfile->fbStatus = status;
+
+ txtfile->fbCurrent = txtfile->fileBuffer;
+ *txtfile->fbCurrent = '\0';
+ txtfile->fbSize = 0;
+ return txtfile;
+}
+
+
+void CloseTextFile(TEXTFILE *txtfile)
+{
+ if (txtfile) {
+ fclose(txtfile->file);
+ free(txtfile);
+ }
+
+}
+
+int FillTextBuffer(TEXTFILE *txtfile)
+{
+ int nLeft, size;
+ nLeft = strlen(txtfile->fbCurrent);
+ memcpy(txtfile->fileBuffer, txtfile->fbCurrent, nLeft+1);
+
+ size = fread(txtfile->fileBuffer + nLeft, 1, FILE_BUFFER_SIZE - nLeft, txtfile->file);
+ if (size == 0)
+ return 0;
+
+ txtfile->fbCurrent = txtfile->fileBuffer;
+ *(txtfile->fbCurrent + size + nLeft) = '\0';
+ txtfile->fbSize = size + nLeft;
+
+ return size;
+}
+
+int ReadTextLine(TEXTFILE *txtfile, char *linebuf)
+{
+ char *p, *q;
+
+ if (txtfile->fbStatus == TEXT_FILE_DONE)
+ return -1;
+
+ p = txtfile->fbCurrent;
+ q = strchr(p, '\n');
+ if (q)
+ {
+ *q = '\0';
+ strcpy(linebuf, p);
+ txtfile->fbCurrent = q + 1;
+ return strlen(linebuf);
+ }
+ else
+ {
+ if (FillTextBuffer(txtfile) == 0)
+ { /* Done with file reading,
+ return last line
+ */
+ txtfile->fbStatus = TEXT_FILE_DONE;
+ if (*txtfile->fbCurrent) {
+ strcpy(linebuf, txtfile->fbCurrent);
+ CloseTextFile(txtfile);
+ return strlen(linebuf);
+ }
+ else {
+ CloseTextFile(txtfile);
+ return -1;
+ }
+ }
+ else {
+ p = txtfile->fbCurrent;
+ q = strchr(p, '\n');
+ if (q)
+ {
+ *q = '\0';
+ strcpy(linebuf, p);
+ txtfile->fbCurrent = q + 1;
+ }
+ else
+ {
+ strcpy(linebuf, txtfile->fbCurrent);
+ txtfile->fbCurrent = txtfile->fbCurrent + strlen(linebuf);
+ }
+ }
+ return strlen(linebuf);
+ }
+}
diff --git a/lib/libsi18n/txtfile.h b/lib/libsi18n/txtfile.h
new file mode 100644
index 00000000..d3f30755
--- /dev/null
+++ b/lib/libsi18n/txtfile.h
@@ -0,0 +1,45 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+#ifndef TXTFILE_H
+#define TXTFILE_H
+
+#define FILE_BUFFER_SIZE 2024
+
+/* file status */
+enum {
+ TEXT_FILE_NONE,
+ TEXT_FILE_READING,
+ TEXT_FILE_WRITING,
+ TEXT_FILE_DONE
+};
+
+typedef struct TEXTFILE {
+ FILE *file;
+ char *fbCurrent;
+ int fbSize;
+ int fbStatus;
+ char fileBuffer[FILE_BUFFER_SIZE + 1];
+} TEXTFILE;
+
+enum {
+ TEXT_OPEN_FOR_READ,
+ TEXT_OPEN_FOR_WRITE
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+TEXTFILE * OpenTextFile(char *filename, int access);
+void CloseTextFile(TEXTFILE *txtfile);
+int ReadTextLine(TEXTFILE *txtfile, char *linebuf);
+
+#ifdef CPLUSPLUS
+};
+#endif
+
+#endif