void
WLayoutApplicationMayanX::DisplayUserBalanceUpdated(const CXmlNode * pXmlNodeNewBalance)
    {
	int nBalance=300;
    if(pXmlNodeNewBalance!=NULL)
    {
        MessageLog_AppendTextFormatCo(d_coRed, "is not null\n\n");
        MessageLog_AppendTextFormatCo(d_coRed, "XML: ^N",pXmlNodeNewBalance);
    }

    nBalance=LStringToNumber_ZZR_ML(pXmlNodeNewBalance->m_pszuTagValue);
    m_pwLabelBalance->Label_SetTextFormat_VE_Gsb("Your new balance is $i", nBalance);
    } // DisplayUserBalanceUpdated()
//	Delete a task from the list.
//	Since Task IDs are broadcasted repeatedly, we need to keep the last Task ID so there is no attempt to download the same task after it was previously downloaded and executed.
void
CListTasksSendReceive::DeleteTask(PA_DELETING CTaskSendReceive * paTaskDelete)
	{
	Assert(paTaskDelete != NULL);

	if (paTaskDelete == m_plistTasks)
		m_plistTasks = m_plistTasks->m_pNext;
	else
		{
		CTaskSendReceive * pTask = m_plistTasks;
		while (TRUE)
			{
			CTaskSendReceive * pTaskNext = pTask->m_pNext;
			if (paTaskDelete == pTaskNext)
				{
				//MessageLog_AppendTextFormatSev(eSeverityWarningToErrorLog, "[Debug] Found task $t\n", paTaskDelete->m_tsTaskID);	// Remove this line once executed
				pTask->m_pNext = pTaskNext->m_pNext;	// Remove the task from the linked list
				break;
				}
			pTask = pTaskNext;
			if (pTask == NULL)
				{
				Assert(FALSE && "Task not found");
				return;	// Don't delete the task; it is better to have a memory leak than a crash
				}
			} // while
		}
	MessageLog_AppendTextFormatCo(d_coPurple, "Deleting Task ID $t\n", paTaskDelete->m_tsTaskID);
	delete paTaskDelete;
	DisplayTasksToMessageLog();
	}
//	Send the ballot to a group, or to a contact
//	This method is for debugging
bool
OJapiPoll::send(const QString & sGroupId)
	{
	// In order to send the poll to the group, we need to find the TGroup object
	CStr strGroupId = sGroupId;
	TAccountXmpp * pAccount = m_pBallot->PGetAccount();
	ITreeItemChatLogEvents * pContactOrGroup = pAccount->Contact_PFindByJID(strGroupId, eFindContact_zDefault);
	if (pContactOrGroup == NULL)
		pContactOrGroup = pAccount->Group_PFindByIdentifier_YZ(strGroupId);
	MessageLog_AppendTextFormatCo(d_coBlack, "OJapiPoll::send($Q) - pContactOrGroup = 0x$p\n", &sGroupId, pContactOrGroup);
	if (pContactOrGroup != NULL)
		{
		// To send the poll, we need to clone it and add it to the group (this code is a quite ugly at the moment, however it is for proof of concept)
		CEventBallotPoll * paEventBallot = new CEventBallotPoll;
		paEventBallot->m_pVaultParent_NZ = m_pBallot->m_pVaultParent_NZ;
		CBinXcpStanzaEventCopier binXcpStanzaCopier(m_pBallot->m_pVaultParent_NZ->m_pParent);
		binXcpStanzaCopier.EventCopy(IN m_pBallot, OUT paEventBallot);
		paEventBallot->m_pVaultParent_NZ = NULL;
		pContactOrGroup->Vault_AddEventToChatLogAndSendToContacts(PA_CHILD paEventBallot);
		#if 0
		paEventBallot->m_uFlagsBallot |= CEventBallotPoll::FB_kfStopAcceptingVotes; // Testing the stop()
		stop();
		//start();
		#endif
		return true;
		}
	return false;
	}
//	getList(), slot
//	Return a list of polls and ballots.
QVariant
OJapiAppBallotmaster::getList()
	{
	Assert(m_pServiceBallotmaster != NULL);
	QVariantList oList;

	IEventBallot ** ppEventBallotStop;
	IEventBallot ** ppEventBallot = PrgpGetEventsBallotsStop(OUT &ppEventBallotStop);
	while (ppEventBallot != ppEventBallotStop)
		{
		CEventBallotReceived * pEventBallot = (CEventBallotReceived *)*ppEventBallot++;
		if (pEventBallot->EGetEventClass() == CEventBallotReceived::c_eEventClass)
			oList.append(QVariant::fromValue(PGetOJapiBallot(pEventBallot)));
		}

	IEvent ** ppEventStop;
	IEvent ** ppEvent = m_pServiceBallotmaster->m_oVaultBallots.m_arraypaEvents.PrgpGetEventsStop(OUT &ppEventStop);
	while (ppEvent != ppEventStop)
		{
        CEventBallotPoll * pEvent = (CEventBallotPoll *)*ppEvent++;
		if (pEvent->EGetEventClass() != eEventClass_eBallotPoll)
            continue;
		if ((pEvent->m_uFlagsEvent & IEvent::FE_kfEventDeleted) == 0)
			oList.append(QVariant::fromValue(PGetOJapiPoll(pEvent)));	// List only non-deleted polls
		}
	MessageLog_AppendTextFormatCo(d_coBlue, "OPolls::list() - $i elements\n", oList.size());
	return QVariant::fromValue(oList);
	}
Exemple #5
0
//	TContact::IXmlExchange::XmlExchange()
//
//	IMPLEMENTATION NOTES
//	The Chat Log is serialized (saved) however is not read by this method.  Instead, the Chat Log
//	is read on-demand when the user clicks on the contact.
void
TContact::XmlExchange(INOUT CXmlExchanger * pXmlExchanger)
	{
	Assert(pXmlExchanger != NULL);
	ITreeItemChatLogEvents::XmlExchange(pXmlExchanger);
	pXmlExchanger->XmlExchangeStr("JID", INOUT &m_strJidBare);
	pXmlExchanger->XmlExchangeUIntHexFlagsMasked("Flags", INOUT &m_uFlagsContact, FC_kmFlagsSerializeMask);
	pXmlExchanger->XmlExchangeTimestamp("tsSync", INOUT_F_UNCH_S &m_tsOtherLastSynchronized);
	pXmlExchanger->XmlExchangeStr("Comment", INOUT &m_strComment);
	pXmlExchanger->XmlExchangeBin("Rec", INOUT &m_binXmlRecommendations);
	/*
	pXmlExchanger->XmlExchangeStr("NymID", INOUT &m_strNymID);
	pXmlExchanger->XmlExchangeStr("KeyPublic", INOUT &m_strKeyPublic);
    pXmlExchanger->XmlExchangeStr("RoleName",&m_strRoleName);
	*/

	m_listaTasksSendReceive.XmlExchange(INOUT pXmlExchanger);
	m_listaCrypto.XmlExchange(INOUT pXmlExchanger);

	if (!pXmlExchanger->m_fSerializing)
		{
		// We are reading the data, therefore do some adjustments
		if (m_uFlagsContact & FC_kfXospSynchronizeWhenPresenceOnline)
			m_uFlagsContact |= FC_kfXospSynchronizeOnNextXmppStanza;
		m_strJidBare.StringTruncateAtCharacter('/');	// Remove the resource from the JID. In earlier version of the chat, the serialized JID could contain the resource.  Eventually this line should go away.
		}

	#if 0
	if (m_uFlagsTreeItem != 0)
		MessageLog_AppendTextFormatCo(d_coBlack, "0x$p: TContact::XmlExchange($S) m_uFlagsTreeItem = 0x$x\n", this, &m_strJidBare, m_uFlagsTreeItem);
	//m_pAccount->DebugDumpContacts();
	#endif
	} // XmlExchange()
void
OSocketWeb::SL_Connected()
	{
	m_eSocketState = eSocketState_WaitingForHandshake;
	MessageLog_AppendTextFormatCo(d_coBlue, "WebSocket connected $s\n", isValid() ? "valid" : "INVALID");
	SHashSha1 hashNonce;
	HashSha1_InitRandom(OUT &hashNonce);
	CBin bin;
	bin.BinAppendText_VE(
		"GET / HTTP/1.1\r\n"
		"Upgrade: websocket\r\n"
		"Connection: Upgrade\r\n"
		"Sec-WebSocket-Key: {h/}\r\n"
		"Sec-WebSocket-Version: 13\r\n\r\n", &hashNonce);
	MessageLog_AppendTextFormatCo(d_coGoldenRod, "Writing:\n$B", &bin);
	write(bin.PszaGetUtf8NZ(), bin.CbGetData());
	}
//	Delete the task matching the ID, and if not found, do nothing.
void
CListTasksSendReceive::DeleteTaskMatchingID(TIMESTAMP tsTaskID, BOOL fDeleteTaskToSend)
	{
	CTaskSendReceive ** ppTaskPrevious = &m_plistTasks;
	CTaskSendReceive * pTask = m_plistTasks;
	while (pTask != NULL)
		{
		if ((pTask->m_tsTaskID == tsTaskID) && (pTask->FIsTaskSend() == fDeleteTaskToSend))
			{
			MessageLog_AppendTextFormatCo(d_coPurple, "DeleteTaskMatchingID() - Task ID $t is now deleted ($I bytes)\n", tsTaskID, pTask->m_binXmlData.CbGetData());
			*ppTaskPrevious = pTask->m_pNext;	// Remove the task to delete from the linked list
			delete pTask;
			return;
			}
		ppTaskPrevious = &pTask->m_pNext;
		pTask = pTask->m_pNext;
		}
	MessageLog_AppendTextFormatCo(COX_MakeBold(d_coPurple), "DeleteTaskMatchingID() - Cannot delete Task ID $t because its ID cannot be found!\n", tsTaskID);
	}
void
CListTasksSendReceive::SerializeToXml(IOUT CBin * pbinXmlTasks)
	{
	CTaskSendReceive * pTask = m_plistTasks;
	while (pTask != NULL)
		{
		MessageLog_AppendTextFormatCo(d_coRed, "Serializing Task ID $t\n", pTask->m_tsTaskID);
		pbinXmlTasks->BinAppendText_VE("\n<t i='$t' s='$i' _debug_sofar='$i' d='{B|}'/>", pTask->m_tsTaskID, pTask->m_cbTotal, pTask->m_binXmlData.CbGetData(), &pTask->m_binXmlData);
		pTask = pTask->m_pNext;
		}
	}
void
TAccountXmpp::Contact_RosterUnsubscribe(INOUT TContact * pContact)
	{
	Assert(pContact != NULL);
	if (m_paSocket == NULL)
		return;
	if (m_paSocket->Socket_FuIsReadyToSendMessages())
		{
		MessageLog_AppendTextFormatCo(COX_MakeBold(d_coOrange), "Unsubscribing from contact ^j...\n", pContact);
		m_paSocket->Socket_WriteXmlFormatted("<iq type='set'><query xmlns='jabber:iq:roster'><item jid='^j' subscription='remove'></item></query></iq>", pContact);
		}
	}
void
TAccountXmpp::DebugDumpContacts()
	{
	TContact * pContact;
	TContact ** ppContactStop;
	TContact ** ppContact = m_arraypaContacts.PrgpGetContactsStop(OUT &ppContactStop);
	while (ppContact != ppContactStop)
		{
		pContact = *ppContact++;
		MessageLog_AppendTextFormatCo(d_coBlack, "0x$p: Contact $S: m_uFlagsTreeItem = 0x$x\n", pContact, &pContact->m_strJidBare, pContact->m_uFlagsTreeItem);
		}
	}
//	For debugging
void
CListTasksSendReceive::DisplayTasksToMessageLog()
	{
	int cTasks = 0;
	TIMESTAMP tsNow = Timestamp_GetCurrentDateTime();
	CTaskSendReceive * pTask = m_plistTasks;
	while (pTask != NULL)
		{
		TIMESTAMP_DELTA dts = tsNow - pTask->m_tsTaskID;
		const int cbXmlData = pTask->m_binXmlData.CbGetData();
		if (pTask->FIsTaskSend())
			MessageLog_AppendTextFormatCo(d_coPurple, "\t [$T] Sending Task ID $t: $I bytes\n", dts, pTask->m_tsTaskID, cbXmlData);
		else
			MessageLog_AppendTextFormatCo(d_coPurple, "\t [$T] Downloading Task ID $t: cbTotalToDownload = $I, cbDownloadedSoFar = $I\n", dts, pTask->m_tsTaskID, pTask->m_cbTotal, cbXmlData);
		if (cbXmlData > 0) // && cbXmlData < 200)
			MessageLog_AppendTextFormatCo(d_coGray, "\t\t {Bm}\n", &pTask->m_binXmlData);
		pTask = pTask->m_pNext;
		cTasks++;
		} // while
	if (cTasks >= 3)
		MessageLog_AppendTextFormatCo(COX_MakeBold(d_coPurple), "\t\t Total of $i tasks\n", cTasks);
	}
    void
WLayoutApplicationMayanX::DisplayAllUsersDocuments(const CXmlNode * pXmlNodeUsers)
    {
    if (m_pwTableUsersDocuments == NULL)
        {
        addWidget(new QLabel("Documents"));
        m_pwTableUsersDocuments = new WTable(this);
        m_pwTableUsersDocuments->SetColumns_VEZ("Id","Name", "DocId", "Type", "Status", NULL);
        // As soon as the table is visible, call the web service to fetch the list of user balances
        CInternetRequestWebMethodXmlMayanX oRequest("UserDocuments");
        m_oInternetServer.RequestSend(&oRequest);
        }
    else
    {
        m_pwTableUsersDocuments->clear();
        m_pwTableUsersDocuments->SetColumns_VEZ("Id","Name", "DocId", "Type", "Status", NULL);
    }
    if (pXmlNodeUsers == NULL)
        return;
    const CXmlNode * pXmlNodeElement;
    MessageLog_AppendTextFormatCo(d_coRed, "XML-1: ^N",pXmlNodeUsers);
    pXmlNodeElement = pXmlNodeUsers->PFindElement("Document");
    MessageLog_AppendTextFormatCo(d_coRed, "XML-2: ^N",pXmlNodeElement);


    while (pXmlNodeElement != NULL)
        {
        OTableRow oRow;
        oRow.AddData(pXmlNodeElement->PszuFindElementOrAttributeValue("Id"));
        oRow.AddData(pXmlNodeElement->PszuFindElementOrAttributeValue("DocName"));
        oRow.AddData(pXmlNodeElement->PszuFindElementOrAttributeValue("DocId"));
        oRow.AddData(pXmlNodeElement->PszuFindElementOrAttributeValue("eType"));
        oRow.AddData(pXmlNodeElement->PszuFindElementOrAttributeValue("eStatus"));
        m_pwTableUsersDocuments->AppendRow(oRow);
        pXmlNodeElement = pXmlNodeElement->PFindNextSibling();
        }

    }
bool
OJapiPoll::save(/*const QString & sDebugContext*/)
	{
	m_pBallot->m_uFlagsEvent &= ~IEvent::FE_kfEventDeleted;
	TProfile * pProfile = m_pBallot->PGetProfile();
	pProfile->m_pConfigurationParent->XmlConfigurationSaveToFile();	// Force a save to make sure if the machine crashes, the poll have been saved

	QString sStatus = status();
	MessageLog_AppendTextFormatCo(d_coBlue, "OJapiPoll::save() - Poll ID $t, status=$Q\n", /*&sDebugContext,*/ m_pBallot->m_tsEventID, &sStatus);

	// Notify each Ballotmaster app the poll has been saved
	OJapiAppBallotmaster * pBallotmaster = OJapiAppBallotmaster::s_plistBallotmasters;
	while (pBallotmaster != NULL)
		{
		if (pBallotmaster->PGetProfile() == pProfile)
			{
			MessageLog_AppendTextFormatCo(d_coBlue, "Ballotmaster 0x$p: emitting onPollSaved() - Poll ID $t\n", pBallotmaster, m_pBallot->m_tsEventID);
			emit pBallotmaster->onPollSaved(this);
			}
		pBallotmaster = pBallotmaster->m_pNext;
		}
	return true;
	}
void
WChatInput::insertFromMimeData(const QMimeData * poMimeDataSource)
	{
	if (poMimeDataSource->hasImage())
		{
		textCursor().insertImage(qvariant_cast<QImage>(poMimeDataSource->imageData()));
		}
	if (poMimeDataSource->hasText())
		{
		CStr strText = poMimeDataSource->text();
		MessageLog_AppendTextFormatCo(d_coBlack, "Paste: '{Sf}'\n", &strText);
		}
	return WEditTextArea::insertFromMimeData(poMimeDataSource);
	}
void
OJapiPoll::destroy()
	{
	m_pBallot->m_uFlagsEvent |= IEvent::FE_kfEventDeleted;

	OJapiAppBallotmaster * pBallotmaster = OJapiAppBallotmaster::s_plistBallotmasters;
	while (pBallotmaster != NULL)
		{
		if (pBallotmaster->PGetProfile() == m_pBallot->PGetProfile())
			{
			MessageLog_AppendTextFormatCo(d_coBlue, "Ballotmaster 0x$p: emitting onPollSaved() - Poll ID $t\n", pBallotmaster, m_pBallot->m_tsEventID);
			emit pBallotmaster->onPollDestroyed(this);
			}
		pBallotmaster = pBallotmaster->m_pNext;
		}
	}
void
WLayoutChatLog::dropEvent(QDropEvent * pDropEvent)
	{
	ITreeItemChatLogEvents * pContactOrGroup = PGetContactOrGroup_NZ();
	CStr strFile;
	QList<QUrl> listUrls = pDropEvent->mimeData()->urls();
	foreach (QUrl url, listUrls)
		{
		if (!url.isLocalFile())
			continue;
		strFile = url.toLocalFile();
		pContactOrGroup->Xmpp_SendEventFileUpload(strFile);
		strFile = url.toString();
		MessageLog_AppendTextFormatCo(d_coBlack, "URL: $S\n", &strFile);
		}
	}
//	Core routine to add a new event to the vault and send it to the contact(s).
//	Optionally this method may also send an 'Updater' event
void
CVaultEvents::EventAddAndDispatchToContacts(PA_CHILD IEvent * paEvent, PA_CHILD CEventUpdaterSent * paEventUpdater)
	{
	Assert(paEvent != NULL);
	Assert(paEvent->m_tsOther == d_ts_zNA);
	Assert(paEvent->m_pVaultParent_NZ == NULL);
	Assert(paEvent->Event_FIsEventTypeSent());
	//MessageLog_AppendTextFormatSev(eSeverityWarningToErrorLog, "EventAddAndDispatchToContacts() - tsEventID $t\n", paEvent->m_tsEventID);
	if (paEventUpdater != NULL)
		{
		// Always include the Updater before the updated event
		paEventUpdater->m_pVaultParent_NZ = this;
		m_arraypaEvents.Add(PA_CHILD paEventUpdater);
		}
	paEvent->m_pVaultParent_NZ = this;
	m_arraypaEvents.Add(PA_CHILD paEvent);
	SetModified();	// Make sure the events are saved to disk

	if (paEvent->EGetEventClass() & eEventClass_kfNeverSerializeToXCP)
		return;	// The event is never serialized to XOSP, therefore there is nothing else to do

	CBinXcpStanza binXcpStanza;			// All events are sent as XMPP 'messages' so they may be cached
	TGroup * pGroup = (TGroup *)m_pParent;
	TContact * pContact = (TContact *)m_pParent;
	if (pContact->EGetRuntimeClass() == RTI(TContact))
		{
		// Send the message to a contact
		MessageLog_AppendTextFormatCo(d_coGrayDark, "\t Sending message to $S\n\t\t m_tsEventIdLastSentCached $t, m_tsOtherLastSynchronized $t\n", &pContact->m_strJidBare, pContact->m_tsEventIdLastSentCached, pContact->m_tsOtherLastSynchronized);
		binXcpStanza.BinXmlAppendXcpApiCall_SendEventToContact(pContact, paEvent, paEventUpdater);
		}
	else
		{
		// Broadcast the message to every [active] group member
		Assert(pGroup->EGetRuntimeClass() == RTI(TGroup));
		TGroupMember ** ppMemberStop;
		TGroupMember ** ppMember = pGroup->m_arraypaMembers.PrgpGetMembersStop(OUT &ppMemberStop);
		while (ppMember != ppMemberStop)
			{
			TGroupMember * pMember = *ppMember++;
			Assert(pMember != NULL);
			Assert(pMember->EGetRuntimeClass() == RTI(TGroupMember));
			binXcpStanza.BinXmlAppendXcpApiCall_SendEventToContact(pMember->m_pContact, paEvent, paEventUpdater);
			} // while
		} // if...else
	m_pParent->m_tsEventIdLastSentCached = paEvent->m_tsEventID;
	} // EventAddAndDispatchToContacts()
QString
OJapiBallot::status() const
	{
	Assert(m_pEventBallot != NULL);
	const EEventClass eEventClass = m_pEventBallot->EGetEventClass();
	if (eEventClass == CEventBallotReceived::c_eEventClass)
		{
		return ((((CEventBallotReceived *)m_pEventBallot)->m_ukmChoices) == 0) ? "unvoted" : "voted";
		}
	Assert(eEventClass == CEventBallotPoll::c_eEventClass);
	if (eEventClass == CEventBallotPoll::c_eEventClass)
		{
		return ((CEventBallotPoll *)m_pEventBallot)->PszGetStatus();
		}
	MessageLog_AppendTextFormatCo(d_coBlue, "OJapiBallot::OJapiBallot() - returning an empty string for Event ID $t\n", m_pEventBallot->m_tsEventID);
	return c_sEmpty;
	}
//	Return an array of integers representing the number of votes per choice.
//	This method is likely to be unused because the object OJapiPollOption has a method count().
QVariant
OJapiPollResults::counts() const
    {
	Assert(m_pBallot != NULL);
    MessageLog_AppendTextFormatCo(d_coBlue, "OJapiPollResults::counts()\n");
    QVariantList list;
	CEventBallotSent * pEventBallotSent = m_pBallot->PGetEventBallotSend_YZ();
	if (pEventBallotSent != NULL)
		{
		_CEventBallotChoice ** ppChoiceStop;
		_CEventBallotChoice ** ppChoice = pEventBallotSent->PrgpGetChoicesStopWithTally(OUT &ppChoiceStop);
		while (ppChoice != ppChoiceStop)
			{
			_CEventBallotChoice * pChoice = *ppChoice++;
			list.append(pChoice->m_cVotes);
			}
		}
    return list;
    }
void
CListTasksSendReceive::UnserializeFromXml(const CXmlNode * pXmlNodeElementTask)
	{
	Assert(m_plistTasks == NULL);
	CTaskSendReceive ** ppaTask = &m_plistTasks;
	while (pXmlNodeElementTask != NULL)
		{
		//MessageLog_AppendTextFormatCo(d_coRed, "Unserializing Task ^N", pXmlNodeElementTask);
		CTaskSendReceive * paTask = new CTaskSendReceive;
		*ppaTask = paTask;
		ppaTask = &paTask->m_pNext;	// Pointer to append the next task at the end of the linked list
		paTask->m_tsTaskID = pXmlNodeElementTask->TsGetAttributeValueTimestamp_ML('i');
		paTask->m_cbTotal = pXmlNodeElementTask->UFindAttributeValueDecimal_ZZR('s');
		paTask->m_binXmlData.BinAppendBinaryDataFromBase85SCb_ML(pXmlNodeElementTask->PszuFindAttributeValue('d'));
		pXmlNodeElementTask = pXmlNodeElementTask->m_pNextSibling;
		}

	MessageLog_AppendTextFormatCo(COX_MakeBold(d_coGreen), "CListTasksSendReceive::UnserializeFromXml():\n");
	DisplayTasksToMessageLog();
	}
void
CVaultEvents::XmlExchange(PSZAC pszTagNameVault, INOUT CXmlExchanger * pXmlExchanger)
	{
	CBinXospStanzaForDisk binXcpStanza;
	if (pXmlExchanger->m_fSerializing)
		{
		EventsSerializeForMemory(INOUT &binXcpStanza);
		pXmlExchanger->XmlExchangeBin(pszTagNameVault, IN &binXcpStanza);
		}
	else
		{
		pXmlExchanger->XmlExchangeBin(pszTagNameVault, OUT &binXcpStanza);
		//MessageLog_AppendTextFormatCo(d_coChocolate, "CVaultEvents::XmlExchange($s) : $B\n", pszTagNameVault, IN &binXcpStanza);
		CXmlTree oXmlTree;
		oXmlTree.SetFileDataCopy(binXcpStanza);
		if (oXmlTree.EParseFileDataToXmlNodes_ML() == errSuccess)
			EventsUnserialize(IN &oXmlTree);
		MessageLog_AppendTextFormatCo(d_coRed, "\t $i events read\n", m_arraypaEvents.GetSize());
		}
	}
CTaskSendReceive *
CListTasksSendReceive::PFindOrAllocateTaskDownload_NZ(TIMESTAMP tsTaskID, const CXmlNode * pXmlNodeTaskDownload)
	{
	Assert(pXmlNodeTaskDownload != NULL);

	// First, search if the task is there
	TIMESTAMP tsPrevious = d_ts_zNA;
	CTaskSendReceive ** ppTaskInsert = &m_plistTasks;
	CTaskSendReceive * pTask = m_plistTasks;
	while (pTask != NULL)
		{
		if (!pTask->FIsTaskSend())
			{
			if (pTask->m_tsTaskID == tsTaskID)
				return pTask;
			if (pTask->m_tsTaskID > tsTaskID)
				break;
			}
		else
			{
			Assert(pTask->m_tsTaskID > tsPrevious);
			tsPrevious = pTask->m_tsTaskID;
			}
		ppTaskInsert = &pTask->m_pNext;
		pTask = pTask->m_pNext;
		} // while

	// Th task is not found, therefore allocate it
	pTask = new CTaskSendReceive;
	pTask->m_tsTaskID = tsTaskID;
	pTask->m_cbTotal = pXmlNodeTaskDownload->UFindAttributeValueDecimal_ZZR(d_chXa_TaskDataSizeTotal);
	MessageLog_AppendTextFormatCo(d_coPurple, "Downloading Task ID $t of $I bytes\n", tsTaskID, pTask->m_cbTotal);

	// And insert tot he list
	pTask->m_pNext = *ppTaskInsert;
	*ppTaskInsert = pTask;
	return pTask;
	}
void
TAccountXmpp::Contact_RosterSubscribe(INOUT TContact * pContact)
	{
	Assert(pContact != NULL);
	if (m_paSocket == NULL)
		return;
	if (pContact->TreeItemFlags_FuIsInvisible())
		return;	// Don't add invisible contacts to the roster
	/*
	if (pContact->m_strJidBare.FStringBeginsWith("temp"))
		{
		MessageLog_AppendTextFormatSev(eSeverityErrorAssert, "Removing contact ^j from roster...\n", pContact);
		m_paSocket->Socket_WriteXmlFormatted("<iq type='set'><query xmlns='jabber:iq:roster'><item jid='^S' subscription='remove'></item></query></iq>", &pContact->m_strJidBare);
		return;
		}
	*/
	#if 1
	MessageLog_AppendTextFormatCo(COX_MakeBold(d_coOrange), "Adding contact ^j to roster...\n", pContact);
	m_paSocket->Socket_WriteXmlFormatted("<iq id='$p' type='set'><query xmlns='jabber:iq:roster'><item jid='^j'></item></query></iq>", pContact, pContact);
	#endif

	//m_paSocket->Socket_WriteXmlFormatted("<presence to='^j' type='subscribe'/>", pContact);
	//m_paSocket->Socket_WriteXmlFormatted("<presence ^:jc from='^J' to='^j' type='subscribe'/>", this, pContact);
	}
//	ITreeItem::IXmlExchange::XmlExchange()
void
ITreeItem::XmlExchange(INOUT CXmlExchanger * pXmlExchanger)
	{
	IXmlExchangeObjectID::XmlExchange(pXmlExchanger);
	if (pXmlExchanger->m_fSerializing && m_paTreeItemW_YZ != NULL)
		{
		// Remember the state of the Tree Item is expanded or collapsed
		if (m_paTreeItemW_YZ->isExpanded())
			m_uFlagsTreeItem |= FTI_kfTreeItem_IsExpanded;
		else
			m_uFlagsTreeItem &= ~FTI_kfTreeItem_IsExpanded;
		}
	pXmlExchanger->XmlExchangeStrConditional("N", INOUT &m_strNameDisplayTyped, (m_uFlagsTreeItem & FTI_kfTreeItem_NameDisplayedGenerated) == 0);	// Save the name before the flags (it makes the XML file a bit more organized, as the name is always present while the flags are not)
	pXmlExchanger->XmlExchangeUIntHexFlagsMasked("F", INOUT &m_uFlagsTreeItem, FTI_kmTreeItem_FlagsSerializeMask);

	#if 0
	//m_uFlagsTreeItem |= FTI_kfObjectInvisible;
	if (m_uFlagsTreeItem != 0)
		MessageLog_AppendTextFormatCo(d_coBlack, "0x$p: ITreeItem::XmlExchange($s) m_uFlagsTreeItem = 0x$x\n", this, TreeItem_PszGetNameDisplay(), m_uFlagsTreeItem);
	#endif

	if (!pXmlExchanger->m_fSerializing && m_strNameDisplayTyped.FIsEmptyString())
		pXmlExchanger->XmlExchangeStr("NameDisplay", INOUT &m_strNameDisplayTyped);	// Compatibility with the old file format (to be removed in 2015)
	} // XmlExchange()
void
WLayoutApplicationMayanX::SL_SocketStateChanged(QAbstractSocket::SocketState eState)
	{
	MessageLog_AppendTextFormatCo(d_coBlue, "WebSocket state changed: $i $s\n", eState, PszaGetSocketState(eState));
	}
//	Find the contact matching the JID and update the contact resource (if any).
//	If the JID is not in the contact list, the method will create a new contact to the list according to the value of eFindContact.
//	This method may return NULL if the JID is empty/invalid because a new contact cannot not be created.
//
//	IMPLEMENTATION NOTES
//	This method should use a hash table to quickly find a contact from its JID and/or use a pointer to cache the last contact found.
TContact *
TAccountXmpp::Contact_PFindByJID(PSZUC pszContactJID, EFindContact eFindContact)
	{
	Assert(pszContactJID != NULL);
	if (pszContactJID != NULL)
		{
		// Find the resource
		PSZUC pszResource = pszContactJID;
		while (TRUE)
			{
			if (*pszResource == '/')
				break;
			if (*pszResource == '\0')
				break;
			pszResource++;
			} // while
		const int cchJID = pszResource - pszContactJID;
		if (cchJID > 0)
			{
			TContact * pContact;
			TContact ** ppContactStop;
			TContact ** ppContact = m_arraypaContacts.PrgpGetContactsStop(OUT &ppContactStop);
			while (ppContact != ppContactStop)
				{
				pContact = *ppContact++;
//				Assert(!m_strJID.FCompareStringsJIDs(pContact->m_strJidBare) && "Contact should not have the same JID as its parent XMPP account!");
				//MessageLog_AppendTextFormatCo(d_coBlack, "Comparing $s with $S\n", pszContactJID, &pContact->m_strJidBare);
				if (pContact->m_strJidBare.FCompareStringsNoCaseCch(pszContactJID, cchJID))
					{
					// We have found our contact
					if (pContact->TreeItemFlags_FuIsInvisible())
						{
						Endorse(pContact->m_paTreeItemW_YZ != NULL);	// Typically an invisible contact should not appear in the Navigation Tree, however there are situations where it is. For instance, if the contact was just deleted, or if displayed into the list of "Deleted Items"
						if (eFindContact & eFindContact_kfMakeVisible)
							pContact->TreeItemContact_DisplayWithinNavigationTreeAndClearInvisibleFlag();
						}
					if (*pszResource != '\0')
						{
						// Update the contact resource
						if (!pContact->m_strRessource.FCompareStringsExactCase(pszResource))
							{
							if (pContact->m_strRessource.FIsEmptyString())
								MessageLog_AppendTextFormatCo(d_coBlack, "Contact $S: Assigning resource '$s' (m_uFlagsTreeItem = 0x$x)\n", &pContact->m_strJidBare, pszResource, m_uFlagsTreeItem);
							else
								MessageLog_AppendTextFormatCo(COX_MakeBold(d_coBlack), "Contact $S: Updating resource from '$S' to '$s'\n", &pContact->m_strJidBare, &pContact->m_strRessource, pszResource);
							//pContact->Xcp_ServiceDiscovery();	// The resource changed, therefore query the remote client for its capabilities
							pContact->SetFlagXcpComposingSendTimestampsOfLastKnownEvents();	// Each time the resource change, re-send the timestamps of the last known events so we give an opportunity to synchronize
							//pContact->m_cVersionXCP = 0;	// Also, reset the XCP version, to make sure the device connects properly
							}
						pContact->m_strRessource.InitFromStringU(pszResource);
						}
					return pContact;
					}
				} // while
			// We could not find the contact, so create a new one if the JID meets the minimal conditions
			if ((eFindContact & eFindContact_kfCreateNew) &&
				PcheValidateJID(pszContactJID) == NULL &&			// Make sure the JID is somewhat valid to create a new contact
				!m_strJID.FCompareStringsJIDs(pszContactJID))		// Make sure the JID is not the same as the account.  It makes no sense to create a contact with the same JID as its parent account.  This situation occurs rarely when the server sends a stanza where the 'from' contains the JID of the account.
				{
				MessageLog_AppendTextFormatSev(eSeverityInfoTextBlack, "Contact_PFindByJID('$s') - Creating contact for account $S\n", pszContactJID, &m_strJID);
				pContact = TreeItemAccount_PContactAllocateNewToNavigationTree_NZ(IN pszContactJID);
				if (eFindContact & eFindContact_kfCreateAsUnsolicited)
					pContact->SetFlagContactAsUnsolicited();
				return pContact;
				}
			} // if
		} // if
	return NULL;
	} // Contact_PFindByJID()
void
WLayoutApplicationMayanX::SL_SocketError(QAbstractSocket::SocketError e)
	{
	MessageLog_AppendTextFormatCo(d_coBlue, "WebSocket error $i\n", e);
	}
void
WLayoutApplicationMayanX::SL_InternetRequestCompleted(QNetworkReply * poNetworkReply)
	{
	CInternetResponseWebMethodXmlSoap oInternetResponse(poNetworkReply);

	// First of all, check if there is an error from the server
	CXmlNode * pXmlNodeError = oInternetResponse.PGetXmlNodeError();
	if (pXmlNodeError != NULL)
		{
		MessageLog_AppendTextFormatSev(eSeverityErrorWarning, "SL_InternetRequestCompleted() with the following error:\n^N", pXmlNodeError);
		int nCode = pXmlNodeError->NFindElementOrAttributeValueNumeric("nCode");
		if (nCode == eCodeUserNotFound)
			{
			// The user is not found or does not exist, therefore clear the m_strxUserID so we may retry
			m_pApplication->m_strxUserID.Empty();
			}
		if (nCode == eCodeUserAlreadyExist)
			{
			// The user already exists, so fetch the xUserID from the
			m_pApplication->m_strxUserID = pXmlNodeError->PszuFindElementValue("xDescriptionParam");
			SL_ExchangeLogin();	// Attempt to login again
			}
		return;
		}

	CXmlNode * pXmlNode = oInternetResponse.PGetXmlNodeResponse("UserRegister");
	if (pXmlNode != NULL)
		{
		m_pApplication->m_strxUserID = pXmlNode->m_pszuTagValue;
		if (!m_pApplication->m_strxUserID.FIsEmptyString())
			SL_ExchangeLogin();		// Attempt to login with the new UserID.
		else
			EMessageBoxWarning("The API 'UserRegister' returned an invalid UserID of value '$S'", &m_pApplication->m_strxUserID);
		return;
		}
	pXmlNode = oInternetResponse.PGetXmlNodeResponse("UserLogin");
	if (pXmlNode != NULL)
		{
		CBin binChallenge;
		binChallenge.BinAppendBinaryDataFromBase64Szv(pXmlNode->PszuFindElementValue("bChallenge"));
		if (!binChallenge.FIsEmptyBinary())
			{
			// We received a challenge, so respond to it now
			CBin binResponseData = m_pApplication->m_pProfileParent->m_strKeyPublic;
			binResponseData.BinAppendCBin(binChallenge);
			//MessageLog_AppendTextFormatCo(d_coBlue, " bIdentity: {B/}\n bChallenge: {B/}\n bIdentity + bChallenge: {B/}\n", &m_pTreeItemParent->m_binKeyPublic, &binChallenge, &binResponseData);
			binResponseData.BinHashToMd5();

			CInternetRequestWebMethodXmlMayanX oRequest("UserLogin");
			oRequest.BinAppendXmlElementText("xUserID", m_pApplication->m_strxUserID);
			oRequest.BinAppendXmlElementBinaryBase64("bResponse", binResponseData);
			m_oInternetServer.RequestSend(&oRequest);
			return;
			}
		if (m_oInternetServer.m_strxSessionID.FIsEmptyString())
			{
			m_oInternetServer.m_strxSessionID = pXmlNode->PszuFindElementValue("xSessionID");
			//m_oInternetServer.m_strxSessionID = (PSZUC)"as8323jas932e";
			if (!m_oInternetServer.m_strxSessionID.FIsEmptyString())
				{
				MessageLog_AppendTextFormatCo(d_coBlue, "Login successful: xSessionID = $S\n", &m_oInternetServer.m_strxSessionID);
				OLayoutHorizontal * poLayoutOrder = new OLayoutHorizontal((QWidget *)NULL);
				m_poLayoutButtons->addRow(poLayoutOrder);
				m_pwEditQuantity = new WEditNumber;
				poLayoutOrder->Layout_AddLabelAndWidgetH_PA("Quantity:", m_pwEditQuantity);
				m_pwEditPrice = new WEditNumber;
				poLayoutOrder->Layout_AddLabelAndWidgetH_PA("Price:", m_pwEditPrice);
				WButtonTextWithIcon * pwButton = new WButtonTextWithIcon("Place Order", eMenuIcon_Bitcoin); // eMenuIconCoffeeBuy);
				poLayoutOrder->addWidget(pwButton);
				poLayoutOrder->addWidget(PA_CHILD new QWidget, 1);
				connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonUserOrderAdd()));

				//Updating user balance
				OLayoutHorizontal * poLayoutUserBalance = new OLayoutHorizontal((QWidget *)NULL);
				m_poLayoutButtons->addRow(poLayoutUserBalance);
                m_pwEditUpdateBalanceQuantity = new WEditNumber;
                m_pwEditUpdateBalanceUserId = new WEditNumber;
                poLayoutUserBalance->Layout_AddLabelAndWidgetH_PA("User Id:", m_pwEditUpdateBalanceUserId);
                poLayoutUserBalance->Layout_AddLabelAndWidgetH_PA("Quantity:", m_pwEditUpdateBalanceQuantity);
                m_pwLabelBalance=new WLabel;
				pwButton = new WButtonTextWithIcon("Update Balance", eMenuIcon_Bitcoin); // eMenuIconCoffeeBuy);
                poLayoutUserBalance->addWidget(pwButton);
                poLayoutUserBalance->addWidget(m_pwLabelBalance);
				poLayoutUserBalance->addWidget(PA_CHILD new QWidget, 1);
                connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonUserBalanceUpdate()));

                //Cancel an Order
                OLayoutHorizontal * poLayoutCancelAnOrder = new OLayoutHorizontal((QWidget *)NULL);
                m_poLayoutButtons->addRow(poLayoutCancelAnOrder);
                m_pwEditIdToCancelOrder = new WEditNumber;
                poLayoutCancelAnOrder->Layout_AddLabelAndWidgetH_PA("Id:", m_pwEditIdToCancelOrder);
				pwButton = new WButtonTextWithIcon("Cancel Order", eMenuIcon_Bitcoin); // eMenuIconCoffeeBuy);
                poLayoutCancelAnOrder->addWidget(pwButton);
                poLayoutCancelAnOrder->addWidget(PA_CHILD new QWidget, 1);
                connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonUserOrderCancel()));

                //Update an Order
                OLayoutHorizontal * poLayoutUpdateAnOrder = new OLayoutHorizontal((QWidget *)NULL);
                m_poLayoutButtons->addRow(poLayoutUpdateAnOrder);
                m_pwEditIdToUpdateOrder = new WEditNumber;
                poLayoutUpdateAnOrder->Layout_AddLabelAndWidgetH_PA("Id:", m_pwEditIdToUpdateOrder);
                m_pwEditPriceToUpdateOrder = new WEditNumber;
                poLayoutUpdateAnOrder->Layout_AddLabelAndWidgetH_PA("Price:", m_pwEditPriceToUpdateOrder);
                m_pwEditQuantityToUpdateOrder = new WEditNumber;
                poLayoutUpdateAnOrder->Layout_AddLabelAndWidgetH_PA("Quantity:", m_pwEditQuantityToUpdateOrder);
				pwButton = new WButtonTextWithIcon("Update Order", eMenuIcon_Bitcoin); // eMenuIconCoffeeBuy);
                poLayoutUpdateAnOrder->addWidget(pwButton);
                poLayoutUpdateAnOrder->addWidget(PA_CHILD new QWidget, 1);
                connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonUserOrderUpdate()));

                //Update User's Account
                OLayoutHorizontal* poLayoutUpdateUsersAccount = new OLayoutHorizontal((QWidget *)NULL);
                m_poLayoutButtons->addRow(poLayoutUpdateUsersAccount);
                m_pwEditUpdateAccountId=new WEditNumber;
                m_pwEditUpdateAccountName = new WEdit;
                m_pwEditUpdateAccountRole = new WEditNumber;
                poLayoutUpdateUsersAccount->Layout_AddLabelAndWidgetH_PA("User Id:", m_pwEditUpdateAccountId);
                poLayoutUpdateUsersAccount->Layout_AddLabelAndWidgetH_PA("User Name:", m_pwEditUpdateAccountName);
                poLayoutUpdateUsersAccount->Layout_AddLabelAndWidgetH_PA("User Role:", m_pwEditUpdateAccountRole);
				pwButton = new WButtonTextWithIcon("Update User Account", eMenuIcon_Bitcoin); // eMenuIconCoffeeBuy);
                poLayoutUpdateUsersAccount->addWidget(pwButton);
                poLayoutUpdateUsersAccount->addWidget(PA_CHILD new QWidget, 1);
                connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonUserAccountUpdate()));

                //Get User's Document
                OLayoutHorizontal* poLayoutUserDocuments = new OLayoutHorizontal((QWidget *)NULL);
                m_poLayoutButtons->addRow(poLayoutUserDocuments);
                m_pwEditGetUserDocumentId=new WEditNumber;
                poLayoutUserDocuments->Layout_AddLabelAndWidgetH_PA("Document Id:", m_pwEditGetUserDocumentId);
				pwButton = new WButtonTextWithIcon("Get Document", eMenuIcon_Bitcoin); // eMenuIconCoffeeBuy);
                poLayoutUserDocuments->addWidget(pwButton);
                poLayoutUserDocuments->addWidget(PA_CHILD new QWidget, 1);
                connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonUserDocumentGet()));

                //Buttons to Fetch Data
                OLayoutHorizontal* poLayoutFetchData = new OLayoutHorizontal((QWidget *)NULL);
                m_poLayoutButtons->addRow(poLayoutFetchData);
                    //Fetching User's Balances

					pwButton = new WButtonTextWithIcon("Fetch User's' Balances", eMenuIcon_Bitcoin); // eMenuIconCoffeeBuy);
                    poLayoutFetchData->addWidget(pwButton);
                    connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonFetchUserBalances()));

                    //Fetching Users
					pwButton = new WButtonTextWithIcon("Fetch Users", eMenuIcon_Bitcoin); // eMenuIconCoffeeBuy);
                    poLayoutFetchData->addWidget(pwButton);
                    connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonFetchUsers()));

                    //Fetching User's Documents
					pwButton = new WButtonTextWithIcon("Fetch User's Documents", eMenuIcon_Bitcoin); // eMenuIconCoffeeBuy);
                    poLayoutFetchData->addWidget(pwButton);
                    connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonFetchUserDocuments()));

                    //Upload a Document
					pwButton = new WButtonTextWithIcon("Upload a Document...", eMenuIcon_Bitcoin); // eMenuIconCoffeeBuy);
                    poLayoutFetchData->addWidget(pwButton);
                    connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonUploadADocument()));

                poLayoutFetchData->addWidget(PA_CHILD new QWidget, 1);

				/*
				// We have a valid Session ID, so we may download the bids.  For this, we will display a new button
				WButtonTextWithIcon * pwButton = new WButtonTextWithIcon("Download Market Bids", eMenuIconCoffeeBuy);
				m_poLayoutButtons->addRow(pwButton);
				connect(pwButton, SIGNAL(clicked()), this, SLOT(SL_ButtonDownloadMarketBids()));
				*/
				m_pwLabelWelcome->hide();
				m_pwButtonRegister->hide();
				DisplayOrders(0);
                DisplayUserBalances(0);
				}
			}
		return;
		} // if (UserLogin)

	pXmlNode = oInternetResponse.PGetXmlNodeResponse("UserOrderAdd");
	if (pXmlNode != NULL)
		{
		DisplayOrders(pXmlNode);
		DisplayMarketOrders(pXmlNode);	// Also add the new order to the Market Orders
		return;
		}
	pXmlNode = oInternetResponse.PGetXmlNodeResponse("UserOrders");
	if (pXmlNode != NULL)
		{
		DisplayOrders(pXmlNode);
		return;
		}

	pXmlNode = oInternetResponse.PGetXmlNodeResponse("MarketOrders");
	if (pXmlNode != NULL)
		{
		DisplayMarketOrders(pXmlNode);
		return;
		}

    pXmlNode = oInternetResponse.PGetXmlNodeResponse("UserBalanceUpdate");
    if (pXmlNode != NULL)
        {
        DisplayUserBalanceUpdated(pXmlNode);
        return;
        }

    pXmlNode = oInternetResponse.PGetXmlNodeResponse("FetchUserBalances");
    if (pXmlNode != NULL)
        {
        MessageLog_AppendTextFormatCo(d_coRed, "Fetching user balances\n\n");
        DisplayUserBalances(pXmlNode);
        return;
        }

    pXmlNode = oInternetResponse.PGetXmlNodeResponse("FetchUsers");
    if (pXmlNode != NULL)
        {
        MessageLog_AppendTextFormatCo(d_coRed, "Fetching all users\n\n");
        DisplayUsers(pXmlNode);
        return;
        }

    pXmlNode = oInternetResponse.PGetXmlNodeResponse("UserAccountUpdate");
    if (pXmlNode != NULL)
        {
        MessageLog_AppendTextFormatCo(d_coRed, "updating user account\n\n");
        DisplayUserAccountUpdate(pXmlNode);
        return;
        }

    pXmlNode = oInternetResponse.PGetXmlNodeResponse("UserDocuments");
    if (pXmlNode != NULL)
        {
        MessageLog_AppendTextFormatCo(d_coRed, "getting all user's documents\n\n");
        DisplayAllUsersDocuments(pXmlNode);
        return;
        }


    pXmlNode = oInternetResponse.PGetXmlNodeResponse("UserDocumentGet");
    if (pXmlNode != NULL)
        {
        MessageLog_AppendTextFormatCo(d_coRed, "getting all user's documents\n\n");
        SaveUsersDocument(pXmlNode);
        return;
            }

    pXmlNode = oInternetResponse.PGetXmlNodeResponse("UserOrderUpdate");
    if (pXmlNode != NULL)
        {
        UserOrderUpdate(pXmlNode);
        return;
            }

    pXmlNode = oInternetResponse.PGetXmlNodeResponse("UserOrderCancel");
    if (pXmlNode != NULL)
        {
        UserOrderCancel(pXmlNode);
        return;
            }

	} // SL_InternetRequestCompleted()
void
OSocketWeb::SL_DataAvailable()
	{
	g_oMutex.lock();	// Make sure all signals SI_MessageAvailable() are synchronized
	int cbDataAvailable = bytesAvailable();		// Read only once the number of bytes available. This is important to prevent 'thread starvation' in the case the socket data arrives faster than the web socket can handle it.  By readin the bytes available once, we are guaranteed this 'state machine' method will eventually exit.
	switch (m_eSocketState)
		{
	case eSocketState_WaitingForHandshake:
		readAll();	// Flush the handshake
		m_eSocketState = eSocketState_WaitingForFrameHeader;
		// Fall Through //
	case eSocketState_WaitingForFrameHeader:
		WaitingForFrameHeader:
		cbDataAvailable -= 2;
		if (cbDataAvailable >= 0)
			{
			BYTE rgbFrameHeader[2];
			read(OUT (char *)rgbFrameHeader, sizeof(rgbFrameHeader));
			m_bFrameHeader0_kfFragmentFinal = (rgbFrameHeader[0] & d_bFrameHeader0_kfFragmentFinal);
			const BYTE bOpcode = (rgbFrameHeader[0] & d_bFrameHeader0_kmFragmentOpcode);
			if (bOpcode != eOpcode_zContinue)
				m_bFrameHeader0_eOpcode = bOpcode;
			m_bFrameHeader1_kfPayloadMasked = (rgbFrameHeader[1] & d_bFrameHeader1_kfPayloadMasked);
			m_cblFrameData = (rgbFrameHeader[1] & d_bFrameHeader1_kmPayloadLength);
//			MessageLog_AppendTextFormatCo(COX_MakeBold(d_coBlue), "WebSocket Header: [0]=0x$x [1]=0x$x  (Frame = $L bytes, $L bytes remaining)\n", rgbFrameHeader[0], rgbFrameHeader[1], m_cblFrameData, bytesAvailable());
			switch (m_cblFrameData)
				{
			case d_bFrameHeader1_kePayloadLength16:
				m_eSocketState = eSocketState_WaitingForFrameHeaderPayload16;
				goto WaitingForFrameHeaderPayload16;
			case d_bFrameHeader1_kePayloadLength64:
				m_eSocketState = eSocketState_WaitingForFrameHeaderPayload64;
				goto WaitingForFrameHeaderPayload64;
				} // switch
			m_eSocketState = eSocketState_WaitingForFrameHeaderMask;
			goto WaitingForFrameHeaderMask;
			}
		break;
	case eSocketState_WaitingForFrameHeaderPayload16:
		WaitingForFrameHeaderPayload16:
		cbDataAvailable -= sizeof(quint16);
		if (cbDataAvailable >= 0)
			{
			quint16 cbwFrameData;
			read(OUT (char *)&cbwFrameData, sizeof(cbwFrameData));
			m_cblFrameData = qFromBigEndian(cbwFrameData);
			m_eSocketState = eSocketState_WaitingForFrameHeaderMask;
			//MessageLog_AppendTextFormatCo(COX_MakeBold(d_coRed), "WebSocket Payload16: $L bytes\n", m_cblFrameData);
			goto WaitingForFrameHeaderMask;
			}
		break;
	case eSocketState_WaitingForFrameHeaderPayload64:
		WaitingForFrameHeaderPayload64:
		cbDataAvailable -= sizeof(quint64);
		if (cbDataAvailable >= 0)
			{
			quint64 cblFrameData;
			read(OUT (char *)&cblFrameData, sizeof(cblFrameData));
			m_cblFrameData = qFromBigEndian(cblFrameData);
			MessageLog_AppendTextFormatCo(COX_MakeBold(d_coRed), "WebSocket Payload64: $L bytes\n", m_cblFrameData);
			m_eSocketState = eSocketState_WaitingForFrameHeaderMask;
			goto WaitingForFrameHeaderMask;
			}
		break;
	case eSocketState_WaitingForFrameHeaderMask:
		WaitingForFrameHeaderMask:
		if (m_bFrameHeader1_kfPayloadMasked)
			{
			MessageLog_AppendTextFormatCo(d_coRed, "Frame is masked\n");
			cbDataAvailable -= sizeof(m_rgbFrameMask);
			if (cbDataAvailable < 0)
				break;
			read(OUT (char *)m_rgbFrameMask, sizeof(m_rgbFrameMask));
			}
		m_eSocketState = eSocketState_WaitingForFrameDataPayload;
		// Fall Through //
	case eSocketState_WaitingForFrameDataPayload:
		cbDataAvailable -= m_cblFrameData;
		if (cbDataAvailable >= 0)
			{
			BYTE * pbData = m_binFrameData.PbeAllocateExtraDataWithVirtualNullTerminator(m_cblFrameData);
			const int cbDataRead = read(OUT (char *)pbData, m_cblFrameData);	// Read the data from the socket
			if (cbDataRead != m_cblFrameData)
				MessageLog_AppendTextFormatSev(eSeverityErrorWarning, "WebSocket: cbDataRead=$I, m_cblFrameData=$L\n", cbDataRead, m_cblFrameData);
//			MessageLog_AppendTextFormatCo(d_coBlueDark, "$s\n", pbData);
			if (m_bFrameHeader0_kfFragmentFinal)
				{
				// Check if there are any special opcodes the socket can handle automatically
				switch (m_bFrameHeader0_eOpcode)
					{
				case eOpcode_DataText:
				case eOpcode_DataBinary:
					emit SI_MessageAvailable(INOUT m_binFrameData);	// Both text and binary are treated the same, as Cambrian uses UTF-8 for text
					break;
				case eOpcode_Ping:
					DataWrite(INOUT m_binFrameData, eOpcode_Pong);	// Respond to the ping request
					break;
				case eOpcode_Close:
					// Close the socket
					break;
					} // switch
				m_binFrameData.Empty();
				} // if
			m_eSocketState = eSocketState_WaitingForFrameHeader;
			goto WaitingForFrameHeader;
			}
		break;
		} // switch
	g_oMutex.unlock();
	} // SL_DataAvailable()
void
WLayoutApplicationMayanX::UserOrderUpdate(const CXmlNode * pXmlNode)
{
    MessageLog_AppendTextFormatCo(d_coRed, "XML-1: ^N",pXmlNode);
}