jcs
/subtext
/amendments
/107
*: Lots of deck chair rearranging
Move things from db files to their respective areas
Make username map contain normal username, just do strcasecmp check
during user_find_by_username.
jcs made amendment 107 over 2 years ago
--- db.c Sun May 15 21:48:28 2022
+++ db.c Mon May 23 13:10:11 2022
@@ -19,6 +19,7 @@
#include <time.h>
#include "subtext.h"
+#include "board.h"
#include "bile.h"
#include "db.h"
#include "user.h"
@@ -52,32 +53,9 @@ struct struct_field config_fields[] = {
};
size_t nconfig_fields = nitems(config_fields);
-struct struct_field board_fields[] = {
- { "Board ID", CONFIG_TYPE_LONG,
- offsetof(struct board, id),
- 1, ULONG_MAX },
- { "Name", CONFIG_TYPE_STRING,
- offsetof(struct board, name),
- 1, member_size(struct board, name) },
- { "Description", CONFIG_TYPE_STRING,
- offsetof(struct board, description),
- 0, member_size(struct board, description) },
- { "Restricted Posting", CONFIG_TYPE_BOOLEAN,
- offsetof(struct board, restricted_posting),
- 0, 0 },
- { "Restricted Viewing", CONFIG_TYPE_BOOLEAN,
- offsetof(struct board, restricted_viewing),
- 0, 0 },
- { "Days of Retention", CONFIG_TYPE_SHORT,
- offsetof(struct board, retention_days),
- 0, USHRT_MAX },
-};
-size_t nboard_fields = nitems(board_fields);
-
struct db * db_init(Str255 file, short vrefnum, struct bile *bile);
short db_migrate(struct db *tdb, short is_new);
void db_config_load(struct db *tdb);
-void db_boards_load(struct db *tdb);
struct db *
db_open(Str255 file, short vrefnum)
@@ -197,7 +175,7 @@ db_init(Str255 path, short vrefnum, struct bile *bile)
if (!was_new) {
db_config_load(tdb);
- db_boards_load(tdb);
+ db_cache_boards(tdb);
}
PtoCstr(fullpath);
@@ -233,6 +211,7 @@ db_migrate(struct db *tdb, short is_new)
{
struct user *user;
struct bile_object *bob;
+ struct db *olddb;
char *error;
char ver;
@@ -256,7 +235,11 @@ db_migrate(struct db *tdb, short is_new)
user->created_at = Time;
user_set_password(user, "p4ssw0rd");
user->is_sysop = DB_TRUE;
+ /* user_save assumes db is already set */
+ olddb = db;
+ db = tdb;
user_save(user);
+ db = olddb;
} else {
if (bile_read(tdb->bile, DB_VERS_RTYPE, 1, &ver, 1) != 1)
ver = 1;
@@ -307,46 +290,82 @@ db_config_load(struct db *tdb)
}
void
-db_boards_load(struct db *tdb)
+db_cache_boards(struct db *tdb)
{
- size_t n;
+ Str255 db_filename, board_filename;
+ size_t n, size;
struct bile_object *obj;
+ char *data = NULL;
if (tdb->boards) {
+ for (n = 0; n < tdb->nboards; n++) {
+ if (tdb->boards[n].bile)
+ bile_close(tdb->boards[n].bile);
+ }
free(tdb->boards);
- tdb->boards = NULL;
}
+
+ 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->nboards = bile_count_by_type(tdb->bile, DB_BOARD_RTYPE);
if (!tdb->nboards)
return;
-
tdb->boards = xmallocarray(tdb->nboards, sizeof(struct board));
for (n = 0; n < tdb->nboards; n++) {
obj = bile_get_nth_of_type(tdb->bile, n, DB_BOARD_RTYPE);
if (obj == NULL)
break;
+
+ size = bile_read_alloc(tdb->bile, DB_BOARD_RTYPE, obj->id,
+ &data);
+ bile_unmarshall_object(tdb->bile, board_object_fields,
+ nboard_object_fields, data, size, (char *)(&tdb->boards[n]));
+ free(data);
+
+ snprintf((char *)board_filename, sizeof(board_filename),
+ "%s:%ld.brd", db_filename, obj->id);
+ CtoPstr(board_filename);
+ tdb->boards[n].bile = bile_open(board_filename, tdb->bile->vrefnum);
+ if (tdb->boards[n].bile != NULL)
+ continue;
- bile_read(tdb->bile, DB_BOARD_RTYPE, obj->id,
- (char *)(&tdb->boards[n]), obj->size);
+ if (ask("Failed to open board bile %s (error %d), recreate it?",
+ PtoCstr(board_filename), bile_error(NULL)) == false)
+ exit(0);
+
+ CtoPstr(board_filename);
+ tdb->boards[n].bile = db_board_create(tdb, &tdb->boards[n]);
}
}
-void
+struct bile *
db_board_create(struct db *tdb, struct board *board)
{
Str255 db_filename, board_filename;
struct bile *board_bile;
+ size_t size;
+ short ret;
+ char *data;
- if (bile_write(tdb->bile, DB_BOARD_RTYPE, board->id,
- board, sizeof(struct board)) != sizeof(struct board))
+ ret = bile_marshall_object(tdb->bile, board_object_fields,
+ nboard_object_fields, board, &data, &size);
+ if (ret != 0 || size == 0) {
+ warn("db_board_create: failed to marshall object");
+ return;
+ }
+
+ if (bile_write(tdb->bile, DB_BOARD_RTYPE, board->id, data,
+ size) != size)
panic("save of new board 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 *)board_filename, sizeof(board_filename), "%s:%ld.brd",
@@ -358,6 +377,6 @@ db_board_create(struct db *tdb, struct board *board)
if (board_bile == NULL)
panic("failed creating new board bile at %s: %d",
PtoCstr(board_filename), bile_error(tdb->bile));
-
- db_boards_load(tdb);
+
+ return board_bile;
}
--- db.h Sun May 15 14:54:06 2022
+++ db.h Mon May 23 13:10:23 2022
@@ -41,13 +41,15 @@
#define DB_TEXT_ISSUE_ID 3
#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 BOARD_THREAD_RTYPE 'BDTH'
+#define BOARD_POST_RTYPE 'BDPS'
+
#include "subtext.h"
#include "settings.h"
#include "bile.h"
@@ -67,38 +69,6 @@ struct config {
extern struct struct_field config_fields[];
extern size_t nconfig_fields;
-struct user {
- /* keep this first so we can quickly read it during caching */
- char username_key[DB_USERNAME_LENGTH + 1];
-
- unsigned long id;
- char username[DB_USERNAME_LENGTH + 1];
- char password_hash[SHA256_DIGEST_STRING_LENGTH + 1]; /* 66 */
- char password_salt[SHA256_DIGEST_STRING_LENGTH + 1];
- unsigned long created_at;
- unsigned long last_seen_at;
- short is_sysop;
-};
-
-struct board {
- unsigned long id;
- char name[DB_BOARD_NAME_LENGTH];
- char description[DB_BOARD_DESCR_LENGTH];
- bool restricted_posting;
- bool restricted_viewing;
- unsigned short retention_days;
- unsigned long last_post_at;
- unsigned long post_count;
-};
-
-extern struct struct_field board_fields[];
-extern size_t nboard_fields;
-
-struct user_map {
- unsigned long id;
- char username_key[DB_USERNAME_LENGTH + 1];
-};
-
struct db {
struct bile *bile;
short fh;
@@ -114,6 +84,7 @@ struct db * db_open(Str255 file, short vrefnum);
struct db * db_create(void);
void db_close(struct db *tdb);
void db_config_save(struct db *tdb);
-void db_board_create(struct db *tdb, struct board *board);
+void db_cache_boards(struct db *tdb);
+struct bile * db_board_create(struct db *tdb, struct board *board);
#endif
--- mail.c Fri May 20 10:40:14 2022
+++ mail.c Sun May 22 21:56:17 2022
@@ -28,30 +28,31 @@
#include "util.h"
struct bile_object_field mail_object_fields[] = {
- { offsetof(struct private_message, recipient_user_id),
- member_size(struct private_message, recipient_user_id), -1 },
- { offsetof(struct private_message, id),
- member_size(struct private_message, id), -1 },
- { offsetof(struct private_message, time),
- member_size(struct private_message, time), -1 },
- { offsetof(struct private_message, read),
- member_size(struct private_message, read), -1 },
- { offsetof(struct private_message, sender_user_id),
- member_size(struct private_message, sender_user_id), -1 },
- { offsetof(struct private_message, subject_size),
- member_size(struct private_message, subject_size), -1 },
- { offsetof(struct private_message, subject),
- -1, offsetof(struct private_message, subject_size) },
- { offsetof(struct private_message, body_size),
- member_size(struct private_message, body_size), -1 },
- { offsetof(struct private_message, body),
- -1, offsetof(struct private_message, body_size) },
- { offsetof(struct private_message, parent_message_id),
- member_size(struct private_message, parent_message_id), -1 },
+ { offsetof(struct mail_message, recipient_user_id),
+ member_size(struct mail_message, recipient_user_id), -1 },
+ { offsetof(struct mail_message, id),
+ member_size(struct mail_message, id), -1 },
+ { offsetof(struct mail_message, time),
+ member_size(struct mail_message, time), -1 },
+ { offsetof(struct mail_message, read),
+ member_size(struct mail_message, read), -1 },
+ { offsetof(struct mail_message, sender_user_id),
+ member_size(struct mail_message, sender_user_id), -1 },
+ { offsetof(struct mail_message, subject_size),
+ member_size(struct mail_message, subject_size), -1 },
+ { offsetof(struct mail_message, subject),
+ -1, offsetof(struct mail_message, subject_size) },
+ { offsetof(struct mail_message, body_size),
+ member_size(struct mail_message, body_size), -1 },
+ { offsetof(struct mail_message, body),
+ -1, offsetof(struct mail_message, body_size) },
+ { offsetof(struct mail_message, parent_message_id),
+ member_size(struct mail_message, parent_message_id), -1 },
};
+size_t nmail_object_fields = nitems(mail_object_fields);
-void mail_free_message_strings(struct private_message *msg);
-short mail_save(struct session *s, struct private_message *msg);
+void mail_free_message_strings(struct mail_message *msg);
+short mail_save(struct session *s, struct mail_message *msg);
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);
@@ -61,7 +62,7 @@ short mail_get_message_id(struct session *s, size_t nm
short initial);
void
-mail_free_message_strings(struct private_message *msg)
+mail_free_message_strings(struct mail_message *msg)
{
if (msg->subject) {
free(msg->subject);
@@ -194,7 +195,7 @@ mail_compose(struct session *s, char *initial_to, char
char *initial_body)
{
struct user *to_user = NULL;
- struct private_message msg = { 0 };
+ struct mail_message msg = { 0 };
char *to_username = NULL, *tmp;
char c;
@@ -344,8 +345,8 @@ mail_list(struct session *s, bool sent, unsigned long
{
char time[24];
size_t n, size;
- struct private_message msg;
- struct user *user;
+ struct mail_message msg;
+ struct user_map *user;
char *data;
*nmsgs = mail_find_for_user_id(s->user->id, mail_ids);
@@ -362,11 +363,9 @@ mail_list(struct session *s, bool sent, unsigned long
&data);
bile_unmarshall_object(db->bile, mail_object_fields,
nitems(mail_object_fields), data, size, &msg);
- user = user_find(msg.sender_user_id);
+ user = user_find_username(msg.sender_user_id);
+ strftime(time, sizeof(time), "%m/%d", localtime(&msg.time));
- strftime(time, sizeof(time), "%Y-%m-%d %H:%M",
- localtime(&msg.time));
-
session_printf(s, "%s%c [%- 3ld] %s %- 10s {{#}}%- 40s%s\r\n",
msg.read ? "" : ansi(s, ANSI_BOLD, ANSI_END),
msg.read ? ' ' : 'N',
@@ -387,15 +386,15 @@ mail_read(struct session *s, unsigned long id)
{
char time[32];
size_t size;
- struct private_message msg;
- struct user *sender, *recipient;
+ struct mail_message msg;
+ struct user_map *sender, *recipient;
char *data;
size = bile_read_alloc(db->bile, DB_MESSAGE_RTYPE, id, &data);
bile_unmarshall_object(db->bile, mail_object_fields,
nitems(mail_object_fields), data, size, &msg);
- sender = user_find(msg.sender_user_id);
- recipient = user_find(msg.recipient_user_id);
+ sender = user_find_username(msg.sender_user_id);
+ recipient = user_find_username(msg.recipient_user_id);
strftime(time, sizeof(time), "%Y-%m-%d %H:%M:%S",
localtime(&msg.time));
@@ -447,7 +446,7 @@ delete_done:
void
mail_mark_unread(struct session *s, unsigned long idx)
{
- struct private_message msg;
+ struct mail_message msg;
unsigned long *mail_ids;
size_t nmsgs, size;
char *data;
@@ -479,7 +478,7 @@ unread_done:
}
short
-mail_save(struct session *s, struct private_message *msg)
+mail_save(struct session *s, struct mail_message *msg)
{
size_t size;
char *data;
--- mail.h Fri Feb 18 14:22:59 2022
+++ mail.h Sun May 22 21:24:22 2022
@@ -20,7 +20,7 @@
#include "bile.h"
#include "session.h"
-struct private_message {
+struct mail_message {
/* key */
unsigned long recipient_user_id;
--- main.c Mon May 9 15:39:21 2022
+++ main.c Mon May 23 13:04:06 2022
@@ -91,8 +91,8 @@ main(void)
_atexit(handle_exit);
logger = logger_init();
- logger_printf(logger, "[db] Updating user cache");
- user_update_cache_map();
+ logger_printf(logger, "[db] Updating username cache");
+ user_cache_usernames();
if (db->config.telnet_port)
telnet_init();
--- session.h Fri May 20 10:38:07 2022
+++ session.h Mon May 23 11:28:56 2022
@@ -21,6 +21,7 @@
#include "db.h"
#include "uthread.h"
+#include "user.h"
enum session_input_state {
SESSION_INPUT_NONE,
--- sysop.c Sun May 15 21:42:53 2022
+++ sysop.c Mon May 23 13:00:44 2022
@@ -14,12 +14,13 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <string.h>
+
#include "subtext.h"
+#include "board.h"
#include "session.h"
#include "sysop.h"
-#include <string.h>
-
void sysop_edit_boards(struct session *s);
void
@@ -98,12 +99,13 @@ sysop_edit_boards(struct session *s)
{ 'q', "QqXx", "Return to sysop menu" },
{ '?', "?", "List menu options" },
};
+ char prompt[30];
struct session_menu_option *dopts = NULL, *opt;
struct board *board, *new_board;
- size_t n;
+ struct bile *new_board_bile;
+ size_t n, size;
short ret;
- char c;
- char prompt[30];
+ char c, *data = NULL;
bool show_help = true;
bool done = false;
bool found = false;
@@ -144,7 +146,11 @@ sysop_edit_boards(struct session *s)
free(board);
continue;
}
- db_board_create(db, new_board);
+
+ new_board_bile = db_board_create(db, new_board);
+ bile_close(new_board_bile);
+ db_cache_boards(db);
+
session_log(s, "Created new board %ld: %s", new_board->id,
new_board->name);
free(board);
@@ -174,10 +180,17 @@ sysop_edit_boards(struct session *s)
if (ret != 0)
continue;
memcpy(&db->boards[n], new_board, sizeof(struct board));
+
+ ret = bile_marshall_object(db->bile, board_object_fields,
+ nboard_object_fields, &db->boards[n], &data, &size);
+ if (ret != 0 || size == 0)
+ panic("db_board_create: failed to marshall object");
+
if (bile_write(db->bile, DB_BOARD_RTYPE, new_board->id,
- new_board, sizeof(struct board)) != sizeof(struct board))
- panic("save of board %ld failed: %d",
- new_board->id, bile_error(db->bile));
+ data, size) != size)
+ panic("save of board failed: %d", bile_error(db->bile));
+ free(data);
+
session_log(s, "Saved changes to board %ld: %s",
new_board->id, new_board->name);
free(new_board);
--- user.c Sun May 15 22:23:17 2022
+++ user.c Mon May 23 13:19:02 2022
@@ -44,8 +44,9 @@ static char *BANNED_USERNAMES[] = {
};
void
-user_update_cache_map(void)
+user_cache_usernames(void)
{
+ struct user user;
struct user_map *muser;
struct bile_object *o;
size_t nuser, len;
@@ -61,13 +62,14 @@ user_update_cache_map(void)
muser = &db->user_map[nuser];
muser->id = o->id;
- /* the lowercased username should be the first bytes of each rec */
- len = bile_read(db->bile, DB_USER_RTYPE, o->id,
- muser->username_key, sizeof(muser->username_key));
- if (len != sizeof(muser->username_key))
+ len = bile_read(db->bile, DB_USER_RTYPE, o->id, (char *)&user,
+ sizeof(user));
+ if (len != sizeof(user))
panic("user_update_cache_map: can't read user %lu: %d", o->id,
bile_error(db->bile));
-
+
+ strncpy(muser->username, user.username, sizeof(muser->username));
+
free(o);
nuser++;
}
@@ -83,18 +85,12 @@ user_save(struct user *user)
user->created_at = Time;
}
- /* update username key */
- memset(user->username_key, 0, sizeof(user->username_key));
- len = strlen(user->username);
- for (n = 0; n < len; n++)
- user->username_key[n] = tolower(user->username[n]);
-
len = bile_write(db->bile, DB_USER_RTYPE, user->id,
user, sizeof(struct user));
if (len != sizeof(struct user))
panic("user_save: failed to write: %d", bile_error(db->bile));
- user_update_cache_map();
+ user_cache_usernames();
}
struct user *
@@ -121,23 +117,33 @@ user_find_by_username(const char *username)
{
struct user suser;
struct user_map *muser;
- char lusername[DB_USERNAME_LENGTH + 1] = { 0 };
short n;
size_t len;
len = strlen(username);
- if (len > sizeof(suser.username_key))
+ if (len > sizeof(suser.username))
return NULL;
- /* downcase username and find it in the cache map */
- for (n = 0; n < len; n++)
- lusername[n] = tolower(username[n]);
-
for (n = 0; n < db->nusers; n++) {
muser = &db->user_map[n];
- if (strcmp(muser->username_key, lusername) == 0)
+ if (strcasecmp(muser->username, username) == 0)
return user_find(muser->id);
+ }
+
+ return NULL;
+}
+
+struct user_map *
+user_find_username(unsigned long id)
+{
+ struct user_map *muser;
+ size_t n;
+
+ for (n = 0; n < db->nusers; n++) {
+ muser = &db->user_map[n];
+ if (muser->id == id)
+ return muser;
}
return NULL;
--- user.h Wed Apr 20 20:24:01 2022
+++ user.h Mon May 23 12:59:50 2022
@@ -24,10 +24,26 @@
#define GUEST_USERNAME "guest"
-void user_update_cache_map(void);
+struct user {
+ unsigned long id;
+ char username[DB_USERNAME_LENGTH + 1];
+ char password_hash[SHA256_DIGEST_STRING_LENGTH + 1]; /* 66 */
+ char password_salt[SHA256_DIGEST_STRING_LENGTH + 1];
+ unsigned long created_at;
+ unsigned long last_seen_at;
+ short is_sysop;
+};
+
+struct user_map {
+ unsigned long id;
+ char username[DB_USERNAME_LENGTH + 1];
+};
+
+void user_cache_usernames(void);
void user_save(struct user *user);
struct user * user_find(unsigned long id);
struct user * user_find_by_username(const char *username);
+struct user_map * user_find_username(unsigned long id);
short user_authenticate(struct user *user, const char *password);
void user_set_password(struct user *user, const char *password);
short user_valid_username(char *username, char **error);
--- user_settings.c Sat May 14 21:49:20 2022
+++ user_settings.c Fri May 20 10:42:25 2022
@@ -87,7 +87,7 @@ get_terminal_size:
s->terminal_lines);
session_flush(s);
- tsize = session_field_input(s, 10, 10, NULL, 0);
+ tsize = session_field_input(s, 10, 10, NULL, false, 0);
if (tsize == NULL)
return;
session_output(s, "\r\n", 2);
@@ -132,7 +132,7 @@ user_settings_password(struct session *s)
for (;;) {
session_output_template(s, "{{B}}New Password:{{/B}} ");
session_flush(s);
- password = session_field_input(s, 64, 64, NULL, '*');
+ password = session_field_input(s, 64, 64, NULL, false, '*');
session_output(s, "\r\n", 2);
session_flush(s);
@@ -148,7 +148,7 @@ user_settings_password(struct session *s)
session_output_template(s, "{{B}}New Password (again):{{/B}} ");
session_flush(s);
- password_confirm = session_field_input(s, 64, 64, NULL, '*');
+ password_confirm = session_field_input(s, 64, 64, NULL, false, '*');
session_output(s, "\r\n", 2);
session_flush(s);