aboutsummaryrefslogtreecommitdiff
path: root/command.c
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2020-07-28 16:05:47 +0200
committerTom Smeding <tom.smeding@gmail.com>2020-07-28 16:07:43 +0200
commit1d28744e532ac73ddff0c6fa829949497b25d4b6 (patch)
tree78cf2b126a75b39dc5a98b6bde5f0a7eb2e2c8ec /command.c
parenta9413077b5839b98fc791fcadbae4f8fa1c3743f (diff)
server: Implement get_message
Diffstat (limited to 'command.c')
-rw-r--r--command.c57
1 files changed, 52 insertions, 5 deletions
diff --git a/command.c b/command.c
index ba8727e..ca70d76 100644
--- a/command.c
+++ b/command.c
@@ -257,9 +257,13 @@ static struct cmd_retval cmd_send(struct conn_data *data,const char *tag,const c
net_send_error(data->fd,tag,"Not in that room");
return RET_OK;
}
- if(replyid>=0&&!db_message_exists(roomid,replyid)){
- net_send_error(data->fd,tag,"Replied-to message not found");
- return RET_OK;
+ if(replyid>=0){
+ struct db_message msg=db_get_message(replyid);
+ if(msg.msgid==-1){
+ net_send_error(data->fd,tag,"Replied-to message not found");
+ return RET_OK;
+ }
+ db_nullify_message(msg);
}
i64 timestamp=make_timestamp();
@@ -361,6 +365,48 @@ static struct cmd_retval cmd_history_before(struct conn_data *data,const char *t
return history_cmd_helper(data,tag,args,"history_before",beforeid);
}
+static struct cmd_retval cmd_get_message(struct conn_data *data, const char *tag, const char **args) {
+ i64 msgid;
+ if (!parse_i64(args[0], &msgid)) {
+ debug("Connection fd=%d sent an invalid number for 'get_message': '%s'",
+ data->fd, args[0]);
+ return RET_CLOSE(true);
+ }
+
+ if (data->userid == -1) {
+ net_send_error(data->fd, tag, "Not logged in");
+ return RET_OK;
+ }
+
+ struct db_message msg = db_get_message(msgid);
+ if (msg.msgid == -1) {
+ net_send_error(data->fd, tag, "Message not found");
+ return RET_OK;
+ }
+
+ if (!db_is_member(msg.roomid, data->userid)) {
+ db_nullify_message(msg);
+ // Don't disclose that the message actually exists elsewhere
+ net_send_error(data->fd, tag, "Message not found");
+ return RET_OK;
+ }
+
+ char *roomname = db_get_roomname(msg.roomid);
+ char *username = db_get_username(msg.userid);
+
+ char *buf = NULL;
+ i64 len = asprintf(&buf, "%s message %s %s %" PRIi64 " %" PRIi64 " %" PRIi64 " %s\n",
+ tag, roomname, username, msg.timestamp, msg.msgid, msg.replyid, msg.message);
+ free(roomname);
+ free(username);
+
+ bool closed = net_send_raw_text(data->fd, buf, len);
+ free(buf);
+
+ db_nullify_message(msg);
+ return RET_CLOSE(closed);
+}
+
static struct cmd_retval cmd_ping(struct conn_data *data,const char *tag,const char **args){
(void)args;
return RET_CLOSE(net_send_pong(data->fd,tag));
@@ -419,8 +465,8 @@ struct cmd_info{
// Use CommandHash.hs to re-generate this perfect hash function for a different
// list of commands.
-#define COMMAND_HASH_MODULUS 31
-#define COMMAND_HASH(cmd0, len) ((cmd0 + 6 * len) % COMMAND_HASH_MODULUS)
+#define COMMAND_HASH_MODULUS 34
+#define COMMAND_HASH(cmd0, len) ((4 * cmd0 + 7 * len) % COMMAND_HASH_MODULUS)
#define COMMAND_ENTRY(cmd0, cmd, nargs, longlast, handler) \
[COMMAND_HASH(cmd0, strlen(cmd))] = {cmd, nargs, longlast, handler}
@@ -439,6 +485,7 @@ static const struct cmd_info commands[COMMAND_HASH_MODULUS] = {
COMMAND_ENTRY('s', "send", 3, true, cmd_send),
COMMAND_ENTRY('h', "history", 2, false, cmd_history),
COMMAND_ENTRY('h', "history_before", 3, false, cmd_history_before),
+ COMMAND_ENTRY('g', "get_message", 1, false, cmd_get_message),
COMMAND_ENTRY('p', "ping", 0, false, cmd_ping),
COMMAND_ENTRY('i', "is_online", 1, false, cmd_is_online),
COMMAND_ENTRY('f', "firebase_token", 1, false, cmd_firebase_token),