From c47ec545d87e622aa950e653e4f91721d79bb049 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 21 May 2018 13:58:47 +0200 Subject: Add command to change avatar and channel name Fix bug where application crashes when deleting message, improve url parsing for messages --- src/main.cpp | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 171 insertions(+), 3 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 8c13c80..ecfd058 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,6 +47,65 @@ static void channelChangeUserNickname(Channel *channel, const StringView data, c // We dont care if there is more data to read (malicious packet), we already got all the data we need } +static bool looksLikeUrl(const string &str) +{ + if(str.find('.') == string::npos) + return false; + + if(str.size() >= 7 && strncmp(str.c_str(), "http://", 7) == 0) + return true; + + if(str.size() >= 8 && strncmp(str.c_str(), "https://", 8) == 0) + return true; + + return false; +} + +static void channelChangeUserAvatar(Channel *channel, const StringView data, const odhtdb::Signature::PublicKey &userPublicKey) +{ + auto user = channel->getUserByPublicKey(userPublicKey); + if(!user) + { + fprintf(stderr, "Avatar change: user with public key %s not found in channel %s\n", userPublicKey.toString().c_str(), channel->getName().c_str()); + return; + } + + sibs::SafeDeserializer deserializer((const u8*)data.data, data.size); + u16 avatarLength = deserializer.extract(); + if(avatarLength >= 10 && avatarLength <= 512) + { + string avatarUrl; + avatarUrl.resize(avatarLength); + deserializer.extract((u8*)&avatarUrl[0], avatarLength); + if(looksLikeUrl(avatarUrl)) + { + user->avatarUrl = move(avatarUrl); + } + } + // We dont care if there is more data to read (malicious packet), we already got all the data we need +} + +static void channelChangeChannelName(Channel *channel, const StringView data, const odhtdb::Signature::PublicKey &userPublicKey) +{ + auto user = channel->getUserByPublicKey(userPublicKey); + if(!user) + { + fprintf(stderr, "Channel change name: user with public key %s not found in channel %s\n", userPublicKey.toString().c_str(), channel->getName().c_str()); + return; + } + + sibs::SafeDeserializer deserializer((const u8*)data.data, data.size); + u16 channelNameLength = deserializer.extract(); + if(channelNameLength > 0 && channelNameLength <= 32) + { + string channelName; + channelName.resize(channelNameLength); + deserializer.extract((u8*)&channelName[0], channelNameLength); + channel->setNameLocally(channelName); + } + // We dont care if there is more data to read (malicious packet), we already got all the data we need +} + static void channelAddStoredMessage(Channel *channel, const odhtdb::Hash &requestHash, const odhtdb::Signature::PublicKey &creatorPublicKey, const StringView decryptedObject, u64 timestamp) { User *user = channel->getUserByPublicKey(creatorPublicKey); @@ -97,6 +156,30 @@ static void channelAddStoredMessage(Channel *channel, const odhtdb::Hash &reques } break; } + case ChannelDataType::CHANGE_AVATAR: + { + try + { + channelChangeUserAvatar(channel, decryptedData, creatorPublicKey); + } + catch(sibs::DeserializeException &e) + { + fprintf(stderr, "Failed to deserialize avatar change\n"); + } + break; + } + case ChannelDataType::CHANGE_CHANNEL_NAME: + { + try + { + channelChangeChannelName(channel, decryptedData, creatorPublicKey); + } + catch(sibs::DeserializeException &e) + { + fprintf(stderr, "Failed to deserialize channel name change\n"); + } + break; + } default: fprintf(stderr, "Got unexpected channel data type: %u\n", channelDataType); break; @@ -242,9 +325,9 @@ int main(int argc, char **argv) }; database = new odhtdb::Database("bootstrap.ring.cx", 4222, Cache::getDchatDir(), callbackFuncs); - auto addSystemMessage = [&lastFocusedTimer](const std::string &msg) + auto addSystemMessage = [&lastFocusedTimer](const std::string &msg, bool plainText = true) { - Channel::getCurrent()->addLocalMessage(msg, Channel::getCurrent()->getSystemUser()); + Channel::getCurrent()->addSystemMessage(msg, plainText); lastFocusedTimer.restart(); }; @@ -634,7 +717,7 @@ int main(int argc, char **argv) msg += " "; msg += bind.second; } - addSystemMessage(msg); + addSystemMessage(msg, false); }); // Change nick of current user in current channel @@ -673,11 +756,96 @@ int main(int argc, char **argv) addSystemMessage(msg); }); + // Change avatar of current user in current channel + Command::add("avatar", [&loggedIn, &offlineChannel, addSystemMessage](const vector &args) + { + if(args.size() != 1) + { + string errMsg = "Expected 1 argument for command avatar, got "; + errMsg += to_string(args.size()); + errMsg += " argument(s)"; + addSystemMessage(errMsg); + return; + } + + if(!loggedIn) + { + addSystemMessage("You need to be logged in to change your avatar"); + return; + } + + if(Channel::getCurrent() == &offlineChannel) + { + addSystemMessage("You need to be in a channel to change your avatar"); + return; + } + + if(args[0].size() < 10 || args[0].size() > 512) + { + addSystemMessage("Invalid avatar url size, expected to be between 10 and 512 bytes"); + return; + } + + if(looksLikeUrl(args[0])) + { + Channel::getCurrent()->setAvatar(args[0]); + addSystemMessage("Your avatar has been changed (Note: max avatar size is 1 Mb, if your avatar is larger then it will not be visible)"); + } + else + { + addSystemMessage("Avatar url needs to start with either http:// or https:// and include a dot"); + } + }); + + // Change name of the current channel + Command::add("channelname", [&loggedIn, &offlineChannel, addSystemMessage](const vector &args) + { + if(args.size() != 1) + { + string errMsg = "Expected 1 argument for command channelname, got "; + errMsg += to_string(args.size()); + errMsg += " argument(s)"; + addSystemMessage(errMsg); + return; + } + + if(!loggedIn) + { + addSystemMessage("You need to be logged in to change channel name"); + return; + } + + if(Channel::getCurrent() == &offlineChannel) + { + addSystemMessage("You need to be in a channel to change channel name"); + return; + } + + if(args[0].size() == 0 || args[0].size() > 32) + { + addSystemMessage("Channel name has to be between 1 and 32 bytes long"); + return; + } + + Channel::getCurrent()->setName(args[0]); + string msg = "Channel name has been changed to "; + msg += args[0]; + addSystemMessage(msg); + }); + Command::add("clearcache", [&database](const vector &args) { printf("Cleared cache (%d bytes)\n", database->clearCache()); }); + string commandsMsg = "Available commands: "; + for(const auto &commandIt : Command::getCommands()) + { + commandsMsg += "\n/"; + commandsMsg += commandIt.first; + } + addSystemMessage(commandsMsg); + sf::Clock frameTimer; while (window.isOpen()) -- cgit v1.2.3