From b5ff7e3beb35b2aeebf523c4ceb66fbf14e0be7e Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Mon, 13 Jun 2005 18:16:44 +0000 Subject: [PATCH] (copy_ascii_no_funny, copy_utf8_no_funny) (copy_utf8_to_ascii_no_funny): New. (flash, wall, prmptrd, uprmptrd, getcommand): Use them to filter input. (uprnf, pr_flash): Use them to filter output. (prtoascii): No longer used, remove. (player_commands, player_commands_index): Internal linkage. --- include/player.h | 2 +- include/prototypes.h | 6 +- src/lib/commands/flash.c | 34 +++++------ src/lib/player/empdis.c | 29 ++++++--- src/lib/subs/pr.c | 124 ++++++++++++++++++++++++++++----------- 5 files changed, 129 insertions(+), 66 deletions(-) diff --git a/include/player.h b/include/player.h index 21c06d491..dbf0904f2 100644 --- a/include/player.h +++ b/include/player.h @@ -57,7 +57,7 @@ struct player { int flags; struct cmndstr *command; struct iop *iop; - s_char combuf[1024]; + char combuf[1024]; /* command input buffer, UTF-8 */ s_char *argp[128]; s_char *condarg; time_t lasttime; diff --git a/include/prototypes.h b/include/prototypes.h index 837c6e3e4..91699e4b5 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -418,7 +418,7 @@ extern void player_accept(void *); /* dispatch.c */ extern int dispatch(char *, char *); /* empdis.c */ -extern int getcommand(s_char *); +extern int getcommand(char *); extern void init_player_commands(void); extern void log_last_commands(void); extern int gamedown(void); @@ -618,7 +618,9 @@ extern void PR(int, s_char *, ...) ATTRIBUTE((format (printf, 2, 3))); extern void PRdate(natid cn); extern void pr_beep(void); extern void mpr(int, s_char *, ...) ATTRIBUTE((format (printf, 2, 3))); -extern void prtoascii(char *buf /* buf is message text */); +extern size_t copy_ascii_no_funny(char *, char *); +extern size_t copy_utf8_no_funny(char *, char *); +extern size_t copy_utf8_to_ascii_no_funny(char *, char *); extern int ufindpfx(char *, int); /* radmap.c */ diff --git a/src/lib/commands/flash.c b/src/lib/commands/flash.c index 98c7e9f79..f7f37eb43 100644 --- a/src/lib/commands/flash.c +++ b/src/lib/commands/flash.c @@ -44,9 +44,9 @@ flash(void) { struct natstr *us; struct natstr *to; - char buf[1024]; /* buf is message text */ + char buf[1024]; /* UTF-8 */ int tocn; - char *sp; /* sp is message text */ + char *sp; /* points into player->combuf[], UTF-8 */ us = getnatp(player->cnum); if ((tocn = natarg(player->argp[1], "to which country? ")) < 0) @@ -76,14 +76,11 @@ flash(void) if (player->argp[2]) { for (sp = &player->combuf[0]; *sp && *sp != ' '; ++sp) ; for (++sp; *sp && *sp != ' '; ++sp) ; - sprintf(buf, ":%s", sp); - for(sp = buf; 0 != *sp; ++sp) { - if ((*sp >= 0x0 && *sp < 0x20 && *sp != '\t') || - *sp == 0x7f) - *sp = '?'; - else if (!(player->flags & PF_UTF8) && (*sp & 0x80)) - *sp = '?'; - } + buf[0] = ':'; + if (player->flags & PF_UTF8) + strcpy(buf+1, sp); + else + copy_utf8_to_ascii_no_funny(buf+1, sp); sendmessage(us, to, buf, 1); } else { sendmessage(us, to, "...", 1); @@ -101,20 +98,17 @@ int wall(void) { struct natstr *us; - char buf[1024]; /* buf is message text */ - char *sp; /* sp is message text */ + char buf[1024]; /* UTF-8 */ + char *sp; /* points into player->combuf[], UTF-8 */ us = getnatp(player->cnum); if (player->argp[1]) { for (sp = &player->combuf[0]; *sp && *sp != ' '; ++sp) ; - sprintf(buf, ":%s", sp); - for(sp = buf; 0 != *sp; ++sp) { - if ((*sp >= 0x0 && *sp < 0x20 && *sp != '\t') || - *sp == 0x7f) - *sp = '?'; - else if (!(player->flags & PF_UTF8) && (*sp & 0x80)) - *sp = '?'; - } + buf[0] = ':'; + if (player->flags & PF_UTF8) + strcpy(buf+1, sp); + else + copy_utf8_to_ascii_no_funny(buf+1, sp); sendmessage(us, 0, buf, 1); } else { sendmessage(us, 0, "...", 1); diff --git a/src/lib/player/empdis.c b/src/lib/player/empdis.c index 3d0f52153..9ad05d6d4 100644 --- a/src/lib/player/empdis.c +++ b/src/lib/player/empdis.c @@ -54,21 +54,29 @@ #include #define KEEP_COMMANDS 50 -s_char player_commands[KEEP_COMMANDS][1024 + 8]; -int player_commands_index = 0; +/* ring buffer of most recent command prompts and commands, user text */ +static char player_commands[KEEP_COMMANDS][1024 + 8]; + +/* the slot holding the most recent command in player_commands[] */ +static int player_commands_index = 0; + +/* + * Get a command from the current player into COMBUFP[1024], in UTF-8. + * Return command's byte length on success, -1 on error. + */ int -getcommand(s_char *combufp) +getcommand(char *combufp) { - struct natstr *natp; - s_char buf[1024]; + struct natstr *natp = getnatp(player->cnum); + char buf[1024]; /* user text */ + int i; -/* Note this now assumes a 1024 byte buffer is being passed in */ - natp = getnatp(player->cnum); if (++player_commands_index >= KEEP_COMMANDS) player_commands_index = 0; sprintf(player_commands[player_commands_index], "%3d %3d [prompt]", player_commands_index, player->cnum); + do { prprompt(natp->nat_minused, natp->nat_btu); buf[0] = 0; @@ -76,12 +84,15 @@ getcommand(s_char *combufp) return -1; } } while (buf[0] == 0); + if (++player_commands_index >= KEEP_COMMANDS) player_commands_index = 0; sprintf(player_commands[player_commands_index], "%3d %3d %s", player_commands_index, player->cnum, buf); - strcpy(combufp, buf); - return (strlen(combufp)); + + if (player->flags & PF_UTF8) + return copy_utf8_no_funny(combufp, buf); + return copy_ascii_no_funny(combufp, buf); } void diff --git a/src/lib/subs/pr.c b/src/lib/subs/pr.c index 45a29d545..86fd78755 100644 --- a/src/lib/subs/pr.c +++ b/src/lib/subs/pr.c @@ -76,11 +76,8 @@ pr(char *format, ...) void uprnf(char *buf /* buf is message text */) { - /* - * Translate to ASCII if the client is not in UTF mode - */ if (!(player->flags & PF_UTF8)) - prtoascii(buf); + copy_utf8_to_ascii_no_funny(buf, buf); pr_player(player, C_DATA, buf); } @@ -114,11 +111,8 @@ pr_flash(struct player *pl, char *format va_start(ap, format); (void)vsprintf(buf, format, ap); va_end(ap); - /* - * Translate to ASCII if the client is not in UTF mode - */ if (!(pl->flags & PF_UTF8)) - prtoascii(buf); + copy_utf8_to_ascii_no_funny(buf, buf); pr_player(pl, C_FLASH, buf); io_output(pl->iop, IO_NOWAIT); } @@ -309,12 +303,9 @@ prmptrd(char *prompt, char *str, int size) time(&player->curup); if (*str == 0) return 1; - for(cp = str; 0 != *cp; ++cp) { - if ((*cp >= 0x0 && *cp < 0x20 && *cp != '\t') || - *cp == 0x7f || *cp & 0x80) - *cp = '?'; - } - return strlen(str); + if (player->flags & PF_UTF8) + return copy_utf8_to_ascii_no_funny(str, str); + return copy_ascii_no_funny(str, str); } int @@ -329,15 +320,9 @@ uprmptrd(char *prompt, char *str /* str is message text */, int size) time(&player->curup); if (*str == 0) return 1; - - for(cp = str; 0 != *cp; ++cp) { - if ((*cp >= 0x0 && *cp < 0x20 && *cp != '\t') || - *cp == 0x7f) - *cp = '?'; - else if (!(player->flags & PF_UTF8) && (*cp & 0x80)) - *cp = '?'; - } - return strlen(str); + if (player->flags & PF_UTF8) + return copy_utf8_no_funny(str, str); + return copy_ascii_no_funny(str, str); } void @@ -422,18 +407,89 @@ mpr(int cn, s_char *format, ...) } } -void -prtoascii(char *buf /* buf is message text */) +/* + * Copy SRC without funny characters to DST. + * Drop control characters, except for '\t'. + * Replace non-ASCII characters by '?'. + * Return length of DST. + * DST must have space. If it overlaps SRC, then DST <= SRC must + * hold. + */ +size_t +copy_ascii_no_funny(char *dst, char *src) { - char *pbuf; /* pbuf is message text */ - - for(pbuf = buf; *pbuf != 0; pbuf++) - if ((*pbuf & 0xc0) == 0xc0) - *pbuf = '?'; - else if (*pbuf & 0x80) { - memmove(pbuf,pbuf+1,strlen(pbuf)-1); - pbuf--; - } + char *p; + unsigned char ch; + + p = dst; + while ((ch = *src++)) { + if ((ch < 0x20 && ch != '\t') || ch == 0x7f) + ; /* ignore control */ + else if (ch > 0x7f) + *p++ = '?'; /* replace non-ASCII */ + else + *p++ = ch; + } + *p = 0; + + return p - dst; +} + +/* + * Copy UTF-8 SRC without funny characters to DST. + * Drop control characters, except for '\t'. + * FIXME Replace malformed UTF-8 sequences by '?'. + * Return byte length of DST. + * DST must have space. If it overlaps SRC, then DST <= SRC must + * hold. + */ +size_t +copy_utf8_no_funny(char *dst, char *src) +{ + char *p; + unsigned char ch; + + p = dst; + while ((ch = *src++)) { + /* FIXME do the right thing for malformed and overlong sequences */ + if ((ch < 0x20 && ch != '\t') || ch == 0x7f) + ; /* ignore control */ + else + *p++ = ch; + } + *p = 0; + + return p - dst; +} + +/* + * Copy UTF-8 SRC without funny characters to ASCII DST. + * Drop control characters, except for '\t'. + * Replace non-ASCII characters by '?'. + * Return length of DST. + * DST must have space. If it overlaps SRC, then DST <= SRC must + * hold. + */ +size_t +copy_utf8_to_ascii_no_funny(char *dst, char *src) +{ + char *p; + unsigned char ch; + + p = dst; + while ((ch = *src++)) { + /* FIXME do the right thing for malformed and overlong sequences */ + if ((ch < 0x20 && ch != '\t') || ch == 0x7f) + ; /* ignore control */ + else if (ch > 0x7f) { + *p++ = '?'; /* replace non-ASCII */ + while ((*src++ & 0xc0) == 0x80) ; + } else + *p++ = ch; + } + *p = 0; + + return p - dst; } /* -- 2.43.0