diff --git a/ChangeLog b/ChangeLog index fd7b99a0..f3d02349 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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. diff --git a/lib/charset.c b/lib/charset.c index 1be922d9..36906fc6 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -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; +} + + + diff --git a/lib/mbselib.h b/lib/mbselib.h index 3be122ec..f70938a0 100644 --- a/lib/mbselib.h +++ b/lib/mbselib.h @@ -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 */ diff --git a/mbsebbs/file.c b/mbsebbs/file.c index 954c75cd..a3772aac 100644 --- a/mbsebbs/file.c +++ b/mbsebbs/file.c @@ -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) { diff --git a/mbsebbs/mail.c b/mbsebbs/mail.c index 1663a35a..554dfb0b 100644 --- a/mbsebbs/mail.c +++ b/mbsebbs/mail.c @@ -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; } diff --git a/mbsebbs/mbsebbs.c b/mbsebbs/mbsebbs.c index aa49df24..1b672ce2 100644 --- a/mbsebbs/mbsebbs.c +++ b/mbsebbs/mbsebbs.c @@ -43,6 +43,9 @@ #include "timeout.h" #include "funcs.h" +#include +#include + 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();