diff options
author | Tom Smeding <tom.smeding@gmail.com> | 2020-07-30 20:45:54 +0200 |
---|---|---|
committer | Tom Smeding <tom.smeding@gmail.com> | 2020-07-30 20:45:54 +0200 |
commit | 6244f4a65aa391cae85bfc6930589ba7feaa536e (patch) | |
tree | d73c2a136bcfd124e8051eb09268af8fedfdbd3b /command.c | |
parent | dd40033d6d6358da8d065db04b3bfbcd834202ff (diff) | |
parent | 79c8ffd915115728070339f30d57a3a3e31bd322 (diff) |
Merge branch 'version2'
Diffstat (limited to 'command.c')
-rw-r--r-- | command.c | 82 |
1 files changed, 72 insertions, 10 deletions
@@ -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), |