diff options
| author | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2005-07-29 03:26:28 +0000 | 
|---|---|---|
| committer | Suren A. Chilingaryan <csa@dside.dyndns.org> | 2005-07-29 03:26:28 +0000 | 
| commit | e3f702e83a26468ee44f3f342a7a40a252f4603c (patch) | |
| tree | 5ff76e9d11a9fdbdb493683d0f0840f46c67b6f8 /src | |
| parent | cfaef1b6c9f33fbaa114628cf513d129bdff3c1c (diff) | |
Translation
    - Language Translation using libtranslate is implemented
    - Autoengine sets current charset (option)
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/fs.c | 2 | ||||
| -rw-r--r-- | src/librcc.c | 45 | ||||
| -rw-r--r-- | src/librcc.h | 58 | ||||
| -rw-r--r-- | src/lngconfig.c | 7 | ||||
| -rw-r--r-- | src/lngconfig.h | 4 | ||||
| -rw-r--r-- | src/rccconfig.c | 6 | ||||
| -rw-r--r-- | src/rccdb4.c | 41 | ||||
| -rw-r--r-- | src/rccdb4.h | 8 | ||||
| -rw-r--r-- | src/rccexternal.c | 210 | ||||
| -rw-r--r-- | src/rccexternal.h | 35 | ||||
| -rw-r--r-- | src/rcciconv.c | 23 | ||||
| -rw-r--r-- | src/rcciconv.h | 14 | ||||
| -rw-r--r-- | src/rcctranslate.c | 151 | ||||
| -rw-r--r-- | src/rcctranslate.h | 31 | ||||
| -rw-r--r-- | src/recode.c | 68 | 
16 files changed, 642 insertions, 63 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 50c6836..baa08a4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,6 +8,7 @@ librcc_la_SOURCES = librcc.c \      rccconfig.c rccconfig.h \      rcclist.c rcclist.h \      plugin.c plugin.h \ +    rccexternal.c rccexternal.h \      fake_enca.h fake_rcd.h \      rccenca.c rccenca.h \      rccdb4.c rccdb4.h \ @@ -15,6 +16,7 @@ librcc_la_SOURCES = librcc.c \      rccstring.c rccstring.h \      rccxml.c rccxml.h \      rcciconv.c rcciconv.h \ +    rcctranslate.c rcctranslate.h \      fs.c fs.h \      recode.c recode.h \      internal.h @@ -195,7 +195,7 @@ const char *rccFS2(rcc_language_config config, iconv_t icnv, const char *prefix,      char *tmpbuffer = config->ctx->tmpbuffer;      if (icnv) {     -	size = rccIConv(config->ctx, icnv, name, 0); +	size = rccIConvInternal(config->ctx, icnv, name, 0);  	if (size == (size_t)-1) return NULL;      } else {  	strncpy(tmpbuffer, name, RCC_MAX_STRING_CHARS); diff --git a/src/librcc.c b/src/librcc.c index ec2df39..c0112df 100644 --- a/src/librcc.c +++ b/src/librcc.c @@ -11,6 +11,9 @@  #ifdef HAVE_SYS_TYPES_H  # include <sys/types.h>  #endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif /* HAVE_SYS_STAT_H */  #ifdef HAVE_PWD_H  # include <pwd.h> @@ -23,6 +26,8 @@  #include "plugin.h"  #include "engine.h"  #include "rccxml.h" +#include "rccexternal.h" +#include "rcctranslate.h"  static int initialized = 0;  char *rcc_home_dir = NULL; @@ -43,6 +48,9 @@ rcc_compiled_configuration rccGetCompiledConfiguration() {  #ifdef HAVE_DB_H      compiled_configuration.flags|=RCC_CC_FLAG_HAVE_BERKLEY_DB;  #endif /* HAVE_DB_H */ +#ifdef HAVE_LIBTRANSLATE +    compiled_configuration.flags|=RCC_CC_FLAG_HAVE_LIBTRANSLATE; +#endif /* HAVE_LIBTRANSLATE */      return &compiled_configuration;  } @@ -72,7 +80,12 @@ int rccInit() {      memcpy(rcc_default_languages, rcc_default_languages_embeded, (RCC_MAX_LANGUAGES + 1)*sizeof(rcc_language));      memcpy(rcc_option_descriptions, rcc_option_descriptions_embeded, (RCC_MAX_OPTIONS + 1)*sizeof(rcc_option_description)); +#ifdef HAVE_LIBTRANSLATE +    rccExternalInit(); +#endif /* HAVE_LIBTRANSLATE */     +      err = rccPluginInit(); +    if (!err) err = rccTranslateInit();      if (!err) err = rccXmlInit(1);      if (!err) err = rccEngineInit(); @@ -94,8 +107,11 @@ void rccFree() {      rccEngineFree();      rccXmlFree(); +    rccTranslateFree();      rccPluginFree(); +    rccExternalFree(); +      if (rcc_home_dir) {  	free(rcc_home_dir);  	rcc_home_dir = NULL; @@ -274,6 +290,35 @@ void rccFreeContext(rcc_context ctx) {      }  } +int rccInitDb4(rcc_context ctx, const char *name, rcc_db4_flags flags) { +    size_t size; +    char *dbname; +     +    if (!ctx) { +	if (rcc_default_ctx) ctx = rcc_default_ctx; +	else return -1; +    } + +    if (!name) name = "default"; + +    size = strlen(rcc_home_dir) + strlen(name) + 32; +    dbname = (char*)malloc(size*sizeof(char)); +    if (!dbname) return -1; + +    sprintf(dbname,"%s/.rcc/",rcc_home_dir); +    mkdir(dbname, 00644); +     +    sprintf(dbname,"%s/.rcc/%s.db/",rcc_home_dir,name); +    mkdir(dbname, 00644); + +    ctx->db4ctx = rccDb4CreateContext(dbname, flags); +    free(dbname);	 +     +    if (!ctx->db4ctx) return -1; + +    return 0; +} +  int rccLockConfiguration(rcc_context ctx, unsigned int lock_code) {      if (!ctx) {  	if (rcc_default_ctx) ctx = rcc_default_ctx; diff --git a/src/librcc.h b/src/librcc.h index a70d6df..52e6be4 100644 --- a/src/librcc.h +++ b/src/librcc.h @@ -371,6 +371,8 @@ typedef enum rcc_option_t {      RCC_OPTION_AUTODETECT_FS_TITLES,	/**< Detect titles of #RCC_CLASS_FS classes */      RCC_OPTION_AUTODETECT_FS_NAMES,	/**< Try to find encoding of #RCC_CLASS_FS by accessing fs */      RCC_OPTION_CONFIGURED_LANGUAGES_ONLY, /**< Use only configured languages or languages with auto-engines */ +    RCC_OPTION_TRANSLATE,		/**< Translate #rcc_string if it's language differs from current one */ +    RCC_OPTION_AUTOENGINE_SET_CURRENT,	/**< If enabled autodetection engine will set current charset */      RCC_MAX_OPTIONS  } rcc_option; @@ -908,7 +910,6 @@ typedef struct rcc_iconv_t *rcc_iconv;    * @result     *	- NULL if no recoding is required    *	- Pointer on initialized context if successful -  *	- Pointer on errnous context in the case of error    */  rcc_iconv rccIConvOpen(const char *from, const char *to);  /** @@ -920,13 +921,53 @@ void rccIConvClose(rcc_iconv icnv);    * Recodes chunk of data.    *    * @param icnv is recoding context -  * @param outbuf is preallocated output buffer -  * @param outsize is size of output buffer (striped string will be returned if buffer to small)     * @param buf is data for recoding -  * @param size is size of the data -  * @return number of recoded bytes in output buffer or -1 in the case of error +  * @param len is size of the data +  * @param rlen is size of recoded data +  * @return recoded string or NULL in the case of error    */ -size_t rccIConvRecode(rcc_iconv icnv, char *outbuf, size_t outsize, const char *buf, size_t size); +char *rccIConv(rcc_iconv icnv, const char *buf, size_t len, size_t *rlen); + +/** +  * translating context +  */ +typedef struct rcc_translate_t *rcc_translate; + +/* rcctranslate.c */ +/** +  * Open translating context. +  * +  * @param from is source language +  * @param to is destination language +  * @return +  *	- NULL if translation is not required or possible +  *	- Pointer on initialized context if successful +  */ +rcc_translate rccTranslateOpen(const char *from, const char *to); +/** +  * Close translating context. +  * +  * @param translate is translating context +  */ +void rccTranslateClose(rcc_translate translate); + +/* + * Set translation timeout + * + * @param translate is translating context  + * @param us is timeout in microseconds (0 - no timeout) + * @return non-zero value is returned in the case of errror + */ +int rccTranslateSetTimeout(rcc_translate translate, unsigned long us); + +/**  +  * Translate string. +  * +  * @param translate is translating context +  * @param buf is UTF-8 encoded string for translating +  * @return recoded string or NULL in the case of error +  */ +char *rccTranslate(rcc_translate translate, const char *buf);  /* recode.c */  /** @@ -1119,6 +1160,11 @@ rcc_context rccEngineGetRccContext(rcc_engine_context ctx);    */  #define RCC_CC_FLAG_HAVE_RCD				0x08  /** +  * Libtranslate translation engine compiled in +  */ +#define RCC_CC_FLAG_HAVE_LIBTRANSLATE			0x10 + +/**    * The library build environment is represented by this structure    */   struct rcc_compiled_configuration_t { diff --git a/src/lngconfig.c b/src/lngconfig.c index efb2c1a..c50ee74 100644 --- a/src/lngconfig.c +++ b/src/lngconfig.c @@ -164,6 +164,7 @@ int rccConfigInit(rcc_language_config config, rcc_context ctx) {      }      config->fsiconv = NULL; +    config->trans = NULL;      config->ctx = ctx;      config->language = NULL; @@ -199,6 +200,10 @@ void rccConfigFreeIConv(rcc_language_config config) {  void rccConfigClear(rcc_language_config config) {      if ((config)&&(config->charset)) {  	rccConfigFreeIConv(config); +	if (config->trans) { +	    rccTranslateClose(config->trans); +	    config->trans = NULL; +	}  	if (config->iconv_to) {  	    free(config->iconv_to);  	    config->iconv_to = NULL; @@ -521,7 +526,7 @@ int rccConfigConfigure(rcc_language_config config) {  	if ((!charset)||(rccIsUTF8(charset))) continue;  	config->iconv_to[i] = rccIConvOpen(charset, "UTF-8");      } -     +      config->configure = 0;      return 0; diff --git a/src/lngconfig.h b/src/lngconfig.h index b136905..92cc050 100644 --- a/src/lngconfig.h +++ b/src/lngconfig.h @@ -2,6 +2,7 @@  #define _RCC_LNGCONFIG_H  #include "rcciconv.h" +#include "rcctranslate.h"  struct rcc_language_config_t {      rcc_context ctx; @@ -16,6 +17,9 @@ struct rcc_language_config_t {      unsigned char configured; +    rcc_translate trans; +    rcc_language_id translang; +          rcc_iconv fsiconv;  };  typedef struct rcc_language_config_t rcc_language_config_s; diff --git a/src/rccconfig.c b/src/rccconfig.c index 57d38c3..ed6d30a 100644 --- a/src/rccconfig.c +++ b/src/rccconfig.c @@ -40,6 +40,10 @@ rcc_language rcc_default_languages_embeded[RCC_MAX_LANGUAGES + 1] = {      &rcc_default_engine,      NULL  }}, +{"en", {rcc_default_charset, rcc_utf8_charset, NULL}, { +    &rcc_default_engine, +    NULL +}},  {"ru", {rcc_default_charset,"KOI8-R","CP1251",rcc_utf8_charset,"IBM866","MACCYRILLIC","ISO8859-5", NULL}, {      &rcc_default_engine,  #ifdef RCC_RCD_SUPPORT @@ -115,6 +119,8 @@ rcc_option_description rcc_option_descriptions_embeded[RCC_MAX_OPTIONS+1] = {      {RCC_OPTION_AUTODETECT_FS_NAMES, 1, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0}, RCC_OPTION_TYPE_STANDARD,  "AUTODETECT_FS_NAMES", rcc_sn_boolean},      {RCC_OPTION_AUTODETECT_FS_TITLES, 1, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0}, RCC_OPTION_TYPE_INVISIBLE, "AUTODETECT_FS_TITLES", rcc_sn_boolean},      {RCC_OPTION_CONFIGURED_LANGUAGES_ONLY, 1, { RCC_OPTION_RANGE_TYPE_MENU, 0, 2, 1}, RCC_OPTION_TYPE_INVISIBLE, "CONFIGURED_LANGUAGES_ONLY", rcc_sn_clo}, +    {RCC_OPTION_TRANSLATE, 0, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0}, RCC_OPTION_TYPE_STANDARD, "TRANSLATE", rcc_sn_boolean }, +    {RCC_OPTION_AUTOENGINE_SET_CURRENT, 0, { RCC_OPTION_RANGE_TYPE_BOOLEAN, 0, 0, 0}, RCC_OPTION_TYPE_STANDARD, "AUTOENGINE_SET_CURRENT", rcc_sn_boolean },      {RCC_MAX_OPTIONS}  }; diff --git a/src/rccdb4.c b/src/rccdb4.c index d3e8cab..9c21477 100644 --- a/src/rccdb4.c +++ b/src/rccdb4.c @@ -4,48 +4,11 @@  #include "../config.h" -#ifdef HAVE_SYS_TYPES_H -# include <sys/types.h> -#endif /* HAVE_SYS_TYPES_H */ - -#ifdef HAVE_SYS_STAT_H -# include <sys/stat.h> -#endif /* HAVE_SYS_STAT_H */ -  #include "internal.h"  #include "rccdb4.h"  #define DATABASE "autolearn.db" -int rccInitDb4(rcc_context ctx, const char *name, rcc_db4_flags flags) { -    size_t size; -    char *dbname; -     -    if (!ctx) { -	if (rcc_default_ctx) ctx = rcc_default_ctx; -	else return -1; -    } - -    if (!name) name = "default"; - -    size = strlen(rcc_home_dir) + strlen(name) + 32; -    dbname = (char*)malloc(size*sizeof(char)); -    if (!dbname) return -1; - -    sprintf(dbname,"%s/.rcc/",rcc_home_dir); -    mkdir(dbname, 00644); -     -    sprintf(dbname,"%s/.rcc/%s.db/",rcc_home_dir,name); -    mkdir(dbname, 00644); - -    ctx->db4ctx = rccDb4CreateContext(dbname, flags); -    free(dbname);	 -     -    if (!ctx->db4ctx) return -1; - -    return 0; -} -  db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags) {      int err;      db4_context ctx; @@ -124,7 +87,7 @@ static void rccDb4Strip(DBT *key) {  }  #endif /* HAVE_DB_H */ -int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const rcc_string string) { +int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const char *string) {  #ifdef HAVE_DB_H      DBT key, data;  #endif /* HAVE_DB_H */ @@ -149,7 +112,7 @@ int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const rcc_strin      return 1;  } -rcc_string rccDb4GetKey(db4_context ctx, const char *orig, size_t olen) { +char *rccDb4GetKey(db4_context ctx, const char *orig, size_t olen) {  #ifdef HAVE_DB_H      DBT key, data;  #endif /* HAVE_DB_H */ diff --git a/src/rccdb4.h b/src/rccdb4.h index 1d5072b..a11e53d 100644 --- a/src/rccdb4.h +++ b/src/rccdb4.h @@ -3,12 +3,12 @@  #include "../config.h" +#include "librcc.h" +  #ifdef HAVE_DB_H  # include <db.h>  #endif /* HAVE_DB_H */ -#include "rccstring.h" -  struct db4_context_t {  #ifdef HAVE_DB_H      DB_ENV *dbe; @@ -24,7 +24,7 @@ typedef struct db4_context_t *db4_context;  db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags);  void rccDb4FreeContext(db4_context ctx); -int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const rcc_string string); -rcc_string rccDb4GetKey(db4_context ctx, const char *orig, size_t olen); +int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const char *string); +char *rccDb4GetKey(db4_context ctx, const char *orig, size_t olen);  #endif /* _RCC_DB4_H */ diff --git a/src/rccexternal.c b/src/rccexternal.c new file mode 100644 index 0000000..16b3667 --- /dev/null +++ b/src/rccexternal.c @@ -0,0 +1,210 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <errno.h> + +#include "../config.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif /* HAVE_FCNTL_H */ +#ifdef HAVE_SIGNAL_H +# include <signal.h> +#endif /* HAVE_SIGNAL_H */ + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_SYS_SOCKET_H +# include <sys/socket.h> +#endif /* HAVE_SYS_SOCKET_H */ +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif /* HAVE_SYS_STAT_H */ +#ifdef HAVE_SYS_UN_H +# include <sys/un.h> +#endif /* HAVE_SYS_UN_H */ +#ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +#endif /* HAVE_SYS_TIME_H */ +#ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +#endif /* HAVE_SYS_SELECT_H */ +#ifdef HAVE_SYS_WAIT_H +# include <sys/wait.h> +#endif /* HAVE_SYS_WAIT_H */ + +#include "rccexternal.h" +#include "internal.h" + +#define RCC_EXT_PROG_NAME "rccexternal" + +static pid_t pid = (pid_t)-1; +static char *addr = NULL; + +int rccExternalInit() { +#ifdef HAVE_SIGNAL_H +    struct sigaction act; +#endif /* HAVE_SIGNAL_H */ + +    if (pid != (pid_t)-1) return 0; + +    if (!addr) { +	addr = (char*)malloc(strlen(rcc_home_dir)+32); +	if (!addr) return -1; +    } + +    pid = fork(); +    if (pid) { +	if (pid == (pid_t)-1) return -1; +	sprintf(addr,"%s/.rcc/comm/%lu.sock", rcc_home_dir, (unsigned long)pid); + +#ifdef HAVE_SIGNAL_H +	act.sa_handler = SIG_IGN; +	sigemptyset(&act.sa_mask); +	act.sa_flags = 0; +	sigaction(SIGPIPE,&act,NULL); +#endif /* HAVE_SIGNAL_H */ + +	return 0; +    } +     +    execl(LIBRCC_DATA_DIR "/" RCC_EXT_PROG_NAME, RCC_EXT_PROG_NAME, NULL); +    exit(1); +} + +void rccExternalFree() { +    if (pid == (pid_t)-1) return; +     +    rccExternalConnect(0);     +    if (addr) free(addr); + +    waitpid(pid, NULL, 0); +    pid = (pid_t)-1; +} + +static int rccExternalSetDeadline(struct timeval *tv, unsigned long timeout) { +    gettimeofday(tv, NULL); +    tv->tv_sec += (tv->tv_usec + timeout + RCC_EXTERNAL_TIMEOUT) / 1000000; +    tv->tv_usec = (tv->tv_usec + timeout + RCC_EXTERNAL_TIMEOUT) % 1000000; +    return 0; +} + +size_t rccExternalWrite(int s, const char *buffer, ssize_t size, unsigned long timeout) { +    int err; +    unsigned char connected = 1; +    ssize_t writed, res = 0; +    struct timeval tv; +    fd_set fdcon; + +    if (s == -1) return -1; +     +    for (writed = 0; (writed < size)&&(connected); writed += connected?res:0) { +	FD_ZERO(&fdcon); +	FD_SET(s, &fdcon); +	rccExternalSetDeadline(&tv, timeout); +	err = select(s+1,NULL,&fdcon,NULL,&tv); +	if (err<=0) connected = 0; +	else { +	    res = write(s, buffer + writed, size - writed); +	    if (res<=0) connected = 0; +	} +    } + +    return size - writed; +} + +size_t rccExternalRead(int s, char *buffer, ssize_t size, unsigned long timeout) { +    int err; +    unsigned char connected = 1; +    ssize_t readed, res = 0; +    struct timeval tv; +    fd_set fdcon; +     +    if (s == -1) return -1; +     +    for (readed = 0; (readed < size)&&(connected); readed += connected?res:0) { +	FD_ZERO(&fdcon); +	FD_SET(s, &fdcon); +	rccExternalSetDeadline(&tv, timeout); +	err = select(s+1,&fdcon,NULL,NULL,&tv); +	if (err<=0) connected = 0; +	else { +	    res = read(s, buffer + readed, size - readed); +	    if (res<=0) connected = 0; +	} +    } + +    return size - readed; +} + +int rccExternalConnect(unsigned char module) { +    int err; +    int retries = 10; +    int sock; +    int flags; +    struct sockaddr_un mysock; +    struct timeval tv; +    struct timespec ts; +    fd_set fdcon; +     +    if (pid == (pid_t)-1) return -1; + +    sock = socket(PF_UNIX, SOCK_STREAM, 0); +    if (sock<=0) return -1; + +    flags = fcntl(sock,F_GETFL,0); +    if (flags<0) flags = 0; +    if (fcntl(sock,F_SETFL,flags|O_NONBLOCK)<0) { +	close(sock); +	return -1; +    } +         +    memset(&mysock, 0, sizeof(mysock)); +    mysock.sun_family=AF_UNIX; +    strncpy(mysock.sun_path,addr,sizeof(mysock.sun_path)); +    mysock.sun_path[sizeof(mysock.sun_path)-1]=0; + +again: +    if (connect(sock,(struct sockaddr*)&mysock,sizeof(mysock))<0) { +        if (errno == EINPROGRESS) { +	    FD_ZERO(&fdcon); +	    FD_SET(sock, &fdcon); + +	    rccExternalSetDeadline(&tv, 0); +	    err = select(sock+1,&fdcon,NULL,NULL,&tv); +	    if (err<=0) { +		close(sock); +		return -1; +	    } +	} else if ((errno == ENOENT)&&(retries)) { +	    ts.tv_sec = (RCC_EXTERNAL_TIMEOUT/10) / 1000000; +	    ts.tv_nsec = ((RCC_EXTERNAL_TIMEOUT/10) % 1000000)*1000; +	    nanosleep(&ts, NULL); +	    retries--; +	    goto again; +	} else { +	    close(sock); +	    return -1; +	} +    } +     +    if (rccExternalWrite(sock, &module, 1, 0)) { +	close(sock); +	return -1; +    } + +    return sock; +} + +void rccExternalClose(int s) { +    unsigned char cmd = 0; +    if (s != -1) { +	write(s, &cmd, 1); +	close(s); +    } +} diff --git a/src/rccexternal.h b/src/rccexternal.h new file mode 100644 index 0000000..bffd6b3 --- /dev/null +++ b/src/rccexternal.h @@ -0,0 +1,35 @@ +#ifndef _RCC_EXTERNAL_H +#define _RCC_EXTERNAL_H + +#define RCC_EXTERNAL_TIMEOUT			1000000 + +typedef enum rcc_external_module_t { +    RCC_EXTERNAL_MODULE_CONTROL = 0, +    RCC_EXTERNAL_MODULE_LIBRTRANSLATE, +    RCC_EXTERNAL_MODULE_MAX +} rcc_external_module; + +struct rcc_external_info_t { +    int s; +}; +typedef struct rcc_external_info_t rcc_external_info_s; +typedef struct rcc_external_info_t *rcc_external_info; + +struct rcc_external_command_t { +    unsigned long size; +    unsigned char cmd; +}; +typedef struct rcc_external_command_t rcc_external_command_s; +typedef struct rcc_external_command_t *rcc_external_command; + +#define RCC_EXTERNAL_COMMAND_CLOSE 0 + +int rccExternalInit(); +void rccExternalFree(); + +size_t rccExternalWrite(int s, const char *buffer, ssize_t size, unsigned long timeout); +size_t rccExternalRead(int s, char *buffer, ssize_t size, unsigned long timeout); +int rccExternalConnect(unsigned char module); +void rccExternalClose(int s); + +#endif /* _RCC_EXTERNAL_H */ diff --git a/src/rcciconv.c b/src/rcciconv.c index 65b32b3..d9903de 100644 --- a/src/rcciconv.c +++ b/src/rcciconv.c @@ -92,7 +92,28 @@ loop:      return outsize - out_left;  } -size_t rccIConv(rcc_context ctx, rcc_iconv icnv, const char *buf, size_t len) { +char *rccIConv(rcc_iconv icnv, const char *buf, size_t len, size_t *rlen) { +    char *res; +    size_t size; +    char tmpbuffer[RCC_MAX_STRING_CHARS+1]; + +    size = rccIConvRecode(icnv, tmpbuffer, RCC_MAX_STRING_CHARS, buf, len); +    if (size != (size_t)-1) { +	res = (char*)malloc((size+1)*sizeof(char)); +	if (!res) return res; +	 +	if (rlen) *rlen = size; +	memcpy(res, tmpbuffer, size); +	res[size] = 0; + +	return res; +    } + +    return NULL; +} + +size_t rccIConvInternal(rcc_context ctx, rcc_iconv icnv, const char *buf, size_t len) {      if (!ctx) return (size_t)-1;      return rccIConvRecode(icnv, ctx->tmpbuffer, RCC_MAX_STRING_CHARS, buf, len);  } + diff --git a/src/rcciconv.h b/src/rcciconv.h index cc1d1b9..0070696 100644 --- a/src/rcciconv.h +++ b/src/rcciconv.h @@ -8,6 +8,18 @@ struct rcc_iconv_t {  };  typedef struct rcc_iconv_t rcc_iconv_s; -size_t rccIConv(rcc_context ctx, rcc_iconv icnv, const char *buf, size_t len); +size_t rccIConvInternal(rcc_context ctx, rcc_iconv icnv, const char *buf, size_t len); + +/**  +  * Recodes chunk of data. +  * +  * @param icnv is recoding context +  * @param outbuf is preallocated output buffer +  * @param outsize is size of output buffer (striped string will be returned if buffer to small)  +  * @param buf is data for recoding +  * @param size is size of the data +  * @return number of recoded bytes in output buffer or -1 in the case of error +  */ +size_t rccIConvRecode(rcc_iconv icnv, char *outbuf, size_t outsize, const char *buf, size_t size);  #endif /* _RCC_ICONV_H */ diff --git a/src/rcctranslate.c b/src/rcctranslate.c new file mode 100644 index 0000000..3bbd916 --- /dev/null +++ b/src/rcctranslate.c @@ -0,0 +1,151 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "internal.h" +#include "rccexternal.h" +#include "rcctranslate.h" + + + +int rccTranslateInit() { + +    return 0; +} + +void rccTranslateFree() { +} + + +rcc_translate rccTranslateOpen(const char *from, const char *to) { +#ifdef HAVE_LIBTRANSLATE +    rcc_translate translate; + +    if ((!from)||(!to)||(!strcasecmp(from,to))) return NULL; +    if ((strlen(from)!=2)||(strlen(to)!=2)) return NULL; +     +    translate = (rcc_translate)malloc(sizeof(rcc_translate_s)); +    if (!translate) return NULL; + +    translate->sock = rccExternalConnect(RCC_EXTERNAL_MODULE_LIBRTRANSLATE); +    if (translate->sock == -1) { +	free(translate); +	return NULL; +    } + +    translate->remaining = 0; +    translate->prefix.cmd.cmd = RCC_EXTERNAL_COMMAND_TRANSLATE; +    translate->prefix.cmd.size = sizeof(rcc_translate_prefix_s); +    memcpy(translate->prefix.from, from, 3*sizeof(char)); +    memcpy(translate->prefix.to, to,  3*sizeof(char)); +    rccTranslateSetTimeout(translate, RCC_TRANSLATE_DEFAULT_TIMEOUT); + +    return translate; +#else +    return NULL; +#endif /* HAVE_LIBTRANSLATE */ +} + +void rccTranslateClose(rcc_translate translate) { +#ifdef HAVE_LIBTRANSLATE +    if (!translate) return; +    if (translate->sock != -1) rccExternalClose(translate->sock); +    free(translate); +#endif /* HAVE_LIBTRANSLATE */ +} + +int rccTranslateSetTimeout(rcc_translate translate, unsigned long us) { +#ifdef HAVE_LIBTRANSLATE_TIMED_TRANSLATE     +    if (!translate) return -1; +    translate->prefix.timeout = us; +    return 0; +#else +    return -1; +#endif /* HAVE_LIBTRANSLATE_TIMED_TRANSLATE */ +} + +char *rccTranslate(rcc_translate translate, const char *buf) { +#ifdef HAVE_LIBTRANSLATE +    size_t i; +    rcc_external_command_s resp; +    size_t err, len; +    char *buffer; + +    if ((!translate)||(!buf)) return NULL; +     +    if (!strcmp(translate->prefix.to, "en")) { +	for (i=0;buf[i];i++)  +	    if ((unsigned char)buf[i]>0x7F) break; +	if (!buf[i]) return NULL; +    } +     +    if (translate->sock == -1) { +	translate->sock = rccExternalConnect(RCC_EXTERNAL_MODULE_LIBRTRANSLATE); +	if (translate->sock == -1) return NULL; +    } else if (translate->remaining) { +	if (translate->remaining == (size_t)-1) { +	    err = rccExternalRead(translate->sock, (char*)&resp, sizeof(rcc_external_command_s), 0); +	    if (err) return NULL; +	    translate->remaining = resp.size; +	} +	 +	buffer = (char*)malloc(translate->remaining*sizeof(char)); +	if (!buffer) { +	    rccExternalClose(translate->sock); +	    translate->sock = -1; +	    return NULL; +	} +	err = rccExternalRead(translate->sock, buffer, translate->remaining, 0); +	free(buffer); +	if (err) { +	    translate->remaining = err; +	    return NULL; +	} +	translate->remaining = 0; +    } +     +    len = strlen(buf); +    translate->prefix.cmd.size = sizeof(rcc_translate_prefix_s) + len - sizeof(rcc_external_command_s); +    err = rccExternalWrite(translate->sock, (char*)&translate->prefix, sizeof(rcc_translate_prefix_s) - 1, 0); +    if (err) { +	rccExternalClose(translate->sock); +	translate->sock = -1; +	return NULL; +    } +    err = rccExternalWrite(translate->sock, buf, len + 1, 0); +    if (err) { +	rccExternalClose(translate->sock); +	translate->sock = -1; +	return NULL; +    } + +    err = rccExternalRead(translate->sock, (char*)&resp, sizeof(rcc_external_command_s), translate->prefix.timeout); +    if (err) { +	if (err == sizeof(rcc_external_command_s)) { +	    translate->remaining = (size_t)-1; +	} else { +	    rccExternalClose(translate->sock); +	    translate->sock = -1; +	} +	return NULL; +    } +    if ((resp.cmd!=RCC_EXTERNAL_COMMAND_TRANSLATE)||(!resp.size)) return NULL; +     +    buffer = (char*)malloc(resp.size*sizeof(char)); +    if (!buffer) { +	rccExternalClose(translate->sock); +	translate->sock = -1; +	return NULL; +    } +    err = rccExternalRead(translate->sock, buffer, resp.size, 0); +    if (err) { +	translate->remaining = err; +	free(buffer); +	return NULL; +    } +     +    return buffer; +#else +    return NULL; +#endif /* HAVE_LIBTRANSLATE */ +} diff --git a/src/rcctranslate.h b/src/rcctranslate.h new file mode 100644 index 0000000..961af6f --- /dev/null +++ b/src/rcctranslate.h @@ -0,0 +1,31 @@ +#ifndef _RCC_TRANSLATE_H +#define _RCC_TRANSLATE_H + +#include "rccexternal.h" +#define RCC_TRANSLATE_DEFAULT_TIMEOUT	5000000	/* 5s */ +#define RCC_EXTERNAL_COMMAND_TRANSLATE 0x80 + + +struct rcc_translate_prefix_t { +    rcc_external_command_s cmd; +    unsigned long timeout; +    char from[3]; +    char to[3]; +    char text[1]; +}; +typedef struct rcc_translate_prefix_t rcc_translate_prefix_s; +typedef struct rcc_translate_prefix_t *rcc_translate_prefix; + + +struct rcc_translate_t { +    rcc_translate_prefix_s prefix; +    size_t remaining; +    int sock; +}; +typedef struct rcc_translate_t rcc_translate_s; + + +int rccTranslateInit(); +void rccTranslateFree(); + +#endif /* _RCC_TRANSLATE_H */ diff --git a/src/recode.c b/src/recode.c index a1b7f31..c44095c 100644 --- a/src/recode.c +++ b/src/recode.c @@ -9,6 +9,7 @@  #include "rccstring.h"  #include "rccconfig.h"  #include "rccdb4.h" +#include "rcctranslate.h" @@ -37,6 +38,7 @@ rcc_string rccSizedFrom(rcc_context ctx, rcc_class_id class_id, const char *buf,      rcc_iconv icnv = NULL;      rcc_string result;      rcc_option_value usedb4; +    const char *charset;      if (!ctx) {  	if (rcc_default_ctx) ctx = rcc_default_ctx; @@ -66,11 +68,17 @@ rcc_string rccSizedFrom(rcc_context ctx, rcc_class_id class_id, const char *buf,      if (err) return NULL;      charset_id = rccIConvAuto(ctx, class_id, buf, len); -    if (charset_id != (rcc_autocharset_id)-1) icnv = ctx->iconv_auto[charset_id]; +    if (charset_id != (rcc_autocharset_id)-1) { +	icnv = ctx->iconv_auto[charset_id]; +	if (rccGetOption(ctx, RCC_OPTION_AUTOENGINE_SET_CURRENT)) { +	    charset = rccGetAutoCharsetName(ctx, charset_id); +	    rccSetCharsetByName(ctx, class_id, charset); +	} +    }      else icnv = ctx->iconv_from[class_id];      if (icnv) { -	ret = rccIConv(ctx, icnv, buf, len); +	ret = rccIConvInternal(ctx, icnv, buf, len);  	if (ret == (size_t)-1) return NULL;  	result = rccCreateString(language_id, ctx->tmpbuffer, ret);      } else { @@ -92,8 +100,10 @@ char *rccSizedTo(rcc_context ctx, rcc_class_id class_id, rcc_const_string buf, s      char *result;      char *prefix, *name;      const char *utfstring; +    char *translated = NULL;      rcc_language_config config;      rcc_language_id language_id; +    rcc_language_id current_language_id;      rcc_class_type class_type;      rcc_iconv icnv; @@ -117,6 +127,38 @@ char *rccSizedTo(rcc_context ctx, rcc_class_id class_id, rcc_const_string buf, s      if (err) return NULL;      class_type = rccGetClassType(ctx, class_id); +    if ((class_type != RCC_CLASS_FS)&&(rccGetOption(ctx, RCC_OPTION_TRANSLATE))) { +	current_language_id = rccGetCurrentLanguage(ctx); +	if (current_language_id != language_id) { +	    if ((config->trans)&&(config->translang != current_language_id)) { +		rccTranslateClose(config->trans); +		config->trans = NULL; +	    } +	    if (!config->trans) { +		config->trans = rccTranslateOpen(rccGetLanguageName(ctx, language_id), rccGetLanguageName(ctx, current_language_id)); +		config->translang = current_language_id; +	    } +	    if (config->trans) { +		translated = rccTranslate(config->trans, utfstring); +		if (translated) { +		    language_id = current_language_id; +		     +		    config = rccGetConfig(ctx, language_id); +		    if (!config) { +			free(translated); +			return NULL; +		    } + +		    err = rccConfigConfigure(config); +		    if (err) { +			free(translated); +			return NULL; +		    } +		} +	    } +	} +    } +          if ((class_type == RCC_CLASS_FS)&&(rccGetOption(ctx, RCC_OPTION_AUTODETECT_FS_NAMES))) {  	    if (rccIsASCII(utfstring)) {  		result = rccStringExtractString(buf); @@ -141,14 +183,20 @@ char *rccSizedTo(rcc_context ctx, rcc_class_id class_id, rcc_const_string buf, s      icnv =  config->iconv_to[class_id];      if (icnv) { -	newlen = rccIConv(ctx, icnv, rccStringGetString((const char*)buf), newlen); +	newlen = rccIConvInternal(ctx, icnv, translated?translated:utfstring, newlen); +	if (translated) free(translated);  	if (newlen == (size_t)-1) return NULL;  	result = rccCreateResult(ctx, newlen);  	if (rlen) *rlen = newlen;      } else { -	result = rccStringExtractString(buf); -	if (rlen) *rlen = newlen; +	if (translated) { +	    result = translated; +	    if (rlen) *rlen = strlen(result); +	} else { +	    result = rccStringExtractString(buf); +	    if (rlen) *rlen = newlen; +	}      }          return result; @@ -274,7 +322,7 @@ rcc_string rccSizedFromCharset(rcc_context ctx, const char *charset, const char      icnv = rccIConvOpen("UTF-8", charset);      if (icnv) { -	res = rccIConv(ctx, icnv, buf, len); +	res = rccIConvInternal(ctx, icnv, buf, len);  	rccIConvClose(icnv);  	if (res == (size_t)-1) return NULL;  	return rccCreateString(language_id, ctx->tmpbuffer, res); @@ -293,7 +341,7 @@ char *rccSizedToCharset(rcc_context ctx, const char *charset, rcc_const_string b      icnv = rccIConvOpen(charset, "UTF-8");      if (icnv) { -	res = rccIConv(ctx, icnv, rccStringGetString(buf), res); +	res = rccIConvInternal(ctx, icnv, rccStringGetString(buf), res);  	rccIConvClose(icnv);  	if (res == (size_t)-1) return NULL; @@ -321,7 +369,7 @@ char *rccSizedRecodeToCharset(rcc_context ctx, rcc_class_id class_id, const char      icnv = rccIConvOpen(charset, "UTF-8");      if (icnv) { -	res = rccIConv(ctx, icnv, str, 0); +	res = rccIConvInternal(ctx, icnv, str, 0);  	rccIConvClose(icnv);  	free(utf8); @@ -349,7 +397,7 @@ char *rccSizedRecodeFromCharset(rcc_context ctx, rcc_class_id class_id, const ch      icnv = rccIConvOpen("UTF-8", charset);      if (icnv) { -	res = rccIConv(ctx, icnv, buf, len); +	res = rccIConvInternal(ctx, icnv, buf, len);  	rccIConvClose(icnv);  	if (res == (size_t)-1) return NULL; @@ -373,7 +421,7 @@ char *rccSizedRecodeCharsets(rcc_context ctx, const char *from, const char *to,      icnv = rccIConvOpen(to, from);      if (!icnv) return NULL; -    res = rccIConv(ctx, icnv, buf, len); +    res = rccIConvInternal(ctx, icnv, buf, len);      rccIConvClose(icnv);      if (res == (size_t)-1) return NULL;  | 
