r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[vlendec/samba-autobuild/.git] / source3 / intl / lang_tdb.c
index 7ebcc9e85e6462bfebf80086abe6e3c8e419ca31..14b075e6d7591964a010df57ab6bda8233b32221 100644 (file)
@@ -1,12 +1,11 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 3.0
+   Unix SMB/CIFS implementation.
    tdb based replacement for gettext 
    Copyright (C) Andrew Tridgell 2001
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -15,8 +14,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -33,15 +31,18 @@ static BOOL load_msg(const char *msg_file)
        char **lines;
        int num_lines, i;
        char *msgid, *msgstr;
-       TDB_DATA key, data;
+       TDB_DATA data;
 
-       lines = file_lines_load(msg_file, &num_lines);
+       lines = file_lines_load(msg_file, &num_lines,0);
 
        if (!lines) {
                return False;
        }
 
-       if (tdb_lockall(tdb) != 0) return False;
+       if (tdb_lockall(tdb) != 0) {
+               file_lines_free(lines);
+               return False;
+       }
 
        /* wipe the db */
        tdb_traverse(tdb, tdb_traverse_delete_fn, NULL);
@@ -54,16 +55,15 @@ static BOOL load_msg(const char *msg_file)
                }
                if (msgid && strncmp(lines[i], "msgstr \"", 8) == 0) {
                        msgstr = lines[i] + 8;
-                       trim_string(msgid, NULL, "\"");
-                       trim_string(msgstr, NULL, "\"");
+                       trim_char(msgid, '\0', '\"');
+                       trim_char(msgstr, '\0', '\"');
                        if (*msgstr == 0) {
                                msgstr = msgid;
                        }
-                       key.dptr = msgid;
-                       key.dsize = strlen(msgid)+1;
-                       data.dptr = msgstr;
-                       data.dsize = strlen(msgstr)+1;
-                       tdb_store(tdb, key, data, 0);
+                       all_string_sub(msgid, "\\n", "\n", 0);
+                       all_string_sub(msgstr, "\\n", "\n", 0);
+                       data = string_term_tdb_data(msgstr);
+                       tdb_store_bystring(tdb, msgid, data, 0);
                        msgid = NULL;
                }
        }
@@ -76,9 +76,9 @@ static BOOL load_msg(const char *msg_file)
 
 
 /* work out what language to use from locale variables */
-static char *get_lang(void)
+static const char *get_lang(void)
 {
-       char *vars[] = {"LANGUAGE", "LC_ALL", "LC_LANG", "LANG", NULL};
+       const char *vars[] = {"LANGUAGE", "LC_ALL", "LC_LANG", "LANG", NULL};
        int i;
        char *p;
 
@@ -100,15 +100,19 @@ BOOL lang_tdb_init(const char *lang)
        struct stat st;
        static int initialised;
        time_t loadtime;
+       BOOL result = False;
 
        /* we only want to init once per process, unless given
           an override */
-       if (initialised && !lang) return True;
+       if (initialised && !lang) 
+               return True;
 
        if (initialised) {
                /* we are re-initialising, free up any old init */
-               tdb_close(tdb);
-               tdb = NULL;
+               if (tdb) {
+                       tdb_close(tdb);
+                       tdb = NULL;
+               }
                SAFE_FREE(current_lang);
        }
 
@@ -120,41 +124,49 @@ BOOL lang_tdb_init(const char *lang)
        }
 
        /* if no lang then we don't translate */
-       if (!lang) return True;
+       if (!lang) 
+               return True;
 
-       asprintf(&msg_path, "%s.msg", lib_path((char *)lang));
+       asprintf(&msg_path, "%s.msg", lib_path((const char *)lang));
        if (stat(msg_path, &st) != 0) {
                /* the msg file isn't available */
-               free(msg_path);
-               return False;
+               DEBUG(10, ("lang_tdb_init: %s: %s\n", msg_path, 
+                          strerror(errno)));
+               goto done;
        }
        
-
        asprintf(&path, "%s%s.tdb", lock_path("lang_"), lang);
 
+       DEBUG(10, ("lang_tdb_init: loading %s\n", path));
+
        tdb = tdb_open_log(path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644);
        if (!tdb) {
                tdb = tdb_open_log(path, 0, TDB_DEFAULT, O_RDONLY, 0);
-               free(path);
-               free(msg_path);
-               if (!tdb) return False;
-               current_lang = strdup(lang);
-               return True;
+               if (!tdb) {
+                       DEBUG(10, ("lang_tdb_init: %s: %s\n", path,
+                                  strerror(errno)));
+                       goto done;
+               }
+               current_lang = SMB_STRDUP(lang);
+               result = True;
+               goto done;
        }
 
-       free(path);
-
        loadtime = tdb_fetch_int32(tdb, "/LOADTIME/");
 
        if (loadtime == -1 || loadtime < st.st_mtime) {
                load_msg(msg_path);
                tdb_store_int32(tdb, "/LOADTIME/", (int)time(NULL));
        }
-       free(msg_path);
 
-       current_lang = strdup(lang);
+       current_lang = SMB_STRDUP(lang);
+       result = True;
 
-       return True;
+ done:
+       SAFE_FREE(msg_path);
+       SAFE_FREE(path);
+
+       return result;
 }
 
 /* translate a msgid to a message string in the current language 
@@ -162,20 +174,50 @@ BOOL lang_tdb_init(const char *lang)
 */
 const char *lang_msg(const char *msgid)
 {
-       TDB_DATA key, data;
+       TDB_DATA data;
+       const char *p;
+       char *q, *msgid_quoted;
+       int count;
 
        lang_tdb_init(NULL);
 
        if (!tdb) return msgid;
 
-       key.dptr = (char *)msgid;
-       key.dsize = strlen(msgid)+1;
-       
-       data = tdb_fetch(tdb, key);
+       /* Due to the way quotes in msgids are escaped in the msg file we
+          must replace " with \" before doing a lookup in the tdb. */
+
+       count = 0;
+
+       for(p = msgid; *p; p++) {
+               if (*p == '\"')
+                       count++;
+       }
+
+       if (!(msgid_quoted = (char *)SMB_MALLOC(strlen(msgid) + count + 1)))
+               return msgid;
+
+       /* string_sub() is unsuitable here as it replaces some punctuation
+          chars with underscores. */
+
+       for(p = msgid, q = msgid_quoted; *p; p++) {
+               if (*p == '\"') {
+                       *q = '\\';
+                       q++;
+               }
+               *q = *p;
+               q++;
+       }
+
+       *q = 0;
+
+       data = tdb_fetch_bystring(tdb, msgid_quoted);
+
+       free(msgid_quoted);
 
        /* if the message isn't found then we still need to return a pointer
           that can be freed. Pity. */
-       if (!data.dptr) return strdup(msgid);
+       if (!data.dptr)
+               return SMB_STRDUP(msgid);
 
        return (const char *)data.dptr;
 }
@@ -188,32 +230,6 @@ void lang_msg_free(const char *msgstr)
        free((void *)msgstr);
 }
 
-
-/*
-  when the _() translation macro is used there is no obvious place to free
-  the resulting string and there is no easy way to give a static pointer.
-  All we can do is rotate between some static buffers and hope a single d_printf() 
-  doesn't have more calls to _() than the number of buffers 
-*/
-const char *lang_msg_rotate(const char *msgid)
-{
-#define NUM_LANG_BUFS 4
-       char *msgstr;
-       static pstring bufs[NUM_LANG_BUFS];
-       static int next;
-
-       msgstr = (char *)lang_msg(msgid);
-       if (!msgstr) return msgid;
-
-       pstrcpy(bufs[next], msgstr);
-       msgstr = bufs[next];
-
-       next = (next+1) % NUM_LANG_BUFS;
-       
-       return msgstr;
-}
-
-
 /* 
    return the current language - needed for language file mappings 
 */