bool CJobWatchDlg::GetCurrentWorkerText( 
	CUtlVector<char> &text, 
	unsigned long &curMessageIndex )
{
	text.SetSize( 0 );

	unsigned long jobWorkerID;
	if ( !GetCurJobWorkerID( jobWorkerID ) )
		return false;

	// Now copy all the text out.
	CMySQLQuery query;
	if ( curMessageIndex == 0 )
		query.Format( "select * from text_messages where JobWorkerID=%lu", jobWorkerID );
	else
		query.Format( "select * from text_messages where JobWorkerID=%lu and MessageIndex >= %lu", jobWorkerID, curMessageIndex );
	
	GetMySQL()->Execute( query );

	while ( GetMySQL()->NextRow() )
	{
		const char *pTextStr = GetMySQL()->GetColumnValue( "text" ).String();
		int len = strlen( pTextStr );
		text.AddMultipleToTail( len, pTextStr );

		curMessageIndex = GetMySQL()->GetColumnValue( "MessageIndex" ).UInt32() + 1;
	}

	text.AddToTail( 0 );
	return true;
}
	virtual int RunCommand()
	{
		CMySQLQuery query;
		query.Format( "insert into job_worker_end ( JobWorkerID, ErrorText, RunningTimeMS ) values ( %lu, \"%s\", %lu )", g_JobWorkerID, "No Errors", g_RunningTimeMS );
		g_pSQL->Execute( query );
		return 1;
	}
void CAdministrationWindow::flush(CMySQLServer *m, int flush_type)
{
  QString f = QString::null;
  switch (flush_type)
  {
  case FLUSH_HOSTS: f = "HOSTS";
    break;
  case FLUSH_LOGS: f = "LOGS";
    break;
  case FLUSH_PRIVILEGES: f = "PRIVILEGES";
    break;
  case FLUSH_TABLES: f = "TABLES";
    break;
  case FLUSH_STATUS: f = "STATUS";
    break;
  case FLUSH_TABLES_RL: f = "TABLES WITH READ LOCK";
    break;
  case FLUSH_DES_KEY_FILE: f = "DES_KEY_FILE";
    break;
  case FLUSH_QUERY_CACHE: f = "QUERY CACHE";
    break;
  case FLUSH_USER_RESOURCES: f = "USER_RESOURCES";
    break;
  }

  CMySQLQuery *qry = new CMySQLQuery(m->mysql());
  qry->setEmitMessages(false);
  if (qry->execStaticQuery("FLUSH " + f))
    m->messagePanel()->information("Flush " + capitalize(f) + " " + tr("successful"));
  delete qry;
}
	virtual int RunCommand()
	{
		CMySQLQuery query;
		query.Format( "insert into text_messages (JobWorkerID, MessageIndex, Text) values ( %lu, %lu, \"%s\" )", g_JobWorkerID, g_CurrentMessageIndex, m_pText );
		query.Execute( g_pSQL );

		++g_CurrentMessageIndex;
		return 1;
	}
	virtual int RunCommand()
	{
		CMySQLQuery query;
		query.Format( "insert into job_master_end values ( %lu, %d, %d, \"no errors\" )", g_JobPrimaryID, g_nWorkersConnected, g_nWorkersDisconnected ); 
		g_pSQL->Execute( query );

		// Now set RunningTimeMS.
		query.Format( "update job_master_start set RunningTimeMS=%lu where JobID=%lu", g_RunningTimeMS, g_JobPrimaryID );
		g_pSQL->Execute( query );
		return 1;
	}
	virtual int RunCommand()
	{
		CMySQLQuery query;
		query.Format( "insert into job_master_end values ( %lu, %d, %d, \"no errors\" )", g_JobPrimaryID, g_nWorkersConnected, g_nWorkersDisconnected ); 
		query.Execute( g_pSQL  );

		// Now set RunningTimeMS.
		unsigned long runningTimeMS = GetTickCount() - g_StatsStartTime;
		query.Format( "update job_master_start set RunningTimeMS=%lu where JobID=%lu", runningTimeMS, g_JobPrimaryID );
		query.Execute( g_pSQL );
		return 1;
	}
bool VMPI_Stats_Init_Worker( const char *pHostName, const char *pDBName, const char *pUserName, unsigned long DBJobID )
{
	g_StatsStartTime = GetTickCount();
	
	// If pDBServerName is null, then we're the master and we just want to make the job_worker_start entry.
	if ( pHostName )
	{
		Assert( !g_pDB );
		
		// Connect the database.
		g_pDB = new CMySqlDatabase;
		if ( !g_pDB || !g_pDB->Initialize() || !LoadMySQLWrapper( pHostName, pDBName, pUserName ) )
		{
			delete g_pDB;
			g_pDB = NULL;
			return false;
		}
		
		// Get our machine name to store in the database.
		DWORD size = sizeof( g_MachineName );
		GetComputerName( g_MachineName, &size );
	}


	g_JobPrimaryID = DBJobID;
	g_JobWorkerID = 0;

	CMySQLQuery query;
	query.Format( "insert into job_worker_start ( JobID, CurrentStage, IsMaster, MachineName ) values ( %lu, \"none\", %d, \"%s\" )",
		g_JobPrimaryID, g_bMaster, g_MachineName );
	query.Execute( g_pSQL );
			
	g_JobWorkerID = g_pSQL->InsertID();
	if ( g_JobWorkerID == 0 )
	{
		delete g_pDB;
		g_pDB = NULL;
		return false;
	}

	// Now create a thread that samples perf data and stores it in the database.
	g_hPerfThreadExitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
	g_hPerfThread = CreateThread(
		NULL,
		0,
		PerfThreadFn,
		NULL,
		0,
		&g_PerfThreadID );

	return true;	
}
	virtual int RunCommand()
	{
		CMySQLQuery query;
		query.Format(	"insert into graph_entry (JobWorkerID, MSSinceJobStart, BytesSent, BytesReceived) "
						"values ( %lu, %lu, %lu, %lu )", 
			g_JobWorkerID, 
			m_msTime, 
			m_nBytesSent, 
			m_nBytesReceived );
		
		g_pSQL->Execute( query );

		++g_CurrentMessageIndex;
		return 1;
	}
bool VMPI_Stats_Init_Master( 
	const char *pHostName, 
	const char *pDBName, 
	const char *pUserName,
	const char *pBSPFilename, 
	unsigned long *pDBJobID )
{
	Assert( !g_pDB );

	g_bMaster = true;
	
	// Connect the database.
	g_pDB = new CMySqlDatabase;
	if ( !g_pDB || !g_pDB->Initialize() || !LoadMySQLWrapper( pHostName, pDBName, pUserName ) )
	{
		delete g_pDB;
		g_pDB = NULL;
		return false;
	}

	DWORD size = sizeof( g_MachineName );
	GetComputerName( g_MachineName, &size );

	// Create the job_master_start row.
	Q_FileBase( pBSPFilename, g_BSPFilename, sizeof( g_BSPFilename ) );

	g_JobPrimaryID = 0;
	CMySQLQuery query;
	query.Format( "insert into job_master_start ( BSPFilename, StartTime, MachineName, RunningTimeMS ) values ( \"%s\", null, \"%s\", %lu )", g_BSPFilename, g_MachineName, RUNNINGTIME_MS_SENTINEL ); 
	query.Execute( g_pSQL );

	g_JobPrimaryID = g_pSQL->InsertID();
	if ( g_JobPrimaryID == 0 )
	{
		delete g_pDB;
		g_pDB = NULL;
		return false;
	}


	// Now init the worker portion.
	*pDBJobID = g_JobPrimaryID;
	return VMPI_Stats_Init_Worker( NULL, NULL, NULL, g_JobPrimaryID );
}
void UpdateJobWorkerRunningTime()
{
	unsigned long runningTimeMS = GetTickCount() - g_StatsStartTime;
	
	char curStage[256];
	VMPI_GetCurrentStage( curStage, sizeof( curStage ) );
	
	CMySQLQuery query;
	query.Format( "update job_worker_start set RunningTimeMS=%lu, CurrentStage=\"%s\", "
		"Thread0WU=%d, Thread1WU=%d, Thread2WU=%d, Thread3WU=%d where JobWorkerID=%lu", 
		runningTimeMS, 
		curStage,
		(int) g_ThreadWUs[0],
		(int) g_ThreadWUs[1],
		(int) g_ThreadWUs[2],
		(int) g_ThreadWUs[3],
		g_JobWorkerID );
	query.Execute( g_pSQL );
}
void CJobWatchDlg::FillGraph()
{
	// Get all the graph samples.
	unsigned long jobWorkerID;
	if ( !GetCurJobWorkerID( jobWorkerID ) )
		return;

	CMySQLQuery query;
	query.Format( "select * from graph_entry where JobWorkerID=%lu", jobWorkerID );
	GetMySQL()->Execute( query );

	int iMSTime = GetMySQL()->GetColumnIndex( "MSSinceJobStart" );	
	int iBytesSent = GetMySQL()->GetColumnIndex( "BytesSent" );
	int iBytesReceived = GetMySQL()->GetColumnIndex( "BytesReceived" );

	// See if there's anything new.
	CUtlVector<CGraphEntry> entries;

	int highest = m_CurGraphTime;
	while ( GetMySQL()->NextRow() )
	{
		CGraphEntry entry;
		entry.m_msTime = GetMySQL()->GetColumnValue( iMSTime ).Int32();
		entry.m_nBytesSent = GetMySQL()->GetColumnValue( iBytesSent ).Int32();
		entry.m_nBytesReceived = GetMySQL()->GetColumnValue( iBytesReceived ).Int32();
		entries.AddToTail( entry );

		highest = max( highest, entry.m_msTime );
	}

	if ( highest > m_CurGraphTime )
	{
		m_CurGraphTime = highest;
		
		m_GraphControl.Clear();
		m_GraphControl.Fill( entries );
	}
}
void CInnoDBStatus::refresh()
{
  clear();
  CMySQLQuery *qry = new CMySQLQuery(mysql->mysql());
  qry->setEmitMessages(false);
  qry->setEmitErrors(false);
  if (qry->exec("SHOW INNODB STATUS"))
  {
    qry->next();
    setText(qry->row(0));
  }
  delete qry;
}
void CAdministrationWindow::CShowServerVariables::insertData()
{
  CMySQLQuery *qry = new CMySQLQuery(mysql()->mysql());

  bool notnew = mysql()->mysql()->version().major <= 3;
  if (!notnew)
    notnew = mysql()->mysql()->version().major == 4 && mysql()->mysql()->version().minor == 0 && mysql()->mysql()->version().relnum <= 2;
  
  qry->setEmitMessages(false);
  QString sql = "SHOW ";
  if (!notnew)
    sql += "GLOBAL ";
  sql += "VARIABLES";
  if (qry->exec(sql))
    while (qry->next())
      insertItem(qry->row(0), qry->row(1));
  delete qry;
}
bool CUserAdminItem::displayUsers()
{
#ifdef DEBUG
  qDebug("CUserAdminItem::displayUsers()");
#endif

  //TODO:  This needs to be modified to NOT use mysql.user for the users list.  SHOW GRANTS FOR % is needed in the server.  
  while (this->childCount() > 0)
    deleteChilds();

  bool hasAccess = false;
  CMySQLQuery *q = new CMySQLQuery(mysql()->mysql());
  q->setEmitMessages(false);
  q->setEmitErrors(false);
  if (q->exec("SELECT User, Host FROM mysql.user ORDER BY User"))
  {
    hasAccess = true;
    while (q->next())
      new CUserItem(this, mysql(), q->row(0), q->row(1), userIcon);
  }
  delete q;
  return hasAccess;
}
bool CInnoDBStatus::hasInnoDB(CMySQLServer *mysql)
{
  bool has_innodb = false;

  CMySQLQuery *qry = new CMySQLQuery(mysql->mysql());
  bool notnew = mysql->mysql()->version().major <= 3;
  if (!notnew)
    notnew = mysql->mysql()->version().major == 4 && mysql->mysql()->version().minor == 0 && mysql->mysql()->version().relnum <= 2;
  
  qry->setEmitMessages(false);
  QString sql = "SHOW ";
  if (!notnew)
    sql += "GLOBAL ";
  sql += "VARIABLES LIKE 'have_innodb'";
  if (qry->exec(sql))
  {
    if (qry->numRows() >= 1)
    {
      qry->next();
      QString tmp = qry->row(1);
      if (tmp.lower() == "yes")
      {
        if (mysql->mysql()->version().major >= 3)
        {
          if (mysql->mysql()->version().major == 3 && mysql->mysql()->version().minor >= 23 && mysql->mysql()->version().relnum >= 53)
            has_innodb = true;
          else
            if (mysql->mysql()->version().major == 4 && mysql->mysql()->version().minor == 0)
            {
              if (mysql->mysql()->version().relnum >= 4)
                has_innodb = true;
            }
            else
              has_innodb = true;
        }
      }
    }
  }
  delete qry;
  return has_innodb;
}
void CCallback::ClearAll() {
	CMySQLQuery *tmpQuery = NULL;
	while(m_CallbackQueue.pop(tmpQuery))
		tmpQuery->Destroy();
}
BOOL CJobWatchDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();


	m_GraphControl.SubclassDlgItem( IDC_GRAPH_AREA, this );


	CString str;

	// Get all our startup info from the command line.
	const char *pJobID = FindArg( "-JobID", NULL );
	const char *pDBName = FindArg( "-dbname", NULL );
	const char *pHostName = FindArg( "-hostname", NULL );
	const char *pUserName = FindArg( "-username", NULL );

	if ( !pJobID || !pDBName || !pHostName || !pUserName )
	{
		str.Format( "Missing a command line parameter (-JobID or -dbname or -hostname or -username)" );
		MessageBox( str, "Error", MB_OK );
		EndDialog( 1 );
		return FALSE;
	}

	m_JobID = atoi( pJobID );
	
	m_pSQL = InitMySQL( pDBName, pHostName, pUserName );
	if ( !m_pSQL )
	{
		str.Format( "Can't init MYSQL db (db = '%s', host = '%s', user = '******')", pDBName, pHostName, pUserName );
		MessageBox( str, "Error", MB_OK );
		EndDialog( 0 );
		return FALSE;
	}
	
	
	// Fill the workers list.
	CMySQLQuery query;
	query.Format( "select * from job_worker_start where JobID=%lu order by MachineName", m_JobID );
	GetMySQL()->Execute( query );

	while ( GetMySQL()->NextRow() )
	{
		const char *pMachineName = GetMySQL()->GetColumnValue( "MachineName" ).String();

		int index;
		if ( GetMySQL()->GetColumnValue( "IsMaster" ).Int32() )
		{
			char tempStr[512];
			Q_snprintf( tempStr, sizeof( tempStr ), "%s (master)", pMachineName );
			index = m_Workers.AddString( tempStr );
		}
		else
		{
			index = m_Workers.AddString( pMachineName );
		}

		unsigned long jobWorkerID = GetMySQL()->GetColumnValue( "JobWorkerID" ).UInt32();
		m_Workers.SetItemData( index, jobWorkerID );
	}
	

	// (Init the idle processor so we can update text and graphs).
	StartIdleProcessing( 300 );


	// Setup anchors.
	m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_WORKERS_PANEL ), ANCHOR_LEFT, ANCHOR_TOP, ANCHOR_WIDTH_PERCENT, ANCHOR_HEIGHT_PERCENT );
	m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_WORKERS ), ANCHOR_LEFT, ANCHOR_TOP, ANCHOR_WIDTH_PERCENT, ANCHOR_HEIGHT_PERCENT );

	m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_TEXT_OUTPUT_PANEL ), ANCHOR_LEFT, ANCHOR_HEIGHT_PERCENT, ANCHOR_WIDTH_PERCENT, ANCHOR_BOTTOM );
	m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_TEXTOUTPUT ), ANCHOR_LEFT, ANCHOR_HEIGHT_PERCENT, ANCHOR_WIDTH_PERCENT, ANCHOR_BOTTOM );

	m_AnchorMgr.AddAnchor( this, GetDlgItem( IDC_GRAPHS_PANEL ), ANCHOR_WIDTH_PERCENT, ANCHOR_TOP, ANCHOR_RIGHT, ANCHOR_HEIGHT_PERCENT );
	m_AnchorMgr.AddAnchor( this, &m_GraphControl, ANCHOR_WIDTH_PERCENT, ANCHOR_TOP, ANCHOR_RIGHT, ANCHOR_HEIGHT_PERCENT );
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}
void CCallback::ProcessCallbacks() {
	CMySQLQuery *Query = NULL;
	while( (Query = GetNextQuery()) != NULL) {
		CCallback *Callback = Query->Callback;
		 
		if(Callback != NULL && (Callback->Name.length() > 0 || Query->OrmObject != NULL) ) { 

			bool PassByReference = Query->Callback->IsInline;

			if(Query->OrmObject != NULL) { //orm, update the variables with the given result
				switch(Query->OrmQueryType) {
				case ORM_QUERYTYPE_SELECT:
					Query->OrmObject->ApplySelectResult(Query->Result);
					break;

				case ORM_QUERYTYPE_INSERT:
					Query->OrmObject->ApplyInsertResult(Query->Result);
					break;
				}
			}

			for (list<AMX *>::iterator a = m_AmxList.begin(), end = m_AmxList.end(); a != end; ++a) { 
				AMX *amx = (*a);
				cell amx_Ret;
				int amx_Index;
				cell amx_MemoryAddress = -1;

				if (amx_FindPublic(amx, Callback->Name.c_str(), &amx_Index) == AMX_ERR_NONE) { 
					
					CLog::Get()->StartCallback(Callback->Name.c_str());

					int StringIndex = Callback->ParamFormat.length()-1; 
					while(!Callback->Parameters.empty() && StringIndex >= 0) {
						switch(Callback->ParamFormat.at(StringIndex)) {
							case 'i':
							case 'd': {
								int val = 0;
								ConvertStrToInt(Callback->Parameters.top().c_str(), val);

								if(PassByReference == false)
									amx_Push(amx, (cell)val);
								else {
									cell tmpAddress;
									amx_PushArray(amx, &tmpAddress, NULL, (cell*)&val, 1);
									if(amx_MemoryAddress < NULL)
										amx_MemoryAddress = tmpAddress;
								}
							} break;

							case 'f': {
								float float_val = 0.0f;
								ConvertStrToFloat(Callback->Parameters.top().c_str(), float_val);
								cell FParam = amx_ftoc(float_val);
								
								if(PassByReference == false)
									amx_Push(amx, FParam);
								else {
									cell tmpAddress;
									amx_PushArray(amx, &tmpAddress, NULL, (cell*)&FParam, 1);
									if(amx_MemoryAddress < NULL)
										amx_MemoryAddress = tmpAddress;
								}

							} break;
							
							default: {
								cell tmpAddress;
								amx_PushString(amx, &tmpAddress, NULL, Callback->Parameters.top().c_str(), 0, 0);
								if(amx_MemoryAddress < NULL)
									amx_MemoryAddress = tmpAddress;
							}
						}

						StringIndex--;
						Callback->Parameters.pop();
					}


					Query->ConnHandle->SetActiveResult(Query->Result);
					Query->Result = NULL;

					amx_Exec(amx, &amx_Ret, amx_Index);
					if (amx_MemoryAddress >= NULL)
						amx_Release(amx, amx_MemoryAddress);

					if(Query->ConnHandle->IsActiveResultSaved() == false)
						delete Query->ConnHandle->GetActiveResult();

					Query->ConnHandle->SetActiveResult((CMySQLResult *)NULL);

					CLog::Get()->EndCallback();
					
					break; //we have found our callback, exit loop
				}
			}
		}
		Query->Destroy();
	}
}
void CTracker :: serverResponseSignupLilyPOST( struct request_t *pRequest, struct response_t *pResponse, CAtomList *pPost )
{
    // Set the start time
    const struct bnbttv btv( UTIL_CurrentTime( ) );

    // Verify that the IP is permitted to access the tracker
    if( m_ucIPBanMode != 0 )
        if( IsIPBanned( pRequest, pResponse, btv, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), NOT_INDEX ) )
            return;

    string cstrLogin = string( );
    string cstrLilyID = string( );

    if( pPost )
    {
        // Initialise segment dictionary
        CAtomDicti *pSegment = 0;
        CAtom *pDisposition = 0;
        CAtom *pData = 0;
        CAtom *pName = 0;
        CAtom *pFile = 0;
        // Get the segments from the post
        vector<CAtom *> vecSegments = pPost->getValue( );

        // Loop through the segments
        for( unsigned long ulCount = 0; ulCount < vecSegments.size( ); ulCount++ )
        {
            // Is the segment a dictionary?
            if( vecSegments[ulCount]->isDicti( ) )
            {
                // Get the segment dictionary
                pSegment = (CAtomDicti *)vecSegments[ulCount];
                // Get the disposition and the data from the segment dictionary
                pDisposition = pSegment->getItem( "disposition" );
                pData = pSegment->getItem( "data" );

                // Did we get a disposition that is a dictionary and has data?
                if( pDisposition && pDisposition->isDicti( ) && pData )
                {
                    // Get the content name from the disposition
                    pName = ( (CAtomDicti *)pDisposition )->getItem( "name" );

                    // Did we get a content name?
                    if( pName )
                    {
                        // What is the content name to be tested?
                        string strName = pName->toString( );

                        if( strName == "us_login")
                            cstrLogin = pData->toString( );
                        else if( strName == "us_lilyid")
                            cstrLilyID = UTIL_ToLower( pData->toString( ) );
                    }
                    else
                    {
                        // Output common HTML head
                        HTML_Common_Begin(  pRequest, pResponse, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), string( ), NOT_INDEX, CODE_400 );

                        // failed
                        pResponse->strContent += "<p class=\"failed\">" + gmapLANG_CFG["failed"] + "</p>\n";
                        // Signal a bad request
                        pResponse->strContent += "<p class=\"body_upload\">400 " + gmapLANG_CFG["server_response_400"] + "</p>\n";

                        // Output common HTML tail
                        HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) );

                        if( gbDebug )
                            UTIL_LogPrint( "Login Warning - Bad request (no users name)\n" );

                        return;
                    }
                }
            }
        }
    }
    else
    {
        // Output common HTML head
        HTML_Common_Begin(  pRequest, pResponse, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), string( ), NOT_INDEX, CODE_400 );

        // failed
        pResponse->strContent += "<p class=\"failed\">" + gmapLANG_CFG["failed"] + "</p>\n";
        // Signal a bad request
        pResponse->strContent += "<p class=\"body_upload\">400 " + gmapLANG_CFG["server_response_400"] + "</p>\n";

        // Output common HTML tail
        HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) );

        if( gbDebug )
            UTIL_LogPrint( "Upload Warning - Bad request (no post received)\n" );

        return;
    }

    if( pRequest->user.ucAccess & ACCESS_SIGNUP )
    {
        HTML_Common_Begin(  pRequest, pResponse, gmapLANG_CFG["signup_page"], string( CSS_SIGNUP ), string( ), NOT_INDEX, CODE_200 );

        if(  !cstrLogin.empty( ) && !cstrLilyID.empty( ) )
        {
// 			if( cstrLogin[0] == ' ' || cstrLogin[cstrLogin.size( ) - 1] == ' ' || cstrLogin.size( ) > m_uiNameLength )
            if( cstrLogin.find( ' ' ) != string :: npos || cstrLogin.find( '.' ) != string :: npos || cstrLogin.find( '%' ) != string :: npos || cstrLogin.find( '&' ) != string :: npos || cstrLilyID.find( ' ' ) != string :: npos || cstrLilyID.find( '.' ) != string :: npos || cstrLilyID.find( '%' ) != string :: npos || cstrLilyID.find( '&' ) != string :: npos || cstrLogin.size( ) > m_uiNameLength )
            {
                // Unable to signup. Your name must be less than " + CAtomInt( m_uiNameLength ).toString( ) + " characters long and it must not start or end with spaces.
                pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_name_error"].c_str( ), CAtomInt( m_uiNameLength ).toString( ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n";

                // Output common HTML tail
                HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) );

                return;
            }
            time_t tNow = time( 0 );
            char pTime[256];
            memset( pTime, 0, sizeof( pTime ) / sizeof( char ) );
            strftime( pTime, sizeof( pTime ) / sizeof( char ), "%Y %m/%d %H:%M:%S", localtime( &tNow ) );

            const string cstrA1( cstrLogin + ":" + gstrRealm + ":" + pTime );

            unsigned char szMD5[16];
            memset( szMD5, 0, sizeof( szMD5 ) / sizeof( unsigned char ) );

            MD5_CTX md5;

            MD5Init( &md5 );
            MD5Update( &md5, (const unsigned char *)cstrA1.c_str( ), (unsigned int)cstrA1.size( ) );
            MD5Final( szMD5, &md5 );

            const string cstrPass = UTIL_HashToString( string( (char *)szMD5, sizeof( szMD5 ) / sizeof( unsigned char ) ) ).substr( 0, 8 );
            const string cstrMail = cstrLilyID + "@bbs.nju.edu.cn";

            if( !getUser( cstrLogin, m_ucGuestAccess ).strLogin.empty( ) )
            {
                // Unable to signup. The user \"" + UTIL_RemoveHTML( cstrLogin ) + "\" already exists.
                pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_exists_error"].c_str( ), UTIL_RemoveHTML( cstrLogin ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n";
            }
            else
            {
                CMySQLQuery *pQuery = new CMySQLQuery( "SELECT blilyid FROM lily WHERE blilyid=\'" + UTIL_StringToMySQL( cstrLilyID ) + "\'" );

                if( pQuery->nextRow( ).size( ) == 1 )
                {
                    pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_exists_error_lily"].c_str( ), UTIL_RemoveHTML( cstrLogin ).c_str( ), UTIL_RemoveHTML( cstrLilyID ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n";
                }
                else
                {
                    if( addUser( cstrLogin, cstrPass, m_ucMemberAccess, cstrMail ) )
                    {
                        CMySQLQuery mq01( "INSERT INTO lily (blilyid,busername,bpassword) VALUES(\'" + UTIL_StringToMySQL( cstrLilyID ) + "\',\'" + UTIL_StringToMySQL( cstrLogin ) + "\',\'" + UTIL_StringToMySQL( cstrPass ) + "\')" );

                        system( string( "echo \"ID: " + cstrLogin + " Password: "******"\" | mutt -s \"ZiJingBT\" " + cstrMail ).c_str( ) );

                        // Thanks! You've successfully signed up!
                        pResponse->strContent += "<p class=\"signup_ok\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_success_lily"].c_str( ), UTIL_RemoveHTML( cstrLilyID ).c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_LOGIN_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n";
                    }
                    else
                        pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["users_max_create_fail"].c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_users"] + "\" href=\"" + RESPONSE_STR_USERS_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n";
                }
                delete pQuery;
            }

            HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) );
        }
    }
    else
    {
        //Unable to signup. You must fill in all the fields.
        pResponse->strContent += "<p class=\"signup_failed\">" + UTIL_Xsprintf( gmapLANG_CFG["signup_fields_error"].c_str( ), string( "<a title=\"" + gmapLANG_CFG["navbar_signup"] + "\" href=\"" + RESPONSE_STR_SIGNUP_LILY_HTML + "\">" ).c_str( ), "</a>" ) + "</p>\n\n";

        // Output common HTML tail
        HTML_Common_End( pRequest, pResponse, btv, NOT_INDEX, string( CSS_SIGNUP ) );

        return;
    }

}