Experimental character set translation message reading

This commit is contained in:
Michiel Broek 2004-02-26 20:16:10 +00:00
parent ce30494be0
commit d296b1fb8a
6 changed files with 284 additions and 145 deletions

View File

@ -35,6 +35,13 @@ v0.51.1 21-Feb-2004
Added login check to see if user has a valid character set.
Added Control-U 9 to display file to show the users character
set in the menus screens.
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.
In delete file in home directory the Y/N keys were read from
the wrong language prompt.
mbmsg:
Writes the ^aCHRS: kludge again in new created messages.

View File

@ -66,3 +66,35 @@ char *getchrsdesc(int val)
}
char *get_iconv_name(char *name)
{
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";
Syslog('+', "get_iconv_name(%s): no usable character set name found", name);
return NULL;
}

View File

@ -2134,6 +2134,7 @@ int attach(faddr, char *, int, char);
*/
char *getchrs(int); /* Return characterset name */
char *getchrsdesc(int); /* Return characterset description */
char *get_iconv_name(char *); /* Return usable name for iconv */

View File

@ -1481,7 +1481,7 @@ void Delete_Home()
fflush(stdout);
i = toupper(Getone());
if (i == Keystroke(368, 0) || i == 13) {
if (i == Keystroke(369, 0) || i == 13) {
i = unlink(temp);
if (i == -1) {

View File

@ -1136,155 +1136,245 @@ int Export_a_Msg(unsigned long Num)
*/
int Read_a_Msg(unsigned long Num, int UpdateLR)
{
char *p = NULL, *fn;
int ShowMsg = TRUE;
lastread LR;
char *p = NULL, *fn, *charset = NULL, *charsin = NULL, *charsout = NULL;
int 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;
WhosDoingWhat(READ_POST, NULL);
LastNum = Num;
iLineCount = 7;
WhosDoingWhat(READ_POST, NULL);
/*
* The area data is already set, so we can do the next things
*/
if (MsgBase.Total == 0) {
colour(WHITE, BLACK);
/* There are no messages in this area */
printf("\n%s\n\n", (char *) Language(205));
sleep(3);
return FALSE;
}
/*
* The area data is already set, so we can do the next things
*/
if (MsgBase.Total == 0) {
colour(WHITE, BLACK);
/* There are no messages in this area */
printf("\n%s\n\n", (char *) Language(205));
sleep(3);
return FALSE;
}
if (!Msg_Open(sMsgAreaBase)) {
WriteError("Error open JAM base %s", sMsgAreaBase);
return FALSE;
}
if (!Msg_ReadHeader(Num)) {
perror("");
colour(WHITE, BLACK);
printf("\n%s\n\n", (char *)Language(77));
Msg_Close();
sleep(3);
return FALSE;
}
if (Msg.Private) {
ShowMsg = FALSE;
if ((strcasecmp(exitinfo.sUserName, Msg.From) == 0) || (strcasecmp(exitinfo.sUserName, Msg.To) == 0))
ShowMsg = TRUE;
if (exitinfo.Security.level >= msgs.SYSec.level)
ShowMsg = TRUE;
}
if (!ShowMsg) {
printf("\n%s\n\n", (char *) Language(82));
Msg_Close();
sleep(3);
return FALSE;
}
ShowMsgHdr();
/*
* Fill Quote file in case the user wants to reply. Note that line
* wrapping is set lower then normal message read, to create room
* for the Quote> strings at the start of each line.
*/
fn = calloc(128, sizeof(char));
sprintf(fn, "%s/%s/.quote", CFG.bbs_usersdir, exitinfo.Name);
if ((qf = fopen(fn, "w")) != NULL) {
if (Msg_Read(Num, 75)) {
if ((p = (char *)MsgText_First()) != NULL)
do {
if ((p[0] == '\001') || (!strncmp(p, "SEEN-BY:", 8)) || (!strncmp(p, "AREA:", 5))) {
if (Kludges) {
if (p[0] == '\001') {
p[0] = 'a';
fprintf(qf, "^%s\n", p);
} else
fprintf(qf, "%s\n", p);
}
} else
fprintf(qf, "%s\n", p);
} while ((p = (char *)MsgText_Next()) != NULL);
}
fclose(qf);
} else {
WriteError("$Can't open %s", p);
}
free(fn);
/*
* Show message text
*/
colour(CFG.TextColourF, CFG.TextColourB);
if (Msg_Read(Num, 78)) {
if ((p = (char *)MsgText_First()) != NULL) {
do {
if ((p[0] == '\001') || (!strncmp(p, "SEEN-BY:", 8)) || (!strncmp(p, "AREA:", 5))) {
if (Kludges) {
colour(7, 0);
printf("%s\n", p);
if (CheckLine(CFG.TextColourF, CFG.TextColourB, FALSE))
break;
}
} else {
colour(CFG.TextColourF, CFG.TextColourB);
if (strchr(p, '>') != NULL)
if ((strlen(p) - strlen(strchr(p, '>'))) < 10)
colour(CFG.HiliteF, CFG.HiliteB);
printf("%s\n", p);
if (CheckLine(CFG.TextColourF, CFG.TextColourB, FALSE))
break;
}
} while ((p = (char *)MsgText_Next()) != NULL);
}
}
/*
* Set the Received status on this message if it's for the user.
*/
if ((!Msg.Received) && (strlen(Msg.To) > 0) &&
((strcasecmp(Msg.To, exitinfo.sUserName) == 0) || (strcasecmp(exitinfo.sHandle, Msg.To) == 0))) {
Syslog('m', "Marking message received");
Msg.Received = TRUE;
Msg.Read = time(NULL) - (gmt_offset((time_t)0) * 60);
if (Msg_Lock(30L)) {
Msg_WriteHeader(Num);
Msg_UnLock();
}
}
/*
* Update lastread pointer if needed. Netmail boards are always updated.
*/
if (Msg_Lock(30L) && (UpdateLR || msgs.Type == NETMAIL)) {
LR.UserID = grecno;
p = xstrcpy(exitinfo.sUserName);
if (Msg_GetLastRead(&LR) == TRUE) {
LR.LastReadMsg = Num;
if (Num > LR.HighReadMsg)
LR.HighReadMsg = Num;
if (LR.HighReadMsg > MsgBase.Highest)
LR.HighReadMsg = MsgBase.Highest;
LR.UserCRC = StringCRC32(tl(p));
if (!Msg_SetLastRead(LR))
WriteError("Error update lastread");
} else {
/*
* Append new lastread pointer
*/
LR.UserCRC = StringCRC32(tl(p));
LR.UserID = grecno;
LR.LastReadMsg = Num;
LR.HighReadMsg = Num;
if (!Msg_NewLastRead(LR))
WriteError("Can't append lastread");
}
free(p);
Msg_UnLock();
}
if (!Msg_Open(sMsgAreaBase)) {
WriteError("Error open JAM base %s", sMsgAreaBase);
return FALSE;
}
if (!Msg_ReadHeader(Num)) {
perror("");
colour(WHITE, BLACK);
printf("\n%s\n\n", (char *)Language(77));
Msg_Close();
return TRUE;
sleep(3);
return FALSE;
}
if (Msg.Private) {
ShowMsg = FALSE;
if ((strcasecmp(exitinfo.sUserName, Msg.From) == 0) || (strcasecmp(exitinfo.sUserName, Msg.To) == 0))
ShowMsg = TRUE;
if (exitinfo.Security.level >= msgs.SYSec.level)
ShowMsg = TRUE;
}
if (!ShowMsg) {
printf("\n%s\n\n", (char *) Language(82));
Msg_Close();
sleep(3);
return FALSE;
}
ShowMsgHdr();
/*
* Fill Quote file in case the user wants to reply. Note that line
* wrapping is set lower then normal message read, to create room
* for the Quote> strings at the start of each line.
*/
fn = calloc(128, sizeof(char));
sprintf(fn, "%s/%s/.quote", CFG.bbs_usersdir, exitinfo.Name);
if ((qf = fopen(fn, "w")) != NULL) {
if (Msg_Read(Num, 75)) {
if ((p = (char *)MsgText_First()) != NULL)
do {
if ((p[0] == '\001') || (!strncmp(p, "SEEN-BY:", 8)) || (!strncmp(p, "AREA:", 5))) {
/*
* While we are here, check for the ^aCHRS: kludge and set the used charset.
*/
if (strncmp(p, "\001CHRS: ", 7) == 0) {
charset = xstrcpy(p + 7);
}
if (strncmp(p, "\001CHARSET: ", 10) == 0) {
charset = xstrcpy(p + 10);
}
if (Kludges) {
if (p[0] == '\001') {
p[0] = 'a';
fprintf(qf, "^%s\n", p);
} else
fprintf(qf, "%s\n", p);
}
} else
fprintf(qf, "%s\n", p);
} while ((p = (char *)MsgText_Next()) != NULL);
}
fclose(qf);
} else {
WriteError("$Can't open %s", p);
}
free(fn);
if ((charset == NULL) && (msgs.Charset != FTNC_NONE)) {
/*
* No charset marked in the message, use the area charset
*/
charset = xstrcpy(getchrs(msgs.Charset));
}
charsin = xstrcpy(get_iconv_name(charset));
charsout = xstrcpy(get_iconv_name(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.
*/
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;
}
}
#endif
/*
* Show message text
*/
colour(CFG.TextColourF, CFG.TextColourB);
if (Msg_Read(Num, 78)) {
if ((p = (char *)MsgText_First()) != NULL) {
do {
if ((p[0] == '\001') || (!strncmp(p, "SEEN-BY:", 8)) || (!strncmp(p, "AREA:", 5))) {
if (Kludges) {
colour(7, 0);
printf("%s\n", p);
if (CheckLine(CFG.TextColourF, CFG.TextColourB, FALSE))
break;
}
} else {
colour(CFG.TextColourF, CFG.TextColourB);
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
*/
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);
}
} else {
printf("%s\n", p);
}
#else
printf("%s\n", p);
#endif
if (CheckLine(CFG.TextColourF, CFG.TextColourB, FALSE))
break;
}
} while ((p = (char *)MsgText_Next()) != NULL);
}
}
if (charset)
free(charset);
if (charsout)
free(charsout);
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.
*/
if ((!Msg.Received) && (strlen(Msg.To) > 0) &&
((strcasecmp(Msg.To, exitinfo.sUserName) == 0) || (strcasecmp(exitinfo.sHandle, Msg.To) == 0))) {
Syslog('m', "Marking message received");
Msg.Received = TRUE;
Msg.Read = time(NULL) - (gmt_offset((time_t)0) * 60);
if (Msg_Lock(30L)) {
Msg_WriteHeader(Num);
Msg_UnLock();
}
}
/*
* Update lastread pointer if needed. Netmail boards are always updated.
*/
if (Msg_Lock(30L) && (UpdateLR || msgs.Type == NETMAIL)) {
LR.UserID = grecno;
p = xstrcpy(exitinfo.sUserName);
if (Msg_GetLastRead(&LR) == TRUE) {
LR.LastReadMsg = Num;
if (Num > LR.HighReadMsg)
LR.HighReadMsg = Num;
if (LR.HighReadMsg > MsgBase.Highest)
LR.HighReadMsg = MsgBase.Highest;
LR.UserCRC = StringCRC32(tl(p));
if (!Msg_SetLastRead(LR))
WriteError("Error update lastread");
} else {
/*
* Append new lastread pointer
*/
LR.UserCRC = StringCRC32(tl(p));
LR.UserID = grecno;
LR.LastReadMsg = Num;
LR.HighReadMsg = Num;
if (!Msg_NewLastRead(LR))
WriteError("Can't append lastread");
}
free(p);
Msg_UnLock();
}
Msg_Close();
return TRUE;
}

View File

@ -43,6 +43,9 @@
#include "timeout.h"
#include "funcs.h"
#include <locale.h>
#include <langinfo.h>
extern int do_quiet; /* Logging quiet flag */
time_t t_start;
@ -205,6 +208,12 @@ int main(int argc, char **argv)
}
}
/*
* Some debugging for me
*/
Syslog('b', "setlocale() returns \"%s\"", printable(setlocale(LC_ALL, NULL), 0));
Syslog('b', "nl_langinfo(LC_CTYPE) returns \"%s\"", printable(nl_langinfo(LC_CTYPE), 0));
sprintf(sMailbox, "mailbox");
colour(LIGHTGRAY, BLACK);
user();