C4Network2IRCChannel *C4Network2IRCClient::getChannel(const char *szName) const 
	{
	for(C4Network2IRCChannel *pChan = pChannels; pChan; pChan = pChan->Next)
		if(SEqualNoCase(pChan->getName(), szName))
			return pChan;
	return NULL;
	}
Beispiel #2
0
void C4ChatControl::ChatSheet::Update(bool fLock) {
  // lock IRC client data if desired
  if (fLock) {
    CStdLock Lock(pChatControl->getIRCClient()->getCSec());
    Update(false);
    return;
  }
  // only channels need updates
  if (eType == CS_Channel) {
    C4Network2IRCChannel *pIRCChan =
        pChatControl->getIRCClient()->getChannel(GetIdent());
    if (pIRCChan) {
      // update user list (if not locked, becuase it's being received)
      if (!pIRCChan->isUsersLocked()) UpdateUsers(pIRCChan->getUsers());
      // update topic
      const char *szTopic = pIRCChan->getTopic();
      sChatTitle.Format("%s%s%s", sIdent.getData(), szTopic ? ": " : "",
                        szTopic ? szTopic : "");
      convUTF8toWindows(sChatTitle);
    }
  }
}
void C4Network2IRCClient::OnNumericCommand(const char *szSender, int iCommand, const char *szParameters)
	{
	bool fShowMessage = true;
	// Get target
	StdStrBuf Target = ircExtractPar(&szParameters);
	// Handle command
	switch(iCommand)
		{

		case 433: // Nickname already in use
			{
			StdStrBuf DesiredNick = ircExtractPar(&szParameters);
			// Automatically try to choose a new one
			DesiredNick.AppendChar('_');
			Send("NICK", DesiredNick.getData());
			break;
			}

		case 376: // End of MOTD
		case 422: // MOTD missing
			// Let's take this a sign that the connection is established.
			OnConnected();
			break;

		case 331: // No topic set
		case 332: // Topic notify / change
			{
			// Get Channel name and topic
			StdStrBuf Channel = ircExtractPar(&szParameters);
			StdStrBuf Topic = (iCommand == 332 ? ircExtractPar(&szParameters) : StdStrBuf(""));
			// Set it
			AddChannel(Channel.getData())->OnTopic(Topic.getData());
			// Log
			if(Topic.getLength())
				PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_TOPICIN"), Channel.getData(), Topic.getData()).getData());
			}
			break;

		case 333: // Last topic change
			fShowMessage = false; // ignore
			break;

		case 353: // Names in channel
			{
			// Get Channel name and name list
			StdStrBuf Junk = ircExtractPar(&szParameters); // ??!
			StdStrBuf Channel = ircExtractPar(&szParameters);
			StdStrBuf Names = ircExtractPar(&szParameters);
			// Set it
			AddChannel(Channel.getData())->OnUsers(Names.getData(), Prefixes.getData());
			fShowMessage = false;
			}
			break;

		case 366: // End of names list
			{
			// Get Channel name
			StdStrBuf Channel = ircExtractPar(&szParameters);
			// Finish
			AddChannel(Channel.getData())->OnUsersEnd();
			fShowMessage = false;
      // Notify
      if(pNotify) pNotify->PushEvent(Ev_IRC_Message, this);
			}
			break;

		case 4: // Server version
			fShowMessage = false; // ignore
			break;

		case 5: // Server support string
			{
			while(szParameters && *szParameters)
				{
				// Get support-token.
				StdStrBuf Token = ircExtractPar(&szParameters);
				StdStrBuf Parameter; Parameter.CopyUntil(Token.getData(), '=');
				// Check if it's interesting and safe data if so.
				if(SEqualNoCase(Parameter.getData(), "PREFIX"))
					Prefixes.Copy(SSearch(Token.getData(), "="));
				}
			fShowMessage = false;
			}
			break;

		}
	// Show embedded message, if any?
	if(fShowMessage)
		{
		// Check if first parameter is some sort of channel name
		C4Network2IRCChannel *pChannel = NULL;
		if(szParameters && *szParameters && *szParameters != ':')
			pChannel = getChannel(ircExtractPar(&szParameters).getData());
		// Go over other parameters
		const char *pMsg = szParameters;
		while(pMsg && *pMsg && *pMsg != ':')
			pMsg = SSearch(pMsg, " ");
		// Show it
		if(pMsg && *pMsg)
			if(!pChannel)
				PushMessage(MSG_Server, szSender, Nick.getData(), pMsg + 1);
			else
				PushMessage(MSG_Status, szSender, pChannel->getName(), pMsg + 1);
		}
	}
void C4Network2IRCClient::OnCommand(const char *szSender, const char *szCommand, const char *szParameters)
	{
	CStdLock Lock(&CSec);
	// Numeric command?
	if(isdigit((unsigned char)*szCommand) && SLen(szCommand) == 3)
		{
		OnNumericCommand(szSender, atoi(szCommand), szParameters);
		return;
		}
	// Sender's nick
	StdStrBuf SenderNick;
	if(szSender) SenderNick.CopyUntil(szSender, '!');
	// Ping?
	if(SEqualNoCase(szCommand, "PING"))
		Send("PONG", szParameters);
	// Message?
	if(SEqualNoCase(szCommand, "NOTICE") || SEqualNoCase(szCommand, "PRIVMSG"))
		{
		// Get target
		StdStrBuf Target = ircExtractPar(&szParameters);
		// Get text
		StdStrBuf Text = ircExtractPar(&szParameters);
		// Process message
		OnMessage(SEqualNoCase(szCommand, "NOTICE"), szSender, Target.getData(), Text.getData());
		}
	// Channel join?
	if(SEqualNoCase(szCommand, "JOIN"))
		{
		// Get channel
		StdStrBuf Channel = ircExtractPar(&szParameters);
		C4Network2IRCChannel *pChan = AddChannel(Channel.getData());
		// Add user
		pChan->OnJoin(SenderNick.getData());
		// Myself?
		if(SenderNick == Nick)
			PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_YOUHAVEJOINEDCHANNEL"), Channel.getData()).getData());
		else
			PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_HASJOINEDTHECHANNEL"), SenderNick.getData()).getData());
		}
	// Channel part?
	if(SEqualNoCase(szCommand, "PART"))
		{
		// Get channel
		StdStrBuf Channel = ircExtractPar(&szParameters);
		C4Network2IRCChannel *pChan = AddChannel(Channel.getData());
		// Get message
		StdStrBuf Comment = ircExtractPar(&szParameters);
		// Remove user
		pChan->OnPart(SenderNick.getData(), Comment.getData());
		// Myself?
		if(SenderNick == Nick)
			{
			DeleteChannel(pChan);
			PushMessage(MSG_Status, szSender, Nick.getData(), FormatString(LoadResStr("IDS_MSG_YOUHAVELEFTCHANNEL"), Channel.getData(), Comment.getData()).getData());
			}
		else
			PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_HASLEFTTHECHANNEL"), SenderNick.getData(), Comment.getData()).getData());
		}
	// Kick?
	if(SEqualNoCase(szCommand, "KICK"))
		{
		// Get channel
		StdStrBuf Channel = ircExtractPar(&szParameters);
		C4Network2IRCChannel *pChan = AddChannel(Channel.getData());
		// Get kicked user
		StdStrBuf Kicked = ircExtractPar(&szParameters);
		// Get message
		StdStrBuf Comment = ircExtractPar(&szParameters);
		// Remove user
		pChan->OnKick(Kicked.getData(), Comment.getData());
		// Myself? 
		if(Kicked == Nick)
			{
			DeleteChannel(pChan);
			PushMessage(MSG_Status, szSender, Nick.getData(), FormatString(LoadResStr("IDS_MSG_YOUWEREKICKEDFROMCHANNEL"), Channel.getData(), Comment.getData()).getData());
			}
		else
			PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_WASKICKEDFROMTHECHANNEL"), Kicked.getData(), Comment.getData()).getData());
		}
	// Quit?
	if(SEqualNoCase(szCommand, "QUIT"))
		{
		// Get comment
		StdStrBuf Comment = ircExtractPar(&szParameters);
		// Format status message
    StdStrBuf Message = FormatString(LoadResStr("IDS_MSG_HASDISCONNECTED"), SenderNick.getData(), Comment.getData());
    // Remove him from all channels
    for(C4Network2IRCChannel *pChan = pChannels; pChan; pChan = pChan->Next)
      if(pChan->getUser(SenderNick.getData()))
        {
        pChan->OnPart(SenderNick.getData(), "Quit");
        PushMessage(MSG_Status, szSender, pChan->getName(), Message.getData());
        }
		}
	// Topic change?
	if(SEqualNoCase(szCommand, "TOPIC"))
		{
		// Get channel and topic
		StdStrBuf Channel = ircExtractPar(&szParameters);
		StdStrBuf Topic = ircExtractPar(&szParameters);
		// Set topic
		AddChannel(Channel.getData())->OnTopic(Topic.getData());
		// Message
		PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_CHANGESTHETOPICTO"), SenderNick.getData(), Topic.getData()).getData());
		}
	// Mode?
	if(SEqualNoCase(szCommand, "MODE"))
		{
		// Get all data
		StdStrBuf Channel = ircExtractPar(&szParameters);
		StdStrBuf Flags = ircExtractPar(&szParameters);
		StdStrBuf What = ircExtractPar(&szParameters);
		// Make sure it's a channel
		C4Network2IRCChannel *pChan = getChannel(Channel.getData());
		if(pChan)
			// Ask for names, because user prefixes might be out of sync
			Send("NAMES", Channel.getData());
		// Show Message
		PushMessage(MSG_Status, szSender, Channel.getData(), FormatString(LoadResStr("IDS_MSG_SETSMODE"), SenderNick.getData(), Flags.getData(), What.getData()).getData());
		}
	// Error?
	if(SEqualNoCase(szCommand, "ERROR"))
		{
		// Get message
		StdStrBuf Message = ircExtractPar(&szParameters);
		// Push it
		PushMessage(MSG_Server, szSender, Nick.getData(), Message.getData());
		}
	// Nickchange?
	if(SEqualNoCase(szCommand, "NICK"))
		{
		// Get new nick
		StdStrBuf NewNick = ircExtractPar(&szParameters);
		// Format status message
    StdStrBuf Message = FormatString(LoadResStr("IDS_MSG_ISNOWKNOWNAS"), SenderNick.getData(), NewNick.getData());
    // Rename on all channels
    for(C4Network2IRCChannel *pChan = pChannels; pChan; pChan = pChan->Next)
      if(pChan->getUser(SenderNick.getData()))
        {
        pChan->OnPart(SenderNick.getData(), "Nickchange");
        pChan->OnJoin(NewNick.getData());
        PushMessage(MSG_Status, szSender, pChan->getName(), Message.getData());
        }
    // Self?
    if(SenderNick == Nick)
      Nick = NewNick;
		}
	}
Beispiel #5
0
void C4ChatControl::Update() {
  CStdLock Lock(pIRCClient->getCSec());
  // update channels
  for (C4Network2IRCChannel *pChan = pIRCClient->getFirstChannel(); pChan;
       pChan = pIRCClient->getNextChannel(pChan)) {
    ChatSheet *pChanSheet =
        GetSheetByIdent(pChan->getName(), ChatSheet::CS_Channel);
    if (!pChanSheet) {
      // new channel! Create sheet for it
      pTabChats->AddCustomSheet(
          pChanSheet = new ChatSheet(this, pChan->getName(), pChan->getName(),
                                     ChatSheet::CS_Channel));
      // and show immediately
      pTabChats->SelectSheet(pChanSheet, false);
    }
  }
  // remove parted channels
  int32_t i = 0;
  C4GUI::Tabular::Sheet *pSheet;
  while (pSheet = pTabChats->GetSheet(i++)) {
    C4Network2IRCChannel *pIRCChan;
    ChatSheet *pChatSheet = static_cast<ChatSheet *>(pSheet);
    if (pChatSheet->GetSheetType() == ChatSheet::CS_Channel)
      if (!(pIRCChan = pIRCClient->getChannel(pChatSheet->GetTitle()))) {
        delete pChatSheet;
        --i;
      }
  }
  // retrieve messages: All messages in initial update; only unread in
  // subsequent calls
  C4Network2IRCMessage *pMsg;
  if (fInitialMessagesReceived) {
    pMsg = pIRCClient->getUnreadMessageLog();
  } else {
    pMsg = pIRCClient->getMessageLog();
    fInitialMessagesReceived = true;
  }
  // update messages
  for (; pMsg; pMsg = pMsg->getNext()) {
    // get target sheet to put message into
    ChatSheet *pChatSheet;
    StdStrBuf sUser, sIdent;
    bool fMsgToService = false;
    if (pMsg->getType() == MSG_Server) {
      // server messages in server sheet
      pChatSheet = GetServerSheet();
    } else {
      if (pMsg->getType() != MSG_Status) sUser.Copy(pMsg->getSource());
      if (!sUser.SplitAtChar('!', &sIdent)) sIdent.Ref(sUser);
      // message: Either channel or user message (or channel notify). Get
      // correct sheet.
      if (pMsg->isChannel()) {
        // if no sheet is found, don't create - assume it's an outdated message
        // with the cahnnel window already closed
        pChatSheet = GetSheetByIdent(pMsg->getTarget(), ChatSheet::CS_Channel);
      } else if (IsServiceName(sUser.getData())) {
        // notices and messages by services always in server sheet
        pChatSheet = GetServerSheet();
      } else if (pMsg->getType() == MSG_Notice) {
        // notifies in current sheet; default to server sheet
        pChatSheet = GetActiveChatSheet();
        if (!pChatSheet) pChatSheet = GetServerSheet();
      } else if (pMsg->getType() == MSG_Status || !sUser.getLength()) {
        // server message
        pChatSheet = GetServerSheet();
      } else if (sUser == pIRCClient->getUserName()) {
        // private message by myself
        // message to a service into service window; otherwise (new) query
        if (IsServiceName(pMsg->getTarget())) {
          pChatSheet = GetServerSheet();
          fMsgToService = true;
        } else {
          pChatSheet = OpenQuery(pMsg->getTarget(), true, NULL);
          if (pChatSheet) pChatSheet->SetChatTitle(pMsg->getTarget());
        }
      } else {
        // private message
        pChatSheet = OpenQuery(sUser.getData(), false, sIdent.getData());
        if (pChatSheet) pChatSheet->SetChatTitle(pMsg->getSource());
      }
    }
    if (pChatSheet) {
      // get message formatting and color
      StdStrBuf sMsg;
      uint32_t dwClr = C4GUI_MessageFontClr;
      switch (pMsg->getType()) {
        case MSG_Server:
          sMsg.Format("- %s", pMsg->getData());
          break;

        case MSG_Status:
          sMsg.Format("- %s", pMsg->getData());
          dwClr = C4GUI_InactMessageFontClr;
          break;

        case MSG_Notice:
          if (sUser.getLength())
            if (sUser != pIRCClient->getUserName())
              sMsg.Format("-%s- %s", sUser.getData(), pMsg->getData());
            else
              sMsg.Format("-> -%s- %s", pMsg->getTarget(), pMsg->getData());
          else
            sMsg.Format("* %s", pMsg->getData());
          dwClr = C4GUI_NotifyFontClr;
          break;

        case MSG_Message:
          if (fMsgToService)
            sMsg.Format("-> *%s* %s", pMsg->getTarget(), pMsg->getData());
          else if (sUser.getLength())
            sMsg.Format("<%s> %s", sUser.getData(), pMsg->getData());
          else
            sMsg.Format("* %s", pMsg->getData());
          break;

        case MSG_Action:
          if (sUser.getLength())
            sMsg.Format("* %s %s", sUser.getData(), pMsg->getData());
          else
            sMsg.Format("* %s", pMsg->getData());
          break;

        default:
          sMsg.Format("??? %s", pMsg->getData());
          dwClr = C4GUI_ErrorFontClr;
          break;
      }
      pChatSheet->AddTextLine(sMsg.getData(), dwClr);
    }
  }
  // OK; all messages processed. Delete overflow messages.
  pIRCClient->MarkMessageLogRead();
  // update selected channel (users, topic)
  ChatSheet *pActiveSheet = GetActiveChatSheet();
  if (pActiveSheet) pActiveSheet->Update(false);
  // update title
  UpdateTitle();
}