Skip to content

Commit

Permalink
Initial version, fallback is hard coded utf-8.
Browse files Browse the repository at this point in the history
  • Loading branch information
thommey committed Apr 21, 2016
1 parent 9a52a9d commit 21b0aad
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/mod/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@
/* 300 - 303 */
#define tcl_resultint ((int (*)(void))global[300])
#define tcl_resultstring ((const char *(*)(void))global[301])
#define tcl_setvarfromexternal ((void (*)(Tcl_Interp *, char *, char *))global[302])

/* hostmasking */
#define maskhost(a,b) maskaddr((a),(b),3)
Expand Down
6 changes: 5 additions & 1 deletion src/mod/server.mod/servmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,14 @@ static int check_tcl_notc(char *nick, char *uhost, struct userrec *u,
static int check_tcl_raw(char *from, char *code, char *msg)
{
int x;

#if 0
Tcl_SetVar(interp, "_raw1", from, 0);
Tcl_SetVar(interp, "_raw2", code, 0);
Tcl_SetVar(interp, "_raw3", msg, 0);
#endif
tcl_setvarfromexternal(interp, "_raw1", from);
tcl_setvarfromexternal(interp, "_raw2", code);
tcl_setvarfromexternal(interp, "_raw3", msg);
x = check_tcl_bind(H_raw, code, 0, " $_raw1 $_raw2 $_raw3",
MATCH_EXACT | BIND_STACKABLE | BIND_WANTRET);

Expand Down
3 changes: 2 additions & 1 deletion src/modules.c
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,8 @@ Function global_table[] = {
(Function) tcl_resultempty,
/* 300 - 304 */
(Function) tcl_resultint,
(Function) tcl_resultstring
(Function) tcl_resultstring,
(Function) tcl_setvarfromexternal
};

void init_modules(void)
Expand Down
64 changes: 59 additions & 5 deletions src/tcl.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include <stdlib.h> /* getenv() */
#include <locale.h> /* setlocale() */
#include <iconv.h>
#include "main.h"

/* Used for read/write to internal strings */
Expand Down Expand Up @@ -366,6 +365,62 @@ int tcl_resultint()
return result;
}

static size_t convert_encoding(iconv_t conversion, char *src, char *dst, size_t dstlen)
{
size_t i, srcbytesleft = strlen(src) + 1;

/* Reset conversion state */
iconv(conversion, NULL, NULL, NULL, NULL);

i = iconv(conversion, &src, &srcbytesleft, &dst, &dstlen);

return (i == -1 || srcbytesleft != 0) ? 0 : 1;
}

/* Set a Tcl variable from an external source, converting it into
* Tcl's internal Utf encoding.
* Static buffer, because this is ONLY ever used for IRC traffic.
*
* Tcl's internal UTF-8 encoding is a modified version of UTF-8
* which encodes the NUL byte as 0xC080.
* This function assumes there are no NUL bytes in bytes.
*
* Bufsize: 512 bytes (IRC including \r\n) + '\0' = 513 bytes.
* TCL_UTF_MAX is the maximum size of a single utf8 character.
*/

void tcl_setvarfromexternal(Tcl_Interp *irp, char *varname, char *bytes)
{
static char buf[513*TCL_UTF_MAX];
static iconv_t fromutf8, fromiso8859;
iconv_t fromsystemencoding;

if (!fromutf8)
fromutf8 = iconv_open("utf-8", "utf-8");
if (!fromiso8859)
fromiso8859 = iconv_open("utf-8", "iso8859-1");

fromsystemencoding = iconv_open("utf-8", "");

/* reset conversion state */
iconv(fromutf8, NULL, NULL, NULL, NULL);

if (convert_encoding(fromutf8, bytes, buf, sizeof buf))
goto ok;
if (convert_encoding(fromsystemencoding, bytes, buf, sizeof buf))
goto ok;
if (convert_encoding(fromiso8859, bytes, buf, sizeof buf))
goto ok;

/* should never happen, can be inefficient */
putlog(LOG_MISC, "*", "Failed to convert '%s' into UTF encoding.", bytes);
strncpyz(buf, bytes, sizeof buf);

ok:
Tcl_SetVar(irp, varname, buf, 0);
iconv_close(fromsystemencoding);
}

static tcl_strings def_tcl_strings[] = {
{"botnet-nick", botnetnick, HANDLEN, 0},
{"userfile", userfile, 120, STR_PROTECT},
Expand Down Expand Up @@ -600,9 +655,8 @@ void init_tcl(int argc, char **argv)
Tcl_NotifierProcs notifierprocs;
#endif /* REPLACE_NOTIFIER */

const char *encoding;
int i, j;
char *langEnv, pver[1024] = "";
int j;
char pver[1024] = "";

#ifdef REPLACE_NOTIFIER
egg_bzero(&notifierprocs, sizeof(notifierprocs));
Expand Down
1 change: 1 addition & 0 deletions src/tclegg.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ void add_tcl_coups(tcl_coups *);
void rem_tcl_coups(tcl_coups *);
void add_tcl_ints(tcl_ints *);
void rem_tcl_ints(tcl_ints *);
void tcl_setvarfromexternal(Tcl_Interp *, char *, char *);
const char *tcl_resultstring();
int tcl_resultint();
int tcl_resultempty();
Expand Down

0 comments on commit 21b0aad

Please sign in to comment.