aboutsummaryrefslogtreecommitdiff
path: root/command.c
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2020-07-30 20:45:54 +0200
committerTom Smeding <tom.smeding@gmail.com>2020-07-30 20:45:54 +0200
commit6244f4a65aa391cae85bfc6930589ba7feaa536e (patch)
treed73c2a136bcfd124e8051eb09268af8fedfdbd3b /command.c
parentdd40033d6d6358da8d065db04b3bfbcd834202ff (diff)
parent79c8ffd915115728070339f30d57a3a3e31bd322 (diff)
Merge branch 'version2'
Diffstat (limited to 'command.c')
-rw-r--r--command.c82
1 files changed, 72 insertions, 10 deletions
diff --git a/command.c b/command.c
index 8fa343d..ca70d76 100644
--- a/command.c
+++ b/command.c
@@ -232,8 +232,18 @@ static struct cmd_retval cmd_send(struct conn_data *data,const char *tag,const c
return RET_OK;
}
userdata_mark_active(data->userid,data->fd,true);
+
const char *roomname=args[0];
- const char *message=args[1];
+
+ i64 replyid;
+ if(!parse_i64(args[1],&replyid)){
+ debug("Connection fd=%d sent an invalid number for 'send': '%s'",
+ data->fd,args[1]);
+ return RET_CLOSE(true);
+ }
+
+ const char *message=args[2];
+
if(strlen(message)>MAX_MESSAGE_LEN){
net_send_error(data->fd,tag,"Message too long");
return RET_OK;
@@ -247,17 +257,26 @@ 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){
+ 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();
- i64 msgid=db_create_message(roomid,data->userid,make_timestamp(),message);
+ i64 msgid=db_create_message(roomid,data->userid,make_timestamp(),replyid,message);
bool closed=net_send_number(data->fd,tag,msgid);
char *pushbuf=NULL;
char *username=db_get_username(data->userid);
- i64 pushbuflen=asprintf(&pushbuf,"_push message %s %s %" PRIi64 " %" PRIi64 " %s\n",
- roomname,username,timestamp,msgid,message);
+ i64 pushbuflen=asprintf(&pushbuf,
+ "_push message %s %s %" PRIi64 " %" PRIi64 " %" PRIi64 " %s\n",
+ roomname,username,timestamp,msgid,replyid,message);
- event_emit_message(timestamp,message,username,roomname);
+ event_emit_message(timestamp,message,username,roomname,replyid);
firebase_send_message(roomname,roomid,username,message);
free(username);
@@ -317,9 +336,9 @@ static struct cmd_retval history_cmd_helper(
for(i64 i=ml.count-1;i>=0;i--){
char *username=db_get_username(ml.list[i].userid);
- len=asprintf(&buf,"%s history_message %" PRIi64 " %s %s %" PRIi64 " %" PRIi64 " %s\n",
+ len=asprintf(&buf,"%s history_message %" PRIi64 " %s %s %" PRIi64 " %" PRIi64 " %" PRIi64 " %s\n",
tag,ml.count-1-i,roomname,username,ml.list[i].timestamp,
- ml.list[i].msgid,ml.list[i].message);
+ ml.list[i].msgid,ml.list[i].replyid,ml.list[i].message);
free(username);
closed=net_send_raw_text(data->fd,buf,len);
free(buf);
@@ -346,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));
@@ -404,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}
@@ -421,9 +482,10 @@ static const struct cmd_info commands[COMMAND_HASH_MODULUS] = {
COMMAND_ENTRY('l', "list_members", 1, false, cmd_list_members),
COMMAND_ENTRY('c', "create_room", 0, false, cmd_create_room),
COMMAND_ENTRY('i', "invite", 2, false, cmd_invite),
- COMMAND_ENTRY('s', "send", 2, true, cmd_send),
+ 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),