jcs
/subtext
/amendments
/74
mail: Implement deleting and marking messages unread
jcs made amendment 74 over 2 years ago
--- mail.c Thu Feb 17 12:16:02 2022
+++ mail.c Thu Feb 17 14:50:25 2022
@@ -50,15 +50,31 @@ struct bile_object_field mail_object_fields[] = {
member_size(struct private_message, parent_message_id), -1 },
};
+void mail_free_message_strings(struct private_message *msg);
short mail_save(struct session *s, struct private_message *msg);
size_t mail_find_for_user_id(unsigned long user_id,
unsigned long **mail_ids);
void mail_help(struct session *s);
-short mail_read(struct session *s, unsigned long idx);
+void mail_read(struct session *s, unsigned long idx);
+void mail_delete(struct session *s, unsigned long idx);
+void mail_mark_unread(struct session *s, unsigned long idx);
void mail_list(struct session *s, bool sent, unsigned long **mail_ids,
size_t *nmsgs);
void
+mail_free_message_strings(struct private_message *msg)
+{
+ if (msg->subject) {
+ free(msg->subject);
+ msg->subject = NULL;
+ }
+ if (msg->body) {
+ free(msg->body);
+ msg->body = NULL;
+ }
+}
+
+void
mail_menu(struct session *s)
{
char arg[32];
@@ -93,6 +109,12 @@ mail_menu(struct session *s)
if (sscanf(field, "c %s%n", &arg, &count) == 1 && count > 1)
mail_compose(s, arg, NULL, NULL);
+ else if (strcmp(field, "c") == 0)
+ mail_compose(s, NULL, NULL, NULL);
+ else if (sscanf(field, "d %ld%n", &id, &count) == 1 && count > 1)
+ mail_delete(s, id);
+ else if (sscanf(field, "u %ld%n", &id, &count) == 1 && count > 1)
+ mail_mark_unread(s, id);
else if (sscanf(field, "%ld%n", &id, &count) == 1 && count > 1) {
if (id < 1 || id > nmsgs) {
session_output_string(s, "Invalid message id\r\n");
@@ -100,13 +122,12 @@ mail_menu(struct session *s)
continue;
}
mail_read(s, mail_ids[id - 1]);
- } else if (strcmp(field, "c") == 0)
- mail_compose(s, NULL, NULL, NULL);
+ }
else if (strcmp(field, "l") == 0)
mail_list(s, false, &mail_ids, &nmsgs);
- else if (strcmp(field, "q") == 0)
+ else if (strcmp(field, "q") == 0 || strcmp(field, "x") == 0)
done = true;
- else if (strcmp(field, "?") == 0)
+ else if (strcmp(field, "?") == 0 || strcmp(field, "h") == 0)
mail_help(s);
else if (field[0] != '\0') {
session_output_template(s,
@@ -122,9 +143,12 @@ void
mail_help(struct session *s)
{
session_output_template(s,
- "({{B}}L{{/}})ist and read mail messages\r\n"
- "({{B}}C{{/}})ompose new message\r\n"
- "({{B}}Q{{/}})uit to main menu\r\n");
+ "{{B}}l{{/}}: List mail messages\r\n"
+ "{{B}}#{{/}}: Read mail message [#]\r\n"
+ "{{B}}d #{{/}}: Delete mail message [#]\r\n"
+ "{{B}}u #{{/}}: Mark mail message [#] unread\r\n"
+ "{{B}}c{{/}}: Compose new mail message\r\n"
+ "{{B}}q{{/}}: Return to main menu\r\n");
session_flush(s);
}
@@ -274,10 +298,7 @@ mail_compose_start:
mail_compose_done:
if (to_username)
free(to_username);
- if (msg.subject)
- free(msg.subject);
- if (msg.body)
- free(msg.body);
+ mail_free_message_strings(&msg);
}
void
@@ -320,15 +341,12 @@ mail_list(struct session *s, bool sent, unsigned long
msg.read ? "" : ansi(s, ANSI_RESET, ANSI_END));
session_flush(s);
- if (msg.subject)
- free(msg.subject);
- if (msg.body)
- free(msg.body);
+ mail_free_message_strings(&msg);
free(data);
}
}
-short
+void
mail_read(struct session *s, unsigned long id)
{
char time[32];
@@ -359,16 +377,71 @@ mail_read(struct session *s, unsigned long id)
if (!msg.read) {
msg.read = Time;
- mail_save(s, &msg);
+ if (mail_save(s, &msg) != 0)
+ session_output_string(s, "Failed marking message read!\r\n");
}
- if (msg.subject)
- free(msg.subject);
- if (msg.body)
- free(msg.body);
+ mail_free_message_strings(&msg);
free(data);
}
+void
+mail_delete(struct session *s, unsigned long idx)
+{
+ unsigned long *mail_ids;
+ size_t nmsgs;
+
+ nmsgs = mail_find_for_user_id(s->user->id, &mail_ids);
+ if (idx > nmsgs) {
+ session_printf(s, "Invalid message id {{B}}%ld{{/}}\r\n", idx);
+ goto delete_done;
+ }
+
+ if (bile_delete(db->bile, DB_MESSAGE_RTYPE, mail_ids[idx - 1]) == 0)
+ session_printf(s, "Deleted message {{B}}%ld{{/}}\r\n", idx);
+ else
+ session_printf(s, "Failed deleting message {{B}}%ld{{/}}! "
+ "(%d)\r\n", idx, bile_error(db->bile));
+
+delete_done:
+ if (mail_ids)
+ free(mail_ids);
+}
+
+void
+mail_mark_unread(struct session *s, unsigned long idx)
+{
+ struct private_message msg;
+ unsigned long *mail_ids;
+ size_t nmsgs, size;
+ char *data;
+
+ nmsgs = mail_find_for_user_id(s->user->id, &mail_ids);
+ if (idx > nmsgs) {
+ session_printf(s, "Invalid message id {{B}}%ld{{/}}\r\n", idx);
+ goto unread_done;
+ }
+
+ size = bile_read_alloc(db->bile, DB_MESSAGE_RTYPE, mail_ids[idx - 1],
+ &data);
+ bile_unmarshall_object(db->bile, mail_object_fields,
+ nitems(mail_object_fields), data, size, &msg);
+ msg.read = 0;
+ if (mail_save(s, &msg) == 0)
+ session_printf(s, "Marked message {{B}}%ld{{/}} unread\r\n",
+ idx);
+ else
+ session_printf(s, "Failed marking message {{B}}%ld{{/}} "
+ "unread!\r\n", idx);
+
+ mail_free_message_strings(&msg);
+ free(data);
+
+unread_done:
+ if (mail_ids)
+ free(mail_ids);
+}
+
short
mail_save(struct session *s, struct private_message *msg)
{
@@ -386,7 +459,13 @@ mail_save(struct session *s, struct private_message *m
return -1;
}
- bile_write(db->bile, DB_MESSAGE_RTYPE, msg->id, data, size);
+ if (bile_write(db->bile, DB_MESSAGE_RTYPE, msg->id, data,
+ size) != size) {
+ warn("mail_save: bile_write failed! %d", bile_error(db->bile));
+ return bile_error(db->bile);
+ }
+
+ return 0;
}
size_t