Using Fidogate code to do charset translation
This commit is contained in:
parent
d296b1fb8a
commit
7a7b810aec
@ -38,8 +38,8 @@ v0.51.1 21-Feb-2004
|
||||
Added experimental characterset translation to message read.
|
||||
This will translate the message character set used to the users
|
||||
character set. When translation is impossible a ? is printed.
|
||||
Doesn't work well with Russion, but seems to work with German
|
||||
text.
|
||||
After problems with iconv, switched to use code from Martin
|
||||
Junius Fidogate package.
|
||||
In delete file in home directory the Y/N keys were read from
|
||||
the wrong language prompt.
|
||||
|
||||
|
2
TODO
2
TODO
@ -112,6 +112,8 @@ mbfido:
|
||||
N: Force processing of arealists so that all tags are forced to
|
||||
uppercase. Seems to give problems in some nets.
|
||||
|
||||
N: Make tic areas check case insensitive.
|
||||
|
||||
N: Let mbfido areas with a special switch update area descriptions.
|
||||
|
||||
N: Send rulefile via netmail for each new connected mail area.
|
||||
|
@ -182,9 +182,6 @@
|
||||
/* Define if you have the <utmpx.h> header file. */
|
||||
#undef HAVE_UTMPX_H
|
||||
|
||||
/* Define if you have the <iconv.h> header file. */
|
||||
#undef HAVE_ICONV_H
|
||||
|
||||
/* Define if you have the memcpy function. */
|
||||
#undef HAVE_MEMCPY
|
||||
|
||||
|
3
configure
vendored
3
configure
vendored
@ -5373,8 +5373,7 @@ done
|
||||
|
||||
|
||||
|
||||
|
||||
for ac_header in sys/resource.h usersec.h gshadow.h shadow.h iconv.h
|
||||
for ac_header in sys/resource.h usersec.h gshadow.h shadow.h
|
||||
do
|
||||
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
if eval "test \"\${$as_ac_Header+set}\" = set"; then
|
||||
|
@ -203,7 +203,7 @@ AC_HEADER_DIRENT
|
||||
AC_HEADER_TIME
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS(sys/time.h termios.h sys/vfs.h unistd.h netinet/in.h regex.h)
|
||||
AC_CHECK_HEADERS(sys/resource.h usersec.h gshadow.h shadow.h iconv.h)
|
||||
AC_CHECK_HEADERS(sys/resource.h usersec.h gshadow.h shadow.h)
|
||||
AC_CHECK_HEADERS(limits.h utmp.h utmpx.h lastlog.h rpc/key_prot.h)
|
||||
AC_STRUCT_TIMEZONE
|
||||
|
||||
|
21
lib/Makefile
21
lib/Makefile
@ -33,17 +33,22 @@ MBINET_HDRS = mbinet.h
|
||||
DIESEL_SRCS = diesel.c mbdiesel.c
|
||||
DIESEL_HDRS = diesel.h
|
||||
DIESEL_OBJS = diesel.o mbdiesel.o
|
||||
CHC_SRCS = mbcharsetc.c
|
||||
CHC_HDRS = mbcharsetc.h
|
||||
CHC_OBJS = mbcharsetc.o
|
||||
OTHER_HDRS = bluewave.h mbse.h users.h
|
||||
SRCS = ${COMMON_SRCS} ${DBASE_SRCS} ${MSGBASE_SRCS} ${MBINET_SRCS} \
|
||||
${DIESEL_SRCS} ${NODELIST_SRCS}
|
||||
${DIESEL_SRCS} ${NODELIST_SRCS} ${CHC_SRCS}
|
||||
OBJS = ${COMMON_OBJS} ${DBASE_OBJS} ${MSGBASE_OBJS} ${MBINET_OBJS} \
|
||||
${DIESEL_OBJS} ${NODELIST_OBJS}
|
||||
${DIESEL_OBJS} ${NODELIST_OBJS} ${CHC_OBJS}
|
||||
HDRS = ${COMMON_HDRS} ${DBASE_HDRS} ${MSGBASE_HDRS} ${MBINET_HDRS} \
|
||||
${DIESEL_HDRS} ${NODELIST_HDRS} ${OTHER_HDRS}
|
||||
${DIESEL_HDRS} ${NODELIST_HDRS} ${CHC_HDRS} ${OTHER_HDRS}
|
||||
MAPS = charset.map russian.map
|
||||
OTHER = Makefile README ftscprod.008 mkprod.awk \
|
||||
README.diesel README.macro Diesel.doc nodelist.conf
|
||||
TARGET = libmbse.a libdbase.a libmsgbase.a libmbinet.a libdiesel.a \
|
||||
libnodelist.a
|
||||
libnodelist.a mbcharsetc charset.bin
|
||||
LIBS += ../lib/libmbse.a
|
||||
|
||||
#############################################################################
|
||||
|
||||
@ -79,8 +84,16 @@ libnodelist.a: ${NODELIST_OBJS}
|
||||
ar r $@ $?
|
||||
${RANLIB} $@
|
||||
|
||||
mbcharsetc: ${CHC_OBJS} ${LIBS}
|
||||
${CC} -o mbcharsetc ${CHC_OBJS} ${LDFLAGS} ${LIBS}
|
||||
|
||||
charset.bin: mbcharsetc ${MAPS}
|
||||
./mbcharsetc charset.map charset.bin
|
||||
|
||||
install: all
|
||||
${INSTALL} -c -o ${OWNER} -g ${GROUP} -m 0444 nodelist.conf ${ETCDIR}
|
||||
${INSTALL} -c -s -g ${GROUP} -o ${OWNER} -m 0751 mbcharsetc ${BINDIR}
|
||||
${INSTALL} -c -o ${OWNER} -g ${GROUP} -m 0444 charset.bin ${ETCDIR}
|
||||
|
||||
clean:
|
||||
rm -f ${TARGET} *.o *.h~ *.c~ ftscprod.c core filelist Makefile.bak
|
||||
|
382
lib/charset.c
382
lib/charset.c
@ -32,6 +32,84 @@
|
||||
#include "mbselib.h"
|
||||
|
||||
|
||||
#define strieq(a,b) (strcasecmp ((a),(b)) == 0)
|
||||
#define BUF_APPEND(d,s) str_append(d,sizeof(d),s)
|
||||
|
||||
|
||||
/*
|
||||
* Alias linked list
|
||||
*/
|
||||
static CharsetAlias *charset_alias_list = NULL;
|
||||
static CharsetAlias *charset_alias_last = NULL;
|
||||
|
||||
/*
|
||||
* Table linked list
|
||||
*/
|
||||
static CharsetTable *charset_table_list = NULL;
|
||||
static CharsetTable *charset_table_last = NULL;
|
||||
|
||||
/*
|
||||
* Current charset mapping table
|
||||
*/
|
||||
static CharsetTable *charset_table_used = NULL;
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* str_printf(): wrapper for sprintf()/snprintf()
|
||||
*/
|
||||
int str_printf(char *buf, size_t len, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int n;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
#ifdef HAS_SNPRINTF
|
||||
n = vsnprintf(buf, len, fmt, args);
|
||||
/**FIXME: check for n==-1 and errno**/
|
||||
#else
|
||||
n = vsprintf(buf, fmt, args);
|
||||
if(n >= len) {
|
||||
WriteError("Internal error - str_printf() buf overflow");
|
||||
/**NOT REACHED**/
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
/* Make sure that buf[] is terminated with a \0. vsnprintf()
|
||||
* should do this automatically as required by the ANSI C99
|
||||
* proposal, but one never knows ... see also discussion on
|
||||
* BugTraq */
|
||||
buf[len - 1] = 0;
|
||||
|
||||
va_end(args);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
char *str_append(char *d, size_t n, char *s)
|
||||
{
|
||||
int max = n - strlen(d) - 1;
|
||||
|
||||
strncat(d, s, max);
|
||||
d[n-1] = 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *str_copy(char *d, size_t n, char *s)
|
||||
{
|
||||
strncpy(d, s, n);
|
||||
d[n-1] = 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
#define BUF_COPY(d,s) str_copy (d,sizeof(d),s)
|
||||
|
||||
|
||||
char *getchrs(int val)
|
||||
{
|
||||
switch (val) {
|
||||
@ -67,34 +145,288 @@ char *getchrsdesc(int val)
|
||||
|
||||
|
||||
|
||||
char *get_iconv_name(char *name)
|
||||
/*
|
||||
* Alloc new CharsetTable and put into linked list
|
||||
*/
|
||||
CharsetTable *charset_table_new(void)
|
||||
{
|
||||
if (!strncasecmp(name, "CP437", 5))
|
||||
return (char *)"IBM437";
|
||||
if (!strncasecmp(name, "CP850", 5))
|
||||
return (char *)"IBM850";
|
||||
if (!strncasecmp(name, "CP865", 5))
|
||||
return (char *)"IBM865";
|
||||
if (!strncasecmp(name, "CP866", 5))
|
||||
return (char *)"IBM866";
|
||||
if (!strncasecmp(name, "LATIN-1", 7))
|
||||
return (char *)"ISO_8859-1";
|
||||
if (!strncasecmp(name, "LATIN-2", 7))
|
||||
return (char *)"ISO_8859-2";
|
||||
if (!strncasecmp(name, "LATIN-5", 7))
|
||||
return (char *)"ISO_8859-5";
|
||||
if (!strncasecmp(name, "PC-8", 4))
|
||||
return (char *)"IBM437";
|
||||
if (!strncasecmp(name, "IBMPC", 5))
|
||||
return (char *)"IBM437";
|
||||
if (!strncasecmp(name, "+7_FIDO", 7))
|
||||
return (char *)"IBM866";
|
||||
if (!strncasecmp(name, "CP1125", 6))
|
||||
return (char *)"CP1125";
|
||||
CharsetTable *p;
|
||||
|
||||
Syslog('+', "get_iconv_name(%s): no usable character set name found", name);
|
||||
return NULL;
|
||||
/* Alloc and clear */
|
||||
p = (CharsetTable *)xmalloc(sizeof(CharsetTable));
|
||||
memset(p, 0, sizeof(CharsetTable));
|
||||
p->next = NULL; /* Just to be sure */
|
||||
|
||||
/* Put into linked list */
|
||||
if(charset_table_list)
|
||||
charset_table_last->next = p;
|
||||
else
|
||||
charset_table_list = p;
|
||||
charset_table_last = p;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Alloc new CharsetAlias and put into linked list
|
||||
*/
|
||||
CharsetAlias *charset_alias_new(void)
|
||||
{
|
||||
CharsetAlias *p;
|
||||
|
||||
/* Alloc and clear */
|
||||
p = (CharsetAlias *)xmalloc(sizeof(CharsetAlias));
|
||||
memset(p, 0, sizeof(CharsetAlias));
|
||||
p->next = NULL; /* Just to be sure */
|
||||
|
||||
/* Put into linked list */
|
||||
if(charset_alias_list)
|
||||
charset_alias_last->next = p;
|
||||
else
|
||||
charset_alias_list = p;
|
||||
charset_alias_last = p;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Write binary mapping file
|
||||
*/
|
||||
int charset_write_bin(char *name)
|
||||
{
|
||||
FILE *fp;
|
||||
CharsetTable *pt;
|
||||
CharsetAlias *pa;
|
||||
|
||||
// debug(14, "Writing charset.bin file %s", name);
|
||||
|
||||
fp = fopen(name, "w+");
|
||||
if(!fp)
|
||||
return FALSE;
|
||||
|
||||
/* Write aliases */
|
||||
for (pa = charset_alias_list; pa; pa=pa->next) {
|
||||
fputc(CHARSET_FILE_ALIAS, fp);
|
||||
fwrite(pa, sizeof(CharsetAlias), 1, fp);
|
||||
if(ferror(fp)) {
|
||||
fclose(fp);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write tables */
|
||||
for(pt = charset_table_list; pt; pt=pt->next) {
|
||||
fputc(CHARSET_FILE_TABLE, fp);
|
||||
fwrite(pt, sizeof(CharsetTable), 1, fp);
|
||||
if(ferror(fp)) {
|
||||
fclose(fp);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read binary mapping file
|
||||
*/
|
||||
int charset_read_bin(void)
|
||||
{
|
||||
FILE *fp;
|
||||
int c, n;
|
||||
CharsetTable *pt;
|
||||
CharsetAlias *pa;
|
||||
char *name;
|
||||
|
||||
name = calloc(PATH_MAX, sizeof(char));
|
||||
sprintf(name, "%s/etc/charset.bin", getenv("MBSE_ROOT"));
|
||||
Syslog('s', "Reading %s", name);
|
||||
if ((fp = fopen(name, "r")) == NULL) {
|
||||
WriteError("$Can't open %s", name);
|
||||
free(name);
|
||||
return FALSE;
|
||||
}
|
||||
free(name);
|
||||
|
||||
while( (c = fgetc(fp)) != EOF ) {
|
||||
switch(c) {
|
||||
case CHARSET_FILE_ALIAS:
|
||||
pa = charset_alias_new();
|
||||
n = fread((void *)pa, sizeof(CharsetAlias), 1, fp);
|
||||
pa->next = NULL; /* overwritten by fread() */
|
||||
if(n != 1)
|
||||
return FALSE;
|
||||
Syslog('s', "read charset alias: %s -> %s", pa->alias, pa->name);
|
||||
break;
|
||||
case CHARSET_FILE_TABLE:
|
||||
pt = charset_table_new();
|
||||
n = fread((void *)pt, sizeof(CharsetTable), 1, fp);
|
||||
pt->next = NULL; /* overwritten by fread() */
|
||||
if(n != 1)
|
||||
return FALSE;
|
||||
Syslog('s', "read charset table: %s -> %s", pt->in, pt->out);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ferror(fp))
|
||||
return FALSE;
|
||||
fclose(fp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Convert to MIME quoted-printable =XX if qp==TRUE
|
||||
*/
|
||||
char *charset_qpen(int c, int qp)
|
||||
{
|
||||
static char buf[4];
|
||||
|
||||
c &= 0xff;
|
||||
|
||||
if( qp && (c == '=' || c >= 0x80) )
|
||||
str_printf(buf, sizeof(buf), "=%02.2X", c & 0xff);
|
||||
else
|
||||
{
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Map single character
|
||||
*/
|
||||
char *charset_map_c(int c, int qp)
|
||||
{
|
||||
static char buf[MAX_CHARSET_OUT * 4];
|
||||
char *s;
|
||||
|
||||
c &= 0xff;
|
||||
buf[0] = 0;
|
||||
|
||||
if(charset_table_used && c>=0x80)
|
||||
{
|
||||
s = charset_table_used->map[c - 0x80];
|
||||
while(*s)
|
||||
BUF_APPEND(buf, charset_qpen(*s++, qp));
|
||||
}
|
||||
else
|
||||
{
|
||||
BUF_COPY(buf, charset_qpen(c, qp));
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Search alias
|
||||
*/
|
||||
char *charset_alias_fsc(char *name)
|
||||
{
|
||||
CharsetAlias *pa;
|
||||
|
||||
/* Search for aliases */
|
||||
for(pa = charset_alias_list; pa; pa=pa->next)
|
||||
{
|
||||
if(strieq(pa->name, name))
|
||||
return pa->alias;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *charset_alias_rfc(char *name)
|
||||
{
|
||||
CharsetAlias *pa;
|
||||
|
||||
/* Search for aliases */
|
||||
for(pa = charset_alias_list; pa; pa=pa->next)
|
||||
{
|
||||
if(strieq(pa->alias, name))
|
||||
return pa->name;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Set character mapping table
|
||||
*/
|
||||
int charset_set_in_out(char *in, char *out)
|
||||
{
|
||||
CharsetTable *pt;
|
||||
CharsetAlias *pa;
|
||||
int i;
|
||||
|
||||
if (!in || !out)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* Check if charset.bin is loaded.
|
||||
*/
|
||||
if ((charset_alias_list == NULL) || (charset_table_list == NULL))
|
||||
charset_read_bin();
|
||||
Syslog('s', "charset1: in=%s out=%s", in, out);
|
||||
|
||||
|
||||
/*
|
||||
* For charset names with a space (level number), shorten the name.
|
||||
*/
|
||||
for (i = 0; i < strlen(in); i++)
|
||||
if (in[i] == ' ') {
|
||||
in[i] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < strlen(out); i++)
|
||||
if (out[i] == ' ') {
|
||||
out[i] = '\0';
|
||||
break;
|
||||
}
|
||||
Syslog('s', "charset2: in=%s out=%s", in, out);
|
||||
|
||||
/* Search for aliases */
|
||||
for (pa = charset_alias_list; pa; pa=pa->next) {
|
||||
if (strieq(pa->alias, in))
|
||||
in = pa->name;
|
||||
if (strieq(pa->alias, out))
|
||||
out = pa->name;
|
||||
}
|
||||
Syslog('s', "charset3: in=%s out=%s", in, out);
|
||||
|
||||
/* Search for matching table */
|
||||
for (pt = charset_table_list; pt; pt=pt->next) {
|
||||
if(strieq(pt->in, in) && strieq(pt->out, out)) {
|
||||
Syslog('s', "charset: table found in=%s out=%s", pt->in, pt->out);
|
||||
charset_table_used = pt;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Syslog('b', "charset: no table found in=%s out=%s", in, out);
|
||||
charset_table_used = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
1321
lib/charset.map
Normal file
1321
lib/charset.map
Normal file
File diff suppressed because it is too large
Load Diff
388
lib/mbcharsetc.c
Normal file
388
lib/mbcharsetc.c
Normal file
@ -0,0 +1,388 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
* Purpose ...............: Characterset Compiler
|
||||
* Author ................: Martin Junius, for Fidogate
|
||||
*
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1997-2004
|
||||
*
|
||||
* Michiel Broek FIDO: 2:280/2802
|
||||
* Beekmansbos 10
|
||||
* 1971 BV IJmuiden
|
||||
* the Netherlands
|
||||
*
|
||||
* This file is part of MBSE BBS.
|
||||
*
|
||||
* This BBS 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, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* MBSE BBS 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
|
||||
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* FIDOGATE --- Gateway UNIX Mail/News <-> FTN NetMail/EchoMail
|
||||
*
|
||||
* Charset mapping table compiler
|
||||
*
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1990-2002
|
||||
* _____ _____
|
||||
* | |___ | Martin Junius <mj@fidogate.org>
|
||||
* | | | | | | Radiumstr. 18
|
||||
* |_|_|_|@home| D-51069 Koeln, Germany
|
||||
*
|
||||
* This file is part of FIDOGATE.
|
||||
*
|
||||
* FIDOGATE 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, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* FIDOGATE 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
|
||||
* along with FIDOGATE; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../config.h"
|
||||
#include "mbselib.h"
|
||||
#include "mbcharsetc.h"
|
||||
|
||||
|
||||
char *str_copy(char *, size_t, char *);
|
||||
|
||||
#define strieq(a,b) (strcasecmp ((a),(b)) == 0)
|
||||
#define PROGRAM "mbcharsetc"
|
||||
#define BUFFERSIZE (32*1024) /* Global buffer */
|
||||
#define BUF_COPY(d,s) str_copy (d,sizeof(d),s)
|
||||
|
||||
char buffer[BUFFERSIZE];
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int charset_parse_c (char *);
|
||||
int charset_do_file (char *);
|
||||
int compile_map (char *, char *);
|
||||
void usage (void);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Check for hex digits, signed char-safe version of isxdigit()
|
||||
*/
|
||||
int is_xdigit(int c)
|
||||
{
|
||||
/*
|
||||
* Some <ctype.h> implementation only accept a parameter value range
|
||||
* of [-1,255]. This may lead to problems, because we're quite often
|
||||
* passing *p's to is_digit() with a char *p variable. The default
|
||||
* char type is signed in most C implementation.
|
||||
*/
|
||||
return isxdigit((c & 0xff));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for octal digits
|
||||
*/
|
||||
int is_odigit(int c)
|
||||
{
|
||||
return c>='0' && c<'8';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* isspace() replacement, checking for SPACE, TAB, CR, LF
|
||||
*/
|
||||
int is_space(int c)
|
||||
{
|
||||
return c==' ' || c=='\t' || c=='\r' || c=='\n';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read line from config file. Strip `\n', leading spaces,
|
||||
* comments (starting with `#'), and empty lines. cf_getline() returns
|
||||
* a pointer to the first non-whitespace in buffer.
|
||||
*/
|
||||
static long cf_lineno = 0;
|
||||
|
||||
long cf_lineno_get(void)
|
||||
{
|
||||
return cf_lineno;
|
||||
}
|
||||
|
||||
|
||||
long cf_lineno_set(long n)
|
||||
{
|
||||
long old;
|
||||
|
||||
old = cf_lineno;
|
||||
cf_lineno = n;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
char *cf_getline(char *cbuffer, int len, FILE *fp)
|
||||
{
|
||||
char *p;
|
||||
|
||||
while (fgets(cbuffer, len, fp)) {
|
||||
cf_lineno++;
|
||||
Striplf(cbuffer);
|
||||
for(p = cbuffer; *p && is_space(*p); p++) ; /* Skip white spaces */
|
||||
if (*p != '#')
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Parse character
|
||||
*/
|
||||
int charset_parse_c(char *s)
|
||||
{
|
||||
int val, n;
|
||||
|
||||
if(s[0] == '\\') { /* Special: \NNN or \xNN */
|
||||
s++;
|
||||
val = 0;
|
||||
n = 0;
|
||||
if(s[0]=='x' || s[0]=='X') { /* Hex */
|
||||
s++;
|
||||
while (is_xdigit(s[0]) && n<2) {
|
||||
s[0] = toupper(s[0]);
|
||||
val = val * 16 + s[0] - (s[0]>'9' ? 'A'-10 : '0');
|
||||
s++;
|
||||
n++;
|
||||
}
|
||||
if(*s)
|
||||
return ERROR;
|
||||
} else { /* Octal */
|
||||
while(is_odigit(s[0]) && n<3) {
|
||||
val = val * 8 + s[0] - '0';
|
||||
s++;
|
||||
n++;
|
||||
}
|
||||
if(*s)
|
||||
return ERROR;
|
||||
}
|
||||
} else {
|
||||
if(s[1] == 0) /* Single char */
|
||||
val = s[0] & 0xff;
|
||||
else
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return val & 0xff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Process one line from charset.map file
|
||||
*/
|
||||
int charset_do_line(char *line)
|
||||
{
|
||||
static CharsetTable *pt = NULL;
|
||||
char *key, *w1, *w2;
|
||||
CharsetAlias *pa;
|
||||
int i, c1, c2;
|
||||
|
||||
key = strtok(line, " \t");
|
||||
if(!key)
|
||||
return TRUE;
|
||||
|
||||
if (strieq(key, "include")) {
|
||||
w1 = strtok(NULL, " \t");
|
||||
if (charset_do_file(w1) == FALSE)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Define alias */
|
||||
else if (strieq(key, "alias")) {
|
||||
w1 = strtok(NULL, " \t");
|
||||
w2 = strtok(NULL, " \t");
|
||||
if(!w1 || !w2) {
|
||||
fprintf(stderr, "%s:%ld: argument(s) for alias missing\n", PROGRAM, cf_lineno_get());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pa = charset_alias_new();
|
||||
BUF_COPY(pa->alias, w1);
|
||||
BUF_COPY(pa->name, w2);
|
||||
}
|
||||
|
||||
/* Define table */
|
||||
else if (strieq(key, "table")) {
|
||||
w1 = strtok(NULL, " \t");
|
||||
w2 = strtok(NULL, " \t");
|
||||
if(!w1 || !w2) {
|
||||
fprintf(stderr, "%s:%ld: argument(s) for table missing\n", PROGRAM, cf_lineno_get());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pt = charset_table_new();
|
||||
BUF_COPY(pt->in, w1);
|
||||
BUF_COPY(pt->out, w2);
|
||||
}
|
||||
|
||||
/* Define mapping for character(s) in table */
|
||||
else if (strieq(key, "map")) {
|
||||
w1 = strtok(NULL, " \t");
|
||||
if (!w1) {
|
||||
fprintf(stderr, "%s:%ld: argument for map missing\n", PROGRAM, cf_lineno_get());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 1:1 mapping */
|
||||
if (strieq(w1, "1:1")) {
|
||||
for(i=0; i<MAX_CHARSET_IN; i++) {
|
||||
if(pt->map[i][0] == 0) {
|
||||
pt->map[i][0] = 0x80 + i;
|
||||
pt->map[i][1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 1:1 mapping, but not for 0x80...0x9f */
|
||||
if(strieq(w1, "1:1-noctrl")) {
|
||||
for(i=0x20; i<MAX_CHARSET_IN; i++) {
|
||||
if(pt->map[i][0] == 0) {
|
||||
pt->map[i][0] = 0x80 + i;
|
||||
pt->map[i][1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Mapping for undefined characters */
|
||||
else if(strieq(w1, "default")) {
|
||||
/**FIXME: not yet implemented**/
|
||||
}
|
||||
/* Normal mapping */
|
||||
else {
|
||||
if ((c1 = charset_parse_c(w1)) == ERROR) {
|
||||
fprintf(stderr, "%s:%ld: illegal char %s\n", PROGRAM, cf_lineno_get(), w1);
|
||||
return FALSE;
|
||||
}
|
||||
if (c1 < 0x80) {
|
||||
fprintf(stderr, "%s:%ld: illegal char %s, must be >= 0x80\n", PROGRAM, cf_lineno_get(), w1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i=0; i<MAX_CHARSET_OUT-1 && (w2 = strtok(NULL, " \t")); i++ ) {
|
||||
if( (c2 = charset_parse_c(w2)) == ERROR) {
|
||||
fprintf(stderr, "%s:%ld: illegal char definition %s\n", PROGRAM, cf_lineno_get(), w2);
|
||||
return FALSE;
|
||||
}
|
||||
pt->map[c1 & 0x7f][i] = c2;
|
||||
}
|
||||
for (; i<MAX_CHARSET_OUT; i++)
|
||||
pt->map[c1 & 0x7f][i] = 0;
|
||||
}
|
||||
}
|
||||
/* Error */
|
||||
else {
|
||||
fprintf(stderr, "%s:%ld: illegal key word %s\n", PROGRAM, cf_lineno_get(), key);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Process charset.map file
|
||||
*/
|
||||
int charset_do_file(char *name)
|
||||
{
|
||||
FILE *fp;
|
||||
char *p;
|
||||
long oldn;
|
||||
|
||||
if(!name)
|
||||
return FALSE;
|
||||
|
||||
oldn = cf_lineno_set(0);
|
||||
fp = fopen(name, "r");
|
||||
if(!fp)
|
||||
return FALSE;
|
||||
|
||||
while ((p = cf_getline(buffer, BUFFERSIZE, fp)))
|
||||
charset_do_line(p);
|
||||
|
||||
fclose(fp);
|
||||
cf_lineno_set(oldn);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Compile charset.map
|
||||
*/
|
||||
int compile_map(char *in, char *out)
|
||||
{
|
||||
/* Read charset.map and compile */
|
||||
if(charset_do_file(in) == FALSE) {
|
||||
fprintf(stderr, "%s: compiling map file %s failed", PROGRAM, in);
|
||||
return MBERR_GENERAL;
|
||||
}
|
||||
|
||||
/* Write binary output file */
|
||||
if (charset_write_bin(out) == ERROR) {
|
||||
fprintf(stderr, "%s: writing binary map file %s failed", PROGRAM, out);
|
||||
return MBERR_GENERAL;
|
||||
}
|
||||
|
||||
return MBERR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "\n%s: MBSE BBS %s Character Map Compiler\n", PROGRAM, VERSION);
|
||||
fprintf(stderr, " %s\n\n", COPYRIGHT);
|
||||
fprintf(stderr, "usage: %s charset.map charset.bin\n\n", PROGRAM);
|
||||
exit(MBERR_OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = MBERR_OK;
|
||||
char *name_in, *name_out;
|
||||
|
||||
if (argc != 3)
|
||||
usage();
|
||||
|
||||
name_in = argv[1];
|
||||
name_out = argv[2];
|
||||
ret = compile_map(name_in, name_out);
|
||||
|
||||
exit(ret);
|
||||
}
|
||||
|
7
lib/mbcharsetc.h
Normal file
7
lib/mbcharsetc.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _MBCHARSET_H
|
||||
#define _MBCHARSET_H
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
#endif
|
@ -92,9 +92,6 @@
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <sys/poll.h>
|
||||
#ifdef HAVE_ICONV_H
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <fcntl.h>
|
||||
@ -376,39 +373,6 @@ struct icmp_filter {
|
||||
#define FTNC_MAXCHARS 8 /* Highest charset number */
|
||||
|
||||
|
||||
/*
|
||||
* Mapping:
|
||||
*
|
||||
* Kludge iconv name
|
||||
* ---------- ---------------
|
||||
* ASCII 1 ISO646-US
|
||||
* DUTCH 1
|
||||
* FINNISH 1 ISO646-FI
|
||||
* FRENCH 1 ISO646-FR
|
||||
* CANADIAN 1 ISO646-CA
|
||||
* GERMAN 1
|
||||
* ITALIAN 1 ISO646-IT
|
||||
* NORWEIG 1 ISO646-NO
|
||||
* PORTU 1 ISO646-PT
|
||||
* SPANISH 1 ISO646-ES
|
||||
* SWEDISH 1 ISO646-SE
|
||||
* SWISS 1
|
||||
* UK 1 ISO646-GB
|
||||
* CP437 2 CP437
|
||||
* CP850 2 CP850
|
||||
* CP865 2 CP865
|
||||
* CP866 2 CP766
|
||||
* LATIN-1 2 ISO8859-1
|
||||
* LATIN-2 2 ISO8859-2
|
||||
* LATIN-5 2 ISO8859-5
|
||||
* MAC 2 MAC
|
||||
* PC-8 ISO646-US
|
||||
* IBMPC 2 CP437
|
||||
* UKR 2 CP866
|
||||
* +7_FIDO CP866
|
||||
*
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Global typedefs.
|
||||
@ -2129,15 +2093,6 @@ int attach(faddr, char *, int, char);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* From charset.c
|
||||
*/
|
||||
char *getchrs(int); /* Return characterset name */
|
||||
char *getchrsdesc(int); /* Return characterset description */
|
||||
char *get_iconv_name(char *); /* Return usable name for iconv */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* From dostran.c
|
||||
*/
|
||||
@ -2461,6 +2416,48 @@ int gpt_running(int); /* Is timer running */
|
||||
int msleep(int); /* Milliseconds timer */
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* Charset mapping
|
||||
*/
|
||||
|
||||
#define MAX_CHARSET_NAME 16
|
||||
#define MAX_CHARSET_IN 128
|
||||
#define MAX_CHARSET_OUT 4
|
||||
|
||||
#define CHARSET_FILE_ALIAS 'A' /* Id for binary file */
|
||||
#define CHARSET_FILE_TABLE 'T' /* Id for binary file */
|
||||
|
||||
|
||||
typedef struct st_charset_alias {
|
||||
char alias[MAX_CHARSET_NAME]; /* Alias charset name */
|
||||
char name[MAX_CHARSET_NAME]; /* Real charset name */
|
||||
struct st_charset_alias *next;
|
||||
} CharsetAlias;
|
||||
|
||||
typedef struct st_charset_table {
|
||||
char in[MAX_CHARSET_NAME]; /* Input charset name */
|
||||
char out[MAX_CHARSET_NAME]; /* Output charset name */
|
||||
char map[MAX_CHARSET_IN][MAX_CHARSET_OUT];
|
||||
struct st_charset_table *next;
|
||||
} CharsetTable;
|
||||
|
||||
|
||||
char *getchrs(int); /* Return characterset name */
|
||||
char *getchrsdesc(int); /* Return characterset description */
|
||||
CharsetTable *charset_table_new(void); /* Add table to linked list */
|
||||
CharsetAlias *charset_alias_new(void); /* Add alias to linked list */
|
||||
int charset_write_bin(char *); /* Save charset.bin */
|
||||
int charset_read_bin(void); /* Load ~/etc/charset.bin */
|
||||
char *charset_qpen(int, int); /* Convert to MIME quoted-printable */
|
||||
char *charset_map_c(int, int); /* map single character */
|
||||
char *charset_alias_fsc(char *); /* Search FSC alias */
|
||||
char *charset_alias_rfc(char *); /* Search RFC alias */
|
||||
int charset_set_in_out(char *, char *); /* Setup mapping */
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
*
|
||||
* Records data
|
||||
|
1111
lib/russian.map
Normal file
1111
lib/russian.map
Normal file
File diff suppressed because it is too large
Load Diff
@ -1137,14 +1137,8 @@ int Export_a_Msg(unsigned long Num)
|
||||
int Read_a_Msg(unsigned long Num, int UpdateLR)
|
||||
{
|
||||
char *p = NULL, *fn, *charset = NULL, *charsin = NULL, *charsout = NULL;
|
||||
int ShowMsg = TRUE, UseIconv = FALSE;
|
||||
int i, ShowMsg = TRUE, UseIconv = FALSE;
|
||||
lastread LR;
|
||||
iconv_t iconvstr = (iconv_t)(0);
|
||||
#ifdef HAVE_ICONV_H
|
||||
size_t cnt, inleft, outleft;
|
||||
char inbuf[256], outbuf[1024];
|
||||
char *inb, *outb;
|
||||
#endif
|
||||
|
||||
LastNum = Num;
|
||||
iLineCount = 7;
|
||||
@ -1234,25 +1228,16 @@ int Read_a_Msg(unsigned long Num, int UpdateLR)
|
||||
*/
|
||||
charset = xstrcpy(getchrs(msgs.Charset));
|
||||
}
|
||||
charsin = xstrcpy(get_iconv_name(charset));
|
||||
charsout = xstrcpy(get_iconv_name(getchrs(exitinfo.Charset)));
|
||||
charsin = xstrcpy(charset);
|
||||
charsout = xstrcpy(getchrs(exitinfo.Charset));
|
||||
Syslog('b', "Stage 3: charset %s, translate %s to %s", MBSE_SS(charset), MBSE_SS(charsin), MBSE_SS(charsout));
|
||||
|
||||
#ifdef HAVE_ICONV_H
|
||||
/*
|
||||
* Try to setup iconv if the charactersets are different.
|
||||
* Try to setup charset mapping if the charactersets are different.
|
||||
*/
|
||||
if (charsin && charsout && strcmp(charsout, charsin)) {
|
||||
|
||||
charsout = xstrcat(charsout, (char *)"//TRANSLIT");
|
||||
iconvstr = iconv_open(charsout, charsin);
|
||||
if (iconvstr == (iconv_t)(-1)) {
|
||||
Syslog('!', "$open_iconv(%s, %s)", charsin, charsout);
|
||||
} else {
|
||||
UseIconv = TRUE;
|
||||
}
|
||||
UseIconv = charset_set_in_out(charsin, charsout);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Show message text
|
||||
@ -1273,42 +1258,18 @@ int Read_a_Msg(unsigned long Num, int UpdateLR)
|
||||
if (strchr(p, '>') != NULL)
|
||||
if ((strlen(p) - strlen(strchr(p, '>'))) < 10)
|
||||
colour(CFG.HiliteF, CFG.HiliteB);
|
||||
#ifdef HAVE_ICONV_H
|
||||
if (UseIconv) {
|
||||
/*
|
||||
* Try to translate character sets with iconv
|
||||
* Try to translate character sets
|
||||
*/
|
||||
inleft = outleft = strlen(p);
|
||||
memset(&inbuf, 0, sizeof(inbuf));
|
||||
memset(&outbuf, 0, sizeof(inbuf));
|
||||
sprintf(inbuf, "%s", p);
|
||||
inb = inbuf;
|
||||
outb = outbuf;
|
||||
cnt = iconv(iconvstr, &inb, &inleft, &outb, &outleft);
|
||||
if (cnt == (size_t)(-1)) {
|
||||
/*
|
||||
* Failed, log and show original line.
|
||||
*/
|
||||
Syslog('b', "iconv cnt=%d inleft=%d outleft=%d", cnt, inleft, outleft);
|
||||
Syslog('b', "%s", printable(p, 0));
|
||||
Syslog('b', "$iconv");
|
||||
printf("%s\n", p);
|
||||
} else {
|
||||
if (strcmp(inbuf, outbuf)) {
|
||||
/*
|
||||
* Success, translated and log
|
||||
*/
|
||||
Syslog('b', "< %s", MBSE_SS(inbuf));
|
||||
Syslog('b', "> %s", MBSE_SS(outbuf));
|
||||
}
|
||||
printf("%s\n", outbuf);
|
||||
for (i = 0; i < strlen(p); i++) {
|
||||
printf("%s", charset_map_c(p[i], FALSE));
|
||||
}
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("%s\n", p);
|
||||
}
|
||||
#else
|
||||
printf("%s\n", p);
|
||||
#endif
|
||||
|
||||
if (CheckLine(CFG.TextColourF, CFG.TextColourB, FALSE))
|
||||
break;
|
||||
}
|
||||
@ -1323,12 +1284,6 @@ int Read_a_Msg(unsigned long Num, int UpdateLR)
|
||||
if (charsin)
|
||||
free(charsin);
|
||||
|
||||
#ifdef HAVE_ICONV_H
|
||||
if (UseIconv && (iconv_close(iconvstr) == -1)) {
|
||||
Syslog('!', "$iconv_close()");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the Received status on this message if it's for the user.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user