void print_ansi(char *buf, size_t buflen, buffered_output_t *output) { unsigned int font_style = 0; unsigned int ansi_state; unsigned int ansi_val[STRLEN]; int ival = 0; size_t i; char *ptr = buf; char *ansi_begin; char *ansi_end; if (ptr == NULL) return; STATE_ZERO(ansi_state); bzero(ansi_val, sizeof(ansi_val)); for (i = 0; i < buflen; i++) { if (STATE_ISSET(ansi_state, STATE_NEW_LINE)) { STATE_CLR(ansi_state, STATE_NEW_LINE); if (i < (buflen - 1) && (buf[i] == ':' && buf[i+1] == ' ')) { STATE_SET(ansi_state, STATE_QUOTE_LINE); if (STATE_ISSET(ansi_state, STATE_FONT_SET)) output->output("</font>", 7, output); /* set quoted line styles */ STYLE_SET(font_style, FONT_STYLE_QUOTE); STYLE_SET_FG(font_style, FONT_COLOR_QUOTE); STYLE_CLR_BG(font_style); print_font_style(font_style, output); output->output(&buf[i], 1, output); STATE_SET(ansi_state, STATE_FONT_SET); STATE_CLR(ansi_state, STATE_ESC_SET); /* clear ansi_val[] array */ bzero(ansi_val, sizeof(ansi_val)); ival = 0; continue; } else STATE_CLR(ansi_state, STATE_QUOTE_LINE); } if (i < (buflen - 1) && (buf[i] == 0x1b && buf[i+1] == '[')) { if (STATE_ISSET(ansi_state, STATE_ESC_SET)) { /* *[*[ or *[13;24*[ */ size_t len; ansi_end = &buf[i - 1]; len = ansi_end - ansi_begin + 1; print_raw_ansi(ansi_begin, len, output); } STATE_SET(ansi_state, STATE_ESC_SET); ansi_begin = &buf[i]; i++; /* skip the next '[' character */ } else if (buf[i] == '\n') { if (STATE_ISSET(ansi_state, STATE_ESC_SET)) { /* *[\n or *[13;24\n */ size_t len; ansi_end = &buf[i - 1]; len = ansi_end - ansi_begin + 1; print_raw_ansi(ansi_begin, len, output); STATE_CLR(ansi_state, STATE_ESC_SET); } if (STATE_ISSET(ansi_state, STATE_QUOTE_LINE)) { /* end of a quoted line */ output->output("</font>", 7, output); STYLE_CLR(font_style, FONT_STYLE_QUOTE); STATE_CLR(ansi_state, STATE_FONT_SET); } output->output("<br />\n", 7, output); STATE_CLR(ansi_state, STATE_QUOTE_LINE); STATE_SET(ansi_state, STATE_NEW_LINE); } else { if (STATE_ISSET(ansi_state, STATE_ESC_SET)) { if (buf[i] == 'm') { /* *[0;1;4;31m */ if (STATE_ISSET(ansi_state, STATE_FONT_SET)) { output->output("</font>", 7, output); STATE_CLR(ansi_state, STATE_FONT_SET); } if (i < buflen - 1) { generate_font_style(&font_style, ansi_val, ival+1); if (STATE_ISSET(ansi_state, STATE_QUOTE_LINE)) STYLE_SET(font_style, FONT_STYLE_QUOTE); print_font_style(font_style, output); STATE_SET(ansi_state, STATE_FONT_SET); STATE_CLR(ansi_state, STATE_ESC_SET); /*STYLE_ZERO(font_style);*/ /* clear ansi_val[] array */ bzero(ansi_val, sizeof(ansi_val)); ival = 0; } } else if (isalpha(buf[i])) { /* *[23;32H */ /* ignore it */ STATE_CLR(ansi_state, STATE_ESC_SET); STYLE_ZERO(font_style); /* clear ansi_val[] array */ bzero(ansi_val, sizeof(ansi_val)); ival = 0; continue; } else if (buf[i] == ';') { if (ival < sizeof(ansi_val) - 1) { ival ++; /* go to next ansi_val[] element */ ansi_val[ival] = 0; } } else if (buf[i] >= '0' && buf[i] <= '9') { ansi_val[ival] *= 10; ansi_val[ival] += (buf[i] - '0'); } else { /* *[1;32/XXXX or *[* or *[[ */ /* not a valid ANSI string, just output it */ size_t len; ansi_end = &buf[i]; len = ansi_end - ansi_begin + 1; print_raw_ansi(ansi_begin, len, output); STATE_CLR(ansi_state, STATE_ESC_SET); /* clear ansi_val[] array */ bzero(ansi_val, sizeof(ansi_val)); ival = 0; } } else print_raw_ansi(&buf[i], 1, output); } } if (STATE_ISSET(ansi_state, STATE_FONT_SET)) { output->output("</font>", 7, output); STATE_CLR(ansi_state, STATE_FONT_SET); } flush_buffer(output); }
int token_next (struct tokenizer *t, char **tok, enum token_type *type) { enum token_type etype = TOKEN_TYPE_SYMBOL; dstring_trunc (&t->tok); for (;;) { switch (chars_get (t)) { case 0: if (STATE_ISSET (STATE_STRING)) return 0; if (STATE_ISSET (STATE_ESCAPE)) return 0; if (STATE_ISSET (STATE_COMMENT)) return 0; etype = TOKEN_TYPE_EOF; goto END; case -1: return 0; default: break; } switch (t->ch_cur) { case ';': if (STATE_ISSET (STATE_STRING) || STATE_ISSET (STATE_ESCAPE)) { if (!dstring_catb (&t->tok, &t->ch_cur, 1)) return 0; break; } if (STATE_ISSET (STATE_COMMENT)) break; STATE_SET (STATE_COMMENT); break; case '\n': if (STATE_ISSET (STATE_COMMENT)) { STATE_UNSET (STATE_COMMENT); break; } t->line++; case ' ': case '\t': if (STATE_ISSET (STATE_COMMENT)) break; if (STATE_ISSET (STATE_ESCAPE)) STATE_UNSET (STATE_ESCAPE); if (STATE_ISSET (STATE_STRING)) { if (!dstring_catb (&t->tok, &t->ch_cur, 1)) return 0; } else { if (t->tok.len) goto END; } break; case '"': if (STATE_ISSET (STATE_COMMENT)) break; if (STATE_ISSET (STATE_STRING)) { if (STATE_ISSET (STATE_ESCAPE)) { if (!dstring_catb (&t->tok, &t->ch_cur, 1)) return 0; STATE_UNSET (STATE_ESCAPE); } else { STATE_UNSET (STATE_STRING); goto END; } } else { STATE_SET (STATE_STRING); etype = TOKEN_TYPE_STRING; } break; case '\\': if (STATE_ISSET (STATE_COMMENT)) break; if (STATE_ISSET (STATE_STRING)) { if (STATE_ISSET (STATE_ESCAPE)) { if (!dstring_catb (&t->tok, &t->ch_cur, 1)) return 0; STATE_UNSET (STATE_ESCAPE); } else { STATE_SET (STATE_ESCAPE); } } break; case '(': if (STATE_ISSET (STATE_COMMENT)) break; if (!dstring_catb (&t->tok, &t->ch_cur, 1)) return 0; if (!STATE_ISSET (STATE_STRING)) { etype = TOKEN_TYPE_PAREN_OPEN; goto END; } break; case ')': if (STATE_ISSET (STATE_COMMENT)) break; if (!dstring_catb (&t->tok, &t->ch_cur, 1)) return 0; if (!STATE_ISSET (STATE_STRING)) { etype = TOKEN_TYPE_PAREN_CLOSE; goto END; } break; default: if (STATE_ISSET (STATE_COMMENT)) break; if (STATE_ISSET (STATE_ESCAPE)) STATE_UNSET (STATE_ESCAPE); if (!dstring_catb (&t->tok, &t->ch_cur, 1)) return 0; switch (t->ch_next) { case ')': case '(': case '"': if (!STATE_ISSET (STATE_STRING)) goto END; default: break; } break; } } END: dstring_0 (&t->tok); *tok = t->tok.s; *type = etype; return 1; }
static void output_ansi_nforum(char *buf, size_t buflen, buffered_output_t * output, zval *attachment) { unsigned int font_style = 0; unsigned int ansi_state; unsigned int ansi_val[STRLEN]; int ival = 0; size_t i; bool att = false; char *ansi_begin = NULL; char *ansi_end; size_t article_len = buflen; if (buf == NULL) return; STATE_ZERO(ansi_state); bzero(ansi_val, sizeof(ansi_val)); for (i = 0; i < article_len; i++) { if (buf[i] == '\0') { //assume ATTACHMENT_PAD[0] is '\0' if (article_len - i >= ATTACHMENT_SIZE + sizeof(int) + 2) { if (!memcmp(buf + i, ATTACHMENT_PAD, ATTACHMENT_SIZE)) { att = true; break; } } } if (STATE_ISSET(ansi_state, STATE_NEW_LINE)) { STATE_CLR(ansi_state, STATE_NEW_LINE); if (i < (buflen - 1) && !STATE_ISSET(ansi_state,STATE_TEX_SET) && (buf[i] == ':' && buf[i + 1] == ' ')) { STATE_SET(ansi_state, STATE_QUOTE_LINE); if (STATE_ISSET(ansi_state, STATE_FONT_SET)) BUFFERED_OUTPUT(output, "</font>", 7); /* * set quoted line styles */ STYLE_SET(font_style, FONT_STYLE_QUOTE); STYLE_SET_FG(font_style, FONT_COLOR_QUOTE); STYLE_CLR_BG(font_style); print_font_style(font_style, output); BUFFERED_OUTPUT(output, &buf[i], 1); STATE_SET(ansi_state, STATE_FONT_SET); STATE_CLR(ansi_state, STATE_ESC_SET); /* * clear ansi_val[] array */ bzero(ansi_val, sizeof(ansi_val)); ival = 0; continue; } else STATE_CLR(ansi_state, STATE_QUOTE_LINE); } /* * is_tex 情况下,\[upload 优先匹配 \[ 而不是 [upload * is_tex 情况下应该还有一个问题是 *[\[ 等,不过暂时不管了 - atppp */ if (i < (buflen - 1) && !STATE_ISSET(ansi_state,STATE_TEX_SET) && (buf[i] == 0x1b && buf[i + 1] == '[')) { if (STATE_ISSET(ansi_state, STATE_ESC_SET)) { /* *[*[ or *[13;24*[ */ size_t len; ansi_end = &buf[i - 1]; len = ansi_end - ansi_begin + 1; print_raw_ansi(ansi_begin, len, output); } STATE_SET(ansi_state, STATE_ESC_SET); ansi_begin = &buf[i]; i++; /* skip the next '[' character */ } else if (buf[i] == '\n') { if (STATE_ISSET(ansi_state, STATE_ESC_SET)) { /* *[\n or *[13;24\n */ size_t len; ansi_end = &buf[i - 1]; len = ansi_end - ansi_begin + 1; print_raw_ansi(ansi_begin, len, output); STATE_CLR(ansi_state, STATE_ESC_SET); } if (STATE_ISSET(ansi_state, STATE_QUOTE_LINE)) { /* * end of a quoted line */ BUFFERED_OUTPUT(output, " </font>", 8); STYLE_CLR(font_style, FONT_STYLE_QUOTE); STATE_CLR(ansi_state, STATE_FONT_SET); } if (!STATE_ISSET(ansi_state,STATE_TEX_SET)) { BUFFERED_OUTPUT(output, " <br /> ", 8); } STATE_CLR(ansi_state, STATE_QUOTE_LINE); STATE_SET(ansi_state, STATE_NEW_LINE); } else { if (STATE_ISSET(ansi_state, STATE_ESC_SET)) { if (buf[i] == 'm') { /* *[0;1;4;31m */ if (STATE_ISSET(ansi_state, STATE_FONT_SET)) { BUFFERED_OUTPUT(output, "</font>", 7); STATE_CLR(ansi_state, STATE_FONT_SET); } if (i < buflen - 1) { generate_font_style(&font_style, ansi_val, ival + 1); if (STATE_ISSET(ansi_state, STATE_QUOTE_LINE)) STYLE_SET(font_style, FONT_STYLE_QUOTE); print_font_style(font_style, output); STATE_SET(ansi_state, STATE_FONT_SET); STATE_CLR(ansi_state, STATE_ESC_SET); /* * STYLE_ZERO(font_style); */ /* * clear ansi_val[] array */ bzero(ansi_val, sizeof(ansi_val)); ival = 0; } } else if (isalpha(buf[i])) { /* *[23;32H */ /* * ignore it */ STATE_CLR(ansi_state, STATE_ESC_SET); STYLE_ZERO(font_style); /* * clear ansi_val[] array */ bzero(ansi_val, sizeof(ansi_val)); ival = 0; continue; } else if (buf[i] == ';') { if (ival < sizeof(ansi_val) - 1) { ival++; /* go to next ansi_val[] element */ ansi_val[ival] = 0; } } else if (buf[i] >= '0' && buf[i] <= '9') { ansi_val[ival] *= 10; ansi_val[ival] += (buf[i] - '0'); } else { /* *[1;32/XXXX or *[* or *[[ */ /* * not a valid ANSI string, just output it */ size_t len; ansi_end = &buf[i]; len = ansi_end - ansi_begin + 1; print_raw_ansi(ansi_begin, len, output); STATE_CLR(ansi_state, STATE_ESC_SET); /* * clear ansi_val[] array */ bzero(ansi_val, sizeof(ansi_val)); ival = 0; } } else print_raw_ansi(&buf[i], 1, output); } } if (STATE_ISSET(ansi_state, STATE_FONT_SET)) { BUFFERED_OUTPUT(output, "</font>", 7); STATE_CLR(ansi_state, STATE_FONT_SET); } if (att) { //attachment char *cur_ptr, *attachfilename, *attachptr; long attach_len, attach_pos, newlen; off_t ptrlen; zval *item; cur_ptr = buf + i; ptrlen = article_len - i; while (ptrlen > 0) { if (((attachfilename = checkattach(cur_ptr, ptrlen, &attach_len, &attachptr)) == NULL)) { break; } attach_pos = attachfilename - buf; newlen = attachptr - cur_ptr + attach_len; cur_ptr += newlen; ptrlen -= newlen; if (ptrlen < 0) break; MAKE_STD_ZVAL(item); array_init(item); add_assoc_string(item, "name", attachfilename, 1); add_assoc_long(item, "size", attach_len); add_assoc_long(item, "pos", attach_pos); add_next_index_zval(attachment, item); } } BUFFERED_FLUSH(output); }