diff options
Diffstat (limited to 'protocols/JabberG/src/jabber_rc.cpp')
-rw-r--r-- | protocols/JabberG/src/jabber_rc.cpp | 814 |
1 files changed, 814 insertions, 0 deletions
diff --git a/protocols/JabberG/src/jabber_rc.cpp b/protocols/JabberG/src/jabber_rc.cpp new file mode 100644 index 0000000000..0021733356 --- /dev/null +++ b/protocols/JabberG/src/jabber_rc.cpp @@ -0,0 +1,814 @@ +/*
+
+Jabber Protocol Plugin for Miranda IM
+Copyright ( C ) 2002-04 Santithorn Bunchua
+Copyright ( C ) 2005-12 George Hazan
+Copyright ( C ) 2007 Maxim Mluhov
+
+XEP-0146 support for Miranda IM
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or ( at your option ) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "jabber.h"
+#include "jabber_iq.h"
+#include "jabber_rc.h"
+#include "m_awaymsg.h"
+
+CJabberAdhocSession::CJabberAdhocSession( CJabberProto* global )
+{
+ m_pNext = NULL;
+ m_pUserData = NULL;
+ m_bAutofreeUserData = FALSE;
+ m_dwStage = 0;
+ ppro = global;
+ m_szSessionId.Format(_T("%u%u"), ppro->SerialNext(), GetTickCount());
+ m_dwStartTime = GetTickCount();
+}
+
+BOOL CJabberProto::IsRcRequestAllowedByACL( CJabberIqInfo* pInfo )
+{
+ if ( !pInfo || !pInfo->GetFrom())
+ return FALSE;
+
+ return IsMyOwnJID( pInfo->GetFrom());
+}
+
+BOOL CJabberProto::HandleAdhocCommandRequest( HXML iqNode, CJabberIqInfo* pInfo )
+{
+ if ( !pInfo->GetChildNode())
+ return TRUE;
+
+ if ( !m_options.EnableRemoteControl || !IsRcRequestAllowedByACL( pInfo )) {
+ // FIXME: send error and return
+ return TRUE;
+ }
+
+ const TCHAR* szNode = xmlGetAttrValue( pInfo->GetChildNode(), _T("node"));
+ if ( !szNode )
+ return TRUE;
+
+ m_adhocManager.HandleCommandRequest( iqNode, pInfo, ( TCHAR* )szNode );
+ return TRUE;
+}
+
+BOOL CJabberAdhocManager::HandleItemsRequest( HXML, CJabberIqInfo* pInfo, const TCHAR* szNode )
+{
+ if ( !szNode || !m_pProto->m_options.EnableRemoteControl || !m_pProto->IsRcRequestAllowedByACL( pInfo ))
+ return FALSE;
+
+ if ( !_tcscmp( szNode, _T(JABBER_FEAT_COMMANDS)))
+ {
+ XmlNodeIq iq( _T("result"), pInfo );
+ HXML resultQuery = iq << XQUERY( _T(JABBER_FEAT_DISCO_ITEMS)) << XATTR( _T("node"), _T(JABBER_FEAT_COMMANDS));
+
+ Lock();
+ CJabberAdhocNode* pNode = GetFirstNode();
+ while ( pNode ) {
+ TCHAR* szJid = pNode->GetJid();
+ if ( !szJid )
+ szJid = m_pProto->m_ThreadInfo->fullJID;
+
+ resultQuery << XCHILD( _T("item")) << XATTR( _T("jid"), szJid )
+ << XATTR( _T("node"), pNode->GetNode()) << XATTR( _T("name"), pNode->GetName());
+
+ pNode = pNode->GetNext();
+ }
+ Unlock();
+
+ m_pProto->m_ThreadInfo->send( iq );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL CJabberAdhocManager::HandleInfoRequest( HXML, CJabberIqInfo* pInfo, const TCHAR* szNode )
+{
+ if ( !szNode || !m_pProto->m_options.EnableRemoteControl || !m_pProto->IsRcRequestAllowedByACL( pInfo ))
+ return FALSE;
+
+ // FIXME: same code twice
+ if ( !_tcscmp( szNode, _T(JABBER_FEAT_COMMANDS))) {
+ XmlNodeIq iq( _T("result"), pInfo );
+ HXML resultQuery = iq << XQUERY( _T(JABBER_FEAT_DISCO_INFO)) << XATTR( _T("node"), _T(JABBER_FEAT_COMMANDS));
+ resultQuery << XCHILD( _T("identity")) << XATTR( _T("name"), _T("Ad-hoc commands"))
+ << XATTR( _T("category"), _T("automation")) << XATTR( _T("type"), _T("command-node"));
+
+ resultQuery << XCHILD( _T("feature")) << XATTR( _T("var"), _T(JABBER_FEAT_COMMANDS));
+ resultQuery << XCHILD( _T("feature")) << XATTR( _T("var"), _T(JABBER_FEAT_DATA_FORMS));
+ resultQuery << XCHILD( _T("feature")) << XATTR( _T("var"), _T(JABBER_FEAT_DISCO_INFO));
+ resultQuery << XCHILD( _T("feature")) << XATTR( _T("var"), _T(JABBER_FEAT_DISCO_ITEMS));
+
+ m_pProto->m_ThreadInfo->send( iq );
+ return TRUE;
+ }
+
+ Lock();
+ CJabberAdhocNode *pNode = FindNode( szNode );
+ if ( pNode ) {
+ XmlNodeIq iq( _T("result"), pInfo );
+ HXML resultQuery = iq << XQUERY( _T(JABBER_FEAT_DISCO_INFO)) << XATTR( _T("node"), _T(JABBER_FEAT_DISCO_INFO));
+ resultQuery << XCHILD( _T("identity")) << XATTR( _T("name"), pNode->GetName())
+ << XATTR( _T("category"), _T("automation")) << XATTR( _T("type"), _T("command-node"));
+
+ resultQuery << XCHILD( _T("feature")) << XATTR( _T("var"), _T(JABBER_FEAT_COMMANDS));
+ resultQuery << XCHILD( _T("feature")) << XATTR( _T("var"), _T(JABBER_FEAT_DATA_FORMS));
+ resultQuery << XCHILD( _T("feature")) << XATTR( _T("var"), _T(JABBER_FEAT_DISCO_INFO));
+
+ Unlock();
+ m_pProto->m_ThreadInfo->send( iq );
+ return TRUE;
+ }
+ Unlock();
+ return FALSE;
+}
+
+BOOL CJabberAdhocManager::HandleCommandRequest( HXML iqNode, CJabberIqInfo* pInfo, const TCHAR* szNode )
+{
+ // ATTN: ACL and db settings checked in calling function
+
+ HXML commandNode = pInfo->GetChildNode();
+
+ Lock();
+ CJabberAdhocNode* pNode = FindNode( szNode );
+ if ( !pNode ) {
+ Unlock();
+
+ m_pProto->m_ThreadInfo->send(
+ XmlNodeIq( _T("error"), pInfo )
+ << XCHILD( _T("error")) << XATTR( _T("type"), _T("cancel"))
+ << XCHILDNS( _T("item-not-found"), _T("urn:ietf:params:xml:ns:xmpp-stanzas")));
+
+ return FALSE;
+ }
+
+ const TCHAR* szSessionId = xmlGetAttrValue( commandNode, _T("sessionid"));
+
+ CJabberAdhocSession* pSession = NULL;
+ if ( szSessionId ) {
+ pSession = FindSession( szSessionId );
+ if ( !pSession ) {
+ Unlock();
+
+ XmlNodeIq iq( _T("error"), pInfo );
+ HXML errorNode = iq << XCHILD( _T("error")) << XATTR( _T("type"), _T("modify"));
+ errorNode << XCHILDNS( _T("bad-request"), _T("urn:ietf:params:xml:ns:xmpp-stanzas"));
+ errorNode << XCHILDNS( _T("bad-sessionid"), _T(JABBER_FEAT_COMMANDS));
+ m_pProto->m_ThreadInfo->send( iq );
+ return FALSE;
+ }
+ }
+ else
+ pSession = AddNewSession();
+
+ if ( !pSession ) {
+ Unlock();
+
+ m_pProto->m_ThreadInfo->send(
+ XmlNodeIq( _T("error"), pInfo )
+ << XCHILD( _T("error")) << XATTR( _T("type"), _T("cancel"))
+ << XCHILDNS( _T("forbidden"), _T("urn:ietf:params:xml:ns:xmpp-stanzas")));
+
+ return FALSE;
+ }
+
+ // session id and node exits here, call handler
+
+ int nResultCode = pNode->CallHandler( iqNode, pInfo, pSession );
+
+ if ( nResultCode == JABBER_ADHOC_HANDLER_STATUS_COMPLETED ) {
+ m_pProto->m_ThreadInfo->send(
+ XmlNodeIq( _T("result"), pInfo )
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), szNode )
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("completed"))
+ << XCHILD( _T("note"), TranslateT("Command completed successfully")) << XATTR( _T("type"), _T("info")));
+
+ RemoveSession( pSession );
+ pSession = NULL;
+ }
+ else if ( nResultCode == JABBER_ADHOC_HANDLER_STATUS_CANCEL ) {
+ m_pProto->m_ThreadInfo->send(
+ XmlNodeIq( _T("result"), pInfo )
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), szNode )
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("canceled"))
+ << XCHILD( _T("note"), TranslateT("Error occured during processing command")) << XATTR( _T("type"), _T("error")));
+
+ RemoveSession( pSession );
+ pSession = NULL;
+ }
+ else if ( nResultCode == JABBER_ADHOC_HANDLER_STATUS_REMOVE_SESSION ) {
+ RemoveSession( pSession );
+ pSession = NULL;
+ }
+ Unlock();
+ return TRUE;
+}
+
+BOOL CJabberAdhocManager::FillDefaultNodes()
+{
+ AddNode( NULL, _T(JABBER_FEAT_RC_SET_STATUS), TranslateT("Set status"), &CJabberProto::AdhocSetStatusHandler );
+ AddNode( NULL, _T(JABBER_FEAT_RC_SET_OPTIONS), TranslateT("Set options"), &CJabberProto::AdhocOptionsHandler );
+ AddNode( NULL, _T(JABBER_FEAT_RC_FORWARD), TranslateT("Forward unread messages"), &CJabberProto::AdhocForwardHandler );
+ AddNode( NULL, _T(JABBER_FEAT_RC_LEAVE_GROUPCHATS), TranslateT("Leave groupchats"), &CJabberProto::AdhocLeaveGroupchatsHandler );
+ AddNode( NULL, _T(JABBER_FEAT_RC_WS_LOCK), TranslateT("Lock workstation"), &CJabberProto::AdhocLockWSHandler );
+ AddNode( NULL, _T(JABBER_FEAT_RC_QUIT_MIRANDA), TranslateT("Quit Miranda NG"), &CJabberProto::AdhocQuitMirandaHandler );
+ return TRUE;
+}
+
+
+static char *StatusModeToDbSetting(int status,const char *suffix)
+{
+ char *prefix;
+ static char str[64];
+
+ switch(status) {
+ case ID_STATUS_AWAY: prefix="Away"; break;
+ case ID_STATUS_NA: prefix="Na"; break;
+ case ID_STATUS_DND: prefix="Dnd"; break;
+ case ID_STATUS_OCCUPIED: prefix="Occupied"; break;
+ case ID_STATUS_FREECHAT: prefix="FreeChat"; break;
+ case ID_STATUS_ONLINE: prefix="On"; break;
+ case ID_STATUS_OFFLINE: prefix="Off"; break;
+ case ID_STATUS_INVISIBLE: prefix="Inv"; break;
+ case ID_STATUS_ONTHEPHONE: prefix="Otp"; break;
+ case ID_STATUS_OUTTOLUNCH: prefix="Otl"; break;
+ case ID_STATUS_IDLE: prefix="Idl"; break;
+ default: return NULL;
+ }
+ lstrcpyA(str,prefix); lstrcatA(str,suffix);
+ return str;
+}
+
+int CJabberProto::AdhocSetStatusHandler( HXML, CJabberIqInfo* pInfo, CJabberAdhocSession* pSession )
+{
+ if ( pSession->GetStage() == 0 ) {
+ // first form
+ pSession->SetStage( 1 );
+
+ XmlNodeIq iq( _T("result"), pInfo );
+ HXML xNode = iq
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), _T(JABBER_FEAT_RC_SET_STATUS))
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("executing"))
+ << XCHILDNS( _T("x"), _T(JABBER_FEAT_DATA_FORMS)) << XATTR( _T("type"), _T("form"));
+
+ xNode << XCHILD( _T("title"), TranslateT("Change Status"));
+ xNode << XCHILD( _T("instructions"), TranslateT("Choose the status and status message"));
+
+ xNode << XCHILD( _T("field")) << XATTR( _T("type"), _T("hidden")) << XATTR( _T("var"), _T("FORM_TYPE"))
+ << XATTR( _T("value"), _T(JABBER_FEAT_RC));
+
+ HXML fieldNode = xNode << XCHILD( _T("field")) << XATTR( _T("label"), TranslateT("Status"))
+ << XATTR( _T("type"), _T("list-single")) << XATTR( _T("var"), _T("status"));
+
+ fieldNode << XCHILD( _T("required"));
+
+ int status = CallService( MS_CLIST_GETSTATUSMODE, 0, 0 );
+ switch ( status ) {
+ case ID_STATUS_INVISIBLE:
+ fieldNode << XCHILD( _T("value"), _T("invisible"));
+ break;
+ case ID_STATUS_AWAY:
+ case ID_STATUS_ONTHEPHONE:
+ case ID_STATUS_OUTTOLUNCH:
+ fieldNode << XCHILD( _T("value"), _T("away"));
+ break;
+ case ID_STATUS_NA:
+ fieldNode << XCHILD( _T("value"), _T("xa"));
+ break;
+ case ID_STATUS_DND:
+ case ID_STATUS_OCCUPIED:
+ fieldNode << XCHILD( _T("value"), _T("dnd"));
+ break;
+ case ID_STATUS_FREECHAT:
+ fieldNode << XCHILD( _T("value"), _T("chat"));
+ break;
+ case ID_STATUS_ONLINE:
+ default:
+ fieldNode << XCHILD( _T("value"), _T("online"));
+ break;
+ }
+
+ fieldNode << XCHILD( _T("option")) << XATTR( _T("label"), TranslateT("Free for chat")) << XCHILD( _T("value"), _T("chat"));
+ fieldNode << XCHILD( _T("option")) << XATTR( _T("label"), TranslateT("Online")) << XCHILD( _T("value"), _T("online"));
+ fieldNode << XCHILD( _T("option")) << XATTR( _T("label"), TranslateT("Away")) << XCHILD( _T("value"), _T("away"));
+ fieldNode << XCHILD( _T("option")) << XATTR( _T("label"), TranslateT("Extended Away (N/A)")) << XCHILD( _T("value"), _T("xa"));
+ fieldNode << XCHILD( _T("option")) << XATTR( _T("label"), TranslateT("Do Not Disturb")) << XCHILD( _T("value"), _T("dnd"));
+ fieldNode << XCHILD( _T("option")) << XATTR( _T("label"), TranslateT("Invisible")) << XCHILD( _T("value"), _T("invisible"));
+ fieldNode << XCHILD( _T("option")) << XATTR( _T("label"), TranslateT("Offline")) << XCHILD( _T("value"), _T("offline"));
+
+ // priority
+ TCHAR szPriority[ 256 ];
+ mir_sntprintf( szPriority, SIZEOF(szPriority), _T("%d"), (short)JGetWord( NULL, "Priority", 5 ));
+ xNode << XCHILD( _T("field")) << XATTR( _T("label"), TranslateT("Priority")) << XATTR( _T("type"), _T("text-single"))
+ << XATTR( _T("var"), _T("status-priority")) << XCHILD( _T("value"), szPriority );
+
+ // status message text
+ xNode << XCHILD( _T("field")) << XATTR( _T("label"), TranslateT("Status message"))
+ << XATTR( _T("type"), _T("text-multi")) << XATTR( _T("var"), _T("status-message"));
+
+ // global status
+ fieldNode = xNode << XCHILD( _T("field")) << XATTR( _T("label"), TranslateT("Change global status"))
+ << XATTR( _T("type"), _T("boolean")) << XATTR( _T("var"), _T("status-global"));
+
+ char* szStatusMsg = (char *)CallService( MS_AWAYMSG_GETSTATUSMSG, status, 0 );
+ if ( szStatusMsg ) {
+ fieldNode << XCHILD( _T("value"), _A2T(szStatusMsg));
+ mir_free( szStatusMsg );
+ }
+
+ m_ThreadInfo->send( iq );
+ return JABBER_ADHOC_HANDLER_STATUS_EXECUTING;
+ }
+ else if ( pSession->GetStage() == 1 ) {
+ // result form here
+ HXML commandNode = pInfo->GetChildNode();
+ HXML xNode = xmlGetChildByTag( commandNode, "x", "xmlns", _T(JABBER_FEAT_DATA_FORMS));
+ if ( !xNode )
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+
+ HXML fieldNode = xmlGetChildByTag( xNode, "field", "var", _T("status"));
+ if ( !xNode )
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+
+ HXML valueNode = xmlGetChild( fieldNode , "value" );
+ if ( !valueNode || !xmlGetText( valueNode ))
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+
+ int status = 0;
+
+ if ( !_tcscmp( xmlGetText( valueNode ), _T("away"))) status = ID_STATUS_AWAY;
+ else if ( !_tcscmp( xmlGetText( valueNode ), _T("xa"))) status = ID_STATUS_NA;
+ else if ( !_tcscmp( xmlGetText( valueNode ), _T("dnd"))) status = ID_STATUS_DND;
+ else if ( !_tcscmp( xmlGetText( valueNode ), _T("chat"))) status = ID_STATUS_FREECHAT;
+ else if ( !_tcscmp( xmlGetText( valueNode ), _T("online"))) status = ID_STATUS_ONLINE;
+ else if ( !_tcscmp( xmlGetText( valueNode ), _T("invisible"))) status = ID_STATUS_INVISIBLE;
+ else if ( !_tcscmp( xmlGetText( valueNode ), _T("offline"))) status = ID_STATUS_OFFLINE;
+
+ if ( !status )
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+
+ int priority = -9999;
+
+ fieldNode = xmlGetChildByTag( xNode, "field", "var", _T("status-priority"));
+ if ( fieldNode && (valueNode = xmlGetChild( fieldNode , "value" ))) {
+ if ( xmlGetText( valueNode ))
+ priority = _ttoi( xmlGetText( valueNode ));
+ }
+
+ if ( priority >= -128 && priority <= 127 )
+ JSetWord( NULL, "Priority", (WORD)priority );
+
+ const TCHAR* szStatusMessage = NULL;
+ fieldNode = xmlGetChildByTag( xNode, "field", "var", _T("status-message"));
+ if ( fieldNode && (valueNode = xmlGetChild( fieldNode , "value" ))) {
+ if ( xmlGetText( valueNode ))
+ szStatusMessage = xmlGetText( valueNode );
+ }
+
+ // skip f...ng away dialog
+ int nNoDlg = DBGetContactSettingByte( NULL, "SRAway", StatusModeToDbSetting( status, "NoDlg" ), 0 );
+ DBWriteContactSettingByte( NULL, "SRAway", StatusModeToDbSetting( status, "NoDlg" ), 1 );
+
+ DBWriteContactSettingTString( NULL, "SRAway", StatusModeToDbSetting( status, "Msg" ), szStatusMessage ? szStatusMessage : _T( "" ));
+
+ fieldNode = xmlGetChildByTag( xNode, "field", "var", _T("status-global"));
+ if ( fieldNode && (valueNode = xmlGetChild( fieldNode , "value" ))) {
+ if ( xmlGetText( valueNode ) && _ttoi( xmlGetText( valueNode )))
+ CallService( MS_CLIST_SETSTATUSMODE, status, NULL );
+ else
+ CallProtoService( m_szModuleName, PS_SETSTATUS, status, NULL );
+ }
+ SetAwayMsg( status, szStatusMessage );
+
+ // return NoDlg setting
+ DBWriteContactSettingByte( NULL, "SRAway", StatusModeToDbSetting( status, "NoDlg" ), (BYTE)nNoDlg );
+
+ return JABBER_ADHOC_HANDLER_STATUS_COMPLETED;
+ }
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+}
+
+int CJabberProto::AdhocOptionsHandler( HXML, CJabberIqInfo* pInfo, CJabberAdhocSession* pSession )
+{
+ if ( pSession->GetStage() == 0 ) {
+ // first form
+ pSession->SetStage( 1 );
+
+ XmlNodeIq iq( _T("result"), pInfo );
+ HXML xNode = iq
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), _T(JABBER_FEAT_RC_SET_OPTIONS))
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("executing"))
+ << XCHILDNS( _T("x"), _T(JABBER_FEAT_DATA_FORMS)) << XATTR( _T("type"), _T("form"));
+
+ xNode << XCHILD( _T("title"), TranslateT("Set Options"));
+ xNode << XCHILD( _T("instructions"), TranslateT("Set the desired options"));
+
+ xNode << XCHILD( _T("field" )) << XATTR( _T("type"), _T("hidden")) << XATTR( _T("var"), _T("FORM_TYPE"))
+ << XATTR( _T("value"), _T(JABBER_FEAT_RC));
+
+ // Automatically Accept File Transfers
+ TCHAR szTmpBuff[ 1024 ];
+ mir_sntprintf( szTmpBuff, SIZEOF(szTmpBuff), _T("%d"), DBGetContactSettingByte( NULL, "SRFile", "AutoAccept", 0 ));
+ xNode << XCHILD( _T("field" )) << XATTR( _T("label"), TranslateT("Automatically Accept File Transfers" ))
+ << XATTR( _T("type"), _T("boolean")) << XATTR( _T("var"), _T("auto-files")) << XCHILD( _T("value"), szTmpBuff );
+
+ // Use sounds
+ mir_sntprintf( szTmpBuff, SIZEOF(szTmpBuff), _T("%d"), DBGetContactSettingByte( NULL, "Skin", "UseSound", 0 ));
+ xNode << XCHILD( _T("field")) << XATTR( _T("label"), TranslateT("Play sounds"))
+ << XATTR( _T("type"), _T("boolean")) << XATTR( _T("var"), _T("sounds")) << XCHILD( _T("value"), szTmpBuff );
+
+ // Disable remote controlling
+ xNode << XCHILD( _T("field")) << XATTR( _T("label"), TranslateT("Disable remote controlling (check twice what you are doing)"))
+ << XATTR( _T("type"), _T("boolean")) << XATTR( _T("var"), _T("enable-rc")) << XCHILD( _T("value"), _T("0"));
+
+ m_ThreadInfo->send( iq );
+ return JABBER_ADHOC_HANDLER_STATUS_EXECUTING;
+ }
+
+ if ( pSession->GetStage() == 1 ) {
+ // result form here
+ HXML commandNode = pInfo->GetChildNode();
+ HXML xNode = xmlGetChildByTag( commandNode, "x", "xmlns", _T(JABBER_FEAT_DATA_FORMS));
+ if ( !xNode )
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+
+ HXML fieldNode, valueNode;
+
+ // Automatically Accept File Transfers
+ fieldNode = xmlGetChildByTag( xNode, "field", "var", _T("auto-files"));
+ if ( fieldNode && (valueNode = xmlGetChild( fieldNode , "value" ))) {
+ if ( xmlGetText( valueNode ))
+ DBWriteContactSettingByte( NULL, "SRFile", "AutoAccept", (BYTE)_ttoi( xmlGetText( valueNode )) );
+ }
+
+ // Use sounds
+ fieldNode = xmlGetChildByTag( xNode, "field", "var", _T("sounds"));
+ if ( fieldNode && (valueNode = xmlGetChild( fieldNode , "value" ))) {
+ if ( xmlGetText( valueNode ))
+ DBWriteContactSettingByte( NULL, "Skin", "UseSound", (BYTE)_ttoi( xmlGetText( valueNode )) );
+ }
+
+ // Disable remote controlling
+ fieldNode = xmlGetChildByTag( xNode, "field", "var", _T("enable-rc"));
+ if ( fieldNode && (valueNode = xmlGetChild( fieldNode , "value" ))) {
+ if ( xmlGetText( valueNode ) && _ttoi( xmlGetText( valueNode )))
+ m_options.EnableRemoteControl = 0;
+ }
+
+ return JABBER_ADHOC_HANDLER_STATUS_COMPLETED;
+ }
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+}
+
+int CJabberProto::RcGetUnreadEventsCount()
+{
+ int nEventsSent = 0;
+ HANDLE hContact = ( HANDLE ) db_find_first();
+ while ( hContact != NULL ) {
+ char* szProto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM ) hContact, 0 );
+ if ( szProto != NULL && !strcmp( szProto, m_szModuleName )) {
+ DBVARIANT dbv;
+ if ( !JGetStringT( hContact, "jid", &dbv )) {
+ HANDLE hDbEvent = (HANDLE)CallService( MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM)hContact, 0 );
+ while ( hDbEvent ) {
+ DBEVENTINFO dbei = { 0 };
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = CallService( MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0 );
+ if ( dbei.cbBlob != -1 ) {
+ dbei.pBlob = (PBYTE)mir_alloc( dbei.cbBlob + 1 );
+ int nGetTextResult = CallService( MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei );
+ if ( !nGetTextResult && dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_READ) && !(dbei.flags & DBEF_SENT)) {
+ TCHAR* szEventText = DbGetEventTextT( &dbei, CP_ACP );
+ if ( szEventText ) {
+ nEventsSent++;
+ mir_free( szEventText );
+ }
+ }
+ mir_free( dbei.pBlob );
+ }
+ hDbEvent = (HANDLE)CallService( MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0 );
+ }
+ JFreeVariant( &dbv );
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+ return nEventsSent;
+}
+
+int CJabberProto::AdhocForwardHandler( HXML, CJabberIqInfo* pInfo, CJabberAdhocSession* pSession )
+{
+ TCHAR szMsg[ 1024 ];
+ if ( pSession->GetStage() == 0 ) {
+ int nUnreadEvents = RcGetUnreadEventsCount();
+ if ( !nUnreadEvents ) {
+ mir_sntprintf( szMsg, SIZEOF(szMsg), TranslateT("There is no messages to forward"));
+
+ m_ThreadInfo->send(
+ XmlNodeIq( _T("result"), pInfo )
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), _T(JABBER_FEAT_RC_FORWARD))
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("completed"))
+ << XCHILD( _T("note"), szMsg ) << XATTR( _T("type"), _T("info")));
+
+ return JABBER_ADHOC_HANDLER_STATUS_REMOVE_SESSION;
+ }
+
+ // first form
+ pSession->SetStage( 1 );
+
+ XmlNodeIq iq( _T("result"), pInfo );
+ HXML xNode = iq
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), _T(JABBER_FEAT_RC_FORWARD))
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("executing"))
+ << XCHILDNS( _T("x"), _T(JABBER_FEAT_DATA_FORMS)) << XATTR( _T("type"), _T("form"));
+
+ xNode << XCHILD( _T("title"), TranslateT("Forward options"));
+
+ mir_sntprintf( szMsg, SIZEOF(szMsg), TranslateT("%d message(s) to be forwarded"), nUnreadEvents );
+ xNode << XCHILD( _T("instructions"), szMsg );
+
+ xNode << XCHILD( _T("field")) << XATTR( _T("type"), _T("hidden")) << XATTR( _T("var"), _T("FORM_TYPE"))
+ << XCHILD( _T("value"), _T(JABBER_FEAT_RC));
+
+ // remove clist events
+ xNode << XCHILD( _T("field")) << XATTR( _T("label"), TranslateT("Mark messages as read")) << XATTR( _T("type"), _T("boolean"))
+ << XATTR( _T("var"), _T("remove-clist-events")) << XCHILD( _T("value"),
+ m_options.RcMarkMessagesAsRead == 1 ? _T("1") : _T("0"));
+
+ m_ThreadInfo->send( iq );
+ return JABBER_ADHOC_HANDLER_STATUS_EXECUTING;
+ }
+
+ if ( pSession->GetStage() == 1 ) {
+ // result form here
+ HXML commandNode = pInfo->GetChildNode();
+ HXML xNode = xmlGetChildByTag( commandNode, "x", "xmlns", _T(JABBER_FEAT_DATA_FORMS));
+ if ( !xNode )
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+
+ HXML fieldNode, valueNode;
+
+ BOOL bRemoveCListEvents = TRUE;
+
+ // remove clist events
+ fieldNode = xmlGetChildByTag( xNode,"field", "var", _T("remove-clist-events"));
+ if ( fieldNode && (valueNode = xmlGetChild( fieldNode , "value" ))) {
+ if ( xmlGetText( valueNode ) && !_ttoi( xmlGetText( valueNode )) ) {
+ bRemoveCListEvents = FALSE;
+ }
+ }
+ m_options.RcMarkMessagesAsRead = bRemoveCListEvents ? 1 : 0;
+
+ int nEventsSent = 0;
+ HANDLE hContact = ( HANDLE ) db_find_first();
+ while ( hContact != NULL ) {
+ char* szProto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM ) hContact, 0 );
+ if ( szProto != NULL && !strcmp( szProto, m_szModuleName )) {
+ DBVARIANT dbv;
+ if ( !JGetStringT( hContact, "jid", &dbv )) {
+
+ HANDLE hDbEvent = (HANDLE)CallService( MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM)hContact, 0 );
+ while ( hDbEvent ) {
+ DBEVENTINFO dbei = { 0 };
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = CallService( MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0 );
+ if ( dbei.cbBlob != -1 ) {
+ dbei.pBlob = (PBYTE)mir_alloc( dbei.cbBlob + 1 );
+ int nGetTextResult = CallService( MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei );
+ if ( !nGetTextResult && dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_READ) && !(dbei.flags & DBEF_SENT)) {
+ TCHAR* szEventText = DbGetEventTextT( &dbei, CP_ACP );
+ if ( szEventText ) {
+ XmlNode msg( _T("message"));
+ msg << XATTR( _T("to"), pInfo->GetFrom()) << XATTRID( SerialNext())
+ << XCHILD( _T("body"), szEventText );
+
+ HXML addressesNode = msg << XCHILDNS( _T("addresses"), _T(JABBER_FEAT_EXT_ADDRESSING));
+ TCHAR szOFrom[ JABBER_MAX_JID_LEN ];
+ EnterCriticalSection( &m_csLastResourceMap );
+ TCHAR *szOResource = FindLastResourceByDbEvent( hDbEvent );
+ if ( szOResource )
+ mir_sntprintf( szOFrom, SIZEOF( szOFrom ), _T("%s/%s"), dbv.ptszVal, szOResource );
+ else
+ mir_sntprintf( szOFrom, SIZEOF( szOFrom ), _T("%s"), dbv.ptszVal );
+ LeaveCriticalSection( &m_csLastResourceMap );
+ addressesNode << XCHILD( _T("address")) << XATTR( _T("type"), _T("ofrom")) << XATTR( _T("jid"), szOFrom );
+ addressesNode << XCHILD( _T("address")) << XATTR( _T("type"), _T("oto")) << XATTR( _T("jid"), m_ThreadInfo->fullJID );
+
+ time_t ltime = ( time_t )dbei.timestamp;
+ struct tm *gmt = gmtime( <ime );
+ TCHAR stime[ 512 ];
+ wsprintf(stime, _T("%.4i-%.2i-%.2iT%.2i:%.2i:%.2iZ"), gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday,
+ gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
+ msg << XCHILDNS( _T("delay"), _T("urn:xmpp:delay")) << XATTR( _T("stamp"), stime );
+
+ m_ThreadInfo->send( msg );
+
+ nEventsSent++;
+
+ CallService( MS_DB_EVENT_MARKREAD, (WPARAM)hContact, (LPARAM)hDbEvent );
+ if ( bRemoveCListEvents )
+ CallService( MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)hDbEvent );
+
+ mir_free( szEventText );
+ }
+ }
+ mir_free( dbei.pBlob );
+ }
+ hDbEvent = (HANDLE)CallService( MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0 );
+ }
+ JFreeVariant( &dbv );
+ }
+ }
+ hContact = db_find_next(hContact);
+ }
+
+ mir_sntprintf( szMsg, SIZEOF(szMsg), TranslateT("%d message(s) forwarded"), nEventsSent );
+
+ m_ThreadInfo->send(
+ XmlNodeIq( _T("result"), pInfo )
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), _T(JABBER_FEAT_RC_FORWARD))
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("completed"))
+ << XCHILD( _T("note"), szMsg ) << XATTR( _T("type"), _T("info")));
+
+ return JABBER_ADHOC_HANDLER_STATUS_REMOVE_SESSION;
+ }
+
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+}
+
+typedef BOOL (WINAPI *LWS )( VOID );
+
+int CJabberProto::AdhocLockWSHandler( HXML, CJabberIqInfo* pInfo, CJabberAdhocSession* pSession )
+{
+ BOOL bOk = FALSE;
+ HMODULE hLibrary = LoadLibrary( _T("user32.dll"));
+ if ( hLibrary ) {
+ LWS pLws = (LWS)GetProcAddress( hLibrary, "LockWorkStation" );
+ if ( pLws )
+ bOk = pLws();
+ FreeLibrary( hLibrary );
+ }
+
+ TCHAR szMsg[ 1024 ];
+ if ( bOk )
+ mir_sntprintf( szMsg, SIZEOF(szMsg), TranslateT("Workstation successfully locked"));
+ else
+ mir_sntprintf( szMsg, SIZEOF(szMsg), TranslateT("Error %d occured during workstation lock"), GetLastError());
+
+ m_ThreadInfo->send(
+ XmlNodeIq( _T("result"), pInfo )
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), _T(JABBER_FEAT_RC_WS_LOCK))
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("completed"))
+ << XCHILD( _T("note"), szMsg ) << XATTR( _T("type"), bOk ? _T("info") : _T("error")));
+
+ return JABBER_ADHOC_HANDLER_STATUS_REMOVE_SESSION;
+}
+
+static void __stdcall JabberQuitMirandaIMThread( void* )
+{
+ CallService( "CloseAction", 0, 0 );
+}
+
+int CJabberProto::AdhocQuitMirandaHandler( HXML, CJabberIqInfo* pInfo, CJabberAdhocSession* pSession )
+{
+ if ( pSession->GetStage() == 0 ) {
+ // first form
+ pSession->SetStage( 1 );
+
+ XmlNodeIq iq( _T("result"), pInfo );
+ HXML xNode = iq
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), _T(JABBER_FEAT_RC_QUIT_MIRANDA))
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("executing"))
+ << XCHILDNS( _T("x"), _T(JABBER_FEAT_DATA_FORMS)) << XATTR( _T("type"), _T("form"));
+
+ xNode << XCHILD( _T("title"), TranslateT("Confirmation needed"));
+ xNode << XCHILD( _T("instructions"), TranslateT("Please confirm Miranda NG shutdown"));
+
+ xNode << XCHILD( _T("field")) << XATTR( _T("type"), _T("hidden")) << XATTR( _T("var"), _T("FORM_TYPE"))
+ << XCHILD( _T("value"), _T(JABBER_FEAT_RC));
+
+ // I Agree checkbox
+ xNode << XCHILD( _T("field")) << XATTR( _T("label"), _T("I agree")) << XATTR( _T("type"), _T("boolean"))
+ << XATTR( _T("var"), _T("allow-shutdown")) << XCHILD( _T("value"), _T("0"));
+
+ m_ThreadInfo->send( iq );
+ return JABBER_ADHOC_HANDLER_STATUS_EXECUTING;
+ }
+
+ if ( pSession->GetStage() == 1 ) {
+ // result form here
+ HXML commandNode = pInfo->GetChildNode();
+ HXML xNode = xmlGetChildByTag( commandNode, "x", "xmlns", _T(JABBER_FEAT_DATA_FORMS));
+ if ( !xNode )
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+
+ HXML fieldNode, valueNode;
+
+ // I Agree checkbox
+ fieldNode = xmlGetChildByTag( xNode,"field", "var", _T("allow-shutdown"));
+ if ( fieldNode && (valueNode = xmlGetChild( fieldNode , "value" )))
+ if ( xmlGetText( valueNode ) && _ttoi( xmlGetText( valueNode )))
+ CallFunctionAsync(JabberQuitMirandaIMThread, 0);
+
+ return JABBER_ADHOC_HANDLER_STATUS_COMPLETED;
+ }
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+}
+
+int CJabberProto::AdhocLeaveGroupchatsHandler( HXML, CJabberIqInfo* pInfo, CJabberAdhocSession* pSession )
+{
+ int i = 0;
+ if ( pSession->GetStage() == 0 ) {
+ // first form
+ TCHAR szMsg[ 1024 ];
+
+ ListLock();
+ int nChatsCount = 0;
+ LISTFOREACH_NODEF(i, this, LIST_CHATROOM)
+ {
+ JABBER_LIST_ITEM *item = ListGetItemPtrFromIndex( i );
+ if ( item != NULL )
+ nChatsCount++;
+ }
+ ListUnlock();
+
+ if ( !nChatsCount ) {
+ mir_sntprintf( szMsg, SIZEOF(szMsg), TranslateT("There is no groupchats to leave"));
+
+ m_ThreadInfo->send(
+ XmlNodeIq( _T("result"), pInfo )
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), _T(JABBER_FEAT_RC_LEAVE_GROUPCHATS))
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("completed"))
+ << XCHILD( _T("note"), szMsg ) << XATTR( _T("type"), _T("info")));
+
+ return JABBER_ADHOC_HANDLER_STATUS_REMOVE_SESSION;
+ }
+
+ pSession->SetStage( 1 );
+
+ XmlNodeIq iq( _T("result"), pInfo );
+ HXML xNode = iq
+ << XCHILDNS( _T("command"), _T(JABBER_FEAT_COMMANDS)) << XATTR( _T("node"), _T(JABBER_FEAT_RC_LEAVE_GROUPCHATS))
+ << XATTR( _T("sessionid"), pSession->GetSessionId()) << XATTR( _T("status"), _T("executing"))
+ << XCHILDNS( _T("x"), _T(JABBER_FEAT_DATA_FORMS)) << XATTR( _T("type"), _T("form"));
+
+ xNode << XCHILD( _T("title"), TranslateT("Leave groupchats"));
+ xNode << XCHILD( _T("instructions"), TranslateT("Choose the groupchats you want to leave"));
+
+ xNode << XCHILD( _T("field")) << XATTR( _T("type"), _T("hidden")) << XATTR( _T("var"), _T("FORM_TYPE"))
+ << XATTR( _T("value"), _T(JABBER_FEAT_RC));
+
+ // Groupchats
+ HXML fieldNode = xNode << XCHILD( _T("field")) << XATTR( _T("label"), NULL ) << XATTR( _T("type"), _T("list-multi")) << XATTR( _T("var"), _T("groupchats"));
+ fieldNode << XCHILD( _T("required"));
+
+ ListLock();
+ LISTFOREACH_NODEF(i, this, LIST_CHATROOM)
+ {
+ JABBER_LIST_ITEM *item = ListGetItemPtrFromIndex( i );
+ if ( item != NULL )
+ fieldNode << XCHILD( _T("option")) << XATTR( _T("label"), item->jid ) << XCHILD( _T("value"), item->jid );
+ }
+ ListUnlock();
+
+ m_ThreadInfo->send( iq );
+ return JABBER_ADHOC_HANDLER_STATUS_EXECUTING;
+ }
+
+ if ( pSession->GetStage() == 1 ) {
+ // result form here
+ HXML commandNode = pInfo->GetChildNode();
+ HXML xNode = xmlGetChildByTag( commandNode, "x", "xmlns", _T(JABBER_FEAT_DATA_FORMS));
+ if ( !xNode )
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+
+ // Groupchat list here:
+ HXML fieldNode = xmlGetChildByTag( xNode,"field", "var", _T("groupchats"));
+ if ( fieldNode ) {
+ for ( i = 0; i < xmlGetChildCount( fieldNode ); i++ ) {
+ HXML valueNode = xmlGetChild( fieldNode, i );
+ if ( valueNode && xmlGetName( valueNode ) && xmlGetText( valueNode ) && !_tcscmp( xmlGetName( valueNode ), _T("value"))) {
+ JABBER_LIST_ITEM* item = ListGetItemPtr( LIST_CHATROOM, xmlGetText( valueNode ));
+ if ( item )
+ GcQuit( item, 0, NULL );
+ }
+ }
+ }
+
+ return JABBER_ADHOC_HANDLER_STATUS_COMPLETED;
+ }
+ return JABBER_ADHOC_HANDLER_STATUS_CANCEL;
+}
\ No newline at end of file |