-/*
- * Text client functions for reading and writing of messages
- *
- * Copyright (c) 1987-2018 by the citadel.org team
- *
- * This program is open source software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
+// Text client functions for reading and writing of messages
+//
+// Copyright (c) 1987-2020 by the citadel.org team
+//
+// This program is open source software. Use, duplication, and/or
+// disclosure are subject to the GNU General Purpose License version 3.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
#include "textclient.h"
struct parts *last_message_parts = NULL; /* Parts from last msg */
-
void ka_sigcatch(int signum)
{
alarm(S_KEEPALIVE);
}
-
/*
* add a newline to the buffer...
*/
/*
* This is a mini RFC2047 decoder.
* It only handles strings encoded from UTF-8 as Quoted-printable.
+ * We can do this "in place" because the converted string will always be smaller than the source string.
*/
void mini_2047_decode(char *s)
{
- if (!s)
+ if (!s) { // no null strings allowed!
return;
+ }
- char *qstart = strstr(s, "=?UTF-8?Q?");
- if (!qstart)
+ char *qstart = strstr(s, "=?UTF-8?Q?"); // Must start with this string
+ if (!qstart) {
return;
+ }
- char *qend = strstr(s, "?=");
- if (!qend)
+ char *qend = strstr(qstart+10, "?="); // Must end with this string
+ if (!qend) {
return;
+ }
- if (qend <= qstart)
+ if (qend <= qstart) { // And there must be something in between them.
return;
+ }
- strcpy(qstart, &qstart[10]);
- qend -= 10;
+ // The string has qualified for conversion.
- char *p = qstart;
- while (p < qend) {
+ strcpy(qend, ""); // Strip the trailer
+ strcpy(qstart, &qstart[10]); // Strip the header
- if (p[0] == '=') {
+ char *r = qstart; // Pointer to where in the string we're reading
+ char *w = s; // Pointer to where in the string we're writing
+ while(*r) { // Loop through the source string
+ if (r[0] == '=') { // "=" means read a hex character
char ch[3];
- ch[0] = p[1];
- ch[1] = p[2];
- ch[2] = p[3];
+ ch[0] = r[1];
+ ch[1] = r[2];
+ ch[2] = r[3];
int c;
sscanf(ch, "%02x", &c);
- p[0] = c;
- strcpy(&p[1], &p[3]);
- qend -= 2;
+ w[0] = c;
+ r += 3;
+ ++w;
}
-
- if (p[0] == '_') {
- p[0] = ' ';
+ else if (r[0] == '_') { // "_" is a space
+ w[0] = ' ';
+ ++r;
+ ++w;
+ }
+ else { // anything else pass through literally
+ w[0] = r[0];
+ ++r;
+ ++w;
}
-
- ++p;
}
-
- strcpy(qend, &qend[2]);
+ w[0] = 0; // null terminate
}
+
/*
* Read a message from the server
*/
-int read_message(CtdlIPC * ipc, long num, /* message number */
- int pagin, /* 0 = normal read, 1 = read with pagination, 2 = header */
- FILE * dest)
-{ /* Destination file, NULL for screen */
+int read_message(CtdlIPC *ipc,
+ long num, /* message number */
+ int pagin, /* 0 = normal read, 1 = read with pagination, 2 = header */
+ FILE *dest /* Destination file, NULL for screen */
+) {
char buf[SIZ];
char now[256];
int format_type = 0;
char ch;
int linelen;
int final_line_is_blank = 0;
-
has_images = 0;
sigcaught = 0;
if (dest) {
fprintf(dest, "\n ");
- } else {
+ }
+ else {
scr_printf("\n");
if (pagin != 2) {
scr_printf(" ");
if (!IsEmptyStr(message->email)) {
scr_printf("rfca=%s\n", message->email);
}
- scr_printf("room=%s\ntime=%s", message->room, asctime(localtime(&message->time))
- );
+ scr_printf("room=%s\ntime=%s", message->room, asctime(localtime(&message->time)));
if (!IsEmptyStr(message->recipient)) {
scr_printf("rcpt=%s\n", message->recipient);
}
if (nhdr == 1 && !is_room_aide) {
if (dest) {
fprintf(dest, " ****");
- } else {
+ }
+ else {
scr_printf(" ****");
}
- } else {
+ }
+ else {
struct tm thetime;
localtime_r(&message->time, &thetime);
strftime(now, sizeof now, "%F %R", &thetime);
if (dest) {
fprintf(dest, "%s from %s ", now, message->author);
- if (!IsEmptyStr(message->email)) {
+ if (!message->is_local) {
fprintf(dest, "<%s> ", message->email);
}
- } else {
+ }
+ else {
color(BRIGHT_CYAN);
scr_printf("%s ", now);
color(DIM_WHITE);
scr_printf("from ");
color(BRIGHT_CYAN);
scr_printf("%s ", message->author);
- if (!IsEmptyStr(message->email)) {
+ if (!message->is_local) {
color(DIM_WHITE);
scr_printf("<");
color(BRIGHT_BLUE);
color(BRIGHT_CYAN);
mini_2047_decode(message->subject);
scr_printf("%s\n", message->subject);
+
}
}
}
* of the client screen.
*/
if (!strcasecmp(message->content_type, "text/html")) {
- converted_text = html_to_ascii(message->text, 0, screenwidth, 0);
+ converted_text = html_to_ascii(message->text, 0, screenwidth);
if (converted_text != NULL) {
free(message->text);
message->text = converted_text;
return (fr);
}
+
/*
* replace string function for the built-in editor
*/
scr_printf("<R>eplace made %d substitution(s).\n\n", substitutions);
}
+
/*
* Function to begin composing a new message
*/
int r; /* IPC response code */
int subject_required = 0;
- if (!entmsg_ok) {
+ if (entmsg_ok == ENTMSG_OK_YES) {
+ /* no problem, go right ahead */
+ }
+ else if (entmsg_ok == ENTMSG_OK_BLOG) {
+ if (!is_reply) {
+ scr_printf("WARNING: this is a BLOG room.\n");
+ scr_printf("The '<E>nter Message' command will create a BLOG POST.\n");
+ scr_printf("If you want to leave a comment or reply to a comment, use the '<R>eply' command.\n");
+ scr_printf("Do you really want to create a new blog post? ");
+ if (!yesno()) {
+ return(1);
+ }
+ }
+ }
+ else {
scr_printf("You may not enter messages in this type of room.\n");
return (1);
}
return (0);
}
+
/*
* Do editing on a quoted file
*/
}
tfile = fopen(temp, "w");
while (fgets(buf, 128, qfile) != NULL) {
- if ((++line >= qstart) && (line <= qend))
+ if ((++line >= qstart) && (line <= qend)) {
fprintf(tfile, " >%s", buf);
+ }
}
fprintf(tfile, " \n");
fclose(qfile);
}
-
/*
- * List the URL's which were embedded in the previous message
+ * List the URLs which were embedded in the previous message
*/
void list_urls(CtdlIPC * ipc)
{
int rv;
if (num_urls == 0) {
- scr_printf("There were no URL's in the previous message.\n\n");
+ scr_printf("There were no URLs in the previous message.\n\n");
return;
}
snprintf(cmd, sizeof cmd, rc_url_cmd, urls[i - 1]);
rv = system(cmd);
- if (rv != 0)
- scr_printf("failed to '%s' by %d\n", cmd, rv);
scr_printf("\n");
}
for (num_msgs = 0; msg_arr[num_msgs]; num_msgs++);
}
- if (num_msgs == 0) { /* TODO look at this later */
- if (c == LastMessages)
+ if (num_msgs == 0) {
+ if (c == LastMessages) {
return;
+ }
scr_printf("*** There are no ");
if (c == NewMessages)
scr_printf("new ");
} /* end read routine */
-
-
/*
* View and edit a system message
*/
}
-
-
/*
- * Loads the contents of a file into memory. Caller must free the allocated
- * memory.
+ * Loads the contents of a file into memory. Caller must free the allocated memory.
*/
char *load_message_from_file(FILE * src)
{