From 6206d9efcead4e4cd92df1b6c9bb0150d13052cc Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 8 Mar 2018 13:58:24 +0300 Subject: fixes #1154 (Invisible" status is broken) This reverts commit 1ca493fc7af16dd20ad13453fc19774da3c65181. --- protocols/IcqOscarJ/src/fam_01service.cpp | 3 +++ protocols/IcqOscarJ/src/fam_15icqserver.cpp | 17 +++++++++++++ protocols/IcqOscarJ/src/icq_proto.cpp | 20 ++++++++++++++- protocols/IcqOscarJ/src/icq_proto.h | 1 + protocols/IcqOscarJ/src/icq_xstatus.cpp | 24 ++++++++++++++++++ protocols/IcqOscarJ/src/utilities.cpp | 38 +++++++++++++++++++++++++++++ 6 files changed, 102 insertions(+), 1 deletion(-) (limited to 'protocols/IcqOscarJ') diff --git a/protocols/IcqOscarJ/src/fam_01service.cpp b/protocols/IcqOscarJ/src/fam_01service.cpp index d6d6e821dc..c77b939f51 100644 --- a/protocols/IcqOscarJ/src/fam_01service.cpp +++ b/protocols/IcqOscarJ/src/fam_01service.cpp @@ -711,6 +711,9 @@ void CIcqProto::handleServUINSettings(int nPort, serverthread_info *info) else szMoodData[0] = '\0'; + //! Tricky code, this ensures that the status note will be saved to the directory + SetStatusNote(szStatusNote, m_bGatewayMode ? 5000 : 2500, TRUE); + size_t wStatusNoteLen = mir_strlen(szStatusNote); size_t wStatusMoodLen = mir_strlen(szMoodData); size_t wSessionDataLen = (wStatusNoteLen ? wStatusNoteLen + 4 : 0) + 4 + wStatusMoodLen + 4; diff --git a/protocols/IcqOscarJ/src/fam_15icqserver.cpp b/protocols/IcqOscarJ/src/fam_15icqserver.cpp index 0bce60710f..3a58297543 100644 --- a/protocols/IcqOscarJ/src/fam_15icqserver.cpp +++ b/protocols/IcqOscarJ/src/fam_15icqserver.cpp @@ -857,6 +857,23 @@ void CIcqProto::parseDirectoryUserDetailsData(MCONTACT hContact, oscar_tlv_chain writeDbInfoSettingTLVStringUtf(hContact, "About", cDetails, 0x186); + // if (hContact) + // writeDbInfoSettingTLVStringUtf(hContact, DBSETTING_STATUS_NOTE, cDetails, 0x226); + // else + if (!hContact) { // Owner contact needs special processing, in the database is current status note for the client + // We just received the last status note set on directory, if it differs call SetStatusNote() to + // ensure the directory will be updated (it should be in process anyway) + char *szClientStatusNote = getSettingStringUtf(hContact, DBSETTING_STATUS_NOTE, nullptr); + char *szDirectoryStatusNote = cDetails->getString(0x226, 1); + + if (mir_strcmp(szClientStatusNote, szDirectoryStatusNote)) + SetStatusNote(szClientStatusNote, 1000, TRUE); + + // Release memory + SAFE_FREE(&szDirectoryStatusNote); + SAFE_FREE(&szClientStatusNote); + } + writeDbInfoSettingTLVByte(hContact, "PrivacyLevel", cDetails, 0x1F9); if (!hContact) { diff --git a/protocols/IcqOscarJ/src/icq_proto.cpp b/protocols/IcqOscarJ/src/icq_proto.cpp index 16efe23929..25ba07ecd5 100644 --- a/protocols/IcqOscarJ/src/icq_proto.cpp +++ b/protocols/IcqOscarJ/src/icq_proto.cpp @@ -1505,6 +1505,12 @@ int __cdecl CIcqProto::SetStatus(int iNewStatus) // New status is OFFLINE if (nNewStatus == ID_STATUS_OFFLINE) { // for quick logoff + if (icqOnline()) { // set offline status note (otherwise the old will remain) + char *szOfflineNote = PrepareStatusNote(nNewStatus); + SetStatusNote(szOfflineNote, 0, FALSE); + SAFE_FREE(&szOfflineNote); + } + m_iDesiredStatus = nNewStatus; if (hServerConn) { // Connected, Send disconnect packet @@ -1557,6 +1563,11 @@ int __cdecl CIcqProto::SetStatus(int iNewStatus) char *szStatusNote = PrepareStatusNote(nNewStatus); + //! This is a bit tricky, we do trigger status note change thread and then + // change the status note right away (this spares one packet) - so SetStatusNote() + // will only change User Details Directory + SetStatusNote(szStatusNote, 6000, FALSE); + if (m_iStatus == ID_STATUS_INVISIBLE) { if (m_bSsiEnabled) updateServVisibilityCode(3); @@ -1730,8 +1741,15 @@ int __cdecl CIcqProto::SetAwayMsg(int status, const wchar_t* msg) *ppszMsg = szNewUtf; szNewUtf = nullptr; - if ((m_iStatus == status) && icqOnline()) // update current status note + if ((m_iStatus == status) && icqOnline()) { // update current status note + char *szNote = *ppszMsg ? *ppszMsg : ""; + + BYTE bXStatus = getContactXStatus(NULL); + if (!bXStatus) + SetStatusNote(szNote, 1000, FALSE); + icq_sendSetAimAwayMsgServ(*ppszMsg); + } } SAFE_FREE(&szNewUtf); diff --git a/protocols/IcqOscarJ/src/icq_proto.h b/protocols/IcqOscarJ/src/icq_proto.h index 294fea1da5..004a7148ed 100644 --- a/protocols/IcqOscarJ/src/icq_proto.h +++ b/protocols/IcqOscarJ/src/icq_proto.h @@ -880,6 +880,7 @@ struct CIcqProto : public PROTO char *setStatusNoteText, *setStatusMoodData; void __cdecl SetStatusNoteThread(void *pArguments); + int SetStatusNote(const char *szStatusNote, DWORD dwDelay, int bForced); int SetStatusMood(const char *szMoodData, DWORD dwDelay); void writeDbInfoSettingTLVStringUtf(MCONTACT hContact, const char *szSetting, oscar_tlv_chain *chain, WORD wTlv); diff --git a/protocols/IcqOscarJ/src/icq_xstatus.cpp b/protocols/IcqOscarJ/src/icq_xstatus.cpp index a06b0a1241..0a98def4bf 100644 --- a/protocols/IcqOscarJ/src/icq_xstatus.cpp +++ b/protocols/IcqOscarJ/src/icq_xstatus.cpp @@ -519,6 +519,30 @@ void CIcqProto::updateServerCustomStatus(int fullUpdate) SetStatusMood(szMoodData, 1500); } + + char *szStatusNote = nullptr; + + // use custom status message as status note + if (bXStatus && (m_bXStatusEnabled || m_bMoodsEnabled)) + szStatusNote = getSettingStringUtf(NULL, DBSETTING_XSTATUS_MSG, ""); + // retrieve standard status message (e.g. custom status set to none) + else { + char **pszMsg = MirandaStatusToAwayMsg(m_iStatus); + { + mir_cslock l(m_modeMsgsMutex); + if (pszMsg) + szStatusNote = null_strdup(*pszMsg); + } + + // no default status message, set empty + if (!szStatusNote) + szStatusNote = null_strdup(""); + } + + if (szStatusNote) + SetStatusNote(szStatusNote, 1500, FALSE); + + SAFE_FREE(&szStatusNote); } static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) diff --git a/protocols/IcqOscarJ/src/utilities.cpp b/protocols/IcqOscarJ/src/utilities.cpp index db1af286c9..97253e2cc1 100644 --- a/protocols/IcqOscarJ/src/utilities.cpp +++ b/protocols/IcqOscarJ/src/utilities.cpp @@ -1095,6 +1095,44 @@ void __cdecl CIcqProto::SetStatusNoteThread(void *pDelay) } +int CIcqProto::SetStatusNote(const char *szStatusNote, DWORD dwDelay, int bForce) +{ + int bChanged = FALSE; + + // bForce is intended for login sequence - need to call this earlier than icqOnline() + // the process is delayed and icqOnline() is ready when needed inside SetStatusNoteThread() + if (!bForce && !icqOnline()) return bChanged; + + // reuse generic critical section (used for cookies list and object variables locks) + mir_cslock l(cookieMutex); + + if (!setStatusNoteText && (!m_bMoodsEnabled || !setStatusMoodData)) { // check if the status note was changed and if yes, create thread to change it + char *szCurrentStatusNote = getSettingStringUtf(NULL, DBSETTING_STATUS_NOTE, nullptr); + + if (mir_strcmp(szCurrentStatusNote, szStatusNote)) { // status note was changed + // create thread to change status note on existing server connection + setStatusNoteText = null_strdup(szStatusNote); + + if (dwDelay) + ForkThread(&CIcqProto::SetStatusNoteThread, (void*)dwDelay); + else // we cannot afford any delay, so do not run in separate thread + SetStatusNoteThread(nullptr); + + bChanged = TRUE; + } + SAFE_FREE(&szCurrentStatusNote); + } + else { // only alter status note object with new status note, keep the thread waiting for execution + SAFE_FREE(&setStatusNoteText); + setStatusNoteText = null_strdup(szStatusNote); + + bChanged = TRUE; + } + + return bChanged; +} + + int CIcqProto::SetStatusMood(const char *szMoodData, DWORD dwDelay) { int bChanged = FALSE; -- cgit v1.2.3