Fix deaf/mute issues. Fix channel moves by admin and admin enter channels with password.
[umurmur.git] / src / messagehandler.c
index 1e7a5566ab30e817fe99bbda820ea9b402332634..fc489fd392e7e1eba7fe4ef011327b2331f5d25c 100644 (file)
@@ -40,6 +40,7 @@
 #include "channel.h"
 #include "conf.h"
 #include "voicetarget.h"
+#include "ban.h"
 
 #define MAX_TEXT 512
 #define MAX_USERNAME 128
@@ -187,7 +188,7 @@ void Mh_handle_message(client_t *client, message_t *msg)
                if (strlen(getStrConf(ADMIN_PASSPHRASE)) > 0 &&
                    Client_token_match(client, getStrConf(ADMIN_PASSPHRASE))) {
                        client->isAdmin = true;
-                       Log_info("User is admin");
+                       Log_info_client(client, "User provided admin password");
                }
                
                /* Setup UDP encryption */
@@ -297,15 +298,22 @@ void Mh_handle_message(client_t *client, message_t *msg)
                        sendmsg->payload.userState->has_channel_id = true;
                        sendmsg->payload.userState->channel_id = ((channel_t *)client_itr->channel)->id;
 
-                       /* Only self_mute/deaf supported */
-                       if (client_itr->deaf) {
+                       if (client_itr->self_deaf) {
                                sendmsg->payload.userState->has_self_deaf = true;
                                sendmsg->payload.userState->self_deaf = true;
                        }
-                       if (client_itr->mute) {
+                       if (client_itr->self_mute) {
                                sendmsg->payload.userState->has_self_mute = true;
                                sendmsg->payload.userState->self_mute = true;
                        }
+                       if (client_itr->deaf) {
+                               sendmsg->payload.userState->has_deaf = true;
+                               sendmsg->payload.userState->deaf = true;
+                       }
+                       if (client_itr->mute) {
+                               sendmsg->payload.userState->has_mute = true;
+                               sendmsg->payload.userState->mute = true;
+                       }
                        if (client_itr->recording) {
                                sendmsg->payload.userState->has_recording = true;
                                sendmsg->payload.userState->recording = true;
@@ -434,18 +442,18 @@ void Mh_handle_message(client_t *client, message_t *msg)
                        if (!target->mute) {
                                msg->payload.userState->has_deaf = true;
                                msg->payload.userState->deaf = false;
-                               client->deaf = false;
+                               target->deaf = false;
                        }
                }
                if (msg->payload.userState->has_self_deaf) {
-                       client->deaf = msg->payload.userState->self_deaf;
+                       client->self_deaf = msg->payload.userState->self_deaf;
                }
                if (msg->payload.userState->has_self_mute) {
-                       client->mute = msg->payload.userState->self_mute;
-                       if (!client->mute) {
+                       client->self_mute = msg->payload.userState->self_mute;
+                       if (!client->self_mute) {
                                msg->payload.userState->has_self_deaf = true;
                                msg->payload.userState->self_deaf = false;
-                               client->deaf = false;
+                               client->self_deaf = false;
                        }
                }
                if (msg->payload.userState->has_recording &&
@@ -474,16 +482,22 @@ void Mh_handle_message(client_t *client, message_t *msg)
                }
                if (msg->payload.userState->has_channel_id) {
                        int leave_id;
-                       channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, client);
+                       channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, target);
                        
                        if (chjoin_rc != CHJOIN_OK) {
-                               if (chjoin_rc == CHJOIN_WRONGPW) {
+                               if (chjoin_rc == CHJOIN_WRONGPW && target == client && !client->isAdmin) {
                                        sendPermissionDenied(client, "Wrong channel password");
+                                       break;
                                }
-                               break;
+                               /* Tricky one: if user hasn't the password, but is moved to the channel by admin then let
+                                * the user in. Also let admin user in regardless of pchannel password.
+                                * Take no action on other errors.
+                                */
+                               else if (!(chjoin_rc == CHJOIN_WRONGPW && (target != client || client->isAdmin)))
+                                       break;
                        }
                        
-                       leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
+                       leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, target);
                        if (leave_id > 0) {
                                Log_debug("Removing channel ID %d", leave_id);
                                sendmsg = Msg_create(ChannelRemove);
@@ -627,6 +641,8 @@ void Mh_handle_message(client_t *client, message_t *msg)
                
                if (!getBoolConf(ALLOW_TEXTMESSAGE))
                        msg->payload.permissionQuery->permissions &= ~PERM_TEXTMESSAGE;
+               if (!getBoolConf(ENABLE_BAN))
+                       msg->payload.permissionQuery->permissions &= ~PERM_BAN;
                
                Client_send_message(client, msg);
                break;
@@ -800,6 +816,7 @@ void Mh_handle_message(client_t *client, message_t *msg)
                        memset(sendmsg->payload.userStats->address.data, 0, 16);
                        /* ipv4 representation as ipv6 address. Supposedly correct. */
                        memcpy(&sendmsg->payload.userStats->address.data[12], &target->remote_tcp.sin_addr, 4);
+                       memset(&sendmsg->payload.userStats->address.data[10], 0xff, 2); /* IPv4 */
                        sendmsg->payload.userStats->address.len = 16;
                }
                /* BW */
@@ -835,9 +852,13 @@ void Mh_handle_message(client_t *client, message_t *msg)
                msg->payload.userRemove->actor = client->sessionId;
 
                if (msg->payload.userRemove->has_ban && msg->payload.userRemove->ban) {
-                       Ban_UserBan(target, msg->payload.userRemove->reason);
+                       if (!getBoolConf(ENABLE_BAN))
+                               sendPermissionDenied(client, "Permission denied");
+                       else
+                               Ban_UserBan(target, msg->payload.userRemove->reason);
                } else {
-                       Log_info("User kicked");
+                       Log_info_client(target, "User kicked. Reason: '%s'",
+                                       strlen(msg->payload.userRemove->reason) == 0 ? "N/A" : msg->payload.userRemove->reason);
                }
                /* Re-use message */
                Msg_inc_ref(msg);
@@ -845,13 +866,32 @@ void Mh_handle_message(client_t *client, message_t *msg)
                Client_send_message_except(NULL, msg);
                Client_close(target);
                break;
+       case BanList:
+               /* Only admin can issue this */
+               if (!client->isAdmin) {
+                       sendPermissionDenied(client, "Permission denied");
+                       break;
+               }
+               if (!getBoolConf(ENABLE_BAN)) {
+                       sendPermissionDenied(client, "Permission denied");
+                       break;
+               }
+               if (msg->payload.banList->has_query && msg->payload.banList->query) {
+                       /* Create banlist message and add banentrys */
+                       sendmsg = Ban_getBanList();
+                       Client_send_message(client, sendmsg);
+               } else {
+                       /* Clear banlist and set the new one */
+                       Ban_clearBanList();
+                       Ban_putBanList(msg, msg->payload.banList->n_bans);
+               }
+               break;
                
                /* Permission denied for all these messages. Not implemented. */
        case ChannelRemove:
        case ContextAction:
        case ContextActionAdd:
        case ACL:
-       case BanList:
        case UserList:
        case QueryUsers:
                sendPermissionDenied(client, "Not supported by uMurmur");