AmendHub

Download:

jcs

/

subtext

/

amendments

/

390

board: Add FidoNet replying/posting


jcs made amendment 390 about 1 year ago
--- board.c Tue Mar 7 22:34:45 2023 +++ board.c Fri Mar 10 14:03:28 2023 @@ -21,6 +21,7 @@ #include "subtext.h" #include "ansi.h" +#include "binkp.h" #include "board.h" #include "logger.h" #include "user.h" @@ -105,8 +106,6 @@ const struct bile_object_field board_fidonet_post_obje member_size(struct board_fidonet_post, id), -1 }, { offsetof(struct board_fidonet_post, msgid), member_size(struct board_fidonet_post, msgid), -1 }, - { offsetof(struct board_fidonet_post, need_dispatch), - member_size(struct board_fidonet_post, need_dispatch), -1 }, { offsetof(struct board_fidonet_post, time), member_size(struct board_fidonet_post, time), -1 }, { offsetof(struct board_fidonet_post, from), @@ -149,7 +148,10 @@ const size_t nboard_thread_object_fields = nitems(boar unsigned long board_compose(struct session *s, struct board *board, struct board_thread *thread, struct board_post *parent_post, - char *initial_subject, char *initial_body); + struct board_fidonet_post *fidonet_parent_post, char *initial_subject, + char *initial_body); +short board_post_create(struct board *board, struct board_thread *thread, + struct board_fidonet_post *fidonet_parent_post, struct board_post *post); void board_list_posts(struct session *s, struct board *board, size_t npost_Ids, unsigned long *post_ids, size_t page, size_t pages); short board_post_read(struct session *s, struct board *board, @@ -169,6 +171,7 @@ board_list_fidonet_boards(struct session *s) }; struct board *fboards = NULL, tboard; size_t nfboards; + char prompt[] = "FidoNet"; char c; short bn, n, i, j; bool done, show_list, show_help; @@ -220,7 +223,7 @@ board_list_fidonet_boards(struct session *s) show_list = false; } - c = session_menu(s, "FidoNet Boards", "FidoNet", opts, + c = session_menu(s, "FidoNet Boards", prompt, opts, nitems(opts), show_help, "Board #", &bn); show_help = false; @@ -234,7 +237,7 @@ board_list_fidonet_boards(struct session *s) session_flush(s); break; } - board_show(s, fboards[bn - 1].id, "FidoNet"); + board_show(s, fboards[bn - 1].id, prompt); break; case '?': show_help = true; @@ -329,7 +332,7 @@ handle_opt: show_list = true; break; case 'p': - if (board_compose(s, board, NULL, NULL, NULL, NULL)) { + if (board_compose(s, board, NULL, NULL, NULL, NULL, NULL)) { find_post_ids = true; show_list = true; } @@ -532,7 +535,8 @@ board_list_posts(struct session *s, struct board *boar unsigned long board_compose(struct session *s, struct board *board, struct board_thread *thread, struct board_post *parent_post, - char *initial_subject, char *initial_body) + struct board_fidonet_post *fidonet_parent_post, char *initial_subject, + char *initial_body) { struct board_post post = { 0 }; char *tmp = NULL; @@ -546,7 +550,7 @@ board_compose(struct session *s, struct board *board, } if (board->restricted_posting && !s->user->is_sysop) { - session_printf(s, "Posting is not available on this board.\r\n"); + session_printf(s, "Posting to this board is not permitted.\r\n"); session_flush(s); return 0; } @@ -579,6 +583,11 @@ post_compose_start: session_printf(s, "{{B}}Subject:{{/B}}{{#}} Re: %s\r\n", thread->subject); session_flush(s); + } else if (fidonet_parent_post) { + session_printf(s, "{{B}}Subject:{{/B}}{{#}} %s%s\r\n", + strncmp("Re:", fidonet_parent_post->subject, 3) == 1 ? + "" : "Re: ", fidonet_parent_post->subject); + session_flush(s); } else { if (initial_subject && !thread->subject) { thread->subject = xstrdup(initial_subject); @@ -662,7 +671,8 @@ post_compose_start: session_printf(s, "Posting message... "); session_flush(s); - if (board_post_create(board, thread, &post) == 0) { + if (board_post_create(board, thread, fidonet_parent_post, + &post) == 0) { session_logf(s, "Posted message %ld to %s", post.id, board->name); session_printf(s, "done\r\n"); @@ -725,7 +735,7 @@ board_post_read(struct session *s, struct board *board short ret = POST_READ_RETURN_DONE; char c; char *data, *subject; - short cc; + short cc, bcret; bool done = false, show_help = false; dopts = xmalloc(sizeof(opts)); @@ -866,7 +876,14 @@ board_post_read(struct session *s, struct board *board } break; case 'r': - if (board_compose(s, board, &thread, &post, NULL, NULL)) { + if (board->fidonet_area[0]) + bcret = board_compose(s, board, NULL, NULL, &fpost, NULL, + NULL); + else + bcret = board_compose(s, board, &thread, &post, NULL, NULL, + NULL); + + if (bcret) { ret = POST_READ_RETURN_FIND; done = true; } @@ -956,91 +973,215 @@ board_find_post_ids(struct session *s, struct board *b short board_post_create(struct board *board, struct board_thread *thread, - struct board_post *post) + struct board_fidonet_post *fidonet_parent_post, struct board_post *post) { + struct board_fidonet_post fidonet_post = { 0 }; + struct fidopkt pkt = { 0 }; + struct username_cache *user; + struct fidopkt_address our_address, hub_address; + struct bile_object *o; short ret; char *data; - size_t size, insert; + size_t size, insert, npost_ids; ssize_t n, j; unsigned long *post_ids, *parent_post_ids; - - if (post->parent_post_id == 0) { - thread->thread_id = bile_next_id(board->bile, BOARD_THREAD_RTYPE); - post->thread_id = thread->thread_id; - } - - post->id = bile_next_id(board->bile, BOARD_POST_RTYPE); - if (!post->time) - post->time = Time; - ret = bile_marshall_object(board->bile, board_post_object_fields, - nboard_post_object_fields, post, &data, &size); - if (ret != 0 || size == 0) { - warn("failed to marshall new post object"); - post->id = 0; - goto done; - } - if (bile_write(board->bile, BOARD_POST_RTYPE, post->id, data, - size) != size) { - warn("bile_write of new post failed! %d", bile_error(board->bile)); - post->id = 0; - xfree(&data); - goto done; - } - xfree(&data); - - if (post->time > thread->last_post_at) - thread->last_post_at = post->time; - thread->nposts++; - post_ids = xreallocarray(thread->post_ids, thread->nposts, - sizeof(long)); - if (post_ids == NULL) - return 0; - thread->post_ids == post_ids; - parent_post_ids = xreallocarray(thread->parent_post_ids, - thread->nposts, sizeof(long)); - if (parent_post_ids == NULL) - return 0; - thread->parent_post_ids = parent_post_ids; - - /* - * Add new post id to thread post_ids, but put it in the right - * place so that reading post_ids will present the tree in order. - * Walk parent_post_ids and find the first match of our parent, - * then insert our new post there. This puts newest replies at - * the top. - */ + if (board->fidonet_area[0]) { + post->id = bile_next_id(board->bile, BOARD_FIDONET_POST_RTYPE); + + if (!post->time) + post->time = Time; - insert = thread->nposts - 1; - for (n = 0; n < thread->nposts - 1; n++) { - if (thread->post_ids[n] != post->parent_post_id) - continue; + if (!fidopkt_parse_address(db->config.fidonet_node_addr, + &our_address)) { + logger_printf("[board] invalid fidonet address, can't " + "create board post"); + post->id = 0; + goto done; + } + if (!fidopkt_parse_address(db->config.fidonet_hub_addr, + &hub_address)) { + logger_printf("[board] invalid fidonet hub address, can't " + "create board post"); + post->id = 0; + goto done; + } - for (j = thread->nposts - 2; j > n; j--) { - thread->post_ids[j + 1] = thread->post_ids[j]; - thread->parent_post_ids[j + 1] = thread->parent_post_ids[j]; + fidonet_post.id = post->id; + fidonet_post.time = post->time; + + if (fidonet_parent_post) { + snprintf(fidonet_post.subject, sizeof(fidonet_post.subject), + "%s%s", + strncmp("Re:", fidonet_parent_post->subject, 3) == 1 ? + "" : "Re: ", + fidonet_parent_post->subject); + strlcpy(fidonet_post.reply, fidonet_parent_post->msgid_orig, + sizeof(fidonet_post.reply)); + strlcpy(fidonet_post.to, fidonet_parent_post->from, + sizeof(fidonet_post.to)); + } else { + strlcpy(fidonet_post.subject, thread->subject, + sizeof(fidonet_post.subject)); + strlcpy(fidonet_post.to, "All", sizeof(fidonet_post.to)); } - insert = n + 1; - break; - } - thread->post_ids[insert] = post->id; - thread->parent_post_ids[insert] = post->parent_post_id; + + user = user_username(post->sender_user_id); + if (user == NULL) { + warn("can't find username of user posting new message?"); + post->id = 0; + goto done; + } + strlcpy(fidonet_post.from, user->username, + sizeof(fidonet_post.from)); + + fidonet_post.body = post->body; + fidonet_post.body_size = post->body_size; + + /* make each board's posts have ids unique to our zone/net/node */ + fidonet_post.msgid.id = (board->id << 16) | post->id; + fidonet_post.msgid.zone = our_address.zone; + fidonet_post.msgid.net = our_address.net; + fidonet_post.msgid.node = our_address.node; + fidonet_post.msgid.point = our_address.point; + + snprintf(fidonet_post.origin, sizeof(fidonet_post.origin), + "%s | %s (%s)", + db->config.name, db->config.hostname, + db->config.fidonet_node_addr); + + pkt.time = fidonet_post.time; + memcpy(&pkt.orig, &our_address, sizeof(pkt.orig)); + memcpy(&pkt.dest, &hub_address, sizeof(pkt.dest)); + strlcpy(pkt.area, board->fidonet_area, sizeof(pkt.area)); + strlcpy(pkt.to, fidonet_post.to, sizeof(pkt.to)); + strlcpy(pkt.from, fidonet_post.from, sizeof(pkt.from)); + strlcpy(pkt.subject, fidonet_post.subject, sizeof(pkt.subject)); + pkt.body = fidonet_post.body; + pkt.body_len = fidonet_post.body_size - 1; + strlcpy(pkt.reply, fidonet_post.reply, sizeof(pkt.reply)); + memcpy(&pkt.msgid, &fidonet_post.msgid, sizeof(pkt.msgid)); + strlcpy(pkt.origin, fidonet_post.origin, sizeof(pkt.origin)); + + if (!binkp_store_outbound_fidopkt(&pkt)) { + warn("failed storing outbound fidopkt"); + post->id = 0; + goto done; + } + + ret = bile_marshall_object(board->bile, + board_fidonet_post_object_fields, + nboard_fidonet_post_object_fields, &fidonet_post, &data, &size); + if (ret != 0 || size == 0) { + warn("failed to marshall new fidonet post object"); + post->id = 0; + goto done; + } + if (bile_write(board->bile, BOARD_FIDONET_POST_RTYPE, + fidonet_post.id, data, size) != size) { + warn("bile_write of new post failed! %d", + bile_error(board->bile)); + post->id = 0; + xfree(&data); + goto done; + } + xfree(&data); + + /* assume our post is now the newest, prepend its id */ + o = bile_find(board->bile, BOARD_SORTED_IDS_RTYPE, 1); + size = (o ? o->size : 0) + sizeof(unsigned long); + npost_ids = (o ? (o->size / sizeof(unsigned long)) : 0) + 1; + post_ids = xmalloc(size); + if (post_ids == NULL) + goto done; + if (o) + bile_read(board->bile, BOARD_SORTED_IDS_RTYPE, 1, + post_ids + sizeof(unsigned long), o->size); + post_ids[0] = post->id; + bile_write(board->bile, BOARD_SORTED_IDS_RTYPE, 1, post_ids, + size); + } else { + if (!post->time) + post->time = Time; + + if (post->parent_post_id == 0) { + thread->thread_id = bile_next_id(board->bile, + BOARD_THREAD_RTYPE); + post->thread_id = thread->thread_id; + } + + ret = bile_marshall_object(board->bile, board_post_object_fields, + nboard_post_object_fields, post, &data, &size); + if (ret != 0 || size == 0) { + warn("failed to marshall new post object"); + post->id = 0; + goto done; + } + if (bile_write(board->bile, BOARD_POST_RTYPE, post->id, data, + size) != size) { + warn("bile_write of new post failed! %d", + bile_error(board->bile)); + post->id = 0; + xfree(&data); + goto done; + } + xfree(&data); + + if (post->time > thread->last_post_at) + thread->last_post_at = post->time; + thread->nposts++; + post_ids = xreallocarray(thread->post_ids, thread->nposts, + sizeof(long)); + if (post_ids == NULL) + return 0; + thread->post_ids == post_ids; + parent_post_ids = xreallocarray(thread->parent_post_ids, + thread->nposts, sizeof(long)); + if (parent_post_ids == NULL) + return 0; + thread->parent_post_ids = parent_post_ids; + + /* + * Add new post id to thread post_ids, but put it in the right + * place so that reading post_ids will present the tree in order. + * Walk parent_post_ids and find the first match of our parent, + * then insert our new post there. This puts newest replies at + * the top. + */ - ret = bile_marshall_object(board->bile, board_thread_object_fields, - nboard_thread_object_fields, thread, &data, &size); - if (ret != 0 || size == 0) { - warn("failed to marshall thread object"); - post->id = 0; - goto done; - } - if (bile_write(board->bile, BOARD_THREAD_RTYPE, thread->thread_id, - data, size) != size) { - warn("bile_write of thread failed! %d", bile_error(board->bile)); - post->id = 0; + insert = thread->nposts - 1; + for (n = 0; n < thread->nposts - 1; n++) { + if (thread->post_ids[n] != post->parent_post_id) + continue; + + for (j = thread->nposts - 2; j > n; j--) { + thread->post_ids[j + 1] = thread->post_ids[j]; + thread->parent_post_ids[j + 1] = + thread->parent_post_ids[j]; + } + insert = n + 1; + break; + } + thread->post_ids[insert] = post->id; + thread->parent_post_ids[insert] = post->parent_post_id; + + ret = bile_marshall_object(board->bile, board_thread_object_fields, + nboard_thread_object_fields, thread, &data, &size); + if (ret != 0 || size == 0) { + warn("failed to marshall thread object"); + post->id = 0; + goto done; + } + if (bile_write(board->bile, BOARD_THREAD_RTYPE, thread->thread_id, + data, size) != size) { + warn("bile_write of thread failed! %d", + bile_error(board->bile)); + post->id = 0; + xfree(&data); + goto done; + } xfree(&data); - goto done; } - xfree(&data); bile_flush(board->bile, true); @@ -1399,10 +1540,9 @@ board_ingest_fidopkt(struct board *board, struct fidop } memset(&post, 0, sizeof(post)); - post.time = fidopkt->time - - ((db->config.timezone_utcoff * 60 * 60) / 100); - post.body_size = fidopkt->message_len + 1; - post.body = fidopkt->message; + post.time = fidopkt->time; + post.body_size = fidopkt->body_len + 1; + post.body = fidopkt->body; strlcpy(post.reply, fidopkt->reply, sizeof(post.reply)); strlcpy(post.from, fidopkt->from, sizeof(post.from)); strlcpy(post.subject, fidopkt->subject, sizeof(post.subject)); --- board.h Tue Mar 7 20:44:42 2023 +++ board.h Thu Mar 9 15:27:08 2023 @@ -57,7 +57,6 @@ extern const size_t nboard_post_object_fields; struct board_fidonet_post { unsigned long id; struct fidopkt_msgid msgid; - short need_dispatch; time_t time; char from[32]; char subject[80]; @@ -85,8 +84,6 @@ extern const size_t nboard_thread_object_fields; void board_list_fidonet_boards(struct session *s); void board_show(struct session *s, short id, char *prompt_prefix); -short board_post_create(struct board *board, struct board_thread *thread, - struct board_post *post); void board_delete_post(struct session *s, struct board *board, struct board_post *post, struct board_thread *thread); void board_delete_fidonet_post(struct session *s, struct board *board,