Пример #1
0
CString CProcessStatus::makeTempPathShort(LPCTSTR lpszFileName, LPCTSTR lpszExtension)
{
	CString& sLong =  makeTempPath(lpszFileName, lpszExtension);

	int iResult = _taccess(sLong, 02); // ask for write permission

	if(-1 == iResult)
	{
		if(errno == EACCES)
		{
			CString sError(_T("Some process left this file open, so it can't be written to: "));
			sError += sLong;
			throw(sError);
		}
		else if (errno == ENOENT)
		{
			TRACE(_T("Creating %s for makeTempPath\n"), sLong);
			USES_CONVERSION;
			FILE* f = fopen(T2CA(sLong), "w"); // create it
			ASSERTX(f);
			fclose(f);
		}
		else
		{
			CString sError(_T("Unknown error trying to check the access permisions of the file: "));
			sError += sLong;
			throw(sError);
		}
	}
	ASSERTX(!_taccess(sLong, 02));

/*	// can't get a shortpath unless the file exists.  So we
	// need to make it exist if it doesn't already

	FILE*f = fopen(sLong, "r"); // does it exist?
	if(!f)
	{
		TRACE("Creating %s for makeTempPath\n", sLong);
		f = fopen(sLong, "w"); // create it
		ASSERTX(f);
	}
	fclose(f);
*/
//return sLong;
	TCHAR shortPath[1000];
	DWORD result = GetShortPathName( sLong, shortPath, 1000);
	ASSERTX(1000 > result);
	if(!result)
	{
		::checkForFileError(sLong, FALSE);
	}
	return CString(shortPath);
}
Пример #2
0
void
ITreeItem::TreeItemW_SetIconError(PSZUC pszuErrorMessage, EMenuAction eMenuIcon)
	{
	Assert(pszuErrorMessage != NULL);
	CString sError(pszuErrorMessage);
	if ((m_uFlagsTreeItem & FTI_kmIconMask) == FTI_keIcon_Error)
		{
		// There is already an error, so concatenate both, unless this is the same error.
		// Sometimes a server may send two stanzas with the same identical error.  I have no idea what is the motivation (or if it is a bug), however the same error should be displayed only once
		if (m_paTreeItemW_YZ != NULL)
			{
			QString sErrorPrevious = m_paTreeItemW_YZ->toolTip(0);
			if (!sErrorPrevious.contains(sError))
				{
				if (!sErrorPrevious.endsWith("</ol>"))
					{
					sError.Format("<div style='margin:-25px;'><ol><li>$Q</li><li>$Q</li></ol></div>", &sErrorPrevious, &sError);
					}
				else
					{
					sErrorPrevious.truncate(sErrorPrevious.length() - 5);	// Remove the "</ul>"
					sError.Format("$Q<li>$Q</li></ol></div>", &sErrorPrevious, &sError);
					}
				}
			}
		}
	//qApp->setStyleSheet("QToolTip { background-color: red }");
	//qApp->setStyleSheet("QToolTip { indent: 3 }");
	TreeItemW_SetIconWithToolTip(eMenuIcon, sError);
	m_uFlagsTreeItem = (m_uFlagsTreeItem & ~FTI_kmIconMask) | FTI_keIcon_Error;
	} // TreeItemW_SetIconError()
Пример #3
0
void SFMFile::logCommentSkip(LPCTSTR lpszField, LPCTSTR lpszMoreInfo)
{
	USES_CONVERSION_U8;
	ostrstream sout;
	if(m_bNothingLogged)
	{
		m_bNothingLogged=FALSE;
		sout << "The following possible problem(s) occurred while parsing the file " << T2CA(m_pathName) << "\r\n";
	}

	if(!m_bDidOutputSkippedCommentNotice)
	{
		m_bDidOutputSkippedCommentNotice = TRUE;
		sout << "Sorry, CarlaStudio did not know where to locate one or more comments.\r\n";
		sout << "You will need to copy these 'skipped comments' and paste them where you want them.\r\n";
	}
	sout << "Skipped comment: \"" << T2CU8(lpszField) << "\"\r\n";
	if(lpszMoreInfo)
				sout << "    " << T2CU8(lpszMoreInfo) <<  "\r\n";
	// to do: add line number?
	sout << "\r\n";
#ifndef rde270
	// I'm just not sure if sout.str is going to be null terminated, so do it the long way.
	int nLen = sout.pcount();
	char* pSout = (char*)alloca(nLen + 1);
	strncpy(pSout, sout.str(), nLen);
	pSout[nLen] = '\0';
	CString sError(U82CT(pSout));
#else   // rde270
	CString sError (sout.str(), sout.pcount());
#endif  // rde270
	sout.rdbuf()->freeze(0); // else get a memory leak
	LOG(sError);
}
Пример #4
0
// TODO: add line number to output
void SFMFile::throwParseFailure(LPCTSTR lpszParserName,
								LPCTSTR lpszMarker,
								LPCTSTR lpszField,
								LPCTSTR lpszMoreInfo)
{
	USES_CONVERSION_U8;
	ostrstream sout;

	sout << "The parser " << T2CA(lpszParserName) << " cannot understand ";
	sout << "\n\\" << T2CA(lpszMarker) << " " << T2CA(lpszField) << '\n';
	if(lpszMoreInfo)
		sout << T2CU8(lpszMoreInfo) << '\n';
	sout << "File: " << T2CA(m_pathName) << '\n';
	// to do: add line number?
#ifndef rde270
	// I'm just not sure if sout.str is going to be null terminated, so do it the long way.
	int nLen = sout.pcount();
	char* pSout = (char*)alloca(nLen + 1);
	strncpy(pSout, sout.str(), nLen);
	pSout[nLen] = '\0';
	CString sError(U82CT(pSout));
#else   // rde270
	CString sError (sout.str(), sout.pcount());
#endif  // rde270
	sout.rdbuf()->freeze(0); // else get a memory leak
	throw(sError);
}
Пример #5
0
TcpConnector::TcpConnector(QWidget *parent)
: QWidget(parent)
, mConnect(false)
{
    socket = new QTcpSocket(this);
    connect(socket , SIGNAL(connected()),    this, SLOT(sConnect()));
    connect(socket,  SIGNAL(disconnected()), this, SLOT(sDisconnect()));
    connect(socket,  SIGNAL(readyRead()),    this, SLOT(readAndSplit()));
    connect(socket,  SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sError(QAbstractSocket::SocketError)));
    connect(socket,  SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT( sState(QAbstractSocket::SocketState)));

    checkboxOnline = new QCheckBox(this);
    layout = new QHBoxLayout(this);
    layout->addWidget( checkboxOnline );
    setLayout(layout);

    setEnabled(false);

    connect(checkboxOnline, SIGNAL(clicked(bool)), this, SLOT(online(bool)));

    checkboxOnline->setMinimumHeight( 19 );
    checkboxOnline->setMaximumHeight( 19 );
    setMinimumHeight( 19 );
    setMaximumHeight( 19 );
    checkboxOnline->setStyleSheet("margin: 0px; border: 1px red solid;");
    setStyleSheet("margin: 0px; border: 1px red solid;");

    layout->setMargin(0);
}
Пример #6
0
// TODO: add line number to output
void SFMFile::logParseFailure(LPCTSTR lpszParserName,
								LPCTSTR lpszMarker,
								LPCTSTR lpszField,
								LPCTSTR lpszMoreInfo)
{
	USES_CONVERSION_U8;
	ostrstream sout;

	if(m_bNothingLogged)
	{
		m_bNothingLogged=FALSE;
		sout << "The following possible problem(s) occurred while parsing the file " << T2CA(m_pathName) << "\r\n";
	}

	sout << "The parser " << T2CA(lpszParserName) << " cannot understand ";
	sout << "\r\n\\" << T2CA(lpszMarker) << " " << T2CA(lpszField) << "\r\n";
	if(lpszMoreInfo)
		sout << T2CU8(lpszMoreInfo) << "\r\n";
	// to do: add line number?
#ifndef rde270
	// I'm just not sure if sout.str is going to be null terminated, so do it the long way.
	int nLen = sout.pcount();
	char* pSout = (char*)alloca(nLen + 1);
	strncpy(pSout, sout.str(), nLen);
	pSout[nLen] = '\0';
	CString sError(U82CT(pSout));
#else   // rde270
	CString sError (sout.str(), sout.pcount());
#endif  // rde270
	sout.rdbuf()->freeze(0); // else get a memory leak
	LOG2(sError,_T(""));
}
Пример #7
0
string NXConnection::GetError() const
{
  char *pError = GetLastError( pSession );
  string sError( pError );
  delete pError;
  return sError;
}
Пример #8
0
const wxArrayString &CVolumes::GetKits() const
{
  if(m_asKits.IsEmpty())
  {
    CPersistKitList *pKits = mainApp::GetKitList();
    map<wxString,CVolume *>::const_iterator itr;
    for(itr = m_mapKitVolume.begin();
      itr != m_mapKitVolume.end();
      ++itr)
    {
      const wxString &sKit(itr->first);
      if(pKits->GetLsArray(sKit) != NULL)
      {
        m_asKits.Add(sKit);
      }

      else
      {
        wxString sError("Cannot find kit: ");
        sError.Append(sKit);
        sError.Append(" in ILSandLadderInfo.xml");
        wxASSERT_MSG(0,sError);
        mainApp::LogMessage(sError);
      }
    }
  }
  return m_asKits;
}
Пример #9
0
bool CPageName::_ExtractParameters(const wxString &s)
{
  wxMemoryInputStream istr(
    (const char *)extractCXSLExportFile,
    sizeof(extractCXSLExportFile)/sizeof(extractCXSLExportFile[0]));
  wxXslSheet sheet(istr);
  bool bRtn = false;
#ifdef __WXDEBUG__
  wxString sError("CPageName::_ExtractParameters(\"");
  sError.Append(s);
  sError.Append(wxS("\"  "));
#endif
  if(sheet.IsOK())
  {
    wxXml2Document XSLin;
    XSLin.Load(s);
    if(XSLin.IsOk())
    {
      auto_ptr<wxXml2Document> apDoc(sheet.TransformToDOM(&XSLin));
      if(apDoc.get() != NULL)
      {
        CXSLExportFileType xp;
        if(xp.LoadFromNode(apDoc->GetRoot()))
        {
          m_pExportEdit->Update(xp);
          m_pExportEdit->SetXSLFile(s);
          bRtn = true;
        }
#ifdef __WXDEBUG__
        else
        {
          sError.Append("Problem loading export info");
        }
#endif
      }
#ifdef __WXDEBUG__
      else
      {
        sError.Append("Problem extracting export info from xsl file");
      }
#endif
    }
#ifdef __WXDEBUG__
    else
    {
      sError.Append("Problem loading xsl file as document");
    }
#endif
  }
#ifdef __WXDEBUG__
  else
  {
    sError.Append("Problem with internal xsl");
  }
  wxASSERT_MSG(bRtn,sError);
#endif
  return bRtn;
}
Пример #10
0
void CPersistKitList::UnitTest()
{
  CPersistKitList kitList;
  wxString sError;
  if(!kitList.Load())
  {
    wxString sError("CPersistKitList::Load() failed\n");
    wxASSERT_MSG(0,sError);
  }
#undef PP12
}
Пример #11
0
	EModRet OnRaw(CString& sLine) override {
		if (sLine.StartsWith("ERROR ")) {
			//ERROR :Closing Link: nick[24.24.24.24] (Excess Flood)
			//ERROR :Closing Link: nick[24.24.24.24] Killer (Local kill by Killer (reason))
			CString sError(sLine.substr(6));
			if (sError.Left(1) == ":")
				sError.LeftChomp();
			Log("[" + GetUser()->GetUserName() + "/" + GetNetwork()->GetName() + "] disconnected from IRC: " +
			    GetNetwork()->GetCurrentServer()->GetName() + " [" + sError + "]", LOG_NOTICE);
		}
		return CONTINUE;
        }
Пример #12
0
	virtual EModRet OnRaw(CString& sLine) {
		if (sLine.Equals("ERROR ", false, 6)) {
			//ERROR :Closing Link: nick[24.24.24.24] (Excess Flood)
			//ERROR :Closing Link: nick[24.24.24.24] Killer (Local kill by Killer (reason))
			CString sError(sLine.substr(7));
			if (sError.Left(1) == ":")
				sError.LeftChomp();
			Log("[" + m_pUser->GetUserName() + "] disconnected from IRC: " +
			    m_pUser->GetCurrentServer()->GetName() + " [" + sError + "]", LOG_NOTICE);
		}
		return CONTINUE;
        }
STDMETHODIMP CSimplePointWorkspaceFactory::OpenWorkspace(BSTR wksString, IPlugInWorkspaceHelper **wksHelper)
{
	HRESULT hr;
	USES_CONVERSION;

	if (! wksHelper ) return E_POINTER;
	
	(*wksHelper) = NULL;

	// Check its a folder
 	if (!IsDirectory(wksString))
	{
		CComBSTR sError(L"Workspace string invalid: ");
		sError.Append(wksString);
  	AtlReportError(CLSID_SimplePointWorkspaceFactory, sError, IID_IPlugInWorkspaceFactoryHelper, E_FAIL);
		return E_FAIL;
	}

  IPlugInWorkspaceHelperPtr ipPlugInWorkspaceHelper;

	// Check if the workspace is in our cache (i.e. is already open)
	PlugInWorkspaces::iterator p;
	p = m_mapWorkspaces.find(wksString);
	if (p != m_mapWorkspaces.end())
	{
		ipPlugInWorkspaceHelper = p->second;
	}
  else
  {
		// create the plug-in workspace helper
		ISimplePointWorkspaceHelperPtr ipSimplePointWorkspaceHelper;
		hr = ipSimplePointWorkspaceHelper.CreateInstance(CLSID_SimplePointWorkspaceHelper);
		if (FAILED(hr)) return hr;
			
		// initialize the workspace helper
		hr = ipSimplePointWorkspaceHelper->put_WorkspacePath(wksString);
		if (FAILED(hr)) return hr;

		ipPlugInWorkspaceHelper = ipSimplePointWorkspaceHelper;
		if (ipPlugInWorkspaceHelper == NULL) return E_FAIL;

		// add to the cache
		m_mapWorkspaces.insert(PlugInWorkspaces::value_type(wksString, ipPlugInWorkspaceHelper));
  }

  *wksHelper = ipPlugInWorkspaceHelper.Detach(); // pass ownership of pointer to client
	return S_OK;
}
Пример #14
0
	CComponent::CComponent(std::string sName, CGraph* pGraph) : m_sName(std::move(sName)), m_hComponent(NULL), m_pGraph(pGraph)
	{
		std::string sStateChangedEventName(m_sName);
		sStateChangedEventName.append(":state_changed_event");
		CHECK_VCOS(vcos_event_create(&m_StateChangedEvent, sStateChangedEventName.c_str()), "failed to create vcos event");
		std::string sEventThreadName(m_sName);
		sEventThreadName.append(":event_thread");
		m_EventThread.Start(&CComponent::EventThreadProc, this, sEventThreadName.c_str());
		std::string sEventQueueMutexName(m_sName);
		sEventQueueMutexName.append(":event_queue_mutex");
		vcos_mutex_create(&m_EventQueueMutex, sEventThreadName.c_str());
		OMX_CALLBACKTYPE Callbacks;
		Callbacks.EventHandler = &CComponent::EventHandler;
		Callbacks.EmptyBufferDone = &CComponent::EmptyBufferDone;
		Callbacks.FillBufferDone = &CComponent::FillBufferDone;
		std::string sError("failed to create component ");
		sError.append(m_sName);
		CHECK_OMX(OMX_GetHandle(&m_hComponent, const_cast<char*>(m_sName.c_str()), this, &Callbacks), sError.c_str());
	}
Пример #15
0
// returns the path compressed into 8.3 format called a "short path"
CString CPathDescriptor::getShortPath() const
{
	if(!fileExists())	// GetShortPathName() won't work unless the file exists
	{
		//jdh 2/9/00 added an exception here, had just an assert
		CString sError("This file doesn't exist: ");
		sError += LPCTSTR(*this);
		throw(sError);

		//ASSERTX(FALSE);
		//return *this;	// at least this is better than returning junk
	}

	char shortPath[1001];
	*shortPath = 0; // testing
	int x = GetShortPathName( LPCTSTR(*this), shortPath, 1000);
	ASSERTX(x <1001 );
	return CString(shortPath);
}
Пример #16
0
CString CProcessStatus::makeTempPath(LPCTSTR lpszFileName, LPCTSTR lpszExtension)
{
	CString sPath(m_sTempFilesDirectory + lpszFileName + lpszExtension);

	int iResult = _taccess(sPath, 02); // ask for write permission

	if(-1 == iResult)
	{
		if(errno == EACCES)
		{
			CString sError(_T("Some process left this file open, so it can't be written to: "));
			sError += sPath;
			throw(sError);
		}
/* to do:		else
		{
			checkForFileError(sPath);
			throw(sError);
		}
*/	}
	return sPath;
}
//
// Load template with specified name
//
INT_32 CTPP2FileSourceLoader::LoadTemplate(CCHAR_P szTemplateName)
{
	sNormalizedFileName.erase();
	INT_32 iStatCode = 0;
	STLW::vector<STLW::string>::const_iterator itvIncludeDirs = vIncludeDirs.begin();
	while(itvIncludeDirs != vIncludeDirs.end())
	{
		STLW::string sTMP = *itvIncludeDirs;
#ifdef WIN32
		if ( sTMP.length() && sTMP[sTMP.length() - 1] != '/' && sTMP[sTMP.length() - 1] != '\\' ) { sTMP.append("\\", 1); }
#else
		if (sTMP.length() && sTMP[sTMP.length() - 1] != '/') { sTMP.append("/", 1); }
#endif
		sTMP.append(szTemplateName);

		sCurrentDir = GetBaseDir(sTMP, sNormalizedFileName);
		if (sNormalizedFileName.length() == 0)
		{
			STLW::string sError("invalid file name `");
			sError.append(sTMP);
			sError.append("`");
			throw CTPPLogicError(sError.c_str());
		}

		// Get file size
		struct stat oStat;
		iStatCode = stat(sNormalizedFileName.c_str(), &oStat);
		if (iStatCode == 0)
		{
			iTemplateSize = oStat.st_size;
			break;
		}
		++itvIncludeDirs;
	}

	if (iStatCode == -1)
	{
		STLW::string sError("cannot find file in include directories ");
		itvIncludeDirs = vIncludeDirs.begin();
		for (;;)
		{
			sError.append("`");
			if (itvIncludeDirs -> size() != 0) { sError.append(*itvIncludeDirs); }
			else
			{
				CHAR_P szPWD = getcwd(NULL, 0);
				sError.append(szPWD);
				free(szPWD);
			}
			sError.append("`");

			++itvIncludeDirs;
			if (itvIncludeDirs == vIncludeDirs.end()) { break; }

			sError.append(", ");
		}
		throw CTPPLogicError(sError.c_str());
	}

	if (iTemplateSize == 0)
	{
		STLW::string sError("empty file `");
		sError.append(sNormalizedFileName);
		sError.append("` found");
		throw CTPPLogicError(sError.c_str());
	}

	// Load file
	FILE * F = fopen(sNormalizedFileName.c_str(), "rb");
	if (F == NULL) { throw CTPPUnixException("fopen", errno); }

	if (sTemplate != NULL) { free(sTemplate); }

	// Allocate memory
	sTemplate = (CHAR_P)malloc(iTemplateSize);

	// Read from file
	if (fread(sTemplate, iTemplateSize, 1, F) != 1)
	{
		if (ferror(F) != 0)
		{
			free(sTemplate);
			fclose(F);
			throw CTPPUnixException("fread", errno);
		}
		else
		{
			free(sTemplate);
			fclose(F);
			throw CTPPLogicError("Cannot read from file");
		}
	}

	fclose(F);

return 0;
}
Пример #18
0
// bDisabled is ignored on input; on return, it is false if a "\dis" was found
// at the beginning of the line.
// bEnabled can be null where it isn't relevant
BOOL SFMFile::getField(CString& marker, CString& contents, BOOL *bEnabled)
{
	ASSERTX(fin.is_open());
	const int kBuffSize = 5000;	// CURRENTLY MAX FIELD SIZE TOO!

	// suck up and thow away lines at the beginning of the file that start
	// with the comment character
	if( fin.peek() == m_cCommentChar)
	{
#ifndef rde270
		// these files are not wide characters... therefore CString won't be that helpful
		LPSTR sLeadingComments = (LPSTR)alloca(kBuffSize+2);
		LPSTR x = sLeadingComments;
		LPSTR xStart = x;
#else   // rde270
		CString sLeadingComments;
		LPTSTR x = sLeadingComments.GetBuffer(kBuffSize+2);
		LPTSTR xStart = x;
#endif  // rde270
		do
		{
			fin.getline(x, kBuffSize - (x-xStart), '\n');
			x += fin.gcount();
			if(fin.gcount())
			{
				*(x-1) = '\n'; // put a carriage return in place of the null terminator
				*x = '\0';		// null terminate in case the next getline fails
			}
		} while (fin.good() && fin.gcount() && fin.peek() != '\\');

#ifndef rde270
#else   // rde270
		sLeadingComments.ReleaseBuffer();
#endif  // rde270
	}


#ifndef rde270
	LPSTR sField = (LPSTR)alloca(kBuffSize+2);
	LPSTR buff = sField;
	LPSTR start_buff = buff;
#else   // rde270
	CString sField;
	//LPTSTR start_buff = sField.GetBuffer(kBuffSize+2);
	//LPTSTR buff = start_buff;
	LPTSTR buff = sField.GetBuffer(kBuffSize+2);
	LPTSTR start_buff = buff;
#endif  // rde270

	fin.eatwhite();
	LPSTR b = buff;

	do
	{
		fin.getline(b, kBuffSize - (b-buff), '\n');
		b += fin.gcount();
		if(fin.gcount())
		{
			*(b-1) = '\n'; // put a carriage return in place of the null terminator
			*b = '\0';		// null terminate in case the next getline fails
		}

		//strlen(buff);

	} while (fin.good() && fin.gcount() && fin.peek() != '\\');



	if( (kBuffSize-1) <= (b-buff))	// to long (and thus fin.gcount() == 0)
	{
		CString s;
		s.Format(_T("The file %s appears to have a line which is longer than the maximum of %d characters which Carla Studio can handle.\n"),
					(LPCTSTR)m_pathName, kBuffSize);
		throw(s);

	}

	if(!buff[0])	// end of file
	{
#ifndef rde270
#else
		sField.ReleaseBuffer(-1);
#endif
		return FALSE;
	}

	if(bEnabled)
	{
		*bEnabled = (strncmp(buff, "\\dis", 4) != 0); // if the first marker is '\dis', the rule is disabled
		if(!*bEnabled)
		{
			buff +=4;	// skip the \dis
		}
	}

	// eat white space before the SFM Code (will always be there after a \dis)
	while(*buff && _ismbcspace(*buff))
	{
		*buff='~'; // a hack so that iSpaceLoc, below, isn't set to the space between the "\dis" and marker
		++buff;
	}

	// say we had \dis sr blah, now we want \sr blah
	//  but don't do anything if \dis \sr foo
	if(bEnabled && !*bEnabled && *buff != '\\')
	{
		--buff;
		*buff= '\\';
	}

	BOOL bHaveEnvironment = FALSE;
	if(buff[0] == '/' || (buff[0] == '+' && buff[1] == '/') || /*sentrans*/(buff[0] == '&' && buff[1] == '/'))
	{
		bHaveEnvironment = TRUE;
	}

	USES_CONVERSION_U8;
	// some lines may begin with \dis and be followed by an environment
	// these must be treated special
	if(!bHaveEnvironment && buff[0] != '\\'
		&& bEnabled && *bEnabled)	// can't expect a \ if we started with a \dis
	{	//ASSERTX(FALSE);	//  line didn't have backslash as first non-whitespace char
		static CString sRest;

#ifndef rde270
		sRest = U82CT(start_buff);
#else   // rde270
		sRest = start_buff;
		sField.ReleaseBuffer(-1);
#endif  // rde270

		ostrstream sout;
		sout << "Carla Studio encountered a serious problem while trying to read\n   " << T2CA(m_pathName) << '\n';
		sout << "It was expecting to find an SFM marker, but found instead:\n";
		sout <<  start_buff << '\n';

		// to do: add line number?
#ifndef rde270
		// I'm just not sure if sout.str is going to be null terminated, so do it the long way.
		int nLen = sout.pcount();
		char* pSout = (char*)alloca(nLen + 1);
		strncpy(pSout, sout.str(), nLen);
		pSout[nLen] = '\0';
		CString sError(U82CT(pSout));
#else   // rde270
		CString sError (sout.str(), sout.pcount());
#endif// rde270
		sout.rdbuf()->freeze(0); // else get a memory leak
		throw(sError);
	}


	int iSpaceLoc ;
	if(bHaveEnvironment)
		iSpaceLoc = (buff-start_buff)-1;
	else
	{
		// figure out where the marker ends and field contents begin
#ifndef rde270
		LPSTR lpsz = strpbrk(sField, " \t\n");
		iSpaceLoc = (lpsz == NULL) ? -1 : (int)(lpsz - sField);
#else
		iSpaceLoc = sField.FindOneOf(" \t\n");
#endif
		if(iSpaceLoc <= 1)// [0] should be the slash, [1] at least one char
		{
#ifndef rde270
#else
			sField.ReleaseBuffer(-1);
#endif
			return FALSE;
		}
	}

	if(bHaveEnvironment)
		marker = _T("ENV");
	else
	{
		start_buff[iSpaceLoc] = '\0';
#ifndef rde270
		marker = U82CT(buff + 1); // +1 to skip the slash
#else
		marker = buff + 1; // +1 to skip the slash
#endif
		marker.TrimRight();
	}

#ifndef rde270
	contents = U82CT(start_buff + iSpaceLoc+1);
#else
	contents = start_buff + iSpaceLoc+1;
#endif

	contents.TrimLeft();
	contents.TrimRight();

#ifndef rde270
#else
	sField.ReleaseBuffer(-1);
#endif
	return TRUE;
}
Пример #19
0
void CIRCSock::ReadLine(const CString& sData) {
	CString sLine = sData;

	sLine.TrimRight("\n\r");

	DEBUG("(" << m_pUser->GetUserName() << ") IRC -> ZNC [" << sLine << "]");

	MODULECALL(OnRaw(sLine), m_pUser, NULL, return);

	if (sLine.Equals("PING ", false, 5)) {
		// Generate a reply and don't forward this to any user,
		// we don't want any PING forwarded
		PutIRC("PONG " + sLine.substr(5));
		return;
	} else if (sLine.Token(1).Equals("PONG")) {
		// Block PONGs, we already responded to the pings
		return;
	} else if (sLine.Equals("ERROR ", false, 6)) {
		//ERROR :Closing Link: nick[24.24.24.24] (Excess Flood)
		CString sError(sLine.substr(6));

		if (sError.Left(1) == ":") {
			sError.LeftChomp();
		}

		m_pUser->PutStatus("Error from Server [" + sError + "]");
		return;
	}

	CString sCmd = sLine.Token(1);

	if ((sCmd.length() == 3) && (isdigit(sCmd[0])) && (isdigit(sCmd[1])) && (isdigit(sCmd[2]))) {
		CString sServer = sLine.Token(0); sServer.LeftChomp();
		unsigned int uRaw = sCmd.ToUInt();
		CString sNick = sLine.Token(2);
		CString sRest = sLine.Token(3, true);

		switch (uRaw) {
			case 1: { // :irc.server.com 001 nick :Welcome to the Internet Relay Network nick
				if (m_bAuthed && sServer == "irc.znc.in") {
					// m_bAuthed == true => we already received another 001 => we might be in a traffic loop
					m_pUser->PutStatus("ZNC seems to be connected to itself, disconnecting...");
					Quit();
					return;
				}

				m_pUser->SetIRCServer(sServer);
				SetTimeout(240, TMO_READ);  // Now that we are connected, let nature take its course
				PutIRC("WHO " + sNick);

				m_bAuthed = true;
				m_pUser->PutStatus("Connected!");

				vector<CClient*>& vClients = m_pUser->GetClients();

				for (unsigned int a = 0; a < vClients.size(); a++) {
					CClient* pClient = vClients[a];
					CString sClientNick = pClient->GetNick(false);

					if (!sClientNick.Equals(sNick)) {
						// If they connected with a nick that doesn't match the one we got on irc, then we need to update them
						pClient->PutClient(":" + sClientNick + "!" + m_Nick.GetIdent() + "@" + m_Nick.GetHost() + " NICK :" + sNick);
					}
				}

				SetNick(sNick);

				MODULECALL(OnIRCConnected(), m_pUser, NULL, );

				m_pUser->ClearRawBuffer();
				m_pUser->AddRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);

				CZNC::Get().ReleaseISpoof();
				m_bISpoofReleased = true;

				break;
			}
			case 5:
				ParseISupport(sRest);
				m_pUser->UpdateExactRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
				break;
			case 2:
			case 3:
			case 4:
			case 250:  // highest connection count
			case 251:  // user count
			case 252:  // oper count
			case 254:  // channel count
			case 255:  // client count
			case 265:  // local users
			case 266:  // global users
				m_pUser->UpdateRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
				break;
			case 305:
				m_pUser->SetIRCAway(false);
				break;
			case 306:
				m_pUser->SetIRCAway(true);
				break;
			case 324: {  // MODE
				sRest.Trim();
				CChan* pChan = m_pUser->FindChan(sRest.Token(0));

				if (pChan) {
					pChan->SetModes(sRest.Token(1, true));
				}
			}
				break;
			case 329: {
				sRest.Trim();
				CChan* pChan = m_pUser->FindChan(sRest.Token(0));

				if (pChan) {
					unsigned long ulDate = sLine.Token(4).ToULong();
					pChan->SetCreationDate(ulDate);
				}
			}
				break;
			case 331: {
				// :irc.server.com 331 yournick #chan :No topic is set.
				CChan* pChan = m_pUser->FindChan(sLine.Token(3));

				if (pChan) {
					pChan->SetTopic("");
				}

				break;
			}
			case 332: {
				// :irc.server.com 332 yournick #chan :This is a topic
				CChan* pChan = m_pUser->FindChan(sLine.Token(3));

				if (pChan) {
					CString sTopic = sLine.Token(4, true);
					sTopic.LeftChomp();
					pChan->SetTopic(sTopic);
				}

				break;
			}
			case 333: {
				// :irc.server.com 333 yournick #chan setternick 1112320796
				CChan* pChan = m_pUser->FindChan(sLine.Token(3));

				if (pChan) {
					sNick = sLine.Token(4);
					unsigned long ulDate = sLine.Token(5).ToULong();

					pChan->SetTopicOwner(sNick);
					pChan->SetTopicDate(ulDate);
				}

				break;
			}
			case 352: {
				// :irc.yourserver.com 352 yournick #chan ident theirhost.com irc.theirserver.com theirnick H :0 Real Name
				sServer = sLine.Token(0);
				sNick = sLine.Token(7);
				CString sIdent = sLine.Token(4);
				CString sHost = sLine.Token(5);

				sServer.LeftChomp();

				if (sNick.Equals(GetNick())) {
					m_Nick.SetIdent(sIdent);
					m_Nick.SetHost(sHost);
				}

				m_pUser->SetIRCNick(m_Nick);
				m_pUser->SetIRCServer(sServer);

				const vector<CChan*>& vChans = m_pUser->GetChans();

				for (unsigned int a = 0; a < vChans.size(); a++) {
					vChans[a]->OnWho(sNick, sIdent, sHost);
				}

				break;
			}
			case 353: {  // NAMES
				sRest.Trim();
				// Todo: allow for non @+= server msgs
				CChan* pChan = m_pUser->FindChan(sRest.Token(1));
				// If we don't know that channel, some client might have
				// requested a /names for it and we really should forward this.
				if (pChan) {
					CString sNicks = sRest.Token(2, true);
					if (sNicks.Left(1) == ":") {
						sNicks.LeftChomp();
					}

					pChan->AddNicks(sNicks);
				}

				ForwardRaw353(sLine);

				// We forwarded it already, so return
				return;
			}
			case 366: {  // end of names list
				m_pUser->PutUser(sLine);  // First send them the raw

				// :irc.server.com 366 nick #chan :End of /NAMES list.
				CChan* pChan = m_pUser->FindChan(sRest.Token(0));

				if (pChan) {
					if (pChan->IsOn()) {
						// If we are the only one in the chan, set our default modes
						if (pChan->GetNickCount() == 1) {
							CString sModes = pChan->GetDefaultModes();

							if (sModes.empty()) {
								sModes = m_pUser->GetDefaultChanModes();
							}

							if (!sModes.empty()) {
								PutIRC("MODE " + pChan->GetName() + " " + sModes);
							}
						}
					}
				}

				return;  // return so we don't send them the raw twice
			}
			case 375:  // begin motd
			case 422:  // MOTD File is missing
				m_pUser->ClearMotdBuffer();
			case 372:  // motd
			case 376:  // end motd
				m_pUser->AddMotdBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
				break;
			case 437:
				// :irc.server.net 437 * badnick :Nick/channel is temporarily unavailable
				// :irc.server.net 437 mynick badnick :Nick/channel is temporarily unavailable
				// :irc.server.net 437 mynick badnick :Cannot change nickname while banned on channel
				if (m_pUser->IsChan(sRest.Token(0)) || sNick != "*")
					break;
			case 432: // :irc.server.com 432 * nick :Erroneous Nickname: Illegal characters
			case 433: {
				CString sBadNick = sRest.Token(0);

				if (!m_bAuthed) {
					SendAltNick(sBadNick);
					return;
				}
				break;
			}
			case 451:
				// :irc.server.com 451 CAP :You have not registered
				// Servers that dont support CAP will give us this error, dont send it to the client
				if (sNick.Equals("CAP"))
					return;
			case 470: {
				// :irc.unreal.net 470 mynick [Link] #chan1 has become full, so you are automatically being transferred to the linked channel #chan2
				// :mccaffrey.freenode.net 470 mynick #electronics ##electronics :Forwarding to another channel

				// freenode style numeric
				CChan* pChan = m_pUser->FindChan(sRest.Token(0));
				if (!pChan) {
					// unreal style numeric
					pChan = m_pUser->FindChan(sRest.Token(1));
				}
				if (pChan) {
					pChan->Disable();
					m_pUser->PutStatus("Channel [" + pChan->GetName() + "] is linked to "
							"another channel and was thus disabled.");
				}
				break;
			}
		}
	} else {
Пример #20
0
void CIRCSock::ReadLine(const CString& sData) {
	CString sLine = sData;

	sLine.TrimRight("\n\r");

	DEBUG("(" << m_pNetwork->GetUser()->GetUserName() << "/" << m_pNetwork->GetName() << ") IRC -> ZNC [" << sLine << "]");

	NETWORKMODULECALL(OnRaw(sLine), m_pNetwork->GetUser(), m_pNetwork, NULL, return);

	if (sLine.Equals("PING ", false, 5)) {
		// Generate a reply and don't forward this to any user,
		// we don't want any PING forwarded
		PutIRC("PONG " + sLine.substr(5));
		return;
	} else if (sLine.Token(1).Equals("PONG")) {
		// Block PONGs, we already responded to the pings
		return;
	} else if (sLine.Equals("ERROR ", false, 6)) {
		//ERROR :Closing Link: nick[24.24.24.24] (Excess Flood)
		CString sError(sLine.substr(6));
		sError.TrimPrefix();
		m_pNetwork->PutStatus("Error from Server [" + sError + "]");
		return;
	}

	CString sCmd = sLine.Token(1);

	if ((sCmd.length() == 3) && (isdigit(sCmd[0])) && (isdigit(sCmd[1])) && (isdigit(sCmd[2]))) {
		CString sServer = sLine.Token(0).LeftChomp_n();
		unsigned int uRaw = sCmd.ToUInt();
		CString sNick = sLine.Token(2);
		CString sRest = sLine.Token(3, true);

		switch (uRaw) {
			case 1: { // :irc.server.com 001 nick :Welcome to the Internet Relay Network nick
				if (m_bAuthed && sServer == "irc.znc.in") {
					// m_bAuthed == true => we already received another 001 => we might be in a traffic loop
					m_pNetwork->PutStatus("ZNC seems to be connected to itself, disconnecting...");
					Quit();
					return;
				}

				m_pNetwork->SetIRCServer(sServer);
				SetTimeout(540, TMO_READ);  // Now that we are connected, let nature take its course
				PutIRC("WHO " + sNick);

				m_bAuthed = true;
				m_pNetwork->PutStatus("Connected!");

				vector<CClient*>& vClients = m_pNetwork->GetClients();

				for (unsigned int a = 0; a < vClients.size(); a++) {
					CClient* pClient = vClients[a];
					CString sClientNick = pClient->GetNick(false);

					if (!sClientNick.Equals(sNick)) {
						// If they connected with a nick that doesn't match the one we got on irc, then we need to update them
						pClient->PutClient(":" + sClientNick + "!" + m_Nick.GetIdent() + "@" + m_Nick.GetHost() + " NICK :" + sNick);
					}
				}

				SetNick(sNick);

				NETWORKMODULECALL(OnIRCConnected(), m_pNetwork->GetUser(), m_pNetwork, NULL, NOTHING);

				m_pNetwork->ClearRawBuffer();
				m_pNetwork->AddRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);

				break;
			}
			case 5:
				ParseISupport(sRest);
				m_pNetwork->UpdateExactRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
				break;
			case 10: { // :irc.server.com 010 nick <hostname> <port> :<info>
				CString sHost = sRest.Token(0);
				CString sPort = sRest.Token(1);
				CString sInfo = sRest.Token(2, true).TrimPrefix_n();
				m_pNetwork->PutStatus("Server [" + m_pNetwork->GetCurrentServer()->GetString(false) +
						"] redirects us to [" + sHost + ":" + sPort + "] with reason [" + sInfo + "]");
				m_pNetwork->PutStatus("Perhaps you want to add it as a new server.");
				// Don't send server redirects to the client
				return;
			}
			case 2:
			case 3:
			case 4:
			case 250:  // highest connection count
			case 251:  // user count
			case 252:  // oper count
			case 254:  // channel count
			case 255:  // client count
			case 265:  // local users
			case 266:  // global users
				m_pNetwork->UpdateRawBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
				break;
			case 305:
				m_pNetwork->SetIRCAway(false);
				break;
			case 306:
				m_pNetwork->SetIRCAway(true);
				break;
			case 324: {  // MODE
				sRest.Trim();
				CChan* pChan = m_pNetwork->FindChan(sRest.Token(0));

				if (pChan) {
					pChan->SetModes(sRest.Token(1, true));

					// We don't SetModeKnown(true) here,
					// because a 329 will follow
					if (!pChan->IsModeKnown()) {
						// When we JOIN, we send a MODE
						// request. This makes sure the
						// reply isn't forwarded.
						return;
					}
				}
			}
				break;
			case 329: {
				sRest.Trim();
				CChan* pChan = m_pNetwork->FindChan(sRest.Token(0));

				if (pChan) {
					unsigned long ulDate = sLine.Token(4).ToULong();
					pChan->SetCreationDate(ulDate);

					if (!pChan->IsModeKnown()) {
						pChan->SetModeKnown(true);
						// When we JOIN, we send a MODE
						// request. This makes sure the
						// reply isn't forwarded.
						return;
					}
				}
			}
				break;
			case 331: {
				// :irc.server.com 331 yournick #chan :No topic is set.
				CChan* pChan = m_pNetwork->FindChan(sLine.Token(3));

				if (pChan) {
					pChan->SetTopic("");
				}

				break;
			}
			case 332: {
				// :irc.server.com 332 yournick #chan :This is a topic
				CChan* pChan = m_pNetwork->FindChan(sLine.Token(3));

				if (pChan) {
					CString sTopic = sLine.Token(4, true);
					sTopic.LeftChomp();
					pChan->SetTopic(sTopic);
				}

				break;
			}
			case 333: {
				// :irc.server.com 333 yournick #chan setternick 1112320796
				CChan* pChan = m_pNetwork->FindChan(sLine.Token(3));

				if (pChan) {
					sNick = sLine.Token(4);
					unsigned long ulDate = sLine.Token(5).ToULong();

					pChan->SetTopicOwner(sNick);
					pChan->SetTopicDate(ulDate);
				}

				break;
			}
			case 352: {
				// :irc.yourserver.com 352 yournick #chan ident theirhost.com irc.theirserver.com theirnick H :0 Real Name
				sServer = sLine.Token(0);
				sNick = sLine.Token(7);
				CString sIdent = sLine.Token(4);
				CString sHost = sLine.Token(5);

				sServer.LeftChomp();

				if (sNick.Equals(GetNick())) {
					m_Nick.SetIdent(sIdent);
					m_Nick.SetHost(sHost);
				}

				m_pNetwork->SetIRCNick(m_Nick);
				m_pNetwork->SetIRCServer(sServer);

				const vector<CChan*>& vChans = m_pNetwork->GetChans();

				for (unsigned int a = 0; a < vChans.size(); a++) {
					vChans[a]->OnWho(sNick, sIdent, sHost);
				}

				break;
			}
			case 353: {  // NAMES
				sRest.Trim();
				// Todo: allow for non @+= server msgs
				CChan* pChan = m_pNetwork->FindChan(sRest.Token(1));
				// If we don't know that channel, some client might have
				// requested a /names for it and we really should forward this.
				if (pChan) {
					CString sNicks = sRest.Token(2, true).TrimPrefix_n();
					pChan->AddNicks(sNicks);
				}

				ForwardRaw353(sLine);

				// We forwarded it already, so return
				return;
			}
			case 366: {  // end of names list
				m_pNetwork->PutUser(sLine);  // First send them the raw

				// :irc.server.com 366 nick #chan :End of /NAMES list.
				CChan* pChan = m_pNetwork->FindChan(sRest.Token(0));

				if (pChan) {
					if (pChan->IsOn()) {
						// If we are the only one in the chan, set our default modes
						if (pChan->GetNickCount() == 1) {
							CString sModes = pChan->GetDefaultModes();

							if (sModes.empty()) {
								sModes = m_pNetwork->GetUser()->GetDefaultChanModes();
							}

							if (!sModes.empty()) {
								PutIRC("MODE " + pChan->GetName() + " " + sModes);
							}
						}
					}
				}

				return;  // return so we don't send them the raw twice
			}
			case 375:  // begin motd
			case 422:  // MOTD File is missing
				m_pNetwork->ClearMotdBuffer();
			case 372:  // motd
			case 376:  // end motd
				m_pNetwork->AddMotdBuffer(":" + sServer + " " + sCmd + " ", " " + sRest);
				break;
			case 437:
				// :irc.server.net 437 * badnick :Nick/channel is temporarily unavailable
				// :irc.server.net 437 mynick badnick :Nick/channel is temporarily unavailable
				// :irc.server.net 437 mynick badnick :Cannot change nickname while banned on channel
				if (m_pNetwork->IsChan(sRest.Token(0)) || sNick != "*")
					break;
			case 432: // :irc.server.com 432 * nick :Erroneous Nickname: Illegal characters
			case 433: {
				CString sBadNick = sRest.Token(0);

				if (!m_bAuthed) {
					SendAltNick(sBadNick);
					return;
				}
				break;
			}
			case 451:
				// :irc.server.com 451 CAP :You have not registered
				// Servers that dont support CAP will give us this error, dont send it to the client
				if (sNick.Equals("CAP"))
					return;
			case 470: {
				// :irc.unreal.net 470 mynick [Link] #chan1 has become full, so you are automatically being transferred to the linked channel #chan2
				// :mccaffrey.freenode.net 470 mynick #electronics ##electronics :Forwarding to another channel

				// freenode style numeric
				CChan* pChan = m_pNetwork->FindChan(sRest.Token(0));
				if (!pChan) {
					// unreal style numeric
					pChan = m_pNetwork->FindChan(sRest.Token(1));
				}
				if (pChan) {
					pChan->Disable();
					m_pNetwork->PutStatus("Channel [" + pChan->GetName() + "] is linked to "
							"another channel and was thus disabled.");
				}
				break;
			}
		}
	} else {
		CNick Nick(sLine.Token(0).TrimPrefix_n());
		sCmd = sLine.Token(1);
		CString sRest = sLine.Token(2, true);

		if (sCmd.Equals("NICK")) {
			CString sNewNick = sRest.TrimPrefix_n();
			bool bIsVisible = false;

			vector<CChan*> vFoundChans;
			const vector<CChan*>& vChans = m_pNetwork->GetChans();

			for (unsigned int a = 0; a < vChans.size(); a++) {
				CChan* pChan = vChans[a];

				if (pChan->ChangeNick(Nick.GetNick(), sNewNick)) {
					vFoundChans.push_back(pChan);

					if (!pChan->IsDetached()) {
						bIsVisible = true;
					}
				}
			}

			// Todo: use nick compare function here
			if (Nick.GetNick().Equals(GetNick())) {
				// We are changing our own nick, the clients always must see this!
				bIsVisible = true;
				SetNick(sNewNick);
			}

			NETWORKMODULECALL(OnNick(Nick, sNewNick, vFoundChans), m_pNetwork->GetUser(), m_pNetwork, NULL, NOTHING);

			if (!bIsVisible) {
				return;
			}
		} else if (sCmd.Equals("QUIT")) {
			CString sMessage = sRest.TrimPrefix_n();
			bool bIsVisible = false;

			// :[email protected] QUIT :message

			if (Nick.GetNick().Equals(GetNick())) {
				m_pNetwork->PutStatus("You quit [" + sMessage + "]");
				// We don't call module hooks and we don't
				// forward this quit to clients (Some clients
				// disconnect if they receive such a QUIT)
				return;
			}

			vector<CChan*> vFoundChans;
			const vector<CChan*>& vChans = m_pNetwork->GetChans();

			for (unsigned int a = 0; a < vChans.size(); a++) {
				CChan* pChan = vChans[a];

				if (pChan->RemNick(Nick.GetNick())) {
					vFoundChans.push_back(pChan);

					if (!pChan->IsDetached()) {
						bIsVisible = true;
					}
				}
			}

			NETWORKMODULECALL(OnQuit(Nick, sMessage, vFoundChans), m_pNetwork->GetUser(), m_pNetwork, NULL, NOTHING);

			if (!bIsVisible) {
				return;
			}
		} else if (sCmd.Equals("JOIN")) {
			CString sChan = sRest.Token(0).TrimPrefix_n();
			CChan* pChan;

			// Todo: use nick compare function
			if (Nick.GetNick().Equals(GetNick())) {
				m_pNetwork->AddChan(sChan, false);
				pChan = m_pNetwork->FindChan(sChan);
				if (pChan) {
					pChan->ResetJoinTries();
					pChan->Enable();
					pChan->SetIsOn(true);
					PutIRC("MODE " + sChan);
				}
			} else {
				pChan = m_pNetwork->FindChan(sChan);
			}

			if (pChan) {
				pChan->AddNick(Nick.GetNickMask());
				NETWORKMODULECALL(OnJoin(Nick.GetNickMask(), *pChan), m_pNetwork->GetUser(), m_pNetwork, NULL, NOTHING);

				if (pChan->IsDetached()) {
					return;
				}
			}
		} else if (sCmd.Equals("PART")) {
			CString sChan = sRest.Token(0).TrimPrefix_n();
			CString sMsg = sRest.Token(1, true).TrimPrefix_n();

			CChan* pChan = m_pNetwork->FindChan(sChan);
			bool bDetached = false;
			if (pChan) {
				pChan->RemNick(Nick.GetNick());
				NETWORKMODULECALL(OnPart(Nick.GetNickMask(), *pChan, sMsg), m_pNetwork->GetUser(), m_pNetwork, NULL, NOTHING);

				if (pChan->IsDetached())
					bDetached = true;
			}

			// Todo: use nick compare function
			if (Nick.GetNick().Equals(GetNick())) {
				m_pNetwork->DelChan(sChan);
			}

			/*
			 * We use this boolean because
			 * m_pNetwork->DelChan() will delete this channel
			 * and thus we would dereference an
			 * already-freed pointer!
			 */
			if (bDetached) {
				return;
			}
		} else if (sCmd.Equals("MODE")) {
			CString sTarget = sRest.Token(0);
			CString sModes = sRest.Token(1, true);
			if (sModes.Left(1) == ":")
				sModes = sModes.substr(1);

			CChan* pChan = m_pNetwork->FindChan(sTarget);
			if (pChan) {
				pChan->ModeChange(sModes, &Nick);

				if (pChan->IsDetached()) {
					return;
				}
			} else if (sTarget == m_Nick.GetNick()) {
				CString sModeArg = sModes.Token(0);
				bool bAdd = true;
/* no module call defined (yet?)
				MODULECALL(OnRawUserMode(*pOpNick, *this, sModeArg, sArgs), m_pNetwork->GetUser(), NULL, );
*/
				for (unsigned int a = 0; a < sModeArg.size(); a++) {
					const unsigned char& uMode = sModeArg[a];

					if (uMode == '+') {
						bAdd = true;
					} else if (uMode == '-') {
						bAdd = false;
					} else {
						if (bAdd) {
							m_scUserModes.insert(uMode);
						} else {
							m_scUserModes.erase(uMode);
						}
					}
				}
			}
		} else if (sCmd.Equals("KICK")) {
			// :[email protected] KICK #chan nick :msg
			CString sChan = sRest.Token(0);
			CString sKickedNick = sRest.Token(1);
			CString sMsg = sRest.Token(2, true);
			sMsg.LeftChomp();

			CChan* pChan = m_pNetwork->FindChan(sChan);

			if (pChan) {
				NETWORKMODULECALL(OnKick(Nick, sKickedNick, *pChan, sMsg), m_pNetwork->GetUser(), m_pNetwork, NULL, NOTHING);
				// do not remove the nick till after the OnKick call, so modules
				// can do Chan.FindNick or something to get more info.
				pChan->RemNick(sKickedNick);
			}

			if (GetNick().Equals(sKickedNick) && pChan) {
				pChan->SetIsOn(false);

				// Don't try to rejoin!
				pChan->Disable();
			}

			if ((pChan) && (pChan->IsDetached())) {
				return;
			}
		} else if (sCmd.Equals("NOTICE")) {
			// :[email protected] NOTICE #chan :Message
			CString sTarget = sRest.Token(0);
			CString sMsg = sRest.Token(1, true);
			sMsg.LeftChomp();

			if (sMsg.WildCmp("\001*\001")) {
				sMsg.LeftChomp();
				sMsg.RightChomp();

				if (sTarget.Equals(GetNick())) {
					if (OnCTCPReply(Nick, sMsg)) {
						return;
					}
				}

				m_pNetwork->PutUser(":" + Nick.GetNickMask() + " NOTICE " + sTarget + " :\001" + sMsg + "\001");
				return;
			} else {
				if (sTarget.Equals(GetNick())) {
					if (OnPrivNotice(Nick, sMsg)) {
						return;
					}
				} else {
					if (OnChanNotice(Nick, sTarget, sMsg)) {
						return;
					}
				}
			}

			if (Nick.GetNick().Equals(m_pNetwork->GetIRCServer())) {
				m_pNetwork->PutUser(":" + Nick.GetNick() + " NOTICE " + sTarget + " :" + sMsg);
			} else {
				m_pNetwork->PutUser(":" + Nick.GetNickMask() + " NOTICE " + sTarget + " :" + sMsg);
			}

			return;
		} else if (sCmd.Equals("TOPIC")) {
			// :[email protected] TOPIC #chan :This is a topic
			CChan* pChan = m_pNetwork->FindChan(sLine.Token(2));

			if (pChan) {
				CString sTopic = sLine.Token(3, true);
				sTopic.LeftChomp();

				NETWORKMODULECALL(OnTopic(Nick, *pChan, sTopic), m_pNetwork->GetUser(), m_pNetwork, NULL, return);

				pChan->SetTopicOwner(Nick.GetNick());
				pChan->SetTopicDate((unsigned long) time(NULL));
				pChan->SetTopic(sTopic);

				if (pChan->IsDetached()) {
					return; // Don't forward this
				}

				sLine = ":" + Nick.GetNickMask() + " TOPIC " + pChan->GetName() + " :" + sTopic;
			}
		} else if (sCmd.Equals("PRIVMSG")) {