Beispiel #1
0
/* process_privmsg: parse a chat message and perform relevant actions */
bool TwitchBot::process_privmsg(char *privmsg)
{
	char *nick, *msg;
	perm_t p;
	char out[MAX_MSG];

	if (strstr(privmsg, ":twitchnotify") == privmsg) {
		if (process_submsg(out, privmsg))
			send_msg(&client, bot_channel, out);
		return true;
	}

	if (!parse_privmsg(privmsg, &nick, &msg, &p)) {
		fprintf(stderr, "error: failed to extract data from message\n");
		return false;
	}

	/* JOIN and PART messages on Twitch are not sent immediately */
	/* add everyone who sends a message to names to keep it up to date */
	active_users[nick] = 1;

	/* check if message contains a URL */
	parser.parse(msg);

	/* perform message moderation */
	if (P_ISREG(p) && mod.active() && moderate(nick, msg))
		return true;

	if ((msg[0] == '$' || (familiarity_mode && msg[0] == '!')) && msg[1]) {
		cmdhnd.process_cmd(out, nick, msg + 1, p);
		send_msg(&client, bot_channel, out);
		return true;
	}

	/* count */
	if (cmdhnd.counting() && msg[0] == '+' && msg[1]) {
		cmdhnd.count(nick, msg + 1);
		return true;
	}

	/* get URL information */
	if (parser.modified()) {
		if (!process_url(out))
			return false;
		if (*out) {
			send_msg(&client, bot_channel, out);
			return true;
		}
	}

	/* check for responses */
	if (cmdhnd.process_resp(out, msg, nick))
		send_msg(&client, bot_channel, out);

	return true;
}
Beispiel #2
0
 void operator()() {
     CPPA_LOG_TRACE("");
     detail::cs_thread fself;
     job_ptr job = nullptr;
     for (;;) {
         aggressive(job) || moderate(job) || relaxed(job);
         CPPA_LOG_DEBUG("dequeued new job");
         if (job == m_dummy) {
             CPPA_LOG_DEBUG("received dummy (quit)");
             // dummy of doom received ...
             m_job_queue->push_back(job); // kill the next guy
             return;                      // and say goodbye
         }
         if (job->resume(&fself) == resumable::done) {
             CPPA_LOG_DEBUG("actor is done");
             /*FIXME bool hidden = job->is_hidden();
             job->deref();
             if (!hidden)*/ get_actor_registry()->dec_running();
         }
         job = nullptr;
     }
 }
bool CModerateMediaAssetsBuilder::Build( CWholePage* pWholePage)
{
	InitPage(pWholePage, "MEDIAASSET-MODERATION", true);
	bool bSuccess = true;

	// do an error page if not an editor or moderator
	// otherwise proceed with the process recommendation page
	CUser* pViewer = m_InputContext.GetCurrentUser();
	if (pViewer == NULL || !(pViewer->GetIsEditor() || pViewer->GetIsModerator()))
	{
		bSuccess = bSuccess && pWholePage->SetPageType("ERROR");
		bSuccess = bSuccess && pWholePage->AddInside("H2G2", "<ERROR TYPE='NOT-EDITOR'>You cannot perform moderation unless you are logged in as an Editor or Moderator.</ERROR>");
		return true;
	}

	//Process Actions.
	if ( ! Process(pWholePage,pViewer) )
	{
		SetDNALastError("CModerateMediaAssetsBuilder::Build","Build","Unable to process");
		pWholePage->AddInside("H2G2",GetLastErrorAsXMLString());
	}

	//Produce XML for page.

	// find out if we are processing referrals or not
	bool bReferrals = m_InputContext.GetParamInt("Referrals") == 1;
	bool bAlerts = m_InputContext.GetParamInt("Alerts") == 1;
	bool bLockedItems = m_InputContext.GetParamInt("Locked") == 1 && pViewer->GetIsSuperuser();
	bool bHeldItems = m_InputContext.GetParamInt("Held") == 1;
	int iShow = 10;
	if ( m_InputContext.ParamExists("show") )
		iShow = m_InputContext.GetParamInt("show");
	//bool bFastMod = m_InputContext.GetParamInt("fastmod") != 0;

	//Add Moderation Classes
	CModerationClasses modclasses(m_InputContext);
	if ( modclasses.GetModerationClasses() )
		bSuccess = bSuccess && pWholePage->AddInside("H2G2",&modclasses);
	else if ( modclasses.ErrorReported() )
		bSuccess && bSuccess && pWholePage->AddInside("H2G2",modclasses.GetLastErrorAsXMLString() );

	//Add Moderation Failure - Reasons
	CModReasons reasons(m_InputContext);
	if ( reasons.GetModReasons(0) )
		bSuccess = bSuccess && pWholePage->AddInside("H2G2",&reasons);

	//Add Refereee List
	CRefereeList referees(m_InputContext);
	if ( referees.FetchTheList() )
		bSuccess = bSuccess && pWholePage->AddInside("H2G2",&referees);

	//Add Site List
	CTDVString sSiteXML;
	bSuccess = bSuccess && m_InputContext.GetSiteListAsXML(&sSiteXML, 2);
	bSuccess = bSuccess && pWholePage->AddInside("H2G2", sSiteXML);

	CModerateMediaAssets moderate(m_InputContext);
	if ( !moderate.GetAssets( pViewer->GetUserID(), bAlerts, bReferrals, bLockedItems, bHeldItems, iShow ) )
		pWholePage->AddInside("H2G2",moderate.GetLastErrorAsXMLString() );
	else
		pWholePage->AddInside("H2G2",&moderate);

	TDVASSERT(bSuccess, "CModerateMediaAssetsBuilder::Build() failed");
	return bSuccess;
}
bool CModerateMediaAssetsBuilder::Process(CWholePage* pPage, CUser* pViewer)
{
	bool	bAuthorEmailOK = false;
	bool	bComplainantEmailOK = false;
	bool	bSuccess = true;
	
	int			iAssetID = 0;
	int			iModID = 0;
	int			iStatus = 0;
	int			iReferTo = 0;
	int			iSiteID = -1;
	CTDVString	sNotes;
	int			i = 0;
	int			iThreadModStatus = 0;
	CTDVString	sEmailType;
	CTDVString	sCustomText;
	CTDVString	sMimeType;

	CStoredProcedure SP;
	m_InputContext.InitialiseStoredProcedureObject(&SP);

	CModerateMediaAssets moderate(m_InputContext);
			
	CMediaAssetModController oMAModController(m_InputContext);

	// first get the total number of post IDs in the submission
	// - there should be an equal number of all the other parameters
	int iNumberOfAssets = m_InputContext.GetParamCount("ModID");
	int iProcessed = 0;
	for ( int i = 0; i < iNumberOfAssets; ++i )
	{
		if ( !bSuccess )
			break;

		// get the AssetID and corresponding decision, plus notes if any
		iModID = m_InputContext.GetParamInt("ModID", i);
		iStatus = m_InputContext.GetParamInt("Decision", i);
		iReferTo = m_InputContext.GetParamInt("ReferTo", i);
		iSiteID = m_InputContext.GetParamInt("SiteID", i);
		iAssetID = m_InputContext.GetParamInt("MediaAssetID", i);

		if (!m_InputContext.GetParamString("MimeType", sMimeType, i))
		{
			sMimeType = "";
		}
		
		if (!m_InputContext.GetParamString("Notes", sNotes, i))
		{
			sNotes = "";
		}

		if (!m_InputContext.GetParamString("EmailType", sEmailType, i))
		{
			sEmailType = "None";
		}

		CTDVString sCustomText;
		bool bSuccess = m_InputContext.GetParamString("CustomEmailText", sCustomText, i);

		// do an update for this post only if we have all necessary data
		if (iModID == 0 || iAssetID == 0 || ((iStatus == 4 || iStatus == 6) && sEmailType.CompareText("None")))
			continue;


		CTDVString	sAuthorsEmail;
		CTDVString sComplainantsEmail;
		int IsLegacy = 0;
		int iAuthorID = 0;
		int iComplainantID = 0; 
		if ( moderate.Update(iModID, iSiteID, pViewer->GetUserID(), iStatus, iReferTo, sNotes, sAuthorsEmail, sComplainantsEmail, iAuthorID, iComplainantID) )
		{
			iProcessed++;
			if ( !SendMailOrSystemMessage(iModID, iAssetID, iStatus, iSiteID, sNotes, sCustomText, sEmailType, sAuthorsEmail, sComplainantsEmail, iAuthorID, iComplainantID) )
			{
				pPage->AddInside("H2G2", GetLastErrorAsXMLString());
			}
		}
		else
		{
			pPage->AddInside("H2G2", moderate.GetLastErrorAsXMLString());
		}

		bool bComplaint = false;
		if (sComplainantsEmail.GetLength() > 0 || (m_InputContext.IsSystemMessagesOn(iSiteID) && iComplainantID > 0))
		{
			bComplaint = true;
		}

		if (iStatus == 3) //Pass - then allow the file to be seen by the world
		{
			if (!oMAModController.Approve(iAssetID, sMimeType, bComplaint))
			{
				//If something has gone wrong for this media asset 
				pPage->AddInside("H2G2", oMAModController.GetLastErrorAsXMLString());
				continue;
			}
		}
		else if (iStatus == 2) //Refer - then move the image to .mod on the ftp server (hide it)
		{
			if (!oMAModController.Requeue(iAssetID, sMimeType, bComplaint))
			{
				//If something has gone wrong for this media asset 
				pPage->AddInside("H2G2", oMAModController.GetLastErrorAsXMLString());
				continue;
			}
		}
		else if (iStatus == 4 || iStatus == 6) //Fail - then move the image to .fail on the ftp server (hide it)
		{
			if (!oMAModController.Reject(iAssetID, sMimeType, bComplaint))
			{
				//If something has gone wrong for this media asset 
				pPage->AddInside("H2G2", oMAModController.GetLastErrorAsXMLString());
				continue;
			}
		}

		if (bSuccess)
		{	
			CTDVString	sKeyPhrase;
			CTDVString	sKeyPhrasesToRemove="";
			//Get all the phrases that have been ticked to be disassociated, the param is built from the 
			//index of the asset we are moderating (I add one as it is passed in as the xsl position() which starts from 1)
			//and the name of the input field in the xsl
			CTDVString	sDisassociateListNumber = "DisassociateAssetPhrases" + CTDVString(i+1);
			int iKeyPhrasesToRemove = m_InputContext.GetParamCount(sDisassociateListNumber);
			for (int j = 0; j < iKeyPhrasesToRemove; j++)
			{
				m_InputContext.GetParamString(sDisassociateListNumber, sKeyPhrase, j);
				sKeyPhrasesToRemove = sKeyPhrasesToRemove + sKeyPhrase + "|";

			}
			if (iKeyPhrasesToRemove > 0)
			{
				CTDVString delimit = m_InputContext.GetCurrentSiteOptionString("KeyPhrases","DelimiterToken");
				CMediaAssetSearchPhrase oMediaAssetKeyPhrase(m_InputContext,delimit);

				oMediaAssetKeyPhrase.RemoveKeyPhrasesFromAsset(iAssetID, sKeyPhrasesToRemove);
			}
		}
	}

	//Create some Feedback XML.
	CTDVString sXML;
	sXML << "<FEEDBACK PROCESSED='" << iProcessed << "'/>";
	pPage->AddInside("H2G2",sXML); 
	return bSuccess;
}
Beispiel #5
0
bool CModeratePostsBuilder::Build(CWholePage* pWholePage)
{
	InitPage(pWholePage, "POST-MODERATION", true);
	bool bSuccess = true;

	// do an error page if not an editor or moderator.
	CUser* pViewer = m_InputContext.GetCurrentUser();
	if (pViewer == NULL || !(pViewer->GetIsEditor() || pViewer->GetIsModerator()) )
	{
		bSuccess = bSuccess && pWholePage->SetPageType("ERROR");
		bSuccess = bSuccess && pWholePage->AddInside("H2G2", "<ERROR TYPE='NOT-EDITOR'>You cannot perform moderation unless you are logged in as an Editor or Moderator.</ERROR>");
		return true;
	}

	//Process Actions.
	if ( ! Process(pWholePage,pViewer) )
	{
		SetDNALastError("CModeratePostsBuilder::Build","Build","Unable to process");
		pWholePage->AddInside("H2G2",GetLastErrorAsXMLString());
	}

	//Handle s_returnto.
	if ( bSuccess && CheckAndUseRedirectIfGiven(pWholePage) )
		return bSuccess;

	//Handle 'Oldstyle' redirect - necessary to handle multiple submit buttons for the same form.  
	if ( m_InputContext.ParamExists("Done") )
	{
		CTDVString sRedirect = "Moderate?newstyle=1";
		if ( m_InputContext.GetParamInt("fastmod") == 1 )
			sRedirect += "&fastmod=1";
		return pWholePage->Redirect(sRedirect);
	}

	//Produce XML for page.

	// find out if we are processing referrals or not
	bool bReferrals = m_InputContext.GetParamInt("Referrals") == 1;
	bool bAlerts = m_InputContext.GetParamInt("Alerts") == 1;
	bool bLockedItems = m_InputContext.GetParamInt("Locked") == 1; //Viewing users locked items only.
	bool bHeldItems = m_InputContext.GetParamInt("Held") == 1;
	int iShow = 10;
	if ( m_InputContext.ParamExists("show") )
		iShow = m_InputContext.GetParamInt("show");
	
	bool bFastMod = m_InputContext.GetParamInt("fastmod") != 0;

	int iModClassId = 0;
	if ( m_InputContext.ParamExists("ModClassId") )
		iModClassId = m_InputContext.GetParamInt("ModClassId");

	//Filter on moderation items for a specific post.
	int iPostId = 0;
	if ( m_InputContext.ParamExists("PostFilterId") )
		iPostId = m_InputContext.GetParamInt("PostFilterId");

	//Add Moderation Classes
	CModerationClasses modclasses(m_InputContext);
	if ( modclasses.GetModerationClasses() )
		bSuccess = bSuccess && pWholePage->AddInside("H2G2",&modclasses);
	else if ( modclasses.ErrorReported() )
		bSuccess && bSuccess && pWholePage->AddInside("H2G2",modclasses.GetLastErrorAsXMLString() );

	//Add Moderation Failure - Reasons
	CModReasons reasons(m_InputContext);
	if ( reasons.GetModReasons(iModClassId) )
		bSuccess = bSuccess && pWholePage->AddInside("H2G2",&reasons);

	//Add Refereee List
	CRefereeList referees(m_InputContext);
	if ( referees.FetchTheList() )
		bSuccess = bSuccess && pWholePage->AddInside("H2G2",&referees);

	//Add Site List
	//CTDVString sSiteXML;
	//bSuccess = bSuccess && m_InputContext.GetSiteListAsXML(&sSiteXML, 2);
	//bSuccess = bSuccess && pWholePage->AddInside("H2G2", sSiteXML);
	CBasicSiteList sitelist(m_InputContext);
	if ( !sitelist.PopulateList() )
		pWholePage->AddInside("H2G2",sitelist.GetLastErrorAsXMLString());
	else
		bSuccess = bSuccess && pWholePage->AddInside("H2G2",sitelist.GetAsXML2());

	//Add User Moderation Statuses
	CUserStatuses modstatuses(m_InputContext);
	if ( modstatuses.GetUserStatuses() )
		pWholePage->AddInside("H2G2",&modstatuses);
	else if ( modstatuses.ErrorReported() )
		pWholePage->AddInside("H2G2",modstatuses.GetLastErrorAsXMLString());

	//Add Distress Messages
	CModerationDistressMessages distressmsgs(m_InputContext);
	if ( distressmsgs.GetDistressMessages(iModClassId) )
		pWholePage->AddInside("H2G2",&distressmsgs);
	else
		pWholePage->AddInside("H2G2",distressmsgs.GetLastErrorAsXMLString() );


	CModeratePosts moderate(m_InputContext);
	if ( !moderate.GetPosts( pViewer->GetUserID(), bAlerts, bReferrals, bLockedItems, bHeldItems, iModClassId, iPostId,  iShow, bFastMod ) )
		pWholePage->AddInside("H2G2",moderate.GetLastErrorAsXMLString() );
	else
		pWholePage->AddInside("H2G2",&moderate);
	

	TDVASSERT(bSuccess, "CModeratePostsBuilder::Build() failed");
	return bSuccess;
}
Beispiel #6
0
bool CModeratePostsBuilder::Process(CWholePage* pPage, CUser* pViewer)
{
	bool	bSuccess = true;
	
	int			iNumberOfPosts = 0;
	int			iForumID = 0;
	int			iThreadID = 0;
	int			iPostID = 0;
	int			iModID = 0;
	int			iStatus = 0;
	int			iReferTo = 0;
	int			iSiteID = -1;
	CTDVString	sNotes;
	int			i = 0;
	int			iThreadModStatus = 0;
	CTDVString	sEmailType;
	CTDVString	sCustomText;
	bool		bDoNotSendEmail = false;
	
	CSiteOptions* pSiteOptions = m_InputContext.GetSiteOptions();	

	CStoredProcedure SP;
	m_InputContext.InitialiseStoredProcedureObject(&SP);

	CModeratePosts moderate(m_InputContext);

	// first get the total number of post IDs in the submission
	// - there should be an equal number of all the other parameters
	iNumberOfPosts = m_InputContext.GetParamCount("PostID");
	int iTotalProcessed = 0;
	CTDVString sFeedback;
	for ( int i = 0; i < iNumberOfPosts; ++i )
	{
		if ( !bSuccess )
			break;

		// get the PostID and corresponding decision, plus notes if any
		iForumID = m_InputContext.GetParamInt("ForumID", i);
		iThreadID = m_InputContext.GetParamInt("ThreadID", i);
		iPostID = m_InputContext.GetParamInt("PostID", i);
		iModID = m_InputContext.GetParamInt("ModID", i);
		iStatus = m_InputContext.GetParamInt("Decision", i);
		iReferTo = m_InputContext.GetParamInt("ReferTo", i);
		iSiteID = m_InputContext.GetParamInt("SiteID", i);
		bDoNotSendEmail = pSiteOptions->GetValueBool(iSiteID, "Moderation", "DoNotSendEmail");
		if ( m_InputContext.ParamExists("ThreadModerationStatus",i) )
			iThreadModStatus = m_InputContext.GetParamInt("ThreadModerationStatus",i);
		if (!m_InputContext.GetParamString("Notes", sNotes, i))
		{
			sNotes = "";
		}

		// Check to see if we're dealing with a PreModPosting Entry!
		bool bIsPreModPosting = false;
		if (iPostID == 0)
		{
			// Check PreModPosting Table to see if we've got a match on the ModID!
			CStoredProcedure SP;
			if (!m_InputContext.InitialiseStoredProcedureObject(&SP))
			{
				SetDNALastError("CForumModerationPageBuilder::ProcessSubmission","FailedCheckingForModID","Failed checking for modid!!!");
			}
			else
			{
				// Check to see if we need to create the post if it exists. If we're editing the post before moderation, then create it
				bool bCreateIfExists = (iStatus == CModeratePosts::MODERATEPOSTS_CONTENTPASSANDEDIT);

				// Check the PreModPosting tables
				if (!SP.CheckPreModPostingExists(iModID,bCreateIfExists))
				{
					SetDNALastError("CForumModerationPageBuilder::ProcessSubmission","FailedCheckingForModID","Failed checking for modid!!!");
				}

				// Did we find it or not?
				bIsPreModPosting = !SP.IsEOF() && SP.FieldExists("ModID");
				if (bCreateIfExists && !SP.IsEOF())
				{
					// Get the postid and threadid for the new post
					iPostID = SP.GetIntField("postid");
					iThreadID = SP.GetIntField("threadid");
				}
			}
		}

		// do an update for this post only if we have all necessary data
		if (iModID == 0 || iForumID == 0 || ((iPostID == 0 || iThreadID == 0) && !bIsPreModPosting) || 
			( (iStatus == CModeratePosts::MODERATEPOSTS_CONTENTFAILED) && !m_InputContext.ParamExists("EmailType") ) )
		{
			CTDVString sErr = "Error processing post ";
			sErr << iPostID << " - Insufficient Details";
			pPage->AddInside("H2G2",CreateErrorXMLString("ModeratePosts::Process","Process",sErr));
			continue;
		}

		CTDVString sCustomText;
		//The value of the drop down entry selected
		m_InputContext.GetParamString("EmailType", sEmailType, i);
		if (sEmailType.CompareText("URLInsert"))
		{
			m_InputContext.GetParamString("UrlEmailText", sCustomText, i);
		}
		else
		{
			m_InputContext.GetParamString("CustomEmailText", sCustomText, i);
		}
		if ( iStatus == CModeratePosts::MODERATEPOSTS_CONTENTPASSANDEDIT  )
		{
			if (m_InputContext.ParamExists("EditPostSubject",i) && m_InputContext.ParamExists("EditPostText",i))
			{
				CTDVString sBody, sSubject;
				m_InputContext.GetParamString("EditPostSubject", sSubject, i);
				m_InputContext.GetParamString("EditPostText",sBody,i);
				CForumPostEditForm editpost(m_InputContext);
				editpost.SetPostID(iPostID);
				if ( !editpost.ProcessForumPostUpdate(pViewer,sSubject,sBody,NULL,true,false,true ) )
				{
					pPage->AddInside("H2G2",editpost.GetLastErrorAsXMLString());
					continue;
				}
			}
			else
			{
				CTDVString err = "Unable to edit post " ;
				err << iPostID << " Missing Subject/Body";
				pPage->AddInside("H2G2",CXMLError::CreateErrorXMLString("CModeratePosts::Process","ModeratePosts",err));
				continue;
			}
		}
		
		CTDVString	sAuthorsEmail;
		std::vector<CTDVString> vComplainantsEmail;
		std::vector<int> vComplainantsID;
		std::vector<int> vComplaintModID;
		int IsLegacy = 0;
		int iProcessed = 0;
		int iAuthorID = 0; 
		int iComplainantID = 0; 

		//Moderate the post.
		if ( moderate.Update(iModID, iSiteID, iForumID, iThreadID, iPostID, pViewer->GetUserID(), iStatus, iReferTo, iThreadModStatus, sNotes, IsLegacy, iProcessed, sAuthorsEmail, vComplainantsEmail, iAuthorID, vComplainantsID, vComplaintModID) )
		{
			if ( moderate.ErrorReported() )
			{
				pPage->AddInside("H2G2",moderate.GetLastErrorAsXMLString());
				moderate.ClearError();
			}

			iTotalProcessed += iProcessed;

			//Distress Message Processing.
			CTDVString sSubject, sBody;
			int iDistressMessageId = m_InputContext.GetParamInt("distressmessageId",i);
			if ( iDistressMessageId > 0 )
			{
				//Get specified Distress Message
				CModerationDistressMessages distressmsgs(m_InputContext);
				CTDVString sSubject, sBody;
				if ( !distressmsgs.GetDistressMessage(iDistressMessageId, sSubject, sBody ) )
				{
					pPage->AddInside("H2G2",distressmsgs.GetLastErrorAsXMLString());
				}
				else 
				{
					int iUserId;
					if ( m_InputContext.DoesSiteHaveDistressMsgUserId(iSiteID, iUserId) )
					{
						//Site concerned has an account specified for posting distress messages.
						CUser postinguser(m_InputContext);
						if ( !postinguser.CreateFromID(iUserId) )
						{
							CTDVString sErr = "Unable to create user for distress message user account ";
							sErr << iUserId;
							CreateErrorXMLString("ModeratePosts", "Process", sErr);
						}

						if ( !distressmsgs.PostDistressMessage(&postinguser,iSiteID,iForumID,iThreadID,iPostID,sSubject,sBody) )
						{
							pPage->AddInside("H2G2", distressmsgs.GetLastErrorAsXMLString());
						}

					}
					else 
					{
						//Send Distress Mesage using current user.
						if ( !distressmsgs.PostDistressMessage(m_InputContext.GetCurrentUser(),iSiteID,iForumID,iThreadID,iPostID,sSubject,sBody) )
							pPage->AddInside("H2G2", distressmsgs.GetLastErrorAsXMLString());
					}
				}
			}
 
			if ( !bDoNotSendEmail )
			{
				//Only send one email to the author if it was the result of a complaint and site option to send emails is not on.
				if (  !SendAuthorEmail(iModID, iStatus, iSiteID, iForumID, iThreadID, iPostID, IsLegacy, sCustomText, sEmailType, sAuthorsEmail, iAuthorID) )
					pPage->AddInside("H2G2",GetLastErrorAsXMLString());
			}

			//Multiple Complaint Handling - Notify each complainant of decision.
			for (unsigned int i = 0; i < vComplainantsEmail.size(); i++) 
			{
				if ( !vComplainantsEmail[i].IsEmpty() && vComplaintModID.size() > i )
				{
					if ( !SendComplainantEmail(vComplaintModID[i], iStatus, iSiteID, iForumID, iThreadID, iPostID, IsLegacy, sNotes, sCustomText, vComplainantsEmail[i], vComplainantsID[i]) )
						pPage->AddInside("H2G2", GetLastErrorAsXMLString());
				}
			}
		}
		else
		{
			pPage->AddInside("H2G2", moderate.GetLastErrorAsXMLString());
		}
	}

	//Create some Feedback XML.
	CTDVString sXML;
	sXML << "<FEEDBACK PROCESSED='" << iTotalProcessed << "'>" << sFeedback << "</FEEDBACK>";
	pPage->AddInside("H2G2",sXML); 
	return bSuccess;
}