2001-10-03 16:18:20 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2001-10-03 16:18:20 +04:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2001-10-03 16:18:20 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2001-10-03 16:18:20 +04:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-03-23 01:58:21 +03:00
# include "intl/lang_tdb.h"
2011-05-05 13:25:29 +04:00
# include "util_tdb.h"
2001-10-03 16:18:20 +04:00
static TDB_CONTEXT * tdb ;
2001-10-14 16:10:29 +04:00
/* the currently selected language */
static char * current_lang ;
2001-10-15 12:10:07 +04:00
/* load a msg file into the tdb */
2007-10-19 04:40:25 +04:00
static bool load_msg ( const char * msg_file )
2001-10-03 16:18:20 +04:00
{
char * * lines ;
int num_lines , i ;
char * msgid , * msgstr ;
2007-03-27 13:12:47 +04:00
TDB_DATA data ;
2001-10-03 16:18:20 +04:00
2008-10-12 19:34:43 +04:00
lines = file_lines_load ( msg_file , & num_lines , 0 , NULL ) ;
2001-10-03 16:18:20 +04:00
if ( ! lines ) {
return False ;
}
2006-03-12 02:58:18 +03:00
if ( tdb_lockall ( tdb ) ! = 0 ) {
2008-10-12 19:34:43 +04:00
TALLOC_FREE ( lines ) ;
2006-03-12 02:58:18 +03:00
return False ;
}
2001-10-03 16:18:20 +04:00
/* wipe the db */
2008-03-26 12:50:08 +03:00
tdb_wipe_all ( tdb ) ;
2001-10-15 12:10:07 +04:00
msgid = NULL ;
2001-10-03 16:18:20 +04:00
for ( i = 0 ; i < num_lines ; i + + ) {
if ( strncmp ( lines [ i ] , " msgid \" " , 7 ) = = 0 ) {
msgid = lines [ i ] + 7 ;
}
2001-10-15 12:10:07 +04:00
if ( msgid & & strncmp ( lines [ i ] , " msgstr \" " , 8 ) = = 0 ) {
2001-10-03 16:18:20 +04:00
msgstr = lines [ i ] + 8 ;
2003-09-05 23:59:55 +04:00
trim_char ( msgid , ' \0 ' , ' \" ' ) ;
trim_char ( msgstr , ' \0 ' , ' \" ' ) ;
2001-10-03 16:18:20 +04:00
if ( * msgstr = = 0 ) {
msgstr = msgid ;
}
2003-09-22 11:25:19 +04:00
all_string_sub ( msgid , " \\ n " , " \n " , 0 ) ;
all_string_sub ( msgstr , " \\ n " , " \n " , 0 ) ;
2007-03-27 13:12:47 +04:00
data = string_term_tdb_data ( msgstr ) ;
tdb_store_bystring ( tdb , msgid , data , 0 ) ;
2001-10-15 12:10:07 +04:00
msgid = NULL ;
2001-10-03 16:18:20 +04:00
}
}
2008-10-12 19:34:43 +04:00
TALLOC_FREE ( lines ) ;
2001-10-03 16:18:20 +04:00
tdb_unlockall ( tdb ) ;
return True ;
}
/* work out what language to use from locale variables */
2003-01-03 11:28:12 +03:00
static const char * get_lang ( void )
2001-10-03 16:18:20 +04:00
{
2003-01-03 11:28:12 +03:00
const char * vars [ ] = { " LANGUAGE " , " LC_ALL " , " LC_LANG " , " LANG " , NULL } ;
2001-10-03 16:18:20 +04:00
int i ;
char * p ;
for ( i = 0 ; vars [ i ] ; i + + ) {
if ( ( p = getenv ( vars [ i ] ) ) ) {
return p ;
}
}
return NULL ;
}
2001-10-14 16:10:29 +04:00
/* initialise the message translation subsystem. If the "lang" argument
is NULL then get the language from the normal environment variables */
2007-10-19 04:40:25 +04:00
bool lang_tdb_init ( const char * lang )
2001-10-03 16:18:20 +04:00
{
char * path = NULL ;
2001-10-15 12:10:07 +04:00
char * msg_path = NULL ;
2001-10-03 16:18:20 +04:00
struct stat st ;
static int initialised ;
time_t loadtime ;
2007-10-19 04:40:25 +04:00
bool result = False ;
2001-10-03 16:18:20 +04:00
2001-10-14 16:10:29 +04:00
/* we only want to init once per process, unless given
an override */
2003-09-19 11:04:29 +04:00
if ( initialised & & ! lang )
return True ;
2001-10-14 16:10:29 +04:00
if ( initialised ) {
/* we are re-initialising, free up any old init */
2002-08-17 21:00:51 +04:00
if ( tdb ) {
tdb_close ( tdb ) ;
tdb = NULL ;
}
2001-10-14 16:10:29 +04:00
SAFE_FREE ( current_lang ) ;
}
2001-10-03 16:18:20 +04:00
initialised = 1 ;
2001-10-14 16:10:29 +04:00
if ( ! lang ) {
/* no lang given, use environment */
lang = get_lang ( ) ;
}
2001-10-03 16:18:20 +04:00
/* if no lang then we don't translate */
2003-09-19 11:04:29 +04:00
if ( ! lang )
return True ;
2001-10-14 16:10:29 +04:00
2008-02-25 17:24:49 +03:00
if ( asprintf ( & msg_path , " %s.msg " ,
2011-06-06 08:37:06 +04:00
data_path ( talloc_tos ( ) , ( const char * ) lang ) ) = = - 1 ) {
2008-02-25 17:24:49 +03:00
DEBUG ( 0 , ( " asprintf failed \n " ) ) ;
goto done ;
}
2001-10-15 12:10:07 +04:00
if ( stat ( msg_path , & st ) ! = 0 ) {
/* the msg file isn't available */
2003-11-07 11:29:29 +03:00
DEBUG ( 10 , ( " lang_tdb_init: %s: %s \n " , msg_path ,
2003-09-19 11:04:29 +04:00
strerror ( errno ) ) ) ;
goto done ;
2001-10-14 16:10:29 +04:00
}
2008-02-25 17:24:49 +03:00
if ( asprintf ( & path , " %s%s.tdb " , lock_path ( " lang_ " ) , lang ) = = - 1 ) {
DEBUG ( 0 , ( " asprintf failed \n " ) ) ;
goto done ;
}
2001-10-03 16:18:20 +04:00
2003-09-19 11:04:29 +04:00
DEBUG ( 10 , ( " lang_tdb_init: loading %s \n " , path ) ) ;
2001-10-03 16:18:20 +04:00
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 ) ;
2003-09-19 11:04:29 +04:00
if ( ! tdb ) {
DEBUG ( 10 , ( " lang_tdb_init: %s: %s \n " , path ,
strerror ( errno ) ) ) ;
goto done ;
}
2004-12-07 21:25:53 +03:00
current_lang = SMB_STRDUP ( lang ) ;
2003-09-19 11:04:29 +04:00
result = True ;
goto done ;
2001-10-03 16:18:20 +04:00
}
2002-01-09 07:13:30 +03:00
loadtime = tdb_fetch_int32 ( tdb , " /LOADTIME/ " ) ;
2001-10-03 16:18:20 +04:00
2001-10-14 16:10:29 +04:00
if ( loadtime = = - 1 | | loadtime < st . st_mtime ) {
2001-10-15 12:10:07 +04:00
load_msg ( msg_path ) ;
2002-01-09 07:13:30 +03:00
tdb_store_int32 ( tdb , " /LOADTIME/ " , ( int ) time ( NULL ) ) ;
2001-10-03 16:18:20 +04:00
}
2001-10-14 16:10:29 +04:00
2004-12-07 21:25:53 +03:00
current_lang = SMB_STRDUP ( lang ) ;
2003-09-22 21:39:44 +04:00
result = True ;
2001-10-14 16:10:29 +04:00
2003-09-19 11:04:29 +04:00
done :
SAFE_FREE ( msg_path ) ;
SAFE_FREE ( path ) ;
return result ;
2001-10-03 16:18:20 +04:00
}
/* translate a msgid to a message string in the current language
returns a string that must be freed by calling lang_msg_free ( )
*/
const char * lang_msg ( const char * msgid )
{
2007-03-27 13:12:47 +04:00
TDB_DATA data ;
2003-11-13 20:35:00 +03:00
const char * p ;
char * q , * msgid_quoted ;
2003-09-26 05:24:09 +04:00
int count ;
2001-10-03 16:18:20 +04:00
2001-10-14 16:10:29 +04:00
lang_tdb_init ( NULL ) ;
2001-10-03 16:18:20 +04:00
if ( ! tdb ) return msgid ;
2003-09-26 05:24:09 +04:00
/* 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 + + ;
}
2006-08-01 00:51:55 +04:00
if ( ! ( msgid_quoted = ( char * ) SMB_MALLOC ( strlen ( msgid ) + count + 1 ) ) )
2003-09-26 05:24:09 +04:00
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 ;
2007-03-27 13:12:47 +04:00
data = tdb_fetch_bystring ( tdb , msgid_quoted ) ;
2001-10-03 16:18:20 +04:00
2003-09-26 05:24:09 +04:00
free ( msgid_quoted ) ;
2001-10-03 16:18:20 +04:00
/* if the message isn't found then we still need to return a pointer
that can be freed . Pity . */
2002-11-23 05:52:36 +03:00
if ( ! data . dptr )
2004-12-07 21:25:53 +03:00
return SMB_STRDUP ( msgid ) ;
2001-10-03 16:18:20 +04:00
return ( const char * ) data . dptr ;
}
/* free up a string from lang_msg() */
void lang_msg_free ( const char * msgstr )
{
if ( ! tdb ) return ;
2011-05-06 00:42:05 +04:00
free ( discard_const_p ( void , msgstr ) ) ;
2001-10-03 16:18:20 +04:00
}
2001-10-14 16:10:29 +04:00
/*
return the current language - needed for language file mappings
*/
char * lang_tdb_current ( void )
{
return current_lang ;
}