From 1a800f37daaf90561e3bab8aadb50c37c0a2bc09 Mon Sep 17 00:00:00 2001 From: Andrew Pamment Date: Mon, 5 Dec 2016 13:38:03 +1000 Subject: [PATCH] Full Ansi support in message reader... beginnings of QWK mail --- bbs.h | 1 + mail_menu.c | 530 +++++++++++++++++++++++++++++++++++++++++++++++++++- main.c | 8 +- 3 files changed, 529 insertions(+), 10 deletions(-) diff --git a/bbs.h b/bbs.h index c109f19..2951fed 100644 --- a/bbs.h +++ b/bbs.h @@ -48,6 +48,7 @@ struct door_config { struct mail_area { char *name; char *path; + char *qwkname; int read_sec_level; int write_sec_level; int type; diff --git a/mail_menu.c b/mail_menu.c index 1531392..ba54cbe 100644 --- a/mail_menu.c +++ b/mail_menu.c @@ -60,7 +60,7 @@ unsigned long generate_msgid() { FILE *fptr; theTime = time(NULL); - localtime_r(&theTime, &timeStruct); + gmtime_r(&theTime, &timeStruct); m = timeStruct.tm_mon + 1; y = timeStruct.tm_year + 1900; @@ -86,7 +86,7 @@ unsigned long generate_msgid() { flock(fileno(fptr), LOCK_EX); fread(&lastread, sizeof(time_t), 1, fptr); fread(&lastid, sizeof(unsigned long), 1, fptr); - localtime_r(&lastread, &fileStruct); + gmtime_r(&lastread, &fileStruct); if (fileStruct.tm_mon != timeStruct.tm_mon || fileStruct.tm_mday != timeStruct.tm_mday || fileStruct.tm_year != timeStruct.tm_year) { @@ -588,6 +588,12 @@ char *editor(struct user_record *user, char *quote, char *from, int email) { i--; } } else { + if (quote[i] == 27) { + while (strchr("ABCDEFGHIGJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", quote[i]) == NULL) + i++; + continue; + } + linebuffer[lineat++] = quote[i]; linebuffer[lineat] = '\0'; } @@ -818,6 +824,507 @@ char *editor(struct user_record *user, char *quote, char *from, int email) { return NULL; } +struct character_t { + char c; + int fg; + int bg; +}; + +void unmangle_ansi(char *body, int len, char **body_out, int *body_len) { + // count lines + int line_count = 1; + int line_at = 1; + int char_at = 1; + int fg = 0x07; + int bg = 0x00; + int state = 0; + int save_char_at = 0; + int save_line_at = 0; + int params[16]; + int param_count = 0; + int bold = 0; + char *out; + int out_len; + int out_max; + char buffer[1024]; + int buf_at; + int i, j, k; + struct character_t ***fake_screen; + int ansi; + + for (i=0;i line_count) { + line_count = line_at; + } + } + } + } + + fake_screen = (struct character_t ***)malloc(sizeof(struct character_t **) * line_count); + for (i=0;ic = ' '; + fake_screen[i][j]->fg = fg; + fake_screen[i][j]->bg = bg; + } + } + + line_at = 1; + char_at = 1; + + for (i=0;ic = body[i]; + fake_screen[line_at -1][char_at - 1]->fg = fg; + fake_screen[line_at -1][char_at - 1]->bg = bg; + char_at++; + while (char_at > 80) { + line_at++; + char_at -= 80; + } + } + } + } else if (state == 1) { + if (body[i] == '[') { + state = 2; + continue; + } + } else if (state == 2) { + param_count = 0; + for (j=0;j<16;j++) { + params[j] = 0; + } + state = 3; + } + if (state == 3) { + if (body[i] == ';') { + if (param_count < 15) { + param_count++; + } + continue; + } else if (body[i] >= '0' && body[i] <= '9') { + if (!param_count) param_count = 1; + params[param_count-1] = params[param_count-1] * 10 + (body[i] - '0'); + continue; + } else { + state = 4; + } + } + + if (state == 4) { + switch(body[i]) { + case 'H': + case 'f': + if (params[0]) params[0]--; + if (params[1]) params[1]--; + line_at = params[0] + 1; + char_at = params[1] + 1; + state = 0; + break; + case 'A': + if (param_count > 0) { + line_at = line_at - params[0]; + } else { + line_at--; + } + state = 0; + break; + case 'B': + if (param_count > 0) { + line_at = line_at + params[0]; + } else { + line_at++; + } + state = 0; + break; + case 'C': + if (param_count > 0) { + char_at = char_at + params[0]; + } else { + char_at ++; + } + if (char_at > 80) { + char_at = 80; + } + state = 0; + break; + case 'D': + if (param_count > 0) { + char_at = char_at - params[0]; + } else { + char_at --; + } + if (char_at < 1) { + char_at = 1; + } + state = 0; + break; + case 's': + save_char_at = char_at; + save_line_at = line_at; + state = 0; + break; + case 'u': + char_at = save_char_at; + line_at = save_line_at; + state = 0; + break; + case 'm': + for (j=0;j 0x07) { + fg -= 0x08; + } + break; + case 30: + if (bold) { + fg = 0x08; + } else { + fg = 0x00; + } + break; + case 31: + if (bold) { + fg = 0x0C; + } else { + fg = 0x04; + } + break; + case 32: + if (bold) { + fg = 0x0A; + } else { + fg = 0x02; + } + break; + case 33: + if (bold) { + fg = 0x0E; + } else { + fg = 0x06; + } + break; + case 34: + if (bold) { + fg = 0x09; + } else { + fg = 0x01; + } + break; + case 35: + if (bold) { + fg = 0x0D; + } else { + fg = 0x05; + } + break; + case 36: + if (bold) { + fg = 0x0B; + } else { + fg = 0x03; + } + break; + case 37: + if (bold) { + fg = 0x0F; + } else { + fg = 0x07; + } + break; + case 40: + bg = 0x00; + break; + case 41: + bg = 0x04; + break; + case 42: + bg = 0x02; + break; + case 43: + bg = 0x06; + break; + case 44: + bg = 0x01; + break; + case 45: + bg = 0x05; + break; + case 46: + bg = 0x03; + break; + case 47: + bg = 0x07; + break; + } + + } + state = 0; + break; + case 'K': + if (params[0] == 0) { + for (k=char_at-1;k<80;k++) { + fake_screen[line_at-1][k]->c = ' '; + fake_screen[line_at-1][k]->fg = fg; + fake_screen[line_at-1][k]->bg = bg; + } + } else if (params[0] == 1) { + for (k=0;kc = ' '; + fake_screen[line_at-1][k]->fg = fg; + fake_screen[line_at-1][k]->bg = bg; + } + } else if (params[0] == 2) { + for (k=0;k<80;k++) { + fake_screen[line_at-1][k]->c = ' '; + fake_screen[line_at-1][k]->fg = fg; + fake_screen[line_at-1][k]->bg = bg; + } + } + state = 0; + break; + case 'J': + if (params[0] == 0) { + for (k=char_at-1;k<80;k++) { + fake_screen[line_at-1][k]->c = ' '; + fake_screen[line_at-1][k]->fg = fg; + fake_screen[line_at-1][k]->bg = bg; + } + + for (k=line_at;kc = ' '; + fake_screen[k][j]->fg = fg; + fake_screen[k][j]->bg = bg; + } + } + } else if (params[0] == 1) { + for (k=0;kc = ' '; + fake_screen[line_at-1][k]->fg = fg; + fake_screen[line_at-1][k]->bg = bg; + } + + for (k=line_at-2;k>=0;k--) { + for (j=0;j<80;j++) { + fake_screen[k][j]->c = ' '; + fake_screen[k][j]->fg = fg; + fake_screen[k][j]->bg = bg; + } + } + } else if (params[0] == 2) { + for (k=0;kc = ' '; + fake_screen[k][j]->fg = fg; + fake_screen[k][j]->bg = bg; + } + } + } + state = 0; + break; + } + } + } + + fg = 0x07; + bg = 0x00; + + out_max = 256; + out_len = 0; + out = (char *)malloc(256); + + for (i=0;ifg != fg || fake_screen[i][j]->bg != bg) { + buffer[buf_at++] = 27; + buffer[buf_at++] = '['; + fg = fake_screen[i][j]->fg; + if (fg < 0x08) { + buffer[buf_at++] = '0'; + buffer[buf_at++] = ';'; + buffer[buf_at++] = '3'; + switch (fg) { + case 0x00: + buffer[buf_at++] = '0'; + break; + case 0x04: + buffer[buf_at++] = '1'; + break; + case 0x02: + buffer[buf_at++] = '2'; + break; + case 0x06: + buffer[buf_at++] = '3'; + break; + case 0x01: + buffer[buf_at++] = '4'; + break; + case 0x05: + buffer[buf_at++] = '5'; + break; + case 0x03: + buffer[buf_at++] = '6'; + break; + case 0x07: + buffer[buf_at++] = '7'; + break; + + + } + } else { + buffer[buf_at++] = '1'; + buffer[buf_at++] = ';'; + buffer[buf_at++] = '3'; + switch (fg) { + case 0x08: + buffer[buf_at++] = '0'; + break; + case 0x0C: + buffer[buf_at++] = '1'; + break; + case 0x0A: + buffer[buf_at++] = '2'; + break; + case 0x0E: + buffer[buf_at++] = '3'; + break; + case 0x09: + buffer[buf_at++] = '4'; + break; + case 0x0D: + buffer[buf_at++] = '5'; + break; + case 0x0B: + buffer[buf_at++] = '6'; + break; + case 0x0F: + buffer[buf_at++] = '7'; + break; + + + } + } + + + bg = fake_screen[i][j]->bg; + buffer[buf_at++] = ';'; + buffer[buf_at++] = '4'; + switch (bg) { + case 0x00: + buffer[buf_at++] = '0'; + break; + case 0x04: + buffer[buf_at++] = '1'; + break; + case 0x02: + buffer[buf_at++] = '2'; + break; + case 0x06: + buffer[buf_at++] = '3'; + break; + case 0x01: + buffer[buf_at++] = '4'; + break; + case 0x05: + buffer[buf_at++] = '5'; + break; + case 0x03: + buffer[buf_at++] = '6'; + break; + case 0x07: + buffer[buf_at++] = '7'; + break; + + + } + buffer[buf_at++] = 'm'; + } + buffer[buf_at++] = fake_screen[i][j]->c; + } + + + while (buf_at > 0 && buffer[buf_at-1] == ' ') { + buf_at--; + } + + buffer[buf_at++] = '\r'; + + while (buf_at + out_len > out_max) { + out_max += 256; + out = (char *)realloc(out, out_max); + } + + memcpy(&out[out_len], buffer, buf_at); + out_len += buf_at; + + } + + for (i=0;icur_mail_conf]->mail_areas[user->cur_mail_area]->path); if (!jb) { @@ -930,7 +1438,11 @@ void read_message(struct user_record *user, struct msg_headers *msghs, int mailn lines = 0; chars = 0; + body2 = body; + z = z2; + unmangle_ansi(body2, z, &body, &z2); + free(body2); msg_line_count = 0; start_line = 0; @@ -959,21 +1471,21 @@ void read_message(struct user_record *user, struct msg_headers *msghs, int mailn } chars = 0; } else { - if (body[z] == '\e') { + if (body[z] == 27) { ansi = z; while (strchr("ABCDEFGHIGJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", body[z]) == NULL) z++; if (body[z] == 'm') { // do nothing - } else if (body[z] == 'C') { - chars += atoi(&body[ansi + 2]); } else { - i = strlen(body); - for (j=ansi;jmail_areas[i]->type = TYPE_NETMAIL_AREA; } + } else if (strcasecmp(name, "qwk name") == 0) { + mc->mail_areas[i]->qwkname = strdup(value); } return 1; } @@ -233,7 +235,9 @@ static int mail_area_handler(void* user, const char* section, const char* name, } mc->mail_areas[mc->mail_area_count] = (struct mail_area *)malloc(sizeof(struct mail_area)); - + + mc->mail_areas[mc->mail_area_count]->qwkname = NULL; + mc->mail_areas[mc->mail_area_count]->name = strdup(section); if (strcasecmp(name, "read sec level") == 0) { mc->mail_areas[mc->mail_area_count]->read_sec_level = atoi(value); @@ -249,6 +253,8 @@ static int mail_area_handler(void* user, const char* section, const char* name, } else if (strcasecmp(value, "netmail") == 0) { mc->mail_areas[mc->mail_area_count]->type = TYPE_NETMAIL_AREA; } + } else if (strcasecmp(name, "qwk name") == 0) { + mc->mail_areas[mc->mail_area_count]->qwkname = strdup(value); } mc->mail_area_count++; }