AmendHub

Download:

jcs

/

subtext

/

amendments

/

179

*: Hook up folders


jcs made amendment 179 over 2 years ago
--- board.c Tue Jun 28 10:06:12 2022 +++ board.c Thu Jun 30 15:42:11 2022 @@ -162,6 +162,10 @@ board_show(struct session *s, short id) while (!done && !s->ending) { if (find_post_ids) { + if (post_ids != NULL) { + free(post_ids); + post_ids = NULL; + } nall_post_ids = board_find_post_ids(board, &npost_ids, &post_ids, page * POSTS_PER_PAGE, POSTS_PER_PAGE); /* ceil(nall_post_ids / POSTS_PER_PAGE) */ @@ -249,6 +253,9 @@ handle_opt: break; } } + + if (post_ids != NULL) + free(post_ids); } void @@ -519,7 +526,7 @@ board_post_read(struct session *s, struct board *board struct board_post post; struct username_cache *sender, *recipient; unsigned long new_id; - char prompt[DB_BOARD_NAME_LENGTH + 8]; + char prompt[BOARD_NAME_LENGTH + 8]; size_t n, size; short ret = POST_READ_RETURN_DONE; char c; @@ -661,6 +668,8 @@ board_find_post_ids(struct board *board, size_t *npost for (n = 0; o = bile_get_nth_of_type(board->bile, n, BOARD_THREAD_RTYPE); n++) { + if (n >= nthreads) + break; bile_read_alloc(board->bile, BOARD_THREAD_RTYPE, o->id, &data); bile_unmarshall_object(board->bile, board_thread_object_fields, nboard_thread_object_fields, data, o->size, &thread, false); --- board.h Thu May 26 15:23:00 2022 +++ board.h Thu Jun 30 13:36:04 2022 @@ -19,11 +19,14 @@ #include <stddef.h> #include "session.h" +#include "settings.h" struct board { unsigned long id; - char name[DB_BOARD_NAME_LENGTH]; - char description[DB_BOARD_DESCR_LENGTH]; +#define BOARD_NAME_LENGTH 32 + char name[BOARD_NAME_LENGTH]; +#define BOARD_DESCR_LENGTH 100 + char description[BOARD_DESCR_LENGTH]; bool restricted_posting; bool restricted_viewing; unsigned short retention_days; --- db.c Wed Jun 22 15:21:14 2022 +++ db.c Wed Jun 29 09:35:09 2022 @@ -22,6 +22,7 @@ #include "board.h" #include "bile.h" #include "db.h" +#include "folder.h" #include "user.h" #include "util.h" @@ -202,6 +203,7 @@ db_init(Str255 path, short vrefnum, struct bile *bile) if (!was_new) { db_config_load(tdb); db_cache_boards(tdb); + db_cache_folders(tdb); } PtoCstr(fullpath); @@ -439,7 +441,7 @@ db_cache_boards(struct db *tdb) for (n = 0; n < tdb->nboards; n++) { snprintf((char *)board_filename, sizeof(board_filename), - "%s:%ld.brd", db_filename, tdb->boards[n].id); + "%s:%ld.%s", db_filename, tdb->boards[n].id, BOARD_FILENAME_EXT); CtoPstr(board_filename); tdb->boards[n].bile = bile_open(board_filename, tdb->bile->vrefnum); @@ -496,8 +498,8 @@ db_board_create(struct db *tdb, struct board *board) panic("getpath failed on %s", PtoCstr(tdb->bile->filename)); PtoCstr(db_filename); - snprintf((char *)board_filename, sizeof(board_filename), "%s:%ld.brd", - db_filename, board->id); + snprintf((char *)board_filename, sizeof(board_filename), "%s:%ld.%s", + db_filename, board->id, BOARD_FILENAME_EXT); CtoPstr(board_filename); board_bile = bile_create(board_filename, tdb->bile->vrefnum, @@ -507,4 +509,120 @@ db_board_create(struct db *tdb, struct board *board) PtoCstr(board_filename), bile_error(NULL)); return board_bile; -} +} + +void +db_cache_folders(struct db *tdb) +{ + Str255 db_filename, folder_filename; + size_t n, size; + struct bile_object *obj; + char *data = NULL; + + if (tdb->folders) { + for (n = 0; n < tdb->nfolders; n++) { + if (tdb->folders[n].bile) + bile_close(tdb->folders[n].bile); + } + free(tdb->folders); + } + + if (getpath(tdb->bile->vrefnum, tdb->bile->filename, &db_filename, + false) != 0) + panic("getpath failed on %s", PtoCstr(tdb->bile->filename)); + PtoCstr(db_filename); + + tdb->nfolders = bile_count_by_type(tdb->bile, DB_FOLDER_RTYPE); + if (!tdb->nfolders) + return; + tdb->folders = xcalloc(tdb->nfolders, sizeof(struct folder)); + + /* + * Read ids first so we have a consistent order, then try to open or + * fix/recreate each bile, which may change their order in the map + */ + for (n = 0; n < tdb->nfolders; n++) { + obj = bile_get_nth_of_type(tdb->bile, n, DB_FOLDER_RTYPE); + if (obj == NULL) + break; + + size = bile_read_alloc(tdb->bile, DB_FOLDER_RTYPE, obj->id, &data); + bile_unmarshall_object(tdb->bile, folder_object_fields, + nfolder_object_fields, data, size, (char *)(&tdb->folders[n]), + true); + free(data); + } + + for (n = 0; n < tdb->nfolders; n++) { + snprintf((char *)folder_filename, sizeof(folder_filename), + "%s:%ld.%s", db_filename, tdb->folders[n].id, + FOLDER_FILENAME_EXT); + CtoPstr(folder_filename); + tdb->folders[n].bile = bile_open(folder_filename, + tdb->bile->vrefnum); + if (tdb->folders[n].bile != NULL) + continue; + + PtoCstr(folder_filename); + + if (bile_error(NULL) != fnfErr && + ask("Attempt recovery of %s with backup map?", + folder_filename)) { + CtoPstr(folder_filename); + tdb->folders[n].bile = bile_open_recover_map(folder_filename, + tdb->bile->vrefnum); + if (tdb->folders[n].bile == NULL) + panic("Failed to recover folder file %s: %d", + PtoCstr(folder_filename), bile_error(NULL)); + continue; + } + + if (ask("Failed to open folder bile %s (error %d), recreate it?", + folder_filename, bile_error(NULL)) == false) + exit(0); + + tdb->folders[n].bile = db_folder_create(tdb, &tdb->folders[n]); + if (tdb->folders[n].bile == NULL) + panic("Failed to create folder file %s: %d", + folder_filename, bile_error(NULL)); + } +} + +struct bile * +db_folder_create(struct db *tdb, struct folder *folder) +{ + Str255 db_filename, folder_filename; + struct bile *folder_bile; + size_t size; + short ret; + char *data; + + ret = bile_marshall_object(tdb->bile, folder_object_fields, + nfolder_object_fields, folder, &data, &size); + if (ret != 0 || size == 0) { + warn("db_folder_create: failed to marshall object"); + return; + } + + if (bile_write(tdb->bile, DB_FOLDER_RTYPE, folder->id, data, + size) != size) + panic("save of new folder failed: %d", bile_error(tdb->bile)); + free(data); + + if (getpath(tdb->bile->vrefnum, tdb->bile->filename, &db_filename, + false) != 0) + panic("getpath failed on %s", PtoCstr(tdb->bile->filename)); + PtoCstr(db_filename); + + snprintf((char *)folder_filename, sizeof(folder_filename), + "%s:%ld.%s", db_filename, folder->id, FOLDER_FILENAME_EXT); + CtoPstr(folder_filename); + + folder_bile = bile_create(folder_filename, tdb->bile->vrefnum, + SUBTEXT_CREATOR, DB_FOLDER_RTYPE); + if (folder_bile == NULL) + panic("Failed creating new folder bile at %s: %d", + PtoCstr(folder_filename), bile_error(NULL)); + + return folder_bile; +} --- db.h Wed Jun 22 15:42:33 2022 +++ db.h Thu Jun 30 13:22:19 2022 @@ -31,7 +31,7 @@ #define DB_CONFIG_RTYPE 'CONF' #define DB_USER_RTYPE 'USER' #define DB_BOARD_RTYPE 'BORD' -#define DB_FILEAREA_RTYPE 'FILA' +#define DB_FOLDER_RTYPE 'FOLD' #define DB_VERS_RTYPE 'VERS' #define DB_MESSAGE_RTYPE 'PMSG' @@ -43,20 +43,23 @@ #define DB_TEXT_PAGE_SYSOP_ID 5 #define DB_USERNAME_LENGTH 16 -#define DB_BOARD_NAME_LENGTH 32 -#define DB_BOARD_DESCR_LENGTH 100 #define SL_TYPE 'STSL' #define SL_LOG_RTYPE 'SLOG' #define SL_TALLY_RTYPE 'STLY' +#define BOARD_FILENAME_EXT "brd" #define BOARD_THREAD_RTYPE 'BDTH' #define BOARD_POST_RTYPE 'BDPS' +#define FOLDER_FILENAME_EXT "fld" +#define FOLDER_FILE_RTYPE 'FILE' + #include "subtext.h" -#include "settings.h" #include "bile.h" -#include "sha2.h" +#include "board.h" +#include "folder.h" +#include "settings.h" struct config { char name[32]; @@ -87,6 +90,8 @@ struct db { struct bile *sessions_bile; struct board *boards; short nboards; + struct folder *folders; + short nfolders; }; struct db * db_open(Str255 file, short vrefnum); @@ -95,5 +100,7 @@ void db_close(struct db *tdb); void db_config_save(struct db *tdb); void db_cache_boards(struct db *tdb); struct bile * db_board_create(struct db *tdb, struct board *board); +void db_cache_folders(struct db *tdb); +struct bile * db_folder_create(struct db *tdb, struct folder *folder); #endif --- session.c Fri Jun 24 16:25:05 2022 +++ session.c Wed Jun 29 11:22:41 2022 @@ -22,6 +22,7 @@ #include "ansi.h" #include "board.h" #include "chat.h" +#include "folder.h" #include "mail.h" #include "subtext.h" #include "session.h" @@ -208,8 +209,7 @@ get_another_char: case 'f': case 'F': /* files */ - session_printf(s, "Coming soon!\r\n"); - session_flush(s); + folder_list(s); break; case 'g': case 'G': @@ -1183,7 +1183,7 @@ session_pause_return(struct session *s, short enforce, { unsigned char c; - session_output_template(s, "{{/B}}Press {{B}}<Enter>{{/B}} "); + session_printf(s, "{{/B}}Press {{B}}<Enter>{{/B}} "); if (msg) session_printf(s, msg); else --- sysop.c Wed Jun 8 10:31:15 2022 +++ sysop.c Tue Jun 28 11:33:14 2022 @@ -25,6 +25,7 @@ #define USERS_PER_PAGE 10 void sysop_edit_boards(struct session *s); +void sysop_edit_folders(struct session *s); void sysop_edit_users(struct session *s); size_t sysop_find_user_ids(size_t nall_user_ids, unsigned long *all_user_ids, unsigned long **user_ids, size_t offset, @@ -36,6 +37,7 @@ sysop_menu(struct session *s) { static struct session_menu_option opts[] = { { 'b', "Bb", "Manage Boards" }, + { 'f', "Ff", "Manage File Folders" }, { 'u', "Uu", "Manage Users" }, { 's', "Ss", "Change BBS Settings" }, { 'q', "QqXx", "Return to main menu" }, @@ -59,6 +61,9 @@ sysop_menu(struct session *s) case 'b': sysop_edit_boards(s); break; + case 'f': + sysop_edit_folders(s); + break; case 's': sysop_edit_settings(s); break; @@ -207,6 +212,127 @@ sysop_edit_boards(struct session *s) } if (!found) { session_printf(s, "Invalid board ID\r\n"); + session_flush(s); + } + break; + case '?': + show_help = true; + break; + default: + done = true; + break; + } + } +} + +void +sysop_edit_folders(struct session *s) +{ + static struct session_menu_option opts[] = { + { 'n', "Nn", "Create new folder" }, + { 'q', "QqXx", "Return to sysop menu" }, + { '?', "?", "List menu options" }, + }; + char prompt[30]; + struct session_menu_option *dopts = NULL, *opt; + struct folder *folder, *new_folder; + struct bile *new_folder_bile; + size_t n, size; + short ret; + char c, *data = NULL; + bool show_help = true; + bool done = false; + bool found = false; + + while (!done && !s->ending) { + /* + * Unfortunately we have to do this every iteration because the + * list of boards may change + */ + if (dopts != NULL) + free(dopts); + dopts = xmalloc(sizeof(opts) + + (db->nboards * sizeof(struct session_menu_option))); + for (n = 0; n < db->nfolders; n++) { + folder = &db->folders[n]; + opt = &dopts[n]; + opt->ret = '0' + folder->id; + opt->key[0] = '0' + folder->id; + opt->key[1] = '\0'; + strlcpy(opt->title, folder->name, sizeof(opts[0].title)); + } + memcpy(&dopts[db->nfolders], opts, sizeof(opts)); + + c = session_menu(s, "Folder Editor", "Sysop:Folders", dopts, + nitems(opts) + db->nfolders, show_help); + show_help = false; + + switch (c) { + case 'n': + folder = xmalloczero(sizeof(struct folder)); + folder->id = bile_next_id(db->bile, DB_FOLDER_RTYPE); + folder->restricted_posting = false; + folder->restricted_viewing = false; + ret = struct_editor(s, folder_fields, nfolder_fields, + folder, sizeof(struct folder), (void *)&new_folder, + "New Folder", "Sysop:Folders:New"); + if (ret != 0) { + free(folder); + continue; + } + + new_folder_bile = db_folder_create(db, new_folder); + bile_close(new_folder_bile); + db_cache_folders(db); + + session_log(s, "Created new folder %ld: %s", new_folder->id, + new_folder->name); + free(folder); + free(new_folder); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + found = false; + for (n = 0; n < db->nfolders; n++) { + folder = &db->folders[n]; + if (folder->id != c - '0') + continue; + found = true; + snprintf(prompt, sizeof(prompt), "Sysop:Folders:%ld", + folder->id); + ret = struct_editor(s, folder_fields, nfolder_fields, + folder, sizeof(struct folder), (void *)&new_folder, + "Edit Folder", prompt); + if (ret != 0) + continue; + memcpy(&db->folders[n], new_folder, sizeof(struct folder)); + + ret = bile_marshall_object(db->bile, folder_object_fields, + nfolder_object_fields, &db->folders[n], &data, &size); + if (ret != 0 || size == 0) + panic("db_folder_create: failed to marshall object"); + + if (bile_write(db->bile, DB_FOLDER_RTYPE, new_folder->id, + data, size) != size) + panic("save of folder failed: %d", + bile_error(db->bile)); + free(data); + + session_log(s, "Saved changes to folder %ld: %s", + new_folder->id, new_folder->name); + free(new_folder); + break; + } + if (!found) { + session_printf(s, "Invalid folder ID\r\n"); session_flush(s); } break;