static void readUnlock(skipList list, skipItem x, void **plock) {

  int startFlush = FALSE;

  if(list->threaded)
    mLock(&list->read);

  if(plock) {
    x->locks++;
    *plock = x;
  }

  if(! list->threaded)
    return;

  list->readers--;

  if((list->readers == 0) && list->block)
    startFlush = TRUE;

  mUnlock(&list->read);

  if(startFlush)
    cSignal(&list->flush);

  return;
}
Beispiel #2
0
	//************************************************************
	//********功能:pop一个工作对象
	//********参数:无
	//********返回值:工作对象的shared_ptr指针
	//************************************************************
	shared_ptr<CJob> CJobQueue::popJop()
	{
		CLock mLock(m_mutex);
		if (m_JobQueue.empty())return NULL;
		shared_ptr<CJob> job = m_JobQueue.front();
		m_JobQueue.pop();
		return job;
	}
Beispiel #3
0
	//************************************************************
	//********功能:向工作队列中压入一个工作对象
	//********参数:工作对象的shared_ptr指针
	//********返回值:
	//************************************************************
	void CJobQueue::pushJob(shared_ptr<CJob>& job)
	{
		if (job != NULL)
		{
			CLock mLock(m_mutex);
			m_JobQueue.push(job);
		}
	}
Beispiel #4
0
	TA3DSock *SockList::getSock(const int id)
	{
		MutexLocker mLock(*this);
		SockType::iterator i = sockets.find(id);
		if (i == sockets.end())
			return NULL;
		return (*i)->sock;
	}
Beispiel #5
0
	SocketThread *SockList::getThread(const int id)
	{
		MutexLocker mLock(*this);
		SockType::iterator i = sockets.find(id);
		if (i == sockets.end())
			return NULL;
		return &((*i)->thread);
	}
Beispiel #6
0
	int SockList::Remove(const int id)
	{
		MutexLocker mLock(*this);
		if (!sockets.contains(id))
			return -1;
		delete sockets[id];
		sockets.remove(id);
		return 0;
	}
static void readBlock(skipList list) {

  mLock(&list->read);

  list->block = TRUE;

  if(list->readers)
    cWait(&list->flush, &list->read);    /* wait until reader locks released */

  return;
}
Beispiel #8
0
NEOERR *nerr_init (void)
{
  NEOERR *err;

  if (Inited == 0)
  {
#ifdef HAVE_PTHREADS
    /* In threaded environments, we have to mutex lock to do this init, but
     * we don't want to use a mutex every time to check that it was Inited.
     * So, we only lock if our first test of Inited was false */
    err = mLock(&InitLock);
    if (err != STATUS_OK) return nerr_pass(err);
    if (Inited == 0) {
#endif
    err = uListInit (&Errors, 10, 0);
    if (err != STATUS_OK) return nerr_pass(err);

    err = nerr_register (&NERR_PASS, "InternalPass");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_ASSERT, "AssertError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_NOT_FOUND, "NotFoundError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_DUPLICATE, "DuplicateError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_NOMEM, "MemoryError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_PARSE, "ParseError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_OUTOFRANGE, "RangeError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_SYSTEM, "SystemError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_IO, "IOError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_LOCK, "LockError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_DB, "DBError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_EXISTS, "ExistsError");
    if (err != STATUS_OK) return nerr_pass(err);
    err = nerr_register (&NERR_MAX_RECURSION, "MaxRecursionError");
    if (err != STATUS_OK) return nerr_pass(err);

    Inited = 1;
#ifdef HAVE_PTHREADS
    }
    err = mUnlock(&InitLock);
    if (err != STATUS_OK) return nerr_pass(err);
#endif
  }
  return STATUS_OK;
}
Beispiel #9
0
	int SockList::Add(TA3DSock* sock)
	{
		MutexLocker mLock(*this);
		if (maxid > 10000) //arbitrary limit
			return -1;
		SocketNode *node = new SocketNode;
		++maxid;
		sockets[maxid] = node;
		node->sock = sock;

		return maxid;
	}
Beispiel #10
0
bool getOnFile(KeyType id, ValueType& value)
{
    char* ptr = NULL;
    int sp;
    {
        boost::lock_guard<boost::mutex> mLock(readWriteMutex_);
        ptr = fileData_.get(id, sp);
    }
    if(ptr==NULL) return false;
    SerializeType::deserialize(ptr, (std::size_t)sp, value);
    free(ptr);
    return true;
}
static void readLock(skipList list) {

  mLock(&list->read);

  if(list->block)
    cWait(&list->resume, &list->read);

  list->readers++;

  mUnlock(&list->read);

  return;
}
void skipRelease(skipList list, void *lock) {

  skipItem x;

  mLock(&list->read);

  x = lock;
  x->locks--;

  mUnlock(&list->read);

  return;
}
Beispiel #13
0
void update(KeyType id, const ValueType& value)
{
    if( !isOpen() ) return;
    std::size_t vsize;
    char* data = SerializeType::serialize(value, vsize);
    if( vsize>0 )
    {
        boost::lock_guard<boost::mutex> mLock(readWriteMutex_);
        fileData_.update(id, data, vsize);
        this->insertToCache(id, value);
        free(data);
    }

}
static void writeLock(skipList list) {

  mLock(&list->write);

  return;
}
Beispiel #15
0
bool
ServerAgent::ParseENums (const char *data, const char *sWord)
{
	int num (atoi (sWord));

	switch (num)
	{
		case ZERO:								 // 0
			{
				// wasn't a numeric, or the server is playing tricks on us
			}
			return false;

		case ERR_UNKNOWNCOMMAND:	 // 421
			{
				BString tempString (RestOfString (data, 4)),
								badCmd (GetWord (data, 4));

				if (badCmd == "VISION_LAG_CHECK")
				{
					int32 difference (system_time() - fLagCheck);
					if (difference > 0)
					{
						int32 secs (difference / 1000000);
						int32 milli (difference / 1000 - secs * 1000);
						char lag[15] = "";
						sprintf (lag, "%0" B_PRId32 ".%03" B_PRId32, secs, milli);
						fMyLag = lag;
						fLagCount = 0;
						fCheckingLag = false;
						fMsgr.SendMessage (M_LAG_CHANGED);
					}
				}
				else
				{
					tempString.RemoveFirst (":");
					tempString.Append ("\n");
					Display (tempString.String());
				}
			}
			return true;


		case RPL_WELCOME:					// 001
		case RPL_YOURHOST:				 // 002
		case RPL_CREATED:					// 003
		case RPL_MYINFO:					 // 004
			{
				fConnected = true;
				fIsConnecting = false;
				fInitialMotd = true;
				fRetry = 0;

				if (num == RPL_WELCOME)
				{
					BString message = B_TRANSLATE("Established");
					message.Prepend("[@] ").Append("\n");
					Display(message.String(), C_ERROR, C_BACKGROUND, F_SERVER);
				}

				if (fNetworkData.FindBool ("lagCheck"))
				{
					fMyLag = "0.000";
					fMsgr.SendMessage (M_LAG_CHANGED);
				}
				BString theNick (GetWord (data, 3));
				fMyNick = theNick;

				if (!IsHidden())
					vision_app->pClientWin()->pStatusView()->SetItemValue (STATUS_NICK,
						theNick.String());

				BString theMsg (RestOfString (data, 4));
				theMsg.RemoveFirst (":");
				theMsg.Prepend ("* ");
				theMsg.Append ("\n");
				Display (theMsg.String());


				if (num == RPL_MYINFO)
				{
					// set "real" hostname
					fServerHostName = (GetWord (data, 1));
					fServerHostName.RemoveFirst (":");
					BString hostName (fId.String());
					hostName += " - [";
					hostName += fServerHostName.String();
					hostName += "]";
					fAgentWinItem->SetName (hostName.String());

					// detect IRCd
					fIrcdtype = IRCD_STANDARD;

					if (theMsg.FindFirst("hybrid") > 0)
						fIrcdtype = IRCD_HYBRID;
					// ultimate and unreal share the same numerics, so treat them with the same
					// identifier for now
					else if ((theMsg.FindFirst("UltimateIRCd") > 0) || (theMsg.FindFirst("Unreal") > 0))
						fIrcdtype = IRCD_ULTIMATE;
					else if (theMsg.FindFirst("comstud") > 0)
						fIrcdtype = IRCD_COMSTUD;
					else if (theMsg.FindFirst("u2.") > 0)
						fIrcdtype = IRCD_UNDERNET;
					else if (theMsg.FindFirst("PTlink") > 0)
						fIrcdtype = IRCD_PTLINK;
					else if (theMsg.FindFirst ("CR") > 0)
						fIrcdtype = IRCD_CONFERENCEROOM;
					else if (theMsg.FindFirst ("nn-") > 0)
						fIrcdtype = IRCD_NEWNET;
				}
			}
			return true;


		case RPL_PROTOCTL:				 // 005
			{
				// this numeric also serves as RPL_NNMAP on Newnet

				BString theMsg (RestOfString (data, 4));
				theMsg.RemoveFirst (":");
				theMsg.Append ("\n");

				switch (fIrcdtype)
				{
					case IRCD_NEWNET:
						{
							// RPL_NNMAP
							Display (theMsg.String());
						}
						break;

					default:
						{
							// RPL_PROTOCTL
							theMsg.Prepend ("* ");
							Display (theMsg.String());
						}
				}
			}
			return true;



		case RPL_LUSERHIGHESTCONN: // 250
		case RPL_LUSERCLIENT:			// 251
		case RPL_LUSEROP:					// 252
		case RPL_LUSERUNKNOWN:		 // 253
		case RPL_LUSERCHANNELS:		// 254
		case RPL_LUSERME:					// 255
		case RPL_LUSERLOCAL:			 // 265
		case RPL_LUSERGLOBAL:			// 266
			{
				BString theMsg (RestOfString (data, 4));
				theMsg.RemoveFirst (":");
				theMsg.Prepend ("* ");
				theMsg.Append ("\n");
				Display (theMsg.String());
			}
			return true;


		/// strip and send to server agent	///
		case RPL_ULMAP:						 // 006
		case RPL_ULMAPEND:					// 007
		case RPL_U2MAP:						 // 015
		case RPL_U2MAPEND:					// 017
		case RPL_TRACELINK:				 // 200
		case RPL_TRACECONNECTING:	 // 201
		case RPL_TRACEHANDSHAKE:		// 202
		case RPL_TRACEUNKNOWN:			// 203
		case RPL_TRACEOPERATOR:		 // 204
		case RPL_TRACEUSER:				 // 205
		case RPL_TRACESERVER:			 // 206
		case RPL_TRACENEWTYPE:			// 208
		case RPL_TRACECLASS:				// 209
		case RPL_STATSLINKINFO:		 // 211
		case RPL_STATSCOMMANDS:		 // 212
		case RPL_STATSCLINE:				// 213
		case RPL_STATSNLINE:				// 214
		case RPL_STATSILINE:				// 215
		case RPL_STATSKLINE:				// 216
		case RPL_STATSQLINE:				// 217
		case RPL_STATSYLINE:				// 218
		case RPL_ENDOFSTATS:				// 219
		case RPL_STATSBLINE:				// 220
		case RPL_DALSTATSE:				 // 223
		case RPL_DALSTATSF:				 // 224
		case RPL_DALSTATSZ:				 // 225
		case RPL_DALSTATSN:				 // 226
		case RPL_DALSTATSG:				 // 227
		case RPL_STATSLLINE:				// 241
		case RPL_STATSUPTIME:			 // 242
		case RPL_STATSOLINE:				// 243
		case RPL_STATSHLINE:				// 244
		case RPL_STATSSLINE:				// 245
		case RPL_DALSTATSX:				 // 246
		case RPL_STATSXLINE:				// 247
		case RPL_STATSPLINE:				// 249
		case RPL_ADMINME:					 // 256
		case RPL_ADMINLOC1:				 // 257
		case RPL_ADMINLOC2:				 // 258
		case RPL_ADMINEMAIL:				// 259
		case RPL_TRACELOG:					// 261
		case RPL_ENDOFTRACE:				// 262
		case RPL_SILELIST:					// 271
		case RPL_ENDOFSILELIST:		 // 272
		case RPL_ENDOFWHO:					// 315
		case RPL_CHANSERVURL:			 // 328
		case RPL_COMMANDSYNTAX:		 // 334
		case RPL_VERSION:					 // 351
		case RPL_WHOREPLY:					// 352
		case RPL_BANLIST:					 // 367
		case RPL_ENDOFBANLIST:			// 368
		case RPL_INFO:							// 371
		case RPL_ENDOFINFO:				 // 374
		case RPL_YOUREOPER:				 // 381
		case RPL_REHASHING:				 // 382
		case RPL_TIME:							// 391
		case ERR_NOORIGIN:					// 409
		case ERR_NOTEXTTOSEND:			// 412
		case ERR_TOOMANYAWAY:			 // 429
		case ERR_NICKCHANGETOOFAST: // 438
		case ERR_TARGETCHANGETOOFAST: // 439
		case ERR_SUMMONDISABLED:		// 445
		case ERR_USERSDISABLED:		 // 446
		case ERR_NOTREGISTERED:		 // 451
		case ERR_NEEDMOREPARMS:		 // 461
		case ERR_PASSWDMISMATCH:		// 464
		case ERR_YOUREBANNEDCREEP:	// 465
		case ERR_NOPRIVILEGES:			// 481
		case ERR_NOOPERHOST:				// 491
		case ERR_USERSDONTMATCH:		// 502
		case ERR_SILELISTFULL:			// 511
		case ERR_TOOMANYWATCH:			// 512
		case ERR_TOOMANYDCC:				// 514
		case ERR_CANTINVITE:				// 518
		case ERR_LISTSYNTAX:				// 521
		case ERR_WHOSYNTAX:				 // 522
		case ERR_WHOLIMEXCEED:			// 523
		case RPL_LOGON:						 // 600
		case RPL_LOGOFF:						// 601
		case RPL_WATCHOFF:					// 602
		case RPL_WATCHSTAT:				 // 603
		case RPL_NOWON:						 // 604
		case RPL_NOWOFF:						// 605
		case RPL_WATCHLIST:				 // 606
		case RPL_ENDOFWATCHLIST:		// 607
		case RPL_DCCALLOWLIST:			// 618
		case RPL_DCCALLOWEND:			 // 619
		case RPL_DCCALLOW:					// 620
			{
				BString tempString (RestOfString (data, 4));
				tempString.RemoveFirst (":");
				tempString.Append ("\n");
				Display (tempString.String());
			}
			return true;

		case RPL_UMODEIS:					 // 221
			{
				BString theMode (GetWord (data, 4));

				BString tempString = B_TRANSLATE("Your current mode is %1");
				tempString.ReplaceFirst("%1", theMode);
				tempString += '\n';

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_WHOIS);
				PostActive (&msg);
			}
			return true;

		/// strip and send to active agent	///
		case RPL_TRYAGAIN:					// 263
		case RPL_UNAWAY:						// 305
		case RPL_NOWAWAY:					 // 306
		case ERR_NOSUCHNICK:				// 401
		case ERR_NOSUCHSERVER:			// 402
		case ERR_NOSUCHCHANNEL:		 // 403
		case ERR_CANNOTSENDTOCHAN:	// 404
		case ERR_TOOMANYCHANNELS:	 // 405
		case ERR_WASNOSUCHNICK:		 // 406
		case ERR_TOOMANYTARGETS:		// 407
		case ERR_NOCOLORSONCHAN:		// 408
		case ERR_YOUCANTDOTHAT:		 // 460
		case ERR_CHANOPRIVSNEEDED:	// 482
			{
				BString tempString ("[x] ");
				if (num == ERR_CHANOPRIVSNEEDED)
					tempString += RestOfString (data, 5);
				else
					tempString += RestOfString (data, 4);
				tempString.RemoveFirst (":");
				tempString.Append ("\n");

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
				PostActive (&msg);
			}
			return true;

		case RPL_AWAY:						 // 301
			{
				BString theNick (GetWord(data, 4));
				BString tempString ("[x] "),
							theReason (RestOfString(data, 5));
				theReason.RemoveFirst(":");
				tempString += "Away: ";
				tempString += theReason;
				tempString += '\n';

				if (fRemoteAwayMessages.find(theNick) != fRemoteAwayMessages.end())
				{
					if (fRemoteAwayMessages[theNick] == theReason)
					{
						return true;
					}
				}
				fRemoteAwayMessages[theNick] = theReason;
				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
				PostActive (&msg);
			}
			return true;

		case RPL_USERHOST:				// 302
			{
				BString theHost (GetWord (data, 4)),
								theHostname (GetAddress (theHost.String()));
				theHost.RemoveFirst (":");

				BString tempString (RestOfString (data, 4));
				tempString.RemoveFirst (":");
				tempString.Append ("\n");
				Display (tempString.String());

				if (fGetLocalIP && (tempString.IFindFirst (fMyNick.String()) == 0))
				{
					fGetLocalIP = false;
					struct addrinfo *info;
					struct addrinfo hints;
					memset(&hints, 0, sizeof(addrinfo));
					hints.ai_family = AF_UNSPEC;
					hints.ai_socktype = SOCK_STREAM;
					hints.ai_protocol = IPPROTO_TCP;
					int result = getaddrinfo(theHostname.String(), NULL, &hints, &info);
					if (result == 0)
					{
						char addr_buf[INET6_ADDRSTRLEN];
						getnameinfo(info->ai_addr, info->ai_addrlen, addr_buf, sizeof(addr_buf),
						NULL, 0, NI_NUMERICHOST);
						fLocalip = addr_buf;
						printf("Got address: %s\n", fLocalip.String());
						freeaddrinfo(info);
						return true;
					}
				}
			}
			return true;

		case RPL_ISON:					 // 303
			{
				BString nicks (RestOfString (data, 4));
				BString onlined, offlined;

				nicks.RemoveFirst (":");

				int hasChanged (0);

				BMessage msg (M_NOTIFYLIST_UPDATE);

				for (int32 i = 0; i < fNotifyNicks.CountItems(); i++)
				{
					NotifyListItem *item (((NotifyListItem *)fNotifyNicks.ItemAt(i)));

					int32 nickidx (nicks.IFindFirst(item->Text()));

					// make sure that the nick isn't a partial match.
					if ((nickidx >= 0) &&
						((nicks[nickidx + strlen(item->Text())] == ' ') || (nicks[nickidx + strlen(item->Text())] == '\0')))
					{
						if (item->GetState() != true)
						{
							item->SetState (true);
							hasChanged = 1;

							if (onlined.Length())
								onlined << ", ";
							onlined << item->Text();
#ifdef USE_INFOPOPPER
							if (be_roster->IsRunning(InfoPopperAppSig) == true) {
								entry_ref ref = vision_app->AppRef();
								BMessage infoMsg(InfoPopper::AddMessage);
								infoMsg.AddString("appTitle", S_INFOPOPPER_TITLE);
								infoMsg.AddString("title", fId.String());
								infoMsg.AddInt8("type", (int8)InfoPopper::Information);

								infoMsg.AddInt32("iconType", InfoPopper::Attribute);
								infoMsg.AddRef("iconRef", &ref);

								BString content;
								content << item->Text() << " is online";
								infoMsg.AddString("content", content);

								BMessenger(InfoPopperAppSig).SendMessage(&infoMsg);
							};
#endif

						}
					}
					else
					{
						if (item->GetState() == true)
						{
							item->SetState (false);
							hasChanged = 2;

							if (offlined.Length())
								offlined << ", ";
							offlined << item->Text();
#ifdef USE_INFOPOPPER
							if (be_roster->IsRunning(InfoPopperAppSig) == true) {
				entry_ref ref = vision_app->AppRef();
								BMessage infoMsg(InfoPopper::AddMessage);
								infoMsg.AddString("appTitle", S_INFOPOPPER_TITLE);
								infoMsg.AddString("title", fId.String());
								infoMsg.AddInt8("type", (int8)InfoPopper::Information);

								infoMsg.AddInt32("iconType", InfoPopper::Attribute);
								infoMsg.AddRef("iconRef", &ref);

								BString content;
								content << item->Text() << " is offline";
								infoMsg.AddString("content", content);

								BMessenger(InfoPopperAppSig).SendMessage(&infoMsg);
							};
#endif

						}
					}
#ifdef __HAIKU__
					if (offlined.Length())
					{
						BNotification notification(B_INFORMATION_NOTIFICATION);
						notification.SetGroup(BString("Vision"));
						entry_ref ref = vision_app->AppRef();
						notification.SetOnClickFile(&ref);
						notification.SetTitle(fServerName.String());
						BString content;
						content << offlined;
						if (offlined.FindFirst(' ') > -1)
							content << " are offline";
						else
							content << " is offline";


						notification.SetContent(content);
						notification.Send();
					}
					if (onlined.Length())
					{
						BNotification notification(B_INFORMATION_NOTIFICATION);
						notification.SetGroup(BString("Vision"));
						entry_ref ref = vision_app->AppRef();
						notification.SetOnClickFile(&ref);
						notification.SetTitle(fServerName.String());
						BString content;
						content << onlined;
						if (onlined.FindFirst(' ') > -1)
							content << " are online";
						else
							content << " is online";


						notification.SetContent(content);
						notification.Send();
					}
#endif
				}
				fNotifyNicks.SortItems(SortNotifyItems);
				msg.AddPointer ("list", &fNotifyNicks);
				msg.AddPointer ("source", this);
				msg.AddInt32 ("change", hasChanged);
				Window()->PostMessage (&msg);
			}
			return true;

		case RPL_WHOISIDENTIFIED:	 // 307
			{
				BString theInfo (RestOfString (data, 5));
				theInfo.RemoveFirst (":");

				if (theInfo == "-9z99")
				{
					// USERIP reply? (RPL_U2USERIP)
					BString tempString (RestOfString (data, 4));
					tempString.RemoveFirst (":");
					tempString.Append ("\n");
					Display (tempString.String());
					return true;
				}

				BMessage display (M_DISPLAY);
				BString buffer;

				buffer += "[x] ";
				buffer += theInfo;
				buffer += "\n";
				PackDisplay (&display, buffer.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
				PostActive (&display);
			}
			return true;

		case RPL_WHOISADMIN:					// 308
		case RPL_WHOISSERVICESADMIN:	// 309
		case RPL_WHOISHELPOP:				 // 310
		case RPL_WHOISOPERATOR:			 // 313
		case RPL_WHOISREGNICK:				// 320
		case RPL_WHOISACTUALLY:			 // 338
		case RPL_WHOISMASK:					 // 550
		case RPL_WHOWASIP:						// 612
		case RPL_WHOISUSERMODESALT:	 // 614
		case RPL_WHOISUSERMODES:			// 615
		case RPL_WHOISREALHOSTNAME:	 // 616
			{
				BString theInfo (RestOfString (data, 5));
				theInfo.RemoveFirst (":");

				BMessage display (M_DISPLAY);
				BString buffer;

				buffer += "[x] ";
				buffer += theInfo;
				buffer += "\n";
				PackDisplay (&display, buffer.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
				PostActive (&display);
			}
			return true;

		case RPL_WHOISUSER:				// 311
			{
				BString theNick (GetWord (data, 4)),
								theIdent (GetWord (data, 5)),
								theAddress (GetWord (data, 6)),
								theName (RestOfString (data, 8));
				theName.RemoveFirst (":");

				BMessage display (M_DISPLAY);
				BString buffer;

				buffer += "[x] ";
				buffer += theNick;
				buffer += " (";
				buffer += theIdent;
				buffer += "@";
				buffer += theAddress;
				buffer += ")\n";
				buffer += "[x] ";
				buffer += theName;
				buffer += "\n";

				PackDisplay (&display, buffer.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
				PostActive (&display);
			}
		return true;

		case RPL_WHOISSERVER:	 // 312
			{
				BString theNick (GetWord (data, 4)),
								theServer (GetWord (data, 5)),
								theInfo (RestOfString (data, 6));
				theInfo.RemoveFirst (":");

				BMessage display (M_DISPLAY);
				BString buffer;

				buffer += "[x] Server: ";
				buffer += theServer;
				buffer += " (";
				buffer += theInfo;
				buffer += ")\n";
				PackDisplay (&display, buffer.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
				PostActive (&display);
			}
			return true;

		case RPL_WHOWASUSER:		 // 314
			{
				BString theNick (GetWord (data, 4)),
								theIdent (GetWord (data, 5)),
								theAddress (GetWord (data, 6)),
								theName (RestOfString (data, 8)),
								tempString ("[x] ");
				theName.RemoveFirst (":");
				tempString += B_TRANSLATE("%1 was (%2)");
				tempString.ReplaceFirst("%1", theNick);
				BString nickString = theIdent << "@" << theAddress;
				tempString.ReplaceFirst("%2", nickString.String());
				tempString += "\n";

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
				PostActive (&msg);
			}
			return true;

		case RPL_WHOISIDLE:			 // 317
			{
				BString theNick (GetWord (data, 4)),
								tempString ("[x] "),
								tempString2 ("[x] "),
								theTime (GetWord (data, 5)),
								signOnTime (GetWord (data, 6));

				int64 idleTime (strtoul(theTime.String(), NULL, 0));
				tempString += B_TRANSLATE("Idle");
				tempString += ": ";
				tempString += DurationString(idleTime * 1000 * 1000);
				tempString += "\n";

				int32 serverTime = strtoul(signOnTime.String(), NULL, 0);
				struct tm ptr;
				time_t st;
				char str[80];
				st = serverTime;
				localtime_r (&st, &ptr);
				strftime (str,80,"%A %b %d %Y %I:%M %p %Z", &ptr);
				BString signOnTimeParsed (str);
				signOnTimeParsed.RemoveAll ("\n");

				tempString2 += B_TRANSLATE("Signon");
				tempString2 += ": ";
				tempString2 += signOnTimeParsed;
				tempString2 += "\n";

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
				PostActive (&msg);
				PackDisplay (&msg, tempString2.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
				PostActive (&msg);
			}
			return true;

		case RPL_ENDOFWHOIS:	 // 318
		case RPL_ENDOFNAMES:	 // 366
		case RPL_ENDOFWHOWAS:	// 369
			{
				// nothing
			}
			return true;

		case RPL_WHOISCHANNELS:	 // 319
			{
				BString theChannels (RestOfString (data, 5));
				theChannels.RemoveFirst(":");

				BMessage display (M_DISPLAY);
				BString buffer = "[x] ";

				buffer += B_TRANSLATE("Channels");
				buffer += ": ";
				buffer += theChannels;
				buffer += "\n";
				PackDisplay (&display, buffer.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
				PostActive (&display);
			}
			return true;

		case RPL_LISTSTART:			 // 321
			{
				BMessage msg (M_LIST_BEGIN);
				if (fListAgent)
					vision_app->pClientWin()->DispatchMessage(&msg, (BView *)fListAgent);
			}
			return true;

		case RPL_LIST:						// 322
			{
				BMessage msg (M_LIST_EVENT);
				BString channel (GetWord (data, 4)),
								users (GetWord (data, 5)),
								topic (RestOfString (data, 6));
				topic.RemoveFirst (":");

				msg.AddString ("channel", channel.String());
				msg.AddString ("users", users.String());
				msg.AddString ("topic", topic.String());

				if (fListAgent)
					vision_app->pClientWin()->DispatchMessage(&msg, (BView *)fListAgent);
			}
			return true;

		case RPL_LISTEND:				 // 323
			{
				BMessage msg (M_LIST_DONE);

				if (fListAgent)
					vision_app->pClientWin()->DispatchMessage(&msg, (BView *)fListAgent);
			}
			return true;

		case RPL_CHANNELMODEIS:	 // 324
			{
				BString theChan (GetWord (data, 4)),
								theMode (GetWord (data, 5)),
								tempStuff (RestOfString (data, 6));

				if (tempStuff != "-9z99")
				{
					theMode.Append(" ");
					theMode.Append(tempStuff); // avoid extra space w/o params
				}

				ClientAgent *aClient (ActiveClient()),
										*theClient (Client (theChan.String()));

				BString tempString("*** ");
				tempString += B_TRANSLATE("Channel mode for %1: %2");
				tempString.ReplaceFirst("%1", theChan.String());
				tempString.ReplaceFirst("%2", theMode.String());
				tempString += '\n';

				BMessage msg (M_CHANNEL_MODES);

				msg.AddString ("msgz", tempString.String());
				msg.AddString ("chan", theChan.String());
				msg.AddString ("mode", theMode.String());

				if (theClient)
					theClient->fMsgr.SendMessage (&msg);
				else if (aClient)
					aClient->fMsgr.SendMessage (&msg);
				else
					Display (tempString.String(), C_OP);
			}
			return true;

		case RPL_CHANNELMLOCK:		// 325
			{
				BString theChan (GetWord (data, 4)),
								mLock (GetWord (data, 8)),
								lockMessage ("*** ");
				lockMessage += B_TRANSLATE("Channel mode lock for %1: %2");
				lockMessage.ReplaceFirst("%1", theChan);
				lockMessage.ReplaceFirst("%2", mLock);
				lockMessage += "\n";

				BMessage display (M_DISPLAY);

				PackDisplay (&display, lockMessage.String(), C_OP, C_BACKGROUND, F_TEXT);
				ClientAgent *theClient (Client (theChan.String()));
				if (theClient)
					theClient->fMsgr.SendMessage (&display);
				else
					fMsgr.SendMessage (&display);
			}
			return true;

		case RPL_CHANNELCREATED:			 // 329
			{
				BString theChan (GetWord (data, 4)),
								theTime (GetWord (data, 5)),
								tempString;

				int32 serverTime (strtoul(theTime.String(), NULL, 0));
				struct tm ptr;
				time_t st;
				char str[80];
				st = serverTime;
				localtime_r (&st, &ptr);
				strftime (str,80,"%a %b %d %Y %I:%M %p %Z",&ptr);
				BString theTimeParsed (str);
				theTimeParsed.RemoveAll ("\n");

			tempString = B_TRANSLATE("Channel %1 was created at %2");
			tempString.ReplaceFirst("%1", theChan);
			tempString.ReplaceFirst("%2", theTimeParsed);
				tempString += '\n';
				Display (tempString.String());
			}
			return true;

		case RPL_NOTOPIC:						 // 331
			{
				BString theChan (GetWord (data, 4)),
								tempString ("[x] ");
				tempString += B_TRANSLATE("No topic set in %1");
				tempString.ReplaceFirst("%1", theChan);
				tempString += '\n';

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_ERROR);
				PostActive (&msg);
			}
			return true;

		case RPL_TOPIC:							 // 332
			{
				BString theChannel (GetWord (data, 4)),
								theTopic (RestOfString (data, 5));
				ClientAgent *client (Client (theChannel.String()));

				theTopic.RemoveFirst (":");

				if (client)
				{
					BMessage display (M_DISPLAY);
					BString buffer;

					buffer += "*** ";
					buffer += B_TRANSLATE("Topic: %1");
					buffer.ReplaceFirst("%1", theTopic);
					buffer += '\n';
					PackDisplay (&display, buffer.String(), C_WHOIS);

					BMessage msg (M_CHANNEL_TOPIC);
					msg.AddString ("topic", theTopic.String());
					msg.AddMessage ("display", &display);

					if (client->fMsgr.IsValid())
						client->fMsgr.SendMessage (&msg);
				}
			}
			return true;

		case RPL_TOPICSET:						// 333
			{
				BString channel (GetWord (data, 4)),
								user (GetWord (data, 5)),
								theTime (GetWord (data, 6));

				int32 serverTime (strtoul(theTime.String(), NULL, 0));
				struct tm ptr;
				time_t st;
				char str[80];
				st = serverTime;
				localtime_r (&st, &ptr);
				strftime (str,80,"%A %b %d %Y %I:%M %p %Z",&ptr);
				BString theTimeParsed (str);
				theTimeParsed.RemoveAll ("\n");

				ClientAgent *client (Client (channel.String()));

				if (client)
				{
					BMessage display (M_DISPLAY);
					BString buffer = "*** ";

					buffer += B_TRANSLATE("Topic set by %1 at %2");
					buffer.ReplaceFirst("%1", user);
					buffer.ReplaceFirst("%2", theTimeParsed);
					buffer += '\n';
					PackDisplay (&display, buffer.String(), C_WHOIS);
					if (client->fMsgr.IsValid())
						client->fMsgr.SendMessage (&display);
				}
			}
			return true;

		case RPL_INVITING:						 // 341
			{
				BString channel (GetWord (data, 5)),
								theNick (GetWord (data, 4)),
								tempString;

				tempString += "*** ";
				tempString += B_TRANSLATE("%1 has been invited to %2.");
				tempString.ReplaceFirst("%1", theNick);
				tempString.ReplaceFirst("%2", channel);
				tempString += "\n";

				BMessage display (M_DISPLAY);

				PackDisplay (&display, tempString.String(), C_WHOIS);
				PostActive (&display);
			}
			return true;


		case RPL_NAMEREPLY:						 // 353
			{
				BString channel (GetWord (data, 5)),
								names (RestOfString (data, 6));
				ClientAgent *client (Client (channel.String()));
				names.RemoveFirst (":");

					BString tempString ("*** ");
					tempString += B_TRANSLATE("Users in %1: %2");
					tempString.ReplaceFirst("%1", channel);
					tempString.ReplaceFirst("%2", names);
					tempString += '\n';
					Display (tempString.String(), C_TEXT);

				if (client) // in the channel
				{
					BMessage msg (M_CHANNEL_NAMES);
					BString nick;
					int32 place (1);

					while ((nick = GetWord (names.String(), place)) != "-9z99")
					{
						const char *sNick (nick.String());
						bool founder (false),
								 protect (false),
								 op (false),
								 voice (false),
								 helper (false),
							 ignored;

						if (nick[0] == '*')
						{
							++sNick;
							founder = true;
						}
						else if (nick[0] == '!')
						{
							++sNick;
							protect = true;
						}
						else if (nick[0] == '@')
						{
							++sNick;
							op = true;
						}
						else if (nick[0] == '+')
						{
							++sNick;
							voice = true;
						}
						else if (nick[0] == '%')
						{
							++sNick;
							helper = true;
						}

						ignored = false;
						// BMessage aMsg (M_IS_IGNORED), reply;
						// aMsg.AddString ("server", fServerName.String());
						// aMsg.AddString ("nick", sNick);

						// be_app_messenger.SendMessage (&aMsg, &reply);
						// reply.FindBool ("ignored", &ignored);

						msg.AddString ("nick", nick.String());
						msg.AddBool ("founder", founder);
						msg.AddBool ("protect", protect);
						msg.AddBool ("op", op);
						msg.AddBool ("voice", voice);
						msg.AddBool ("helper", helper);
						msg.AddBool ("ignored", ignored);
						++place;
					}

					if (client->fMsgr.IsValid())
						client->fMsgr.SendMessage (&msg);
				}
			}
			return true;

		case RPL_MOTD:						// 372
		case RPL_MOTDALT:				 // 378
		case RPL_OPERMOTDSTART:	 // 609
		case RPL_OPERMOTD:				// 610
		case RPL_OPERENDOFMOTD:	 // 611
			{
				BString tempString (RestOfString(data, 4));
				tempString.RemoveFirst (":");
				tempString.Append ("\n");
				Display (tempString.String(), C_SERVER, C_BACKGROUND, F_SERVER);
			}
			return true;

		case RPL_MOTDSTART:				// 375
			{

				BString tempString ("- ");
				tempString += B_TRANSLATE("Server Message Of the Day");
				tempString += ":\n";
				Display (tempString.String(), C_SERVER, C_BACKGROUND, F_SERVER);
			}
			return true;

		case RPL_ENDOFMOTD:				// 376
		case ERR_NOMOTD:					 // 422
			{
				BString tempString (RestOfString (data, 4));
			tempString.RemoveFirst (":");
			tempString.Append ("\n");

				Display (tempString.String(), C_SERVER, C_BACKGROUND, F_SERVER);

				if (fInitialMotd && fCmds.Length())
				{
					BMessage msg (M_SUBMIT_INPUT);
					const char *place (fCmds.String()), *eol;

					msg.AddInt32 ("which", PASTE_MULTI_NODELAY);

					while ((eol = strchr (place, '\n')) != 0)
					{
						BString line;

						line.Append (place, eol - place);
						msg.AddString ("data", line.String());
						ParseAutoexecChans (line);
						place = eol + 1;
					}

					if (*place)
					{
						// check in case this was the only line
						ParseAutoexecChans (BString(place));
						msg.AddString ("data", place);
					}

					msg.AddInt32 ("which", 3);
					msg.AddBool ("autoexec", true);
					fMsgr.SendMessage (&msg);
				}

				BString IPCommand ("/userhost ");
				IPCommand += fMyNick;
				ParseCmd (IPCommand.String());

				if (fReconnecting)
				{
					BString reString = "[@] ";
					reString += B_TRANSLATE("Successful reconnect");
					reString += "\n";
					Display (reString.String(), C_ERROR);
					DisplayAll (reString.String(), C_ERROR, C_BACKGROUND, F_SERVER);
					fMsgr.SendMessage (M_REJOIN_ALL);
					fReconnecting = false;
				}

				fInitialMotd = false;
			}
			return true;

		case RPL_USERSSTART:			 // 392
			{
				// empty for now
		}
			return true;

		case RPL_USERS:						// 393
			{
				// empty for now
			}
			return true;

		case ERR_ERRONEOUSNICKNAME:		// 432
		case ERR_NICKNAMEINUSE:				// 433
		case ERR_RESOURCEUNAVAILABLE:	// 437
			{
				BString theNick (GetWord (data, 4));

				if (fIsConnecting)
				{
					BString nextNick (GetNextNick());
					if (nextNick != "")
					{
						BString tempString = "* ";
						tempString += B_TRANSLATE("Nickname \"%1\" in use or unavailable, trying \"%2\"");
						tempString.ReplaceFirst("%1", theNick.String());
						tempString.ReplaceFirst("%2", nextNick.String());
						tempString += "\n";
						Display (tempString.String());

						tempString = "NICK ";
						tempString += nextNick;
						SendData (tempString.String());
						return true;
					}
					else
					{
						BString tempString = "* ";
						tempString += B_TRANSLATE("All your pre-selected nicknames are in use.");
						tempString += "\n";
						Display (tempString.String());
						tempString = "* ";
						tempString += B_TRANSLATE("Please type /NICK <NEWNICK> to try another.");
						tempString += "\n";
						Display (tempString.String());
						return true;
					}
				}
				BString tempString = "[x] ";
				tempString += B_TRANSLATE("Nickname/Channel \"%1\" is already in use or unavailable.");
				tempString.ReplaceFirst("%1", theNick);
				tempString += "\n";

				BMessage display (M_DISPLAY);
				PackDisplay (&display, tempString.String(), C_NICK);
				PostActive (&display);
			}
			return true;

		case ERR_USERNOTINCHANNEL:		// 441
			{
				BString theChannel (GetWord (data, 5)),
								theNick (GetWord (data, 4)),
								tempString ("[x] ");
				tempString += B_TRANSLATE("%1 not in %2.");
				tempString.ReplaceFirst("%1", theNick);
				tempString.ReplaceFirst("%2", theChannel);
				tempString += "\n";

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_ERROR);
				PostActive (&msg);
			}
			return true;

		case ERR_NOTONCHANNEL:			 // 442
			{
				BString theChannel (GetWord (data, 4)),
								tempString ("[x] ");
				tempString += B_TRANSLATE("You're not in %1.");
				tempString.ReplaceFirst("%1", theChannel);
				tempString += "\n";

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_ERROR);
				PostActive (&msg);
			}
			return true;

		case ERR_USERONCHANNEL:		 // 443
			{
				BString theChannel (GetWord (data, 5)),
								theNick (GetWord (data, 4)),
				tempString ("[x] ");
				tempString += B_TRANSLATE("%1 is already in %2.");
				tempString.ReplaceFirst("%1", theNick);
				tempString.ReplaceFirst("%2", theChannel);
				tempString += "\n";

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_ERROR);
				PostActive (&msg);
			}
			return true;

		case ERR_KEYSET:						// 467
			{
				BString theChannel (GetWord (data, 4)),
								tempString ("[x] ");
				tempString += B_TRANSLATE("Channel key already set in %1.");
				tempString.ReplaceFirst("%1", theChannel);
				tempString += "\n";

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_ERROR);
				PostActive (&msg);
			}
			return true;

		case ERR_UNKNOWNMODE:				// 472
			{
				BString theMode (GetWord (data, 4)),
								tempString ("[x] ");
				tempString += B_TRANSLATE("Unknown channel mode: '%1'.");
				tempString.ReplaceFirst("%1", theMode);
				tempString += "\n";

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_QUIT);
				PostActive (&msg);
			}
			return true;

		case ERR_INVITEONLYCHAN:		 // 473
			{
				BString theChan (GetWord (data, 4)),
								tempString ("[x] "),
								theReason (RestOfString (data, 5));
				theReason.RemoveFirst(":");
				theReason.ReplaceLast("channel", theChan.String());
				tempString << theReason < " ";
				tempString += B_TRANSLATE("(invite only)");
				tempString += "\n";

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_QUIT, C_BACKGROUND, F_SERVER);
				PostActive (&msg);
				RemoveAutoexecChan (theChan);
			}
			return true;

		case ERR_BANNEDFROMCHAN:		 // 474
			{
				BString theChan (GetWord (data, 4)),
								tempString ("[x] "),
								theReason (RestOfString (data, 5));
				theReason.RemoveFirst(":");
				theReason.ReplaceLast("channel", theChan.String());

				tempString << theReason < " ";
				tempString += B_TRANSLATE("(you're banned)");
				tempString += "\n";

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_QUIT, C_BACKGROUND, F_SERVER);
				PostActive (&msg);
				RemoveAutoexecChan (theChan);
			}
			return true;

		case ERR_BADCHANNELKEY:			// 475
			{
				BString theChan (GetWord(data, 4)),
								theReason (RestOfString(data, 5)),
								tempString("[x] ");
				theReason.RemoveFirst(":");
				theReason.ReplaceLast("channel", theChan.String());
				tempString << theReason << " ";
				tempString += B_TRANSLATE("(bad channel key)");
				tempString += "\n";

				BMessage msg (M_DISPLAY);
				PackDisplay (&msg, tempString.String(), C_QUIT, C_BACKGROUND, F_SERVER);
				PostActive (&msg);
				RemoveAutoexecChan (theChan);
			}
			return true;

		case ERR_UMODEUNKNOWNFLAG:		// 501
			{
				BMessage msg (M_DISPLAY);
				BString buffer = "[x] ";

		buffer += B_TRANSLATE("Unknown mode flag.");
				buffer += "\n";
				PackDisplay (&msg, buffer.String(), C_QUIT);
				PostActive (&msg);
			}
			return true;

		// not sure what these numerics are,
		// but they are usually on-connect messages
		case RPL_290:								 // 290
		case RPL_291:								 // 291
		case RPL_292:								 // 292
			{
				BString tempString (RestOfString(data, 4));
				tempString.RemoveFirst (":");
				tempString.Append ("\n");
				tempString.Prepend ("- ");
				Display (tempString.String());
			}
			return true;

		case RPL_WHOISREGISTEREDBOT:	// 617
			{
				// conflicts with RPL_DCCALLOWCHANGE
				BString theNick (GetWord (data, 4)),
								theMessage (RestOfString (data, 5)),
								tempString;
				theNick.RemoveFirst (":");
				theMessage.RemoveFirst (":");
				theMessage.Append ("\n");

				switch (fIrcdtype)
				{
					case IRCD_ULTIMATE:
						{
							tempString += "[@] ";
							tempString += theMessage;
							BMessage msg (M_DISPLAY);
							PackDisplay (&msg, tempString.String(), C_WHOIS, C_BACKGROUND, F_SERVER);
							PostActive (&msg);
						}
						break;

					default:
						{
							tempString += theNick;
							tempString += " ";
							tempString += theMessage;
							Display (tempString.String());
						}
				}
			}
			return true;

		default:
			break;
	}

	return false;
}
Beispiel #16
0
static NEOERR *split_and_convert (const char *src, int slen,
                                  STRING *out, HTML_CONVERT_OPTS *opts)
{
  NEOERR *err = STATUS_OK;
  regmatch_t email_match, url_match;
  int errcode;
  char *ptr, *esc;
  char errbuf[256];
  struct _parts *parts;
  int part_count;
  int part;
  int x, i;
  int spaces = 0;

  if (!CompiledRe)
  {
#ifdef HAVE_PTHREADS
    /* In threaded environments, we have to mutex lock to do this regcomp, but
     * we don't want to use a mutex every time to check that it was regcomp.
     * So, we only lock if our first test of compiled was false */
    err = mLock(&InitLock);
    if (err != STATUS_OK) return nerr_pass(err);
    if (CompiledRe == 0) {
#endif
    if ((errcode = regcomp (&EmailRegex, EmailRe, REG_ICASE | REG_EXTENDED)))
    {
      regerror (errcode, &EmailRegex, errbuf, sizeof(errbuf));
      err = nerr_raise (NERR_PARSE, "Unable to compile EmailRE: %s", errbuf);
    }
    if ((errcode = regcomp (&UrlRegex, URLRe, REG_ICASE | REG_EXTENDED)))
    {
      regerror (errcode, &UrlRegex, errbuf, sizeof(errbuf));
      err = nerr_raise (NERR_PARSE, "Unable to compile URLRe: %s", errbuf);
    }
    CompiledRe = 1;
#ifdef HAVE_PTHREADS
    }
    if (err) {
      mUnlock(&InitLock);
      return err;
    }
    err = mUnlock(&InitLock);
    if (err != STATUS_OK) return nerr_pass(err);
#else
    if (err) {
      return err;
    }
#endif
  }

  part_count = 20;
  parts = (struct _parts *) malloc (sizeof(struct _parts) * part_count);
  part = 0;

  x = 0;
  if (regexec (&EmailRegex, src+x, 1, &email_match, 0) != 0)
  {
    email_match.rm_so = -1;
    email_match.rm_eo = -1;
  }
  else
  {
    email_match.rm_so += x;
    email_match.rm_eo += x;
  }
  if (regexec (&UrlRegex, src+x, 1, &url_match, 0) != 0)
  {
    url_match.rm_so = -1;
    url_match.rm_eo = -1;
  }
  else
  {
    url_match.rm_so += x;
    url_match.rm_eo += x;
  }
  while ((x < slen) && !((email_match.rm_so == -1) && (url_match.rm_so == -1)))
  {
    if (part >= part_count)
    {
      void *new_ptr;

      part_count *= 2;
      new_ptr = realloc (parts, sizeof(struct _parts) * part_count);
      if (new_ptr == NULL) {
        free(parts);
        return nerr_raise (NERR_NOMEM,
                           "Unable to increase url matcher to %d urls",
                           part_count);
      }
      parts = (struct _parts *) new_ptr;
    }
    if ((url_match.rm_so != -1) && ((email_match.rm_so == -1) || (url_match.rm_so <= email_match.rm_so)))
    {
      parts[part].begin = url_match.rm_so;
      parts[part].end = url_match.rm_eo;
      parts[part].type = SC_TYPE_URL;
      x = parts[part].end + 1;
      part++;
      if (x < slen)
      {
	if (regexec (&UrlRegex, src+x, 1, &url_match, 0) != 0)
	{
	  url_match.rm_so = -1;
	  url_match.rm_eo = -1;
	}
	else
	{
	  url_match.rm_so += x;
	  url_match.rm_eo += x;
	}
	if ((email_match.rm_so != -1) && (x > email_match.rm_so))
	{
	  if (regexec (&EmailRegex, src+x, 1, &email_match, 0) != 0)
	  {
	    email_match.rm_so = -1;
	    email_match.rm_eo = -1;
	  }
	  else
	  {
	    email_match.rm_so += x;
	    email_match.rm_eo += x;
	  }
	}
      }
    }
    else
    {
      parts[part].begin = email_match.rm_so;
      parts[part].end = email_match.rm_eo;
      parts[part].type = SC_TYPE_EMAIL;
      x = parts[part].end + 1;
      part++;
      if (x < slen)
      {
	if (regexec (&EmailRegex, src+x, 1, &email_match, 0) != 0)
	{
	  email_match.rm_so = -1;
	  email_match.rm_eo = -1;
	}
	else
	{
	  email_match.rm_so += x;
	  email_match.rm_eo += x;
	}
	if ((url_match.rm_so != -1) && (x > url_match.rm_so))
	{
	  if (regexec (&UrlRegex, src+x, 1, &url_match, 0) != 0)
	  {
	    url_match.rm_so = -1;
	    url_match.rm_eo = -1;
	  }
	  else
	  {
	    url_match.rm_so += x;
	    url_match.rm_eo += x;
	  }
	}
      }
    }
  }

  i = 0;
  x = 0;
  while (x < slen)
  {
    if ((i >= part) || (x < parts[i].begin))
    {
      ptr = strpbrk(src + x, "&<>\r\n ");
      if (ptr == NULL)
      {
	if (spaces)
	{
	  int sp;
	  for (sp = 0; sp < spaces - 1; sp++)
	  {
	    err = string_append (out, "&nbsp;");
	    if (err != STATUS_OK) break;
	  }
	  if (err != STATUS_OK) break;
	  err = string_append_char (out, ' ');
	}
	spaces = 0;
	if (i < part)
	{
	  err = string_appendn (out, src + x, parts[i].begin - x);
	  x = parts[i].begin;
	}
	else
	{
	  err = string_append (out, src + x);
	  x = slen;
	}
      }
      else
      {
	if ((i >= part) || ((ptr - src) < parts[i].begin))
	{
	  if (spaces)
	  {
	    int sp;
	    for (sp = 0; sp < spaces - 1; sp++)
	    {
	      err = string_append (out, "&nbsp;");
	      if (err != STATUS_OK) break;
	    }
	    if (err != STATUS_OK) break;
	    err = string_append_char (out, ' ');
	  }
	  spaces = 0;
	  err = string_appendn (out, src + x, (ptr - src) - x);
	  if (err != STATUS_OK) break;
	  x = ptr - src;
	  if (src[x] == ' ')
	  {
	    if (opts->space_convert)
	    {
	      spaces++;
	    }
	    else
	      err = string_append_char (out, ' ');
	  }
	  else
	  {
	    if (src[x] != '\n' && spaces)
	    {
	      int sp;
	      for (sp = 0; sp < spaces - 1; sp++)
	      {
		err = string_append (out, "&nbsp;");
		if (err != STATUS_OK) break;
	      }
	      if (err != STATUS_OK) break;
	      err = string_append_char (out, ' ');
	    }
	    spaces = 0;

	    if (src[x] == '&')
	      err = string_append (out, "&amp;");
	    else if (src[x] == '<')
	      err = string_append (out, "&lt;");
	    else if (src[x] == '>')
	      err = string_append (out, "&gt;");
	    else if (src[x] == '\n')
	      if (opts->newlines_convert)
		err = string_append (out, "<br/>\n");
	      else if (x && src[x-1] == '\n')
		err = string_append (out, "<p/>\n");
	      else
		err = string_append_char (out, '\n');
	    else if (src[x] != '\r')
	      err = nerr_raise (NERR_ASSERT, "src[x] == '%c'", src[x]);
	  }
	  x++;
	}
	else
	{
	  if (spaces)
	  {
	    int sp;
	    for (sp = 0; sp < spaces - 1; sp++)
	    {
	      err = string_append (out, "&nbsp;");
	      if (err != STATUS_OK) break;
	    }
	    if (err != STATUS_OK) break;
	    err = string_append_char (out, ' ');
	  }
	  spaces = 0;
	  err = string_appendn (out, src + x, parts[i].begin - x);
	  x = parts[i].begin;
	}
      }
    }
    else
    {
      if (spaces)
      {
	int sp;
	for (sp = 0; sp < spaces - 1; sp++)
	{
	  err = string_append (out, "&nbsp;");
	  if (err != STATUS_OK) break;
	}
	if (err != STATUS_OK) break;
	err = string_append_char (out, ' ');
      }
      spaces = 0;
      if (parts[i].type == SC_TYPE_URL)
      {
        char last_char = src[parts[i].end-1];
        int suffix=0;
        if (last_char == '.' || last_char == ',') { suffix=1; }
	err = string_append (out, " <a ");
	if (err != STATUS_OK) break;
	if (opts->url_class)
	{
	    err = string_appendf (out, "class=%s ", opts->url_class);
	    if (err) break;
	}
	if (opts->url_target)
	{
	  err = string_appendf (out, "target=\"%s\" ", opts->url_target);
	  if (err) break;
	}
	err = string_append(out, "href=\"");
	if (err) break;
	if (opts->bounce_url)
	{
	  char *url, *esc_url, *new_url;
	  int url_len;
	  if (!strncasecmp(src + x, "www.", 4))
	  {
	    url_len = 7 + parts[i].end - x - suffix;
	    url = (char *) malloc(url_len+1);
	    if (url == NULL)
	    {
	      err = nerr_raise(NERR_NOMEM,
		  "Unable to allocate memory to convert url");
	      break;
	    }
	    strcpy(url, "http://");
	    strncat(url, src + x, parts[i].end - x - suffix);
	  }
	  else
	  {
	    url_len = parts[i].end - x - suffix;
	    url = (char *) malloc(url_len+1);
	    if (url == NULL)
	    {
	      err = nerr_raise(NERR_NOMEM,
		  "Unable to allocate memory to convert url");
	      break;
	    }
	    strncpy(url, src + x, parts[i].end - x - suffix);
	    url[url_len] = '\0';
	  }
	  err = cgi_url_escape(url, &esc_url);
	  free(url);
	  if (err) {
	    free(esc_url);
	    break;
	  }

	  new_url = sprintf_alloc(opts->bounce_url, esc_url);
	  free(esc_url);
	  if (new_url == NULL)
	  {
	    err = nerr_raise(NERR_NOMEM, "Unable to allocate memory to convert url");
	    break;
	  }
	  err = string_append (out, new_url);
	  free(new_url);
	  if (err) break;
	}
	else
	{
	  if (!strncasecmp(src + x, "www.", 4))
	  {
	    err = string_append (out, "http://");
	    if (err != STATUS_OK) break;
	  }
	  err = string_appendn (out, src + x, parts[i].end - x - suffix);
	  if (err != STATUS_OK) break;
	}
	err = string_append (out, "\">");
	if (err != STATUS_OK) break;
        if (opts->link_name) {
          err = html_escape_alloc((opts->link_name),
                                  strlen(opts->link_name), &esc);
        } else {
          err = html_escape_alloc((src + x), parts[i].end - x - suffix, &esc);
        }
	if (err != STATUS_OK) break;
	err = string_append (out, esc);
	free(esc);
	if (err != STATUS_OK) break;
	err = string_append (out, "</a>");
        if (suffix) {
            err  = string_appendn(out,src + parts[i].end - 1,1);
	    if (err != STATUS_OK) break;
        }
      }
      else /* type == SC_TYPE_EMAIL */
      {
	err = string_append (out, "<a ");
	if (err != STATUS_OK) break;
	if (opts->mailto_class)
	{
	    err = string_appendf (out, "class=%s ", opts->mailto_class);
	    if (err) break;
	}
	err = string_append(out, "href=\"mailto:");
	if (err) break;
	err = string_appendn (out, src + x, parts[i].end - x);
	if (err != STATUS_OK) break;
	err = string_append (out, "\">");
	if (err != STATUS_OK) break;
	err = html_escape_alloc(src + x, parts[i].end - x, &esc);
	if (err != STATUS_OK) break;
	err = string_append (out, esc);
	free(esc);
	if (err != STATUS_OK) break;
	err = string_append (out, "</a>");
      }
      x = parts[i].end;
      i++;
    }
    if (err != STATUS_OK) break;
  }
  free (parts);
  return err;
}
af::Msg* threadProcessMsgCase( ThreadArgs * i_args, af::Msg * i_msg)
{
    //i_msg->stdOut();
    //printf("IM=%d LM=%d MM=%d\n", i_msg->getMagicNumber(), af::Msg::Magic, af::Environment::getMagicMode());
    af::Msg * o_msg_response = NULL;

    switch( i_msg->type())
    {
    case af::Msg::TVersionMismatch:
    {
        AFCommon::QueueLogError( i_msg->v_generateInfoString( false));
        o_msg_response = new af::Msg( af::Msg::TVersionMismatch, 1);
        break;
    }
    case af::Msg::TMagicMismatch:
    {
        std::string err = "Magick number mismatch: recieved ";
        err += af::itos( i_msg->getMagicNumber()) + " != " + af::itos( af::Msg::Magic) += " local.";
        AFCommon::QueueLogError( err);
        o_msg_response = new af::Msg( af::Msg::TMagicMismatch, 1);
        break;
    }
    case af::Msg::TMagicNumber:
    {
        std::string msg = "Magick Number " + af::itos( af::Msg::Magic)
                          + " changed to " + af::itos( i_msg->int32());
        AFCommon::QueueLog( msg);
        o_msg_response = new af::Msg();
        o_msg_response->setString( msg);
        af::Msg::Magic = i_msg->int32();
        break;
    }
    case af::Msg::TInvalid:
    {
        AFCommon::QueueLogError( std::string("Invalid message recieved: ") + i_msg->v_generateInfoString( false));
        break;
    }
    case af::Msg::TNULL:
    case af::Msg::TDATA:
    case af::Msg::TTESTDATA:
    case af::Msg::TStringList:
    {
        i_msg->stdOutData();
        break;
    }
    case af::Msg::THTTP:
    case af::Msg::TJSON:
    {
        return threadProcessJSON( i_args, i_msg);
    }
    case af::Msg::TString:
    {
        std::string str = i_msg->getString();
        if( str.empty()) break;

        AFCommon::QueueLog( str);
        AfContainerLock mLock( i_args->monitors, AfContainerLock::WRITELOCK);
        i_args->monitors->sendMessage( str);
        break;
    }
    case af::Msg::TStatRequest:
    {
        o_msg_response = new af::Msg;
        af::statwrite( o_msg_response);
        break;
    }
    case af::Msg::TConfirm:
    {
        printf("Thread process message: Msg::TConfirm: %d\n", i_msg->int32());
        i_args->msgQueue->pushMsg( new af::Msg( af::Msg::TConfirm, 1));
        o_msg_response = new af::Msg( af::Msg::TConfirm, 1 - i_msg->int32());
        break;
    }
    case af::Msg::TConfigLoad:
    {
        AfContainerLock jlock( i_args->jobs,	 AfContainerLock::WRITELOCK);
        AfContainerLock rlock( i_args->renders, AfContainerLock::WRITELOCK);
        AfContainerLock tlock( i_args->talks,	AfContainerLock::WRITELOCK);
        AfContainerLock ulock( i_args->users,	AfContainerLock::WRITELOCK);
        printf("\n	========= RELOADING CONFIG =========\n\n");
        std::string message;
        if( af::Environment::reload())
        {
            message = "Reloaded successfully.";
            printf("\n	========= CONFIG RELOADED SUCCESSFULLY =========\n\n");
        }
        else
        {
            message = "Failed, see server logs fo details.";
            printf("\n	========= CONFIG RELOADING FAILED =========\n\n");
        }
        o_msg_response = new af::Msg();
        o_msg_response->setString( message);
        break;
    }
    case af::Msg::TFarmLoad:
    {
        AfContainerLock mLock( i_args->monitors, AfContainerLock::WRITELOCK);
        AfContainerLock rlock( i_args->renders,  AfContainerLock::WRITELOCK);

        printf("\n	========= RELOADING FARM =========\n\n");
        std::string message;
        if( af::loadFarm( true))
        {
            RenderContainerIt rendersIt( i_args->renders);
            for( RenderAf *render = rendersIt.render(); render != NULL; rendersIt.next(), render = rendersIt.render())
            {
                render->getFarmHost();
                i_args->monitors->addEvent( af::Msg::TMonitorRendersChanged, render->getId());
            }
            message = "Reloaded successfully.";
            printf("\n	========= FARM RELOADED SUCCESSFULLY =========\n\n");
        }
        else
        {
            message = "Failed, see server logs fo details. Check farm with \"afcmd fcheck\" at first.";
            printf("\n	========= FARM RELOADING FAILED =========\n\n");
        }
        o_msg_response = new af::Msg();
        o_msg_response->setString( message);
        break;
    }

// ---------------------------------- Monitor ---------------------------------//
    case af::Msg::TMonitorRegister:
    {
        AfContainerLock lock( i_args->monitors, AfContainerLock::WRITELOCK);

        MonitorAf * newMonitor = new MonitorAf( i_msg);
        newMonitor->setAddressIP( i_msg->getAddress());
        o_msg_response = i_args->monitors->addMonitor( newMonitor);
        break;
    }
    case af::Msg::TMonitorUpdateId:
    {
        AfContainerLock lock( i_args->monitors, AfContainerLock::READLOCK);

        if( i_args->monitors->updateId( i_msg->int32()))
        {
            o_msg_response = new af::Msg( af::Msg::TMonitorId, i_msg->int32());
        }
        else
        {
            o_msg_response = new af::Msg( af::Msg::TMonitorId, 0);
        }
        break;
    }
    case af::Msg::TMonitorsListRequest:
    {
        AfContainerLock lock( i_args->monitors, AfContainerLock::READLOCK);

        o_msg_response = i_args->monitors->generateList( af::Msg::TMonitorsList);
        break;
    }
    case af::Msg::TMonitorsListRequestIds:
    {
        AfContainerLock lock( i_args->monitors, AfContainerLock::READLOCK);

        af::MCGeneral ids( i_msg);
        o_msg_response = i_args->monitors->generateList( af::Msg::TMonitorsList, ids);
        break;
    }
    case af::Msg::TMonitorLogRequestId:
    {
        AfContainerLock lock( i_args->monitors,  AfContainerLock::READLOCK);

        MonitorContainerIt it( i_args->monitors);
        MonitorAf* node = it.getMonitor( i_msg->int32());
        if( node == NULL )
        {   // FIXME: Better to return some message in any case.
            break;
        }
        o_msg_response = new af::Msg();
        o_msg_response->setStringList( node->getLog());
        break;
    }

// ---------------------------------- Talk ---------------------------------//
    case af::Msg::TTalkRegister:
    {
        AfContainerLock mlock( i_args->monitors, AfContainerLock::WRITELOCK);
        AfContainerLock tlock( i_args->talks,	 AfContainerLock::WRITELOCK);

        TalkAf * newTalk = new TalkAf( i_msg);
        newTalk->setAddressIP( i_msg->getAddress());
        o_msg_response = i_args->talks->addTalk( newTalk, i_args->monitors);
        break;
    }
    case af::Msg::TTalksListRequest:
    {
        AfContainerLock lock( i_args->talks, AfContainerLock::READLOCK);

        o_msg_response = i_args->talks->generateList( af::Msg::TTalksList);
        break;
    }
    case af::Msg::TTalksListRequestIds:
    {
        AfContainerLock lock( i_args->talks, AfContainerLock::READLOCK);

        af::MCGeneral ids( i_msg);
        o_msg_response = i_args->talks->generateList( af::Msg::TTalksList, ids);
        break;
    }
    case af::Msg::TTalkUpdateId:
    {
        AfContainerLock lock( i_args->talks, AfContainerLock::READLOCK);

        if( i_args->talks->updateId( i_msg->int32()))
        {
            o_msg_response = i_args->talks->generateList( af::Msg::TTalksList);
        }
        else
        {
            o_msg_response = new af::Msg( af::Msg::TTalkId, 0);
        }
        break;
    }
    case af::Msg::TTalkDistributeData:
    {
        AfContainerLock lock( i_args->talks, AfContainerLock::READLOCK);

        i_args->talks->distributeData( i_msg);
        break;
    }

// ---------------------------------- Render -------------------------------//
    case af::Msg::TRenderRegister:
    {
//printf("case af::Msg::TRenderRegister:\n");
        AfContainerLock mLock( i_args->monitors, AfContainerLock::WRITELOCK);
        AfContainerLock rLock( i_args->renders,  AfContainerLock::WRITELOCK);

        RenderAf * newRender = new RenderAf( i_msg);
        newRender->setAddressIP( i_msg->getAddress());
        o_msg_response = i_args->renders->addRender( newRender, i_args->monitors);
        break;
    }
    case af::Msg::TRenderUpdate:
    {
//printf("case af::Msg::TRenderUpdate:\n");
        AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK);

        af::Render render_up( i_msg);
//printf("Msg::TRenderUpdate: %s - %s\n", render_up.getName().toUtf8().data(), time2Qstr( time(NULL)).toUtf8().data());
        RenderContainerIt rendersIt( i_args->renders);
        RenderAf* render = rendersIt.getRender( render_up.getId());

        int id = 0;
        // If there is not such render, a zero id will be send.
        // It is a signal for client to register again (may be server was restarted).
        if((render != NULL) && ( render->update( &render_up)))
        {
            id = render->getId();
        }
        o_msg_response = new af::Msg( af::Msg::TRenderId, id);
        break;
    }
    case af::Msg::TRendersListRequest:
    {
        AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK);

        o_msg_response = i_args->renders->generateList( af::Msg::TRendersList);
        break;
    }
    case af::Msg::TRendersListRequestIds:
    {
        AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK);

        af::MCGeneral ids( i_msg);
        o_msg_response = i_args->renders->generateList( af::Msg::TRendersList, ids);
        break;
    }
    case af::Msg::TRendersResourcesRequestIds:
    {
        AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK);

        af::MCGeneral ids( i_msg);
        o_msg_response = i_args->renders->generateList( af::Msg::TRendersResources, ids);
        break;
    }
    case af::Msg::TRenderLogRequestId:
    {
        AfContainerLock lock( i_args->renders,  AfContainerLock::READLOCK);

        RenderContainerIt rendersIt( i_args->renders);
        RenderAf* render = rendersIt.getRender( i_msg->int32());
        if( render == NULL )
        {   // FIXME: Better to return some message in any case.
            break;
        }
        o_msg_response = new af::Msg;
        o_msg_response->setStringList( render->getLog());
        break;
    }
    case af::Msg::TRenderTasksLogRequestId:
    {
        AfContainerLock lock( i_args->renders,  AfContainerLock::READLOCK);

        RenderContainerIt rendersIt( i_args->renders);
        RenderAf* render = rendersIt.getRender( i_msg->int32());
        if( render == NULL )
        {   // FIXME: Better to return some message in any case.
            break;
        }
        o_msg_response = new af::Msg;
        if( render->getTasksLog().empty())
        {
            o_msg_response->setString("No tasks execution log.");
        }
        else
        {
            o_msg_response->setStringList( render->getTasksLog());
        }
        break;
    }
    case af::Msg::TRenderInfoRequestId:
    {
        AfContainerLock lock( i_args->renders,  AfContainerLock::READLOCK);

        RenderContainerIt rendersIt( i_args->renders);
        RenderAf* render = rendersIt.getRender( i_msg->int32());
        if( render == NULL )
        {   // FIXME: Better to return some message in any case.
            break;
        }
        o_msg_response = render->writeFullInfo();
        break;
    }

// ---------------------------------- Users -------------------------------//
    case af::Msg::TUserIdRequest:
    {
        AfContainerLock lock( i_args->users, AfContainerLock::READLOCK);

        af::MsgClassUserHost usr( i_msg);
        std::string name = usr.getUserName();
        int id = 0;
        UserContainerIt usersIt( i_args->users);
        for( af::User *user = usersIt.user(); user != NULL; usersIt.next(), user = usersIt.user())
        {
            if( user->getName() == name)
            {
                id = user->getId();
            }
        }
        o_msg_response = new af::Msg( af::Msg::TUserId, id);
        break;
    }
    case af::Msg::TUsersListRequest:
    {
        AfContainerLock lock( i_args->users, AfContainerLock::READLOCK);

        o_msg_response = i_args->users->generateList( af::Msg::TUsersList);
        break;
    }
    case af::Msg::TUsersListRequestIds:
    {
        AfContainerLock lock( i_args->users, AfContainerLock::READLOCK);

        af::MCGeneral ids( i_msg);
        o_msg_response = i_args->users->generateList( af::Msg::TUsersList, ids);
        break;
    }
    case af::Msg::TUserLogRequestId:
    {
        AfContainerLock lock( i_args->users,  AfContainerLock::READLOCK);

        UserContainerIt usersIt( i_args->users);
        UserAf* user = usersIt.getUser( i_msg->int32());
        if( user == NULL )
        {   // FIXME: Better to return some message in any case.
            break;
        }
        o_msg_response = new af::Msg();
        o_msg_response->setStringList( user->getLog());
        break;
    }
    case af::Msg::TUserJobsOrderRequestId:
    {
        AfContainerLock lock( i_args->users,  AfContainerLock::READLOCK);

        UserContainerIt usersIt( i_args->users);
        UserAf* user = usersIt.getUser( i_msg->int32());
        if( user == NULL )
        {   // FIXME: Better to return some message in any case.
            break;
        }
        af::MCGeneral ids;
        ids.setId( user->getId());
        ids.setList( user->generateJobsIds());
        o_msg_response = new af::Msg( af::Msg::TUserJobsOrder, &ids);
        break;
    }

// ------------------------------------- Job -------------------------------//
    case af::Msg::TJobRequestId:
    {
        AfContainerLock lock( i_args->jobs,  AfContainerLock::READLOCK);

        JobContainerIt jobsIt( i_args->jobs);
        JobAf* job = jobsIt.getJob( i_msg->int32());
        if( job == NULL )
        {
            o_msg_response = new af::Msg( af::Msg::TJobRequestId, 0);
            break;
        }
        o_msg_response = new af::Msg( af::Msg::TJob, job);
        break;
    }
    case af::Msg::TJobLogRequestId:
    {
        AfContainerLock lock( i_args->jobs,  AfContainerLock::READLOCK);

        JobContainerIt jobsIt( i_args->jobs);
        JobAf* job = jobsIt.getJob( i_msg->int32());
        if( job == NULL )
        {   // FIXME: Better to return some message in any case.
            break;
        }
        o_msg_response = new af::Msg();
        o_msg_response->setStringList( job->getLog());
        break;
    }
    case af::Msg::TJobErrorHostsRequestId:
    {
        AfContainerLock lock( i_args->jobs,  AfContainerLock::READLOCK);

        JobContainerIt jobsIt( i_args->jobs);
        JobAf* job = jobsIt.getJob( i_msg->int32());
        if( job == NULL )
        {   // FIXME: Better to return some message in any case.
            break;
        }
        o_msg_response = new af::Msg();
        o_msg_response->setString( job->v_getErrorHostsListString());
        break;
    }
    case af::Msg::TJobProgressRequestId:
    {
        AfContainerLock lock( i_args->jobs,  AfContainerLock::READLOCK);

        JobContainerIt jobsIt( i_args->jobs);
        JobAf* job = jobsIt.getJob( i_msg->int32());
        if( job == NULL )
        {
            // FIXME: Send back the same message on error - is it good?
            o_msg_response = new af::Msg( af::Msg::TJobProgressRequestId, 0);
            break;
        }
        o_msg_response = new af::Msg;
        job->writeProgress( *o_msg_response);
        break;
    }
    case af::Msg::TJobsListRequest:
    {
        AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK);

        o_msg_response = i_args->jobs->generateList( af::Msg::TJobsList);
        break;
    }
    case af::Msg::TJobsListRequestIds:
    {
        AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK);

        af::MCGeneral ids( i_msg);
        o_msg_response = i_args->jobs->generateList( af::Msg::TJobsList, ids);
        break;
    }
    case af::Msg::TJobsListRequestUserId:
    {
        AfContainerLock jLock( i_args->jobs,  AfContainerLock::READLOCK);
        AfContainerLock uLock( i_args->users, AfContainerLock::READLOCK);

        o_msg_response = i_args->users->generateJobsList( i_msg->int32());
        if( o_msg_response == NULL )
        {
            o_msg_response = new af::Msg( af::Msg::TUserId, 0);
        }
        break;
    }
    case af::Msg::TJobsListRequestUsersIds:
    {
        AfContainerLock jLock( i_args->jobs,  AfContainerLock::READLOCK);
        AfContainerLock uLock( i_args->users, AfContainerLock::READLOCK);

        af::MCGeneral mcids( i_msg);
        std::string type_name;
        o_msg_response = i_args->users->generateJobsList( mcids.getList(), type_name);
        break;
    }
    case af::Msg::TTaskRequest:
    {
        AfContainerLock lock( i_args->jobs,  AfContainerLock::READLOCK);

        af::MCTaskPos mctaskpos( i_msg);
        JobContainerIt jobsIt( i_args->jobs);
        JobAf* job = jobsIt.getJob( mctaskpos.getJobId());
        if( job == NULL )
        {
            o_msg_response = new af::Msg();
            std::ostringstream stream;
            stream << "Msg::TTaskRequest: No job with id=" << mctaskpos.getJobId();
            o_msg_response->setString( stream.str());
            break;
        }
        af::TaskExec * task = job->generateTask( mctaskpos.getNumBlock(), mctaskpos.getNumTask());
        if( task )
        {
            o_msg_response = new af::Msg( af::Msg::TTask, task);
            delete task;
        }
        else
        {
            o_msg_response = new af::Msg();
            std::ostringstream stream;
            stream << "Msg::TTaskRequest: No such task[" << mctaskpos.getJobId() << "][" << mctaskpos.getNumBlock() << "][" << mctaskpos.getNumTask() << "]";
            o_msg_response->setString( stream.str());
        }
        break;
    }
    case af::Msg::TTaskLogRequest:
    {
        AfContainerLock lock( i_args->jobs,  AfContainerLock::READLOCK);

        af::MCTaskPos mctaskpos( i_msg);
        JobContainerIt jobsIt( i_args->jobs);
        JobAf* job = jobsIt.getJob( mctaskpos.getJobId());
        if( job == NULL )
        {
            o_msg_response = new af::Msg();
            std::ostringstream stream;
            stream << "Msg::TTaskLogRequest: No job with id=" << mctaskpos.getJobId();
            o_msg_response->setString( stream.str());
            break;
        }
        const std::list<std::string> * list = &(job->getTaskLog( mctaskpos.getNumBlock(), mctaskpos.getNumTask()));
        if( list == NULL )
        {
            // FIXME: Better to return some message in any case.
            break;
        }
        o_msg_response = new af::Msg();
        if( list->size() == 0)
        {
            std::list<std::string> list;
            list.push_back("Task log is empty.");
            o_msg_response->setStringList( list);
        }
        else
        {
            o_msg_response->setStringList( *list);
        }
        break;
    }
    case af::Msg::TTaskErrorHostsRequest:
    {
        AfContainerLock lock( i_args->jobs,  AfContainerLock::READLOCK);

        af::MCTaskPos mctaskpos( i_msg);
        JobContainerIt jobsIt( i_args->jobs);
        JobAf* job = jobsIt.getJob( mctaskpos.getJobId());
        if( job == NULL )
        {
            // FIXME: Better to return some message in any case.
            break;
        }
        o_msg_response = new af::Msg();
        o_msg_response->setString( job->v_getErrorHostsListString( mctaskpos.getNumBlock(), mctaskpos.getNumTask()));
        break;
    }
    case af::Msg::TTaskOutputRequest:
    {
        af::Msg * msg_request_render = NULL;
        std::string filename, error;
        af::MCTaskPos tp( i_msg);
//printf("ThreadReadMsg::msgCase: case af::Msg::TJobTaskOutputRequest: job=%d, block=%d, task=%d, number=%d\n", tp.getJobId(), tp.getNumBlock(), tp.getNumTask(), tp.getNumber());
        {
            AfContainerLock jLock( i_args->jobs,	 AfContainerLock::READLOCK);
            AfContainerLock rLock( i_args->renders, AfContainerLock::READLOCK);

            JobContainerIt jobsIt( i_args->jobs);
            JobAf* job = jobsIt.getJob( tp.getJobId());
            if( job == NULL )
            {
                o_msg_response = af::msgString("Error: Job is NULL.");
                AFCommon::QueueLogError("Jobs is NULL");
                break;
            }

            // Trying to set message to request output from running remote host.
            msg_request_render = job->v_getTaskStdOut( tp.getNumBlock(), tp.getNumTask(), tp.getNumber(),
                                 i_args->renders, filename, error);

            if( error.size())
            {
                if( msg_request_render )
                    delete msg_request_render;
                o_msg_response = af::msgString( error);
                AFCommon::QueueLogError( error);
                break;
            }
        }
        if( filename.size())
        {
            //
            //	 Retrieving output from file
            //
            int readsize = -1;
            char * data = af::fileRead( filename, readsize, af::Msg::SizeDataMax, &error);
            if( data )
            {
                o_msg_response = new af::Msg();
                o_msg_response->setData( readsize, data);
                delete [] data;
            }
            else if( error.size())
            {
                error = std::string("Getting task output: ") + error;
                AFCommon::QueueLogError( error);
                o_msg_response = af::msgString( error);
            }
        }
        else if( msg_request_render)
        {
            //
            //	 Retrieving output from render
            //
            msg_request_render->setReceiving();
            bool ok;
            o_msg_response = af::msgsend( msg_request_render, ok, af::VerboseOn);
            if( o_msg_response == NULL )
            {
                error = "Retrieving output from render failed. See server logs for details.";
                o_msg_response = af::msgString( error);
                AFCommon::QueueLogError( error);
            }
            delete msg_request_render;
        }
        else
        {
            if( error.size())
            {
                o_msg_response = af::msgString( error);
                AFCommon::QueueLogError("TTaskOutputRequest: Neiter message nor filename\n" + error);
            }
            else
                AFCommon::QueueLogError("TTaskOutputRequest: Neiter message nor filename.");
        }
        break;
    }
    case af::Msg::TJobsWeightRequest:
    {
        AfContainerLock jLock( i_args->jobs,	 AfContainerLock::READLOCK);

        af::MCJobsWeight jobsWeight;
        i_args->jobs->getWeight( jobsWeight);
        o_msg_response = new af::Msg( af::Msg::TJobsWeight, &jobsWeight);
        break;
    }
    // Cases for run cycle thread:
    case af::Msg::TTaskUpdateState:
    {
        af::MCTaskUp taskup( i_msg);
        af::MCTaskPos taskpos( taskup.getNumJob(), taskup.getNumBlock(), taskup.getNumTask(), taskup.getNumber());
        o_msg_response = new af::Msg( af::Msg::TRenderCloseTask, &taskpos);
    }
    case af::Msg::TTaskUpdatePercent:
    case af::Msg::TTaskListenOutput:
    case af::Msg::TRenderDeregister:
    case af::Msg::TTalkDeregister:
    /*	{
    		// Check magic number mismatch mode:
    		// All message types above are not allowed in "GetOnly" mode.
    		if( i_msg->isMagicInvalid() && ( af::Environment::getMagicMode() <= af::MMM_GetOnly ))
    		{
    			std::string err = "Magic Mismatch Mode: \"";
    			err += af::Environment::getMagicModeName();
    			err += "\"";
    			err += "\nMessage type not allowed: \"";
    			err += af::Msg::TNAMES[i_msg->type()];
    			err += "\"";
    			AFCommon::QueueLogError( err);
    			delete i_msg;
    			return o_msg_response;
    		}
    		// Only Monitor message types are allowed in "GetOnly" mode.
    	}*/
    case af::Msg::TMonitorSubscribe:
    case af::Msg::TMonitorUnsubscribe:
    case af::Msg::TMonitorDeregister:
    case af::Msg::TMonitorUsersJobs:
    case af::Msg::TMonitorJobsIdsAdd:
    case af::Msg::TMonitorJobsIdsSet:
    case af::Msg::TMonitorJobsIdsDel:
    case af::Msg::TMonitorMessage:
    {
        // Push message for run cycle thread.
        i_args->msgQueue->pushMsg( i_msg);
        // Need to return here to not to delete input message (i_msg) later.
        return o_msg_response;
        //  ( o_msg_response is NULL in all cases except Msg::TTaskUpdateState,
        //	 in that case render should recieve an answer to close task
        //	 and finish sending any updates for the task )
    }
    // -------------------------------------------------------------------------//
    default:
    {
        AFCommon::QueueLogError( std::string("Unknown message recieved: ") + i_msg->v_generateInfoString( false));
        break;
    }
    }

    // Deleting input message as it not needed any more.
    delete i_msg;

    // Returning an answer
    return o_msg_response;
}
Beispiel #18
0
bool JobContainer::registerJob( JobAf *job, std::string & o_err, UserContainer *users, MonitorContainer * monitoring)
{
	if( job == NULL )
	{
		AF_ERR << "JobContainer::registerJob: Can't allocate memory for a new job.";
		return false;
	}

	if( users == NULL )
	{
		AF_ERR << "JobContainer::registerJob: Users container is not set.";
		delete job;
		return false;
	}

	// Job from store is already checked for validness
	if(( job->isFromStore() == false ) && (job->isValidConstructed() == false ))
	{
		o_err = "Invalid job.";
		delete job;
		return false;
	}

	UserAf *user;

	{  // Register new user if job has a new user name.
		AfContainerLock jLock( this, AfContainerLock::WRITELOCK);
		AfContainerLock uLock( users, AfContainerLock::WRITELOCK  );

		if( monitoring) AfContainerLock mLock( monitoring, AfContainerLock::WRITELOCK  );

		AF_DEBUG << "JobContainer::registerJob: Checking job user: "******"JobContainer::registerJob: Can't register new user.";
			return false;
		}

		// Add job node to container.
		if( add( job) == false )
		{
			delete job;
			o_err = "JobContainer::registerJob: Can't add job to container.";
			return false;
		}
		AF_DEBUG << "JobContainer::registerJob: locking job.";
		job->lock();

		AF_DEBUG << "JobContainer::registerJob: locking user.";
		user->lock();
		user->addJob( job);
		if( monitoring )
		{
			AF_DEBUG << "JobContainer::registerJob: monitor new job events.";
			monitoring->addJobEvent( af::Monitor::EVT_jobs_add, job->getId(), user->getId());
			monitoring->addEvent( af::Monitor::EVT_users_change, user->getId());
		}
	}

	// initialize job ( create tasks output root_dir, execute "pre"commands if any)
	AF_DEBUG << "JobContainer::registerJob: initiaizing new job with user.";
	if( job->initialize() == false)
	{
		AF_DEBUG << "JobContainer::registerJob: Job initialization failed.";

		if( monitoring )
		{
			AfContainerLock mLock( monitoring,  AfContainerLock::WRITELOCK  );

			monitoring->addJobEvent( af::Monitor::EVT_jobs_del, job->getId(), user->getId());
			monitoring->addEvent( af::Monitor::EVT_users_change, user->getId());
		}

		{   // Set job to zombie:
			AfContainerLock jLock( this, AfContainerLock::WRITELOCK);
			AfContainerLock uLock( users, AfContainerLock::WRITELOCK);
			user->unLock();
			job->deleteNode( NULL, NULL);
		}

		return false;
	}

	if( monitoring )
	{
		AfContainerLock mLock( monitoring,  AfContainerLock::WRITELOCK  );

		AF_DEBUG << "JobContainer::registerJob: monitor unlock job and user events.";
		monitoring->addJobEvent( af::Monitor::EVT_jobs_change, job->getId(), user->getId());
		monitoring->addEvent( af::Monitor::EVT_users_change, user->getId());
	}

	AF_DEBUG << "JobContainer::registerJob: unlocking user and job.";

	{
		AfContainerLock jLock( this,  AfContainerLock::WRITELOCK);
		AfContainerLock uLock( users, AfContainerLock::WRITELOCK);
		user->unLock();
		job->unLock();
	}

	AFCommon::QueueLog("Job registered: " + job->v_generateInfoString());

	return true;
}
Beispiel #19
0
	//************************************************************
	//********功能:清空一个工作队列
	//********参数:无
	//********返回值:
	//************************************************************
	void CJobQueue::clear()
	{
		CLock mLock(m_mutex);
		while (!m_JobQueue.empty())
			m_JobQueue.pop();
	}
Beispiel #20
0
af::Msg * threadProcessJSON( ThreadArgs * i_args, af::Msg * i_msg)
{
	rapidjson::Document document;
	std::string error;
	char * data = af::jsonParseMsg( document, i_msg, &error);
	if( data == NULL )
	{
		AFCommon::QueueLogError( error);
		delete i_msg;
		return NULL;
	}

	af::Msg * o_msg_response = NULL;

	JSON & getObj = document["get"];
	if( getObj.IsObject())
	{
		std::string type, mode;
		bool binary = false;
		af::jr_string("type", type, getObj);
		af::jr_string("mode", mode, getObj);
		af::jr_bool("binary", binary, getObj);

		bool json = true;
		if( binary )
			json = false;
		bool full = false;
		if( mode == "full")
			full = true;

		std::vector<int32_t> ids;
		af::jr_int32vec("ids", ids, getObj);

		std::string mask;
		af::jr_string("mask", mask, getObj);

		if( type == "jobs" )
		{
			if( getObj.HasMember("uids"))
			{
				std::vector<int32_t> uids;
				af::jr_int32vec("uids", uids, getObj);
				if( uids.size())
				{
					AfContainerLock jLock( i_args->jobs,  AfContainerLock::READLOCK);
					AfContainerLock uLock( i_args->users, AfContainerLock::READLOCK);
					o_msg_response = i_args->users->generateJobsList( uids, type, json);
				}
			}
			if( getObj.HasMember("users"))
			{
				std::vector<std::string> users;
				af::jr_stringvec("users", users, getObj);
				if( users.size())
				{
					AfContainerLock jLock( i_args->jobs,  AfContainerLock::READLOCK);
					AfContainerLock uLock( i_args->users, AfContainerLock::READLOCK);
					o_msg_response = i_args->users->generateJobsList( users, type, json);
				}
			}
			else if( mode == "output")
			{
				std::vector<int32_t> block_ids;
				std::vector<int32_t> task_ids;
				int number = 0;
				af::jr_int32vec("block_ids", block_ids, getObj);
				af::jr_int32vec("task_ids", task_ids, getObj);
				af::jr_int("number", number, getObj);
				if(( ids.size() == 1 ) && ( block_ids.size() == 1 ) && ( task_ids.size() == 1 ))
				{
					af::Msg * msg_request_render = NULL;
					std::string filename, error, name;

					// Get output from job, it can return a request message for render or a filename
					{
						AfContainerLock jlock( i_args->jobs,    AfContainerLock::READLOCK);
						AfContainerLock rLock( i_args->renders, AfContainerLock::READLOCK);

						JobContainerIt it( i_args->jobs);
						JobAf * job = it.getJob( ids[0]);
						if( job == NULL )
							o_msg_response = af::jsonMsgError("Invalid ID");
						else
						{
							msg_request_render = job->v_getTaskStdOut( block_ids[0], task_ids[0], number,
								i_args->renders, filename, error);
							name = job->generateTaskName( block_ids[0], task_ids[0]);
							if( number > 0 )
								name += "["+af::itos(number)+"]";
						}
					}

					if( filename.size()) // Reading output from file
					{
						int readsize = -1;
						char * data = af::fileRead( filename, &readsize, af::Msg::SizeDataMax, &error);
						if( data )
						{
							o_msg_response = af::jsonMsg( mode, name, data, readsize);
							delete [] data;
						}
					}
					else if( msg_request_render) // Retrieving output from render
					{
						msg_request_render->setReceiving();
						bool ok;
						af::Msg * response = af::msgsend( msg_request_render, ok, af::VerboseOn);
						if( response )
						{
							o_msg_response = af::jsonMsg( mode, name, response->data(), response->dataLen());
							delete response;
						}
						else
							error = "Retrieving output from render failed. See server logs for details.";
						delete msg_request_render;
					}
	
					if( error.size())
					{
						if( o_msg_response == NULL )
							o_msg_response = af::jsonMsgError( error);
						AFCommon::QueueLogError("TTaskOutputRequest: " + error);
					}
				}
			}
			else
			{
				AfContainerLock lock( i_args->jobs, AfContainerLock::READLOCK);
				JobAf * job = NULL;
				bool was_error = false;
				if( ids.size() == 1 )
				{
					JobContainerIt it( i_args->jobs);
					job = it.getJob( ids[0]);
					if( job == NULL )
						o_msg_response = af::jsonMsgError( "Invalid ID");
				}

				if( job )
				{
					std::vector<int32_t> block_ids;
					af::jr_int32vec("block_ids", block_ids, getObj);
					if( block_ids.size() && ( block_ids[0] != -1 ))
					{
						std::vector<int32_t> task_ids;
						af::jr_int32vec("task_ids", task_ids, getObj);
						if( task_ids.size() && ( task_ids[0] != -1))
							o_msg_response = job->writeTask( block_ids[0], task_ids[0], mode, binary);
						else
						{
							std::vector<std::string> modes;
							af::jr_stringvec("mode", modes, getObj);
							o_msg_response = job->writeBlocks( block_ids, modes);
						}
					}
					else if( mode.size())
					{
						if( mode == "thumbnail" )
							o_msg_response = job->writeThumbnail( binary);
						else if( mode == "progress" )
							o_msg_response = job->writeProgress( json);
						else if( mode == "error_hosts" )
							o_msg_response = job->writeErrorHosts();
						else if( mode == "log" )
							o_msg_response = job->writeLog();
					}
				}
				
				if( o_msg_response == NULL )
					o_msg_response = i_args->jobs->generateList(
						full ? af::Msg::TJob : af::Msg::TJobsList, type, ids, mask, json);
			}
		}
		else if( type == "renders")
		{
			AfContainerLock lock( i_args->renders, AfContainerLock::READLOCK);
			if( mode.size())
			{
				RenderAf * render = NULL;
				if( ids.size() == 1 )
				{
					RenderContainerIt it( i_args->renders);
					render = it.getRender( ids[0]);
					if( render == NULL )
						o_msg_response = af::jsonMsgError( "Invalid ID");
				}
				if( render )
				{
					if( full )
						o_msg_response = render->jsonWriteSrvFarm();
					else if( mode == "log" )
						o_msg_response = render->writeLog();
					else if( mode == "tasks_log" )
						o_msg_response = af::jsonMsg("tasks_log", render->getName(), render->getTasksLog());
				}
			}
			if( o_msg_response == NULL )
			{
				if( mode == "resources" )
					o_msg_response = i_args->renders->generateList( af::Msg::TRendersResources, type, ids, mask, json);
				else
					o_msg_response = i_args->renders->generateList( af::Msg::TRendersList, type, ids, mask, json);
			}
		}
		else if( type == "users")
		{
			AfContainerLock lock( i_args->users, AfContainerLock::READLOCK);
			if( mode.size())
			{
				UserAf * user = NULL;
				if( ids.size() == 1 )
				{
					UserContainerIt it( i_args->users);
					user = it.getUser( ids[0]);
					if( user == NULL )
						o_msg_response = af::jsonMsgError( "Invalid ID");
				}
				if( user )
				{
					if( mode == "jobs_order" )
						o_msg_response = user->writeJobdsOrder();
					else if( mode == "log" )
						o_msg_response = user->writeLog();
				}
			}
			if( o_msg_response == NULL )
				o_msg_response = i_args->users->generateList( af::Msg::TUsersList, type, ids, mask, json);
		}
		else if( type == "monitors")
		{
			AfContainerLock lock( i_args->monitors, AfContainerLock::READLOCK);
			if( mode == "events")
			{
				MonitorContainerIt it( i_args->monitors);
				if( ids.size() )
				{
					MonitorAf* node = it.getMonitor( ids[0]);
					if( node != NULL )
					{
						o_msg_response = node->getEvents();
					}
					else
					{
						o_msg_response = af::jsonMsg("{\"monitor\":{\"id\":0}}");
					}
				}
				else
				{
					o_msg_response = af::jsonMsgError("id is not specified");
				}
			}
			else
				o_msg_response = i_args->monitors->generateList( af::Msg::TMonitorsList, type, ids, mask, json);
		}
		else if( type == "files")
		{
			std::string path;
			std::ostringstream files;
			af::jr_string("path", path, getObj);
			std::vector<std::string> list = af::getFilesListSafe( path);
			files << "{\"path\":\"" << path << "\",\n";
			files << "\"files\":[";
			for( int i = 0; i < list.size(); i++)
			{
				if( i )
					files << ',';
				files << '"' << list[i] << '"';
			}
			files << "]}";
			o_msg_response = af::jsonMsg( files);
		}
		else if( type == "config" )
		{
			o_msg_response = af::jsonMsg( af::Environment::getConfigData());
		}
	}
	else if( document.HasMember("action"))
	{
		i_args->msgQueue->pushMsg( i_msg);
		// To not to detele it, set to NULL, as it pushed to another queue
		i_msg = NULL;
	}
	else if( document.HasMember("job"))
	{
		if( af::Environment::isDemoMode() )
		{
			AFCommon::QueueLogError("Job registration is not allowed: Server demo mode.");
		}
		else
		{
			// No containers locks needed here.
			// Job registration is a complex procedure.
			// It locks and unlocks needed containers itself.
			i_args->jobs->job_register( new JobAf( document["job"]), i_args->users, i_args->monitors);
		}
	}
	else if( document.HasMember("monitor"))
	{
		AfContainerLock mlock( i_args->monitors, AfContainerLock::WRITELOCK);
		AfContainerLock ulock( i_args->users,    AfContainerLock::READLOCK);
		MonitorAf * newMonitor = new MonitorAf( document["monitor"], i_args->users);
		newMonitor->setAddressIP( i_msg->getAddress());
		o_msg_response = i_args->monitors->addMonitor( newMonitor, /*JSON = */ true);
	}
	else if( document.HasMember("user"))
	{
		AfContainerLock ulock( i_args->users, AfContainerLock::WRITELOCK);
		o_msg_response = i_args->users->addUser( new UserAf( document["user"]), i_args->monitors);
	}
	else if( document.HasMember("reload_farm"))
	{
		AfContainerLock mLock( i_args->monitors, AfContainerLock::WRITELOCK);
		AfContainerLock rlock( i_args->renders,  AfContainerLock::WRITELOCK);

		printf("\n	========= RELOADING FARM =========\n\n");
		if( af::loadFarm( true))
		{
			RenderContainerIt rendersIt( i_args->renders);
			for( RenderAf *render = rendersIt.render(); render != NULL; rendersIt.next(), render = rendersIt.render())
			{
				render->getFarmHost();
				i_args->monitors->addEvent( af::Msg::TMonitorRendersChanged, render->getId());
			}
			printf("\n	========= FARM RELOADED SUCCESSFULLY =========\n\n");
			o_msg_response = af::jsonMsgStatus( true, "reload_farm",
				"Reloaded successfully.");
		}
		else
		{
			printf("\n	========= FARM RELOADING FAILED =========\n\n");
			o_msg_response = af::jsonMsgStatus( false, "reload_farm",
				"Failed, see server logs fo details. Check farm with \"afcmd fcheck\" at first.");
		}
	}
	else if( document.HasMember("reload_config"))
	{
		AfContainerLock jlock( i_args->jobs,	AfContainerLock::WRITELOCK);
		AfContainerLock rlock( i_args->renders, AfContainerLock::WRITELOCK);
		AfContainerLock ulock( i_args->users,	AfContainerLock::WRITELOCK);
		printf("\n	========= RELOADING CONFIG =========\n\n");
		std::string message;
		if( af::Environment::reload())
		{
			printf("\n	========= CONFIG RELOADED SUCCESSFULLY =========\n\n");
			o_msg_response = af::jsonMsgStatus( true, "reload_config",
				"Reloaded successfully.");
		}
		else
		{
			printf("\n	========= CONFIG RELOADING FAILED =========\n\n");
			o_msg_response = af::jsonMsgStatus( false, "reload_config",
				"Failed, see server logs fo details.");
		}
	}

	delete [] data;
	if( i_msg ) delete i_msg;

	return o_msg_response;
}