Пример #1
0
void UserDbObject::OnConfigUpdate(void)
{
	Dictionary::Ptr fields = make_shared<Dictionary>();
	User::Ptr user = static_pointer_cast<User>(GetObject());

	/* contact addresses */
	Log(LogDebug, "UserDbObject", "contact addresses for '" + user->GetName() + "'");

	Dictionary::Ptr vars = user->GetVars();

	if (vars) { /* This is sparta. */
		for (int i = 1; i <= 6; i++) {
			String key = "address" + Convert::ToString(i);
			String val = vars->Get(key);

			if (val.IsEmpty())
				continue;

			fields->Set("contact_id", DbValue::FromObjectInsertID(user));
			fields->Set("address_number", i);
			fields->Set("address", val);
			fields->Set("instance_id", 0); /* DbConnection class fills in real ID */

			DbQuery query;
			query.Type = DbQueryInsert;
			query.Table = "contact_addresses";
			query.Fields = fields;
			OnQuery(query);
		}
	}
}
Пример #2
0
Dictionary::Ptr UserDbObject::GetConfigFields(void) const
{
	Dictionary::Ptr fields = new Dictionary();
	User::Ptr user = static_pointer_cast<User>(GetObject());

	fields->Set("alias", user->GetDisplayName());
	fields->Set("email_address", user->GetEmail());
	fields->Set("pager_address", user->GetPager());
	fields->Set("host_timeperiod_object_id", user->GetPeriod());
	fields->Set("service_timeperiod_object_id", user->GetPeriod());
	fields->Set("host_notifications_enabled", user->GetEnableNotifications());
	fields->Set("service_notifications_enabled", user->GetEnableNotifications());
	fields->Set("can_submit_commands", 1);

	int typeFilter = user->GetTypeFilter();
	int stateFilter = user->GetStateFilter();

	fields->Set("notify_service_recovery", (typeFilter & NotificationRecovery) != 0);
	fields->Set("notify_service_warning", (stateFilter & StateFilterWarning) != 0);
	fields->Set("notify_service_unknown", (stateFilter & StateFilterUnknown) != 0);
	fields->Set("notify_service_critical", (stateFilter & StateFilterCritical) != 0);
	fields->Set("notify_service_flapping", (typeFilter & (NotificationFlappingStart | NotificationFlappingEnd)) != 0);
	fields->Set("notify_service_downtime", (typeFilter & (NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved)) != 0);
	fields->Set("notify_host_recovery", (typeFilter & NotificationRecovery) != 0);
	fields->Set("notify_host_down", (stateFilter & StateFilterDown) != 0);
	fields->Set("notify_host_flapping", (typeFilter & (NotificationFlappingStart | NotificationFlappingEnd)) != 0);
	fields->Set("notify_host_downtime", (typeFilter & (NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved)) != 0);

	return fields;
}
Пример #3
0
/**
 * @threadsafety Always.
 */
void CompatLogger::NotificationSentHandler(const Notification::Ptr& notification, const Checkable::Ptr& checkable,
	const User::Ptr& user, NotificationType notification_type, CheckResult::Ptr const& cr,
	const String& author, const String& comment_text, const String& command_name)
{
	Host::Ptr host;
	Service::Ptr service;
	tie(host, service) = GetHostService(checkable);

	String notification_type_str = Notification::NotificationTypeToString(notification_type);

	/* override problem notifications with their current state string */
	if (notification_type == NotificationProblem) {
		if (service)
			notification_type_str = Service::StateToString(service->GetState());
		else
			notification_type_str = GetHostStateString(host);
	}

	String author_comment = "";
	if (notification_type == NotificationCustom || notification_type == NotificationAcknowledgement) {
		author_comment = author + ";" + comment_text;
	}

	if (!cr)
		return;

	String output;
	if (cr)
		output = CompatUtility::GetCheckResultOutput(cr);

	std::ostringstream msgbuf;

	if (service) {
		msgbuf << "SERVICE NOTIFICATION: "
			<< user->GetName() << ";"
			<< host->GetName() << ";"
			<< service->GetShortName() << ";"
			<< notification_type_str << ";"
			<< command_name << ";"
			<< output << ";"
			<< author_comment
			<< "";
	} else {
		msgbuf << "HOST NOTIFICATION: "
			<< user->GetName() << ";"
			<< host->GetName() << ";"
			<< notification_type_str << " "
			<< "(" << GetHostStateString(host) << ");"
			<< command_name << ";"
			<< output << ";"
			<< author_comment
			<< "";
	}

	{
		ObjectLock oLock(this);
		WriteLine(msgbuf.str());
		Flush();
	}
}
Пример #4
0
bool UserGroup::EvaluateObjectRuleOne(const User::Ptr user, const ObjectRule& rule)
{
	DebugInfo di = rule.GetDebugInfo();

	std::ostringstream msgbuf;
	msgbuf << "Evaluating 'object' rule (" << di << ")";
	CONTEXT(msgbuf.str());

	Dictionary::Ptr locals = make_shared<Dictionary>();
	locals->Set("user", user);

	if (!rule.EvaluateFilter(locals))
		return false;

	std::ostringstream msgbuf2;
	msgbuf2 << "Assigning membership for group '" << rule.GetName() << "' to user '" << user->GetName() << "' for rule " << di;
	Log(LogDebug, "UserGroup", msgbuf2.str());

	String group_name = rule.GetName();
	UserGroup::Ptr group = UserGroup::GetByName(group_name);

	if (!group) {
		Log(LogCritical, "UserGroup", "Invalid membership assignment. Group '" + group_name + "' does not exist.");
		return false;
	}

	/* assign user group membership */
	group->ResolveGroupMembership(user, true);

	/* update groups attribute for apply */
	user->AddGroup(group_name);

	return true;
}
Пример #5
0
Value ContactsTable::EmailAccessor(const Value& row)
{
    User::Ptr user = static_cast<User::Ptr>(row);

    if (!user)
        return Empty;

    return user->GetEmail();
}
Пример #6
0
Value ContactsTable::AliasAccessor(const Value& row)
{
    User::Ptr user = static_cast<User::Ptr>(row);

    if (!user)
        return Empty;

    return user->GetDisplayName();
}
Пример #7
0
Value ContactsTable::ServiceNotificationsEnabledAccessor(const Value& row)
{
    User::Ptr user = static_cast<User::Ptr>(row);

    if (!user)
        return Empty;

    return (user->GetEnableNotifications() ? 1 : 0);
}
Пример #8
0
Dictionary::Ptr UserDbObject::GetStatusFields(void) const
{
	Dictionary::Ptr fields = new Dictionary();
	User::Ptr user = static_pointer_cast<User>(GetObject());

	fields->Set("host_notifications_enabled", user->GetEnableNotifications());
	fields->Set("service_notifications_enabled", user->GetEnableNotifications());
	fields->Set("last_host_notification", DbValue::FromTimestamp(user->GetLastNotification()));
	fields->Set("last_service_notification", DbValue::FromTimestamp(user->GetLastNotification()));

	return fields;
}
Пример #9
0
String UserDbObject::CalculateConfigHash(const Dictionary::Ptr& configFields) const
{
	String hashData = DbObject::CalculateConfigHash(configFields);

	User::Ptr user = static_pointer_cast<User>(GetObject());

	Array::Ptr groups = user->GetGroups();

	if (groups)
		hashData += DbObject::HashValue(groups);

	return SHA256(hashData);
}
Пример #10
0
Value ContactsTable::InServiceNotificationPeriodAccessor(const Value& row)
{
    User::Ptr user = static_cast<User::Ptr>(row);

    if (!user)
        return Empty;

    TimePeriod::Ptr timeperiod = user->GetPeriod();

    if (!timeperiod)
        return Empty;

    return (timeperiod->IsInside(Utility::GetTime()) ? 1 : 0);
}
Пример #11
0
Value ContactsTable::ServiceNotificationPeriodAccessor(const Value& row)
{
    User::Ptr user = static_cast<User::Ptr>(row);

    if (!user)
        return Empty;

    TimePeriod::Ptr timeperiod = user->GetPeriod();

    if (!timeperiod)
        return Empty;

    return timeperiod->GetName();
}
Пример #12
0
void Notification::ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author, const String& text)
{
	try {
		NotificationCommand::Ptr command = GetCommand();

		if (!command) {
			Log(LogDebug, "Notification")
			    << "No command found for notification '" << GetName() << "'. Skipping execution.";
			return;
		}

		command->Execute(this, user, cr, type, author, text);

		/* required by compatlogger */
		Service::OnNotificationSentToUser(this, GetCheckable(), user, type, cr, author, text, command->GetName(), MessageOrigin::Ptr());

		Log(LogInformation, "Notification")
		    << "Completed sending '" << NotificationTypeToStringInternal(type)
		    << "' notification '" << GetName()
		    << "' for checkable '" << GetCheckable()->GetName()
		    << "' and user '" << user->GetName() << "'.";
	} catch (const std::exception& ex) {
		Log(LogWarning, "Notification")
		    << "Exception occured during notification for checkable '"
		    << GetCheckable()->GetName() << "': " << DiagnosticInformation(ex);
	}
}
Пример #13
0
void ClusterEvents::NotificationSentUserHandler(const Notification::Ptr& notification, const Checkable::Ptr& checkable, const User::Ptr& user,
	NotificationType notificationType, const CheckResult::Ptr& cr, const NotificationResult::Ptr& nr, const String& author, const String& commentText, const String& command,
	const MessageOrigin::Ptr& origin)
{
	ApiListener::Ptr listener = ApiListener::GetInstance();

	if (!listener)
		return;

	Host::Ptr host;
	Service::Ptr service;
	tie(host, service) = GetHostService(checkable);

	Dictionary::Ptr params = new Dictionary();
	params->Set("host", host->GetName());
	if (service)
		params->Set("service", service->GetShortName());
	params->Set("notification", notification->GetName());
	params->Set("user", user->GetName());
	params->Set("type", notificationType);
	params->Set("cr", Serialize(cr));
	params->Set("nr", Serialize(nr));
	params->Set("author", author);
	params->Set("text", commentText);
	params->Set("command", command);

	Dictionary::Ptr message = new Dictionary();
	message->Set("jsonrpc", "2.0");
	message->Set("method", "event::NotificationSentUser");
	message->Set("params", params);

	listener->RelayMessage(origin, nullptr, message, true);
}
Пример #14
0
void UserGroup::AddMember(const User::Ptr& user)
{
	user->AddGroup(GetName());

	boost::mutex::scoped_lock lock(m_UserGroupMutex);
	m_Members.insert(user);
}
Пример #15
0
bool UserGroup::ResolveGroupMembership(const User::Ptr& user, bool add, int rstack) {

	if (add && rstack > 20) {
		Log(LogWarning, "UserGroup")
		    << "Too many nested groups for group '" << GetName() << "': User '"
		    << user->GetName() << "' membership assignment failed.";

		return false;
	}

	Array::Ptr groups = GetGroups();

	if (groups && groups->GetLength() > 0) {
		ObjectLock olock(groups);

		for (const String& name : groups) {
			UserGroup::Ptr group = UserGroup::GetByName(name);

			if (group && !group->ResolveGroupMembership(user, add, rstack + 1))
				return false;
		}
	}

	if (add)
		AddMember(user);
	else
		RemoveMember(user);

	return true;
}
Пример #16
0
void ClientManager::connect(const User::Ptr& p) {
	Lock l(cs);
	OnlineIter i = onlineUsers.find(p->getCID());
	if(i != onlineUsers.end()) {
		OnlineUser* u = i->second;
		u->getClient().connect(*u);
	}
}
Пример #17
0
void UploadManager::reserveSlot(const User::Ptr& aUser) {
	{
		Lock l(cs);
		reservedSlots.insert(aUser);
	}
	if(aUser->isOnline())
		ClientManager::getInstance()->connect(aUser);
}
Пример #18
0
void ClientManager::privateMessage(const User::Ptr& p, const string& msg) {
	Lock l(cs);
	OnlineIter i = onlineUsers.find(p->getCID());
	if(i != onlineUsers.end()) {
		OnlineUser* u = i->second;
		u->getClient().privateMessage(*u, msg);
	}
}
Пример #19
0
void UploadManager::reserveSlot(const User::Ptr& aUser) {
	{
		Lock l(cs);
		reservedSlots.insert(aUser);
	}
	if(aUser->isOnline())
		const_cast<User::Ptr&>(aUser)->connect();
}
Пример #20
0
void UsersFrame::updateUser(const User::Ptr& aUser) {
	for(int i = 0; i < ctrlUsers.GetItemCount(); ++i) {
		UserInfo *ui = ctrlUsers.getItemData(i);
		if(ui->user == aUser) {
			ui->columns[COLUMN_SEEN] = aUser->isOnline() ? TSTRING(ONLINE) : Text::toT(Util::formatTime("%Y-%m-%d %H:%M", FavoriteManager::getInstance()->getLastSeen(aUser)));
			ctrlUsers.updateItem(i);
		}
	}
}
Пример #21
0
bool ClientManager::isOp(const User::Ptr& user, const string& aHubUrl) const {
	Lock l(cs);
	OnlinePairC p = onlineUsers.equal_range(user->getCID());
	for(OnlineIterC i = p.first; i != p.second; ++i) {
		if(i->second->getClient().getHubUrl() == aHubUrl) {
			return i->second->getIdentity().isOp();
		}
	}
	return false;
}
Пример #22
0
void AdcHub::handle(Command::MSG, Command& c) throw() {
	if(c.getFrom().isZero() || c.getParameters().empty())
		return;
	User::Ptr p = ClientManager::getInstance()->getUser(c.getFrom(), false);
	if(!p)
		return;
	if(c.getParameters().size() == 2 && c.getParameters()[1] == "PM") { // add PM<group-cid> as well
		const string& msg = c.getParameters()[0];
		if(c.getFrom() == getMe()->getCID()) {
			p = ClientManager::getInstance()->getUser(c.getTo(), false);
			if(!p)
				return;
		}
		fire(ClientListener::PrivateMessage(), this, p, msg);
	} else {
		string msg = '<' + p->getNick() + "> " + c.getParameters()[0];
		fire(ClientListener::Message(), this, msg);
	}		
}
Пример #23
0
void NmdcHub::kick(const User::Ptr& aUser, const string& aMsg) {
	checkstate(); 
	dcdebug("NmdcHub::kick\n");
	static const char str[] = 
		"$To: %s From: %s $<%s> You are being kicked because: %s|<%s> %s is kicking %s because: %s|";
	string msg2 = toNmdc(Util::validateMessage(aMsg, false));
	
	char* tmp = new char[sizeof(str) + 2*aUser->getNick().length() + 2*msg2.length() + 4*getNick().length()];
	const char* u = aUser->getNick().c_str();
	const char* n = getNick().c_str();
	const char* m = msg2.c_str();
	sprintf(tmp, str, u, n, n, m, n, n, u, m);
	send(tmp);
	delete[] tmp;
	
	// Short, short break to allow the message to reach the NmdcHub...
	Thread::sleep(200);
	send("$Kick " + toNmdc(aUser->getNick()) + "|");
}
Пример #24
0
void UserGroup::EvaluateObjectRules(const User::Ptr& user)
{
	CONTEXT("Evaluating group membership for user '" + user->GetName() + "'");

	for (const ConfigItem::Ptr& group : ConfigItem::GetItems("UserGroup"))
	{
		if (!group->GetFilter())
			continue;

		EvaluateObjectRule(user, group);
	}
}
Пример #25
0
void SearchManager::onRES(const AdcCommand& cmd, const User::Ptr& from, const string& remoteIp) {
	int freeSlots = -1;
	int64_t size = -1;
	string file;
	string tth;
	string token;

	for(StringIterC i = cmd.getParameters().begin(); i != cmd.getParameters().end(); ++i) {
		const string& str = *i;
		if(str.compare(0, 2, "FN") == 0) {
			file = Util::toNmdcFile(str.substr(2));
		} else if(str.compare(0, 2, "SL") == 0) {
			freeSlots = Util::toInt(str.substr(2));
		} else if(str.compare(0, 2, "SI") == 0) {
			size = Util::toInt64(str.substr(2));
		} else if(str.compare(0, 2, "TR") == 0) {
			tth = str.substr(2);
		} else if(str.compare(0, 2, "TO") == 0) {
			token = str.substr(2);
		}
	}

	if(!file.empty() && freeSlots != -1 && size != -1) {

		StringList names = ClientManager::getInstance()->getHubNames(from->getCID());
		string hubName = names.empty() ? STRING(OFFLINE) : Util::toString(names);
		StringList hubs = ClientManager::getInstance()->getHubs(from->getCID());
		string hub = hubs.empty() ? STRING(OFFLINE) : Util::toString(hubs);

		SearchResult::Types type = (file[file.length() - 1] == '\\' ? SearchResult::TYPE_DIRECTORY : SearchResult::TYPE_FILE);
		if(type == SearchResult::TYPE_FILE && tth.empty())
			return;
		/// @todo Something about the slots
		SearchResult* sr = new SearchResult(from, type, 0, freeSlots, size,
			file, hubName, hub, remoteIp, TTHValue(tth), token);
		fire(SearchManagerListener::SR(), sr);
		sr->decRef();
	}
}
Пример #26
0
bool UserGroup::EvaluateObjectRule(const User::Ptr& user, const ConfigItem::Ptr& group)
{
	String group_name = group->GetName();

	CONTEXT("Evaluating rule for group '" + group_name + "'");

	ScriptFrame frame;
	if (group->GetScope())
		group->GetScope()->CopyTo(frame.Locals);
	frame.Locals->Set("user", user);

	if (!group->GetFilter()->Evaluate(frame).GetValue().ToBool())
		return false;

	Log(LogDebug, "UserGroup")
	    << "Assigning membership for group '" << group_name << "' to user '" << user->GetName() << "'";

	Array::Ptr groups = user->GetGroups();
	groups->Add(group_name);

	return true;
}
Пример #27
0
void ClientManager::userCommand(const User::Ptr& p, const ::UserCommand& uc, StringMap& params, bool compatibility) {
	Lock l(cs);
	OnlineIter i = onlineUsers.find(p->getCID());
	if(i == onlineUsers.end())
		return;

	OnlineUser& ou = *i->second;
	ou.getIdentity().getParams(params, "user", compatibility);
	ou.getClient().getHubIdentity().getParams(params, "hub", false);
	ou.getClient().getMyIdentity().getParams(params, "my", compatibility);
	ou.getClient().escapeParams(params);
	ou.getClient().sendUserCmd(Util::formatParams(uc.getCommand(), params, false));
}
User::Ptr DirectoryListing::getUserFromFilename(const string& fileName) {
	// General file list name format: [username].[CID].[xml|xml.bz2|DcLst]

	string name = Util::getFileName(fileName);

	// Strip off any extensions
	if(Util::stricmp(name.c_str() + name.length() - 6, ".DcLst") == 0) {
		name.erase(name.length() - 6);
	}

	if(Util::stricmp(name.c_str() + name.length() - 4, ".bz2") == 0) {
		name.erase(name.length() - 4);
	}

	if(Util::stricmp(name.c_str() + name.length() - 4, ".xml") == 0) {
		name.erase(name.length() - 4);
	}

	// Find CID
	string::size_type i = name.rfind('.');
	if(i == string::npos) {
		return NULL;
	}

	size_t n = name.length() - (i + 1);
	// CID's always 39 chars long...
	if(n != 39)
		return NULL;

	CID cid(name.substr(i + 1));
	if(cid.isZero())
		return NULL;

	User::Ptr p = ClientManager::getInstance()->getUser(cid);
	if(p->getFirstNick().empty())
		p->setFirstNick(name.substr(0, i));
	return p;
}
Пример #29
0
Dictionary::Ptr UserDbObject::GetStatusFields(void) const
{
	Dictionary::Ptr fields = make_shared<Dictionary>();
	User::Ptr user = static_pointer_cast<User>(GetObject());

	fields->Set("host_notifications_enabled", user->GetEnableNotifications());
	fields->Set("service_notifications_enabled", user->GetEnableNotifications());
	fields->Set("last_host_notification", DbValue::FromTimestamp(user->GetLastNotification()));
	fields->Set("last_service_notification", DbValue::FromTimestamp(user->GetLastNotification()));
	fields->Set("modified_attributes", user->GetModifiedAttributes());
	fields->Set("modified_host_attributes", Empty);
	fields->Set("modified_service_attributes", Empty);

	return fields;
}
Пример #30
0
void NmdcHub::onLine(const string& aLine) throw() {
	lastActivity = GET_TICK();

	if(aLine.length() == 0)
		return;
	
	if(aLine[0] != '$') {
		// Check if we're being banned...
		if(state != STATE_CONNECTED) {
			if(Util::findSubString(aLine, "banned") != string::npos) {
				reconnect = false;
			}
		}
		Speaker<NmdcHubListener>::fire(NmdcHubListener::Message(), this, Util::validateMessage(fromNmdc(aLine), true));
		return;
	}

	string cmd;
	string param;
	string::size_type x;
	
	if( (x = aLine.find(' ')) == string::npos) {
		cmd = aLine;
	} else {
		cmd = aLine.substr(0, x);
		param = aLine.substr(x+1);
	}

	if(cmd == "$Search") {
		if(state != STATE_CONNECTED) {
			return;
		}
		string::size_type i = 0;
		string::size_type j = param.find(' ', i);
		if(j == string::npos || i == j)
			return;
		
		string seeker = fromNmdc(param.substr(i, j-i));

		// Filter own searches
		if(SETTING(CONNECTION_TYPE) == SettingsManager::CONNECTION_ACTIVE) {
			if(seeker == (getLocalIp() + ":" + Util::toString(SETTING(IN_PORT)))) {
				return;
			}
		} else {
			// Hub:seeker
			if(Util::stricmp(seeker.c_str() + 4, getNick().c_str()) == 0) {
				return;
			}
		}

		i = j + 1;
		
		{
			Lock l(cs);
			u_int32_t tick = GET_TICK();

			seekers.push_back(make_pair(seeker, tick));

			// First, check if it's a flooder
			FloodIter fi;
			for(fi = flooders.begin(); fi != flooders.end(); ++fi) {
				if(fi->first == seeker) {
					return;
				}
			}

			int count = 0;
			for(fi = seekers.begin(); fi != seekers.end(); ++fi) {
				if(fi->first == seeker)
					count++;

				if(count > 7) {
					if(seeker.compare(0, 4, "Hub:") == 0)
						Speaker<NmdcHubListener>::fire(NmdcHubListener::SearchFlood(), this, seeker.substr(4));
					else
						Speaker<NmdcHubListener>::fire(NmdcHubListener::SearchFlood(), this, seeker + STRING(NICK_UNKNOWN));

					flooders.push_back(make_pair(seeker, tick));
					return;
				}
			}
		}

		int a;
		if(param[i] == 'F') {
			a = SearchManager::SIZE_DONTCARE;
		} else if(param[i+2] == 'F') {
			a = SearchManager::SIZE_ATLEAST;
		} else {
			a = SearchManager::SIZE_ATMOST;
		}
		i += 4;
		j = param.find('?', i);
		if(j == string::npos || i == j)
			return;
		string size = param.substr(i, j-i);
		i = j + 1;
		j = param.find('?', i);
		if(j == string::npos || i == j)
			return;
		int type = Util::toInt(param.substr(i, j-i)) - 1;
		i = j + 1;
		param = param.substr(i);

		if(param.size() > 0) {
			Speaker<NmdcHubListener>::fire(NmdcHubListener::Search(), this, seeker, a, Util::toInt64(size), type, fromNmdc(param));
			
			if(seeker.compare(0, 4, "Hub:") == 0) {
				User::Ptr u;
				{
					Lock l(cs);
					User::NickIter ni = users.find(seeker.substr(4));
					if(ni != users.end() && !ni->second->isSet(User::PASSIVE)) {
						u = ni->second;
						u->setFlag(User::PASSIVE);
					}
				}

				if(u) {
					updated(u);
				}
			}
		}
	} else if(cmd == "$MyINFO") {
		string::size_type i, j;
		i = 5;
		j = param.find(' ', i);
		if( (j == string::npos) || (j == i) )
			return;
		string nick = fromNmdc(param.substr(i, j-i));
		i = j + 1;
		User::Ptr u;
		dcassert(nick.size() > 0);

		{
			Lock l(cs);
			User::NickIter ni = users.find(nick);
			if(ni == users.end()) {
				u = users[nick] = ClientManager::getInstance()->getUser(nick, this);
			} else {
				u  = ni->second;
			}
		}
		j = param.find('$', i);
		if(j == string::npos)
			return;
		string tmpDesc = Util::validateMessage(fromNmdc(param.substr(i, j-i)), true);
		// Look for a tag...
		if(tmpDesc.size() > 0 && tmpDesc[tmpDesc.size()-1] == '>') {
			x = tmpDesc.rfind('<');
			if(x != string::npos) {
				// Hm, we have something...
				u->setTag(tmpDesc.substr(x));
				tmpDesc.erase(x);
			} else {
				u->setTag(Util::emptyString);
			}
		} else {
			u->setTag(Util::emptyString);
		}
		u->setDescription(tmpDesc);
		i = j + 3;
		j = param.find('$', i);
		if(j == string::npos)
			return;
		u->setConnection(fromNmdc(param.substr(i, j-i-1)));
		i = j + 1;
		j = param.find('$', i);
		if(j == string::npos)
			return;
		u->setEmail(Util::validateMessage(fromNmdc(param.substr(i, j-i)), true));
		i = j + 1;
		j = param.find('$', i);
		if(j == string::npos)
			return;
		u->setBytesShared(param.substr(i, j-i));

		Speaker<NmdcHubListener>::fire(NmdcHubListener::MyInfo(), this, u);
	} else if(cmd == "$Quit") {
		if(!param.empty()) {
			User::Ptr u;
			{
				Lock l(cs);
				User::NickIter i = users.find(fromNmdc(param));
				if(i == users.end()) {
					dcdebug("C::onLine Quitting user %s not found\n", param.c_str());
					return;
				}
				
				u = i->second;
				users.erase(i);
			}
			
			Speaker<NmdcHubListener>::fire(NmdcHubListener::Quit(), this, u);
			ClientManager::getInstance()->putUserOffline(u, true);
		}
	} else if(cmd == "$ConnectToMe") {
		if(state != STATE_CONNECTED) {
			return;
		}
		string::size_type i = param.find(' ');
		string::size_type j;
		if( (i == string::npos) || ((i + 1) >= param.size()) ) {
			return;
		}
		i++;
		j = param.find(':', i);
		if(j == string::npos) {
			return;
		}
		string server = fromNmdc(param.substr(i, j-i));
		if(j+1 >= param.size()) {
			return;
		}
		string port = param.substr(j+1);
		ConnectionManager::getInstance()->connect(server, (short)Util::toInt(port), getNick()); 
		Speaker<NmdcHubListener>::fire(NmdcHubListener::ConnectToMe(), this, server, (short)Util::toInt(port));
	} else if(cmd == "$RevConnectToMe") {
		if(state != STATE_CONNECTED) {
			return;
		}
		User::Ptr u;
		bool up = false;
		{
			Lock l(cs);
			string::size_type j = param.find(' ');
			if(j == string::npos) {
				return;
			}

			User::NickIter i = users.find(fromNmdc(param.substr(0, j)));
			if(i == users.end()) {
				return;
			}

			u = i->second;
			if(!u->isSet(User::PASSIVE)) {
				u->setFlag(User::PASSIVE);
				up = true;
			}
		}

		if(u) {
			if(SETTING(CONNECTION_TYPE) == SettingsManager::CONNECTION_ACTIVE) {
				connectToMe(u);
				Speaker<NmdcHubListener>::fire(NmdcHubListener::RevConnectToMe(), this, u);
			} else {
				// Notify the user that we're passive too...
				if(up)
					revConnectToMe(u);
			}

			if(up)
				updated(u);
		}
	} else if(cmd == "$SR") {
		SearchManager::getInstance()->onSearchResult(aLine);
	} else if(cmd == "$HubName") {
		name = fromNmdc(param);
		Speaker<NmdcHubListener>::fire(NmdcHubListener::HubName(), this);
	} else if(cmd == "$Supports") {
		StringTokenizer<string> st(param, ' ');
		StringList& sl = st.getTokens();
		for(StringIter i = sl.begin(); i != sl.end(); ++i) {
			if(*i == "UserCommand") {
				supportFlags |= SUPPORTS_USERCOMMAND;
			} else if(*i == "NoGetINFO") {
				supportFlags |= SUPPORTS_NOGETINFO;
			} else if(*i == "UserIP2") {
				supportFlags |= SUPPORTS_USERIP2;
			}
		}
		Speaker<NmdcHubListener>::fire(NmdcHubListener::Supports(), this, sl);
	} else if(cmd == "$UserCommand") {
		string::size_type i = 0;
		string::size_type j = param.find(' ');
		if(j == string::npos)
			return;

		int type = Util::toInt(param.substr(0, j));
		i = j+1;
 		if(type == UserCommand::TYPE_SEPARATOR || type == UserCommand::TYPE_CLEAR) {
			int ctx = Util::toInt(param.substr(i));
			Speaker<NmdcHubListener>::fire(NmdcHubListener::UserCommand(), this, type, ctx, Util::emptyString, Util::emptyString);
		} else if(type == UserCommand::TYPE_RAW || type == UserCommand::TYPE_RAW_ONCE) {
			j = param.find(' ', i);
			if(j == string::npos)
				return;
			int ctx = Util::toInt(param.substr(i));
			i = j+1;
			j = param.find('$');
			if(j == string::npos)
				return;
			string name = fromNmdc(param.substr(i, j-i));
			i = j+1;
			string command = fromNmdc(param.substr(i, param.length() - i));
			Speaker<NmdcHubListener>::fire(NmdcHubListener::UserCommand(), this, type, ctx, Util::validateMessage(name, true, false), Util::validateMessage(command, true, false));
		}
	} else if(cmd == "$Lock") {
		if(state != STATE_LOCK) {
			return;
		}
		state = STATE_HELLO;

		if(!param.empty()) {
			string::size_type j = param.find(" Pk=");
			string lock, pk;
			if( j != string::npos ) {
				lock = param.substr(0, j);
				pk = param.substr(j + 4);
			} else {
				// Workaround for faulty linux hubs...
				j = param.find(" ");
				if(j != string::npos)
					lock = param.substr(0, j);
				else
					lock = param;
			}

			if(CryptoManager::getInstance()->isExtended(lock)) {
				StringList feat;
				feat.push_back("UserCommand");
				feat.push_back("NoGetINFO");
				feat.push_back("NoHello");
				feat.push_back("UserIP2");
				feat.push_back("TTHSearch");

				if(BOOLSETTING(COMPRESS_TRANSFERS))
					feat.push_back("GetZBlock");
				supports(feat);
			}

			key(CryptoManager::getInstance()->makeKey(lock));
			validateNick(getNick());

			Speaker<NmdcHubListener>::fire(NmdcHubListener::CLock(), this, lock, pk);	
		}
	} else if(cmd == "$Hello") {
		if(!param.empty()) {
			string nick = fromNmdc(param);
			User::Ptr u = ClientManager::getInstance()->getUser(nick, this);
			{
				Lock l(cs);
				users[nick] = u;
			}

			if(getNick() == nick) {
				setMe(u);

				u->setFlag(User::DCPLUSPLUS);
				if(SETTING(CONNECTION_TYPE) != SettingsManager::CONNECTION_ACTIVE)
					u->setFlag(User::PASSIVE);
				else
					u->unsetFlag(User::PASSIVE);
			}

			if(state == STATE_HELLO) {
				state = STATE_CONNECTED;
				updateCounts(false);

				version();
				getNickList();
				myInfo();
			}

			Speaker<NmdcHubListener>::fire(NmdcHubListener::Hello(), this, u);
		}
	} else if(cmd == "$ForceMove") {
		disconnect();
		Speaker<NmdcHubListener>::fire(NmdcHubListener::Redirect(), this, param);
	} else if(cmd == "$HubIsFull") {
		Speaker<NmdcHubListener>::fire(NmdcHubListener::HubFull(), this);
	} else if(cmd == "$ValidateDenide") {		// Mind the spelling...
		disconnect();
		Speaker<NmdcHubListener>::fire(NmdcHubListener::ValidateDenied(), this);
	} else if(cmd == "$UserIP") {
		if(!param.empty()) {
			User::List v;
			StringTokenizer<string> t(fromNmdc(param), "$$");
			StringList& l = t.getTokens();
			for(StringIter it = l.begin(); it != l.end(); ++it) {
				string::size_type j = 0;
				if((j = it->find(' ')) == string::npos)
					continue;
				if((j+1) == it->length())
					continue;
				v.push_back(ClientManager::getInstance()->getUser(it->substr(0, j), this));
				v.back()->setIp(it->substr(j+1));
			}

			Speaker<NmdcHubListener>::fire(NmdcHubListener::UserIp(), this, v);
		}
	} else if(cmd == "$NickList") {
		if(!param.empty()) {
			User::List v;
			StringTokenizer<string> t(fromNmdc(param), "$$");
			StringList& sl = t.getTokens();

			for(StringIter it = sl.begin(); it != sl.end(); ++it) {
				v.push_back(ClientManager::getInstance()->getUser(*it, this));
			}

			{
				Lock l(cs);
				for(User::Iter it2 = v.begin(); it2 != v.end(); ++it2) {
					users[(*it2)->getNick()] = *it2;
				}
			}
			
			if(!(getSupportFlags() & SUPPORTS_NOGETINFO)) {
				string tmp;
				// Let's assume 10 characters per nick...
				tmp.reserve(v.size() * (11 + 10 + getNick().length())); 
				for(User::List::const_iterator i = v.begin(); i != v.end(); ++i) {
					tmp += "$GetINFO ";
					tmp += (*i)->getNick();
					tmp += ' ';
					tmp += getNick(); 
					tmp += '|';
				}
				if(!tmp.empty()) {
					send(tmp);
				}
			} 

			Speaker<NmdcHubListener>::fire(NmdcHubListener::NickList(), this, v);
		}
	} else if(cmd == "$OpList") {
		if(!param.empty()) {
			User::List v;
			StringTokenizer<string> t(fromNmdc(param), "$$");
			StringList& sl = t.getTokens();
			for(StringIter it = sl.begin(); it != sl.end(); ++it) {
				v.push_back(ClientManager::getInstance()->getUser(*it, this));
				v.back()->setFlag(User::OP);
			}

			{
				Lock l(cs);
				for(User::Iter it2 = v.begin(); it2 != v.end(); ++it2) {
					users[(*it2)->getNick()] = *it2;
				}
			}
			Speaker<NmdcHubListener>::fire(NmdcHubListener::OpList(), this, v);
			updateCounts(false);
			// Special...to avoid op's complaining that their count is not correctly
			// updated when they log in (they'll be counted as registered first...)
			myInfo();
		}
	} else if(cmd == "$To:") {
		string::size_type i = param.find("From:");
		if(i != string::npos) {
			i+=6;
			string::size_type j = param.find("$");
			if(j != string::npos) {
				string from = fromNmdc(param.substr(i, j - 1 - i));
				if(from.size() > 0 && param.size() > (j + 1)) {
					Speaker<NmdcHubListener>::fire(NmdcHubListener::PrivateMessage(), this, ClientManager::getInstance()->getUser(from, this, false), Util::validateMessage(fromNmdc(param.substr(j + 1)), true));
				}
			}
		}
	} else if(cmd == "$GetPass") {
		setRegistered(true);
		Speaker<NmdcHubListener>::fire(NmdcHubListener::GetPassword(), this);
	} else if(cmd == "$BadPass") {
		Speaker<NmdcHubListener>::fire(NmdcHubListener::BadPassword(), this);
	} else if(cmd == "$LogedIn") {
		Speaker<NmdcHubListener>::fire(NmdcHubListener::LoggedIn(), this);
	} else {
		dcassert(cmd[0] == '$');
		dcdebug("NmdcHub::onLine Unknown command %s\n", aLine.c_str());
	} 
}