Example #1
0
bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload) {
	if (CONFIG_STRING(m_config, "service.protocol") == "irc") {
		Swift::GetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify);
		return true;
	}

	std::string barejid = from.toBare().toString();

// 	AbstractUser *user = m_component->userManager()->getUserByJID(barejid);
	if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) {
		std::list<std::string> const &x = CONFIG_LIST(m_config,"service.allowed_servers");
		if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) {
// 			Log("UserRegistration", "This user has no permissions to register an account");
			Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify);
			return true;
		}
	}

	UserInfo res;
	bool registered = m_storageBackend->getUser(barejid, res);

	std::string encoding;
	std::string language;

	Form::ref form = payload->getForm();
	if (form) {
		const std::vector<FormField::ref> fields = form->getFields();
		for (std::vector<FormField::ref>::const_iterator it = fields.begin(); it != fields.end(); it++) {
			TextSingleFormField::ref textSingle = boost::dynamic_pointer_cast<TextSingleFormField>(*it);
			if (textSingle) {
				if (textSingle->getName() == "username") {
					payload->setUsername(textSingle->getValue());
				}
				else if (textSingle->getName() == "encoding") {
					encoding = textSingle->getValue();
				}
				continue;
			}

			TextPrivateFormField::ref textPrivate = boost::dynamic_pointer_cast<TextPrivateFormField>(*it);
			if (textPrivate) {
				if (textPrivate->getName() == "password") {
					payload->setPassword(textPrivate->getValue());
				}
				continue;
			}

			ListSingleFormField::ref listSingle = boost::dynamic_pointer_cast<ListSingleFormField>(*it);
			if (listSingle) {
				if (listSingle->getName() == "language") {
					language = listSingle->getValue();
				}
				continue;
			}

			BooleanFormField::ref boolean = boost::dynamic_pointer_cast<BooleanFormField>(*it);
			if (boolean) {
				if (boolean->getName() == "unregister") {
					if (boolean->getValue()) {
						payload->setRemove(true);
					}
				}
				continue;
			}
		}
	}

	if (payload->isRemove()) {
		unregisterUser(barejid);
		Swift::SetResponder<Swift::InBandRegistrationPayload>::sendResponse(from, id, InBandRegistrationPayload::ref());
		return true;
	}

	if (!payload->getUsername() || !payload->getPassword()) {
		Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
		return true;
	}

	// Register or change password
	if (payload->getUsername()->empty() ||
		(payload->getPassword()->empty() && CONFIG_STRING(m_config, "service.protocol") != "twitter" && CONFIG_STRING(m_config, "service.protocol") != "bonjour")
// 		|| localization.getLanguages().find(language) == localization.getLanguages().end()
	)
	{
		Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
		return true;
	}

	if (CONFIG_STRING(m_config, "service.protocol") == "xmpp") {
		// User tries to register himself.
		if ((Swift::JID(*payload->getUsername()).toBare() == from.toBare())) {
			Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
			return true;
		}

		// User tries to register someone who's already registered.
		UserInfo user_row;
		bool registered = m_storageBackend->getUser(Swift::JID(*payload->getUsername()).toBare().toString(), user_row);
		if (registered) {
			Swift::SetResponder<Swift::InBandRegistrationPayload>::sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
			return true;
		}
	}

	std::string username = *payload->getUsername();
// 	m_component->protocol()->prepareUsername(username);

	std::string newUsername(username);
	if (!CONFIG_STRING(m_config, "registration.username_mask").empty()) {
		newUsername = CONFIG_STRING(m_config, "registration.username_mask");
// 		replace(newUsername, "$username", username.c_str());
	}

// 	if (!m_component->protocol()->isValidUsername(newUsername)) {
// 		Log("UserRegistration", "This is not valid username: "******"registration.reg_allowed_usernames").empty() &&
// 		!g_regex_match_simple(CONFIG_STRING(m_config, "registration.reg_allowed_usernames"), newUsername.c_str(),(GRegexCompileFlags) (G_REGEX_CASELESS | G_REGEX_EXTENDED), (GRegexMatchFlags) 0)) {
// 		Log("UserRegistration", "This is not valid username: "******"UserRegistration", "changing user password: "******", " << username);
		res.jid = barejid;
		res.password = *payload->getPassword();
		res.language = language;
		res.encoding = encoding;
		m_storageBackend->setUser(res);
		onUserUpdated(res);
	}

	Swift::SetResponder<Swift::InBandRegistrationPayload>::sendResponse(from, id, InBandRegistrationPayload::ref());
	return true;
}
Example #2
0
bool GlooxRegisterHandler::handleIq(const Tag *iqTag) {
	Log("GlooxRegisterHandler", iqTag->findAttribute("from") << ": iq:register received (" << iqTag->findAttribute("type") << ")");

	JID from(iqTag->findAttribute("from"));

	if (CONFIG().protocol == "irc") {
		sendError(400, "bad-request", iqTag);
		return false;
	}
	
	AbstractUser *user = Transport::instance()->userManager()->getUserByJID(from.bare());
	if (!Transport::instance()->getConfiguration().enable_public_registration) {
		std::list<std::string> const &x = Transport::instance()->getConfiguration().allowedServers;
		if (std::find(x.begin(), x.end(), from.server()) == x.end()) {
			Log("GlooxRegisterHandler", "This user has no permissions to register an account");
			sendError(400, "bad-request", iqTag);
			return false;
		}
	}

	const char *_language = user ? user->getLang() : Transport::instance()->getConfiguration().language.c_str();

	// send registration form
	if (iqTag->findAttribute("type") == "get") {
		Tag *reply = new Tag( "iq" );
		reply->addAttribute( "id", iqTag->findAttribute("id") );
		reply->addAttribute( "type", "result" );
		reply->addAttribute( "to", iqTag->findAttribute("from") );
		reply->addAttribute( "from", Transport::instance()->jid() );
		Tag *query = new Tag( "query" );
		query->addAttribute( "xmlns", "jabber:iq:register" );
		UserRow res = Transport::instance()->sql()->getUserByJid(from.bare());

		std::string instructions = CONFIG().reg_instructions.empty() ? PROTOCOL()->text("instructions") : CONFIG().reg_instructions;
		std::string usernameField = CONFIG().reg_username_field.empty() ? PROTOCOL()->text("username") : CONFIG().reg_username_field;

		if (res.id == -1) {
			Log("GlooxRegisterHandler", "* sending registration form; user is not registered");
			query->addChild( new Tag("instructions", tr(_language, instructions)) );
			query->addChild( new Tag("username") );
			if (CONFIG().protocol != "twitter" && CONFIG().protocol != "bonjour")
				query->addChild( new Tag("password") );
		}
		else {
			Log("GlooxRegisterHandler", "* sending registration form; user is registered");
			query->addChild( new Tag("instructions", tr(_language, instructions)) );
			query->addChild( new Tag("registered") );
			query->addChild( new Tag("username", res.uin));
			if (CONFIG().protocol != "twitter" && CONFIG().protocol != "bonjour")
				query->addChild( new Tag("password"));
		}

		Tag *x = new Tag("x");
		x->addAttribute("xmlns", "jabber:x:data");
		x->addAttribute("type", "form");
		x->addChild( new Tag("title", tr(_language, _("Registration"))));
		x->addChild( new Tag("instructions", tr(_language, instructions)) );

		Tag *field = new Tag("field");
		field->addAttribute("type", "hidden");
		field->addAttribute("var", "FORM_TYPE");
		field->addChild( new Tag("value", "jabber:iq:register") );
		x->addChild(field);

		field = new Tag("field");
		field->addAttribute("type", "text-single");
		field->addAttribute("var", "username");
		field->addAttribute("label", tr(_language, usernameField));
		field->addChild( new Tag("required") );
		if (res.id!=-1)
			field->addChild( new Tag("value", res.uin) );
		x->addChild(field);

		if (CONFIG().protocol != "twitter" && CONFIG().protocol != "bonjour") {
			field = new Tag("field");
			field->addAttribute("type", "text-private");
			field->addAttribute("var", "password");
			field->addAttribute("label", tr(_language, _("Password")));
			x->addChild(field);
		}

		field = new Tag("field");
		field->addAttribute("type", "list-single");
		field->addAttribute("var", "language");
		field->addAttribute("label", tr(_language, _("Language")));
		if (res.id!=-1)
			field->addChild( new Tag("value", res.language) );
		else
			field->addChild( new Tag("value", Transport::instance()->getConfiguration().language) );
		x->addChild(field);

		std::map <std::string, std::string> languages = localization.getLanguages();
		for (std::map <std::string, std::string>::iterator it = languages.begin(); it != languages.end(); it++) {
			Tag *option = new Tag("option");
			option->addAttribute("label", (*it).second);
			option->addChild( new Tag("value", (*it).first) );
			field->addChild(option);
		}

		field = new Tag("field");
		field->addAttribute("type", "text-single");
		field->addAttribute("var", "encoding");
		field->addAttribute("label", tr(_language, _("Encoding")));
		if (res.id!=-1)
			field->addChild( new Tag("value", res.encoding) );
		else
			field->addChild( new Tag("value", Transport::instance()->getConfiguration().encoding) );
		x->addChild(field);

		if (res.id != -1) {
			field = new Tag("field");
			field->addAttribute("type", "boolean");
			field->addAttribute("var", "unregister");
			field->addAttribute("label", tr(_language, _("Remove your registration")));
			field->addChild( new Tag("value", "0") );
			x->addChild(field);
		}

		query->addChild(x);
		reply->addChild(query);
		Transport::instance()->send( reply );
		return true;
	}
	else if (iqTag->findAttribute("type") == "set") {
		bool remove = false;
		Tag *query;
		Tag *usernametag;
		Tag *passwordtag;
		Tag *languagetag;
		Tag *encodingtag;
		std::string username("");
		std::string password("");
		std::string language("");
		std::string encoding("");

		UserRow res = Transport::instance()->sql()->getUserByJid(from.bare());
		
		query = iqTag->findChild( "query" );
		if (!query) return true;

		Tag *xdata = query->findChild("x", "xmlns", "jabber:x:data");
		if (xdata) {
			if (query->hasChild( "remove" ))
				remove = true;
			for (std::list<Tag*>::const_iterator it = xdata->children().begin(); it != xdata->children().end(); ++it) {
				std::string key = (*it)->findAttribute("var");
				if (key.empty()) continue;

				Tag *v = (*it)->findChild("value");
				if (!v) continue;

				if (key == "username")
					username = v->cdata();
				else if (key == "password")
					password = v->cdata();
				else if (key == "language")
					language = v->cdata();
				else if (key == "encoding")
					encoding = v->cdata();
				else if (key == "unregister")
					remove = atoi(v->cdata().c_str());
			}
		}
		else {
			if (query->hasChild( "remove" ))
				remove = true;
			else {
				usernametag = query->findChild("username");
				passwordtag = query->findChild("password");
				languagetag = query->findChild("language");
				encodingtag = query->findChild("encoding");

				if (languagetag)
					language = languagetag->cdata();
				else
					language = Transport::instance()->getConfiguration().language;

				if (encodingtag)
					encoding = encodingtag->cdata();
				else
					encoding = Transport::instance()->getConfiguration().encoding;

				if (usernametag==NULL || (passwordtag==NULL && CONFIG().protocol != "twitter" && CONFIG().protocol != "bonjour")) {
					sendError(406, "not-acceptable", iqTag);
					return false;
				}
				else {
					username = usernametag->cdata();
					if (passwordtag)
						password = passwordtag->cdata();
					if (username.empty() || (password.empty() && CONFIG().protocol != "twitter" && CONFIG().protocol != "bonjour")) {
						sendError(406, "not-acceptable", iqTag);
						return false;
					}
				}
			}
		}

		if (Transport::instance()->getConfiguration().protocol == "xmpp") {
			// User tries to register himself.
			if ((JID(username).bare() == from.bare())) {
				sendError(406, "not-acceptable", iqTag);
				return false;
			}

			// User tries to register someone who's already registered.
			UserRow user_row = Transport::instance()->sql()->getUserByJid(JID(username).bare());
			if (user_row.id != -1) {
				sendError(406, "not-acceptable", iqTag);
				return false;
			}
		}

		if (remove) {
			unregisterUser(from.bare());

			Tag *reply = new Tag("iq");
			reply->addAttribute( "type", "result" );
			reply->addAttribute( "from", Transport::instance()->jid() );
			reply->addAttribute( "to", iqTag->findAttribute("from") );
			reply->addAttribute( "id", iqTag->findAttribute("id") );
			Transport::instance()->send( reply );

			return true;
		}

		// Register or change password

		std::string jid = from.bare();

		if (username.empty() || (password.empty() && CONFIG().protocol != "twitter" && CONFIG().protocol != "bonjour") || localization.getLanguages().find(language) == localization.getLanguages().end()) {
			sendError(406, "not-acceptable", iqTag);
			return false;
		}

		Transport::instance()->protocol()->prepareUsername(username);

		std::string newUsername(username);
		if (!CONFIG().username_mask.empty()) {
			newUsername = CONFIG().username_mask;
			replace(newUsername, "$username", username.c_str());
		}

		if (!Transport::instance()->protocol()->isValidUsername(newUsername)) {
			Log("GlooxRegisterHandler", "This is not valid username: "******"bad-request", iqTag);
			return false;
		}

#if GLIB_CHECK_VERSION(2,14,0)
		if (!CONFIG().reg_allowed_usernames.empty() &&
			!g_regex_match_simple(CONFIG().reg_allowed_usernames.c_str(), newUsername.c_str(),(GRegexCompileFlags) (G_REGEX_CASELESS | G_REGEX_EXTENDED), (GRegexMatchFlags) 0)) {
			Log("GlooxRegisterHandler", "This is not valid username: "******"bad-request", iqTag);
			return false;
		}
#endif
		if (res.id == -1) {
			res.jid = from.bare();
			res.uin = username;
			res.password = password;
			res.language = language;
			res.encoding = encoding;
			res.vip = 0;

			registerUser(res);
		}
		else {
			// change passwordhttp://soumar.jabbim.cz/phpmyadmin/index.php
			Log("GlooxRegisterHandler", "changing user password: "******", " << username);
			res.jid = from.bare();
			res.password = password;
			res.language = language;
			res.encoding = encoding;
			Transport::instance()->sql()->updateUser(res);
		}

		Tag *reply = new Tag( "iq" );
		reply->addAttribute( "id", iqTag->findAttribute("id") );
		reply->addAttribute( "type", "result" );
		reply->addAttribute( "to", iqTag->findAttribute("from") );
		reply->addAttribute( "from", Transport::instance()->jid() );
		Transport::instance()->send( reply );

		return true;
	}
	return false;
}
Example #3
-1
  void Server::acceptUser() {
    //to be called every time a new connection is received
    QTcpSocket *socket = m_tcp_server->nextPendingConnection();
    debugInfo("New incoming connection, from IP " +
	      socket->peerAddress().toString() +
	      " and port: " + QString::number(socket->peerPort()));
    //check if ip is registered
    if (!isThisIpRegistered(socket->peerAddress().toString())) {
      //then parse user
      UE new_ue;
      new_ue.name = "";
      new_ue.ip = socket->peerAddress().toString();
      //will change when ue_name() is sent
      new_ue.rx_port = 0;
      m_online_users.append(new_ue);
      debugInfo("New empty UE registered!");
    } else {
      debugInfo("user is transmitting either its name or data");
      socket->waitForReadyRead(1000);
      //parse data
      QDataStream in(socket);
      in.setVersion(QDataStream::Qt_4_0);
      debugInfo("m_block_size: " + QString::number(m_block_size));
      if (m_block_size == 0) {
	if (socket->bytesAvailable() < (int)sizeof(quint16))
	  return;
      
	in >> m_block_size;
      }
      debugInfo("bytes available in socket: " + QString::number(socket->bytesAvailable()));
    
      if (socket->bytesAvailable() < m_block_size)
	return;
    
      QString message;
      in >> message;
    
      debugInfo(">Message: [" + message + "]");

      ProtocolStreamType_UE type;
      QStringList params = m_protocol->parseStream_UE(type, message);

      switch (type) {
      case UE_REGISTER:
	{
	  QString temp_name = params.at(0);
	  quint16 temp_port = (quint16) params.at(1).toInt();
	  DLOG (INFO) << "Parsed port: " << temp_port;
	  if (temp_name.isEmpty()) {
	    m_block_size=0;
	    return;
	  }
	  UE temp;
	  int index;
	  if (!isThisNameRegistered(temp_name)) {
	    //case for same ip, different name
	    debugInfo("New user " + temp_name + " connected from same IP. Registering user.");
	    temp.name = temp_name;
	    temp.ip = socket->peerAddress().toString();
	    //parse ue_rx_port
	    temp.rx_port = temp_port;
	    index = getIndexOfUEIp(socket->peerAddress().toString());
	    if (m_online_users.at(index).name.isEmpty()) {
	      //first time, when username is still empty
	      if (index != -1) {
		temp = m_online_users.at(index);
		temp.name = temp_name;
		temp.rx_port = temp_port;
		m_online_users.replace(index,temp);
	      }
	    } else {
	      //same ip but different username, then append new UE
	      m_online_users.append(temp);
	    }
	  } else {
	    LOG (ERROR) << "User already exists on server. Notifying user...";
	    //inform user of currently online users
	    QByteArray block;
	    QDataStream out(&block, QIODevice::WriteOnly);
	    out.setVersion(QDataStream::Qt_4_0);
	    out << (quint16)0;
	    out << QString("ue_error(Existing user on server. Choose other username);");
	    out.device()->seek(0);
	    out << (quint16)(block.size() - sizeof(quint16));
	    DLOG (INFO) <<"Sending error message to UE ...\n";
	    m_log_label->setText(m_log_label->toPlainText()
			      + "\nError: attempted connection with same "
			      "username from same IP. Sending error to client...");
	    socket->write(block);
	    //reset m_block_size
	    m_block_size = 0;
	    return;
	  }
	  DLOG (INFO) << "New user is online: " << temp;
	  debugInfo("Nr. online users: " + QString::number(m_online_users.size()));
	  if (m_log_label->toPlainText() != "") {
	    m_log_label->setText(m_log_label->toPlainText() + "\n[" + temp.name + "]@" +
			      temp.ip + ":" +
			      QString::number(temp.rx_port) + " is now online.");
	  } else {
	    m_log_label->setText(m_log_label->toPlainText() + "[" + temp.name + "]@" +
			      temp.ip + ":" +
			      QString::number(temp.rx_port) + " is now online.");
	  }
	  //parse online users
	  QString users;
	  for (auto user: m_online_users) {
	    users += user.name + "\n";
	  }
	  users.chop(1);
	  m_online_users_label->setText(users);
	  qobject_cast<QLabel*>(m_main_layout->itemAt(2)->widget())->setText("Currently online users("
									  + QString::number(m_online_users.size()) + "):");
	  //inform user of currently online users
	  QByteArray block;
	  QDataStream out(&block, QIODevice::WriteOnly);
	  out.setVersion(QDataStream::Qt_4_0);
	  out << (quint16)0;
	  QStringList params;
	  for (auto user: m_online_users) {
	    params << user.name;
	  }
	  out << m_protocol->constructStream_Server(params,
						    ProtocolStreamType_Server::SERVER_ALL);
	  out.device()->seek(0);
	  out << (quint16)(block.size() - sizeof(quint16));
	  DLOG (INFO) <<"Sending information about currently online users...\n";
	  /*At this point, this block will be sent to all current users, not only to the
	    user that is currently connected*/
	  for (auto connection: m_online_users) {
	    QTcpSocket *temp_socket = new QTcpSocket(this);
	    temp_socket->connectToHost(QHostAddress(connection.ip), connection.rx_port);
	    if (!temp_socket->waitForConnected(3000)) {
	      LOG (ERROR) << "ERROR: Connection attempt @"
			  << connection.ip.toStdString() << ":"
			  << connection.rx_port << " timed out. Omitting current...";
	    } else {
	      debugInfo("Connection to client @" + connection.ip + ":"
			+ QString::number(connection.rx_port) + " was established. Now sending...");
	      temp_socket->write(block);
	      if (!temp_socket->waitForBytesWritten()) {
		LOG (ERROR) << "ERROR: Connection attempt @"
			    << connection.ip.toStdString() << ":"
			    << connection.rx_port << " timed out. Omitting current...";
	      } else {
		debugInfo("Transmission to client @" + connection.ip + ":"
			  + QString::number(connection.rx_port) + " was successful!");
	      }
	    }
	    temp_socket->disconnectFromHost();
	    if (temp_socket->state() == QAbstractSocket::UnconnectedState ||
		temp_socket->waitForDisconnected(1000)) {
	      debugInfo("Socket disconnected.");
	    }
	  }

	  break;

	  
	}
      case UE_ACK:
	{
	  m_log_label->setText(m_log_label->toPlainText() + "\n" + message);
	  debugInfo("Going to forward user ack to destination");
	  QByteArray block;
	  QDataStream out(&block, QIODevice::WriteOnly);
	  out.setVersion(QDataStream::Qt_4_0);
	  out << (quint16)0;
	  out << m_protocol->constructStream_Server(QStringList(message),
						    ProtocolStreamType_Server::SERVER_FWD_TO_SENDER);
	  out.device()->seek(0);
	  out << (quint16)(block.size() - sizeof(quint16));

	  //and lookup destination details for given user
	  QString dest = params.at(0);
	  QString from = params.at(1);
	  unsigned int message_id = (unsigned int) params.at(2).toInt();

	  //Create temporary socket
	  QTcpSocket* dest_socket = new QTcpSocket(this);
	  QString dest_ip;
	  quint16 dest_port;
	  int index = getIndexOfUEName(dest);
	  if (index != -1) {
	    dest_ip = m_online_users.at(index).ip;
	    dest_port = m_online_users.at(index).rx_port;
	    debugInfo("Going to forward ack to " + dest_ip + ":" + QString::number(dest_port));
	  } else {
	    LOG (ERROR) << "ERROR: name was not found on server. Returning...";
	    m_block_size=0;
	    return;
	  }
	  dest_socket->connectToHost(QHostAddress(dest_ip), dest_port);

	  if (!dest_socket->waitForConnected(2000)) {
	    debugInfo("ERROR: request timed out");
	  } else {
	    debugInfo("Established connection with client. Forwarding user ack...");
	    dest_socket->write(block);
	    if (!dest_socket->waitForBytesWritten(5000)) {
	      debugInfo("ERROR: transmission timed out");
	    } else {
	      debugInfo("Success! ACK was forwarded to destination");
	    }
	    dest_socket->disconnectFromHost();
	  }
	  break;
	}
      case UE_ERROR:
	{
	  debugInfo("Some error encountered by user. Returning ...");
	  m_block_size=0;
	  return;
	}
      case UE_MESSAGE:
	{
	  m_log_label->setText(m_log_label->toPlainText() + "\n" + message);
	  //and send it back to the user
	  debugInfo("Going to resend message to dest client: [" + message + "]");
	  
	  QString content = params.at(0);
	  QString dest = params.at(1);
	  QString from = params.at(2);
	  unsigned int message_id = (unsigned int) params.at(3).toInt();
	  
	  DLOG (INFO) << "Message: " << content.toStdString() << ", from " << from.toStdString()
		      << " and to " << dest.toStdString()
		      << ", with message ID: " << message_id;
	  QByteArray block;
	  QDataStream out(&block, QIODevice::WriteOnly);
	  out.setVersion(QDataStream::Qt_4_0);
	  out << (quint16)0;
	  out << m_protocol->constructStream_Server(QStringList(message),
						    ProtocolStreamType_Server::SERVER_FWD_TO_SENDER);
	  out.device()->seek(0);
	  out << (quint16)(block.size() - sizeof(quint16));
	  if (dest == from) {
	    debugInfo("WARNING: Message intended for self UE. Sending back to user...");
	    socket->write(block);
	    if (!socket->waitForBytesWritten(2000)) {
	      LOG (ERROR) << "ERROR: transmission timeout";
	    } else {
	      debugInfo("Success!");
	    }
	  } else {
	    QTcpSocket *dest_socket = new QTcpSocket(this);
	    QString dest_ip;
	    quint16 dest_port;
	    int index = getIndexOfUEName(dest);
	    if (index != -1) {
	      dest_ip = m_online_users.at(index).ip;
	      dest_port = m_online_users.at(index).rx_port;
	      debugInfo("Going to forward message to " + dest_ip + ":" + QString::number(dest_port));
	    } else {
	      LOG (ERROR) << "ERROR: name was not found on server. Returning...";
	      m_block_size=0;
	      return;
	    }
	    dest_socket->connectToHost(QHostAddress(dest_ip), dest_port);
	    if (!dest_socket->waitForConnected(2000)) {
	      debugInfo("ERROR: request timed out");
	    } else {
	      debugInfo("Established connection with client. Sending...");
	      dest_socket->write(block);
	      if (!dest_socket->waitForBytesWritten(5000)) {
		debugInfo("ERROR: transmission timed out");
	      } else {
		debugInfo("Success! Message was forwarded to destination");
	      }
	      dest_socket->disconnectFromHost();
	      //and send an ack to the user to inform that message was received
	      QByteArray ack_data;
	      QDataStream ack(&ack_data, QIODevice::WriteOnly);
	      ack.setVersion(QDataStream::Qt_4_0);
	      ack << (quint16)0;
	      QStringList params;
	      params << from << QString::number(message_id);
	      ack << m_protocol->constructStream_Server(params,
							ProtocolStreamType_Server::SERVER_ACK);
	      ack.device()->seek(0);
	      debugInfo("Sending ack to user: "******"ERROR: transmission timeout!";
	      } else {
		debugInfo("Success!");
	      }
	    }
	  }
	  break;
	}
      case UE_UNREGISTER:
	{
	  unregisterUser();
	  break;
	}
      case UE_TYPING:
	{
	  debugInfo("User is typing...");
	  m_log_label->setText(m_log_label->toPlainText() + "\n" + message);
	  //no need to parse parameters, going to forward to user
	  
	  QString dest = params.at(0);
	  QString from = params.at(1);

	  debugInfo(dest + "," + from);
	  
	  QByteArray typing_data;
	  QDataStream typing_stream(&typing_data, QIODevice::WriteOnly);
	  typing_stream.setVersion(QDataStream::Qt_4_0);
	  typing_stream << (quint16)0;
	  QStringList typing_params;
	  typing_params << params.at(0) << params.at(1) << params.at(2);
	  typing_stream << m_protocol->constructStream_Server(typing_params,
							      ProtocolStreamType_Server::SERVER_FWD_TYPING);
	  typing_stream.device()->seek(0);

	  DLOG (INFO) << "Sending: " << m_protocol->constructStream_Server(typing_params,
							    ProtocolStreamType_Server::SERVER_FWD_TYPING).toStdString();
	  
	  QTcpSocket *dest_socket = new QTcpSocket(this);
	  QString dest_ip;
	  quint16 dest_port;
	  int index = getIndexOfUEName(dest);
	  if (index != -1) {
	    dest_ip = m_online_users.at(index).ip;
	    dest_port = m_online_users.at(index).rx_port;
	    debugInfo("Going to forward typing info to " +
		      dest_ip + ":" + QString::number(dest_port));
	  } else {
	    LOG (ERROR) << "ERROR: name was not found on server. Returning...";
	    m_block_size=0;
	    return;
	  }
	  dest_socket->connectToHost(QHostAddress(dest_ip), dest_port);
	  if (!dest_socket->waitForConnected(2000)) {
	    debugInfo("ERROR: request timed out");
	  } else {
	    debugInfo("Established connection with client. Sending...");
	    dest_socket->write(typing_data);
	    if (!dest_socket->waitForBytesWritten(5000)) {
	      debugInfo("ERROR: transmission timed out");
	    } else {
	      debugInfo("Success! Typing information was forwarded to destination");
	    }
	    dest_socket->disconnectFromHost();
	  }

	  break;
	}
      default:
	LOG (WARNING) << "Unrecognized stream type";
	break;
      }
    
    }
    //reset m_block_size
    m_block_size=0;
  }