summaryrefslogtreecommitdiff
path: root/src/modules/protocols/protochains.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /src/modules/protocols/protochains.cpp
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'src/modules/protocols/protochains.cpp')
-rw-r--r--src/modules/protocols/protochains.cpp274
1 files changed, 274 insertions, 0 deletions
diff --git a/src/modules/protocols/protochains.cpp b/src/modules/protocols/protochains.cpp
new file mode 100644
index 0000000000..f7f3729806
--- /dev/null
+++ b/src/modules/protocols/protochains.cpp
@@ -0,0 +1,274 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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 "commonheaders.h"
+#include <m_protomod.h>
+
+//Protocol chain is list of integers "0".."n", with network protocol named "p"
+INT_PTR Proto_CallContactService(WPARAM wParam,LPARAM lParam)
+//note that this is ChainSend() too, due to a quirk of function definitions
+{
+ CCSDATA *ccs=(CCSDATA*)lParam;
+ int i;
+ char str[10];
+ DBVARIANT dbv;
+ INT_PTR ret;
+ PROTOACCOUNT* pa;
+
+ if ( wParam == (WPARAM)(-1))
+ return 1;
+
+ for ( i = wParam;; i++ ) {
+ _itoa( i, str, 10 );
+ if ( DBGetContactSettingString( ccs->hContact, "_Filter", str, &dbv ))
+ break;
+
+ if (( ret = CallProtoService( dbv.pszVal, ccs->szProtoService, i+1, lParam )) != CALLSERVICE_NOTFOUND ) {
+ //chain was started, exit
+ mir_free( dbv.pszVal );
+ return ret;
+ }
+ mir_free( dbv.pszVal );
+ }
+ if ( DBGetContactSettingString( ccs->hContact, "Protocol", "p", &dbv ))
+ return 1;
+
+ pa = Proto_GetAccount( dbv.pszVal );
+ if ( pa == NULL || pa->ppro == NULL )
+ ret = 1;
+ else {
+ if ( pa->bOldProto )
+ ret = CallProtoServiceInt( ccs->hContact, dbv.pszVal, ccs->szProtoService, (WPARAM)(-1), ( LPARAM)ccs );
+ else
+ ret = CallProtoServiceInt( ccs->hContact, dbv.pszVal, ccs->szProtoService, ccs->wParam, ccs->lParam );
+ if ( ret == CALLSERVICE_NOTFOUND )
+ ret = 1;
+ }
+
+ mir_free(dbv.pszVal);
+ return ret;
+}
+
+static INT_PTR CallRecvChain(WPARAM wParam,LPARAM lParam)
+{
+ CCSDATA *ccs=(CCSDATA*)lParam;
+ int i;
+ INT_PTR ret;
+ char str[10];
+ DBVARIANT dbv;
+ PROTOACCOUNT* pa;
+
+ if ( wParam == (WPARAM)(-1)) return 1; //shouldn't happen - sanity check
+ if ( wParam == 0 ) { //begin processing by finding end of chain
+ for( ;;wParam++ ) {
+ _itoa( wParam, str, 10 );
+ if ( DBGetContactSettingString( ccs->hContact, "_Filter", str, &dbv ))
+ break;
+ mir_free(dbv.pszVal);
+ }
+ }
+ else wParam--;
+
+ for ( i = wParam-1; i >= 0; i-- ) {
+ _itoa( i, str, 10 );
+ if ( DBGetContactSettingString( ccs->hContact, "_Filter", str, &dbv )) //never happens
+ return 1;
+
+ if (( ret = CallProtoService( dbv.pszVal, ccs->szProtoService, i+1, lParam )) != CALLSERVICE_NOTFOUND ) {
+ //chain was started, exit
+ mir_free( dbv.pszVal );
+ return ret;
+ }
+ mir_free( dbv.pszVal );
+ }
+
+ //end of chain, call network protocol again
+ if ( DBGetContactSettingString( ccs->hContact, "Protocol", "p", &dbv ))
+ return 1;
+
+ pa = Proto_GetAccount( dbv.pszVal );
+ if ( pa == NULL || pa->ppro == NULL )
+ ret = 1;
+ else {
+ if ( pa->bOldProto )
+ ret = CallProtoServiceInt( ccs->hContact, dbv.pszVal, ccs->szProtoService, (WPARAM)(-1), ( LPARAM)ccs );
+ else
+ ret = CallProtoServiceInt( ccs->hContact, dbv.pszVal, ccs->szProtoService, ccs->wParam, ccs->lParam );
+ if ( ret == CALLSERVICE_NOTFOUND )
+ ret = 1;
+ }
+
+ mir_free( dbv.pszVal );
+ return ret;
+}
+
+static INT_PTR Proto_ChainRecv(WPARAM wParam,LPARAM lParam)
+{
+ /* this will switch threads just like before */
+ return CallServiceSync(MS_PROTO_CHAINRECV "ThreadSafe",wParam,lParam);
+}
+
+PROTOACCOUNT* __fastcall Proto_GetAccount(HANDLE hContact)
+{
+ DBVARIANT dbv;
+ DBCONTACTGETSETTING dbcgs;
+ char name[32];
+
+ dbv.type = DBVT_ASCIIZ;
+ dbv.pszVal = name;
+ dbv.cchVal = SIZEOF(name);
+ dbcgs.pValue = &dbv;
+ dbcgs.szModule = "Protocol";
+ dbcgs.szSetting = "p";
+ if (CallService(MS_DB_CONTACT_GETSETTINGSTATIC, (WPARAM)hContact, (LPARAM)&dbcgs))
+ return 0;
+
+ return Proto_GetAccount((char* )dbv.pszVal);
+}
+
+static INT_PTR Proto_GetContactBaseProto(WPARAM wParam, LPARAM)
+{
+ PROTOACCOUNT* pa = Proto_GetAccount((HANDLE)wParam);
+ return (INT_PTR)(Proto_IsAccountEnabled( pa ) ? pa->szModuleName : NULL);
+}
+
+static INT_PTR Proto_GetContactBaseAccount(WPARAM wParam, LPARAM)
+{
+ PROTOACCOUNT* pa = Proto_GetAccount((HANDLE)wParam);
+ return (INT_PTR)(pa ? pa->szModuleName : NULL);
+}
+
+static INT_PTR Proto_IsProtoOnContact(WPARAM wParam,LPARAM lParam)
+{
+ int i;
+ char str[10];
+ DBVARIANT dbv;
+
+ if (!lParam) return 0;
+
+ if(!DBGetContactSettingString((HANDLE)wParam,"Protocol","p",&dbv)) {
+ if(!_stricmp((char*)lParam,dbv.pszVal)) {
+ mir_free(dbv.pszVal);
+ return -1;
+ }
+ mir_free(dbv.pszVal);
+ }
+ for(i=0;;i++) {
+ _itoa(i,str,10);
+ if(DBGetContactSettingString((HANDLE)wParam,"_Filter",str,&dbv)) break;
+ if(!strcmp((char*)lParam,dbv.pszVal)) {
+ mir_free(dbv.pszVal);
+ return i+1;
+ }
+ mir_free(dbv.pszVal);
+ }
+ return 0;
+}
+
+static INT_PTR Proto_AddToContact(WPARAM wParam,LPARAM lParam)
+{
+ PROTOCOLDESCRIPTOR *pd,*pdCompare;
+
+ pd = Proto_IsProtocolLoaded(( char* )lParam );
+ if ( pd == NULL ) {
+ PROTOACCOUNT* pa = Proto_GetAccount(( char* )lParam );
+ if ( pa ) {
+ DBWriteContactSettingString((HANDLE)wParam,"Protocol","p",(char*)lParam);
+ return 0;
+ }
+ return 1;
+ }
+
+ if ( pd->type == PROTOTYPE_PROTOCOL ) {
+ DBWriteContactSettingString((HANDLE)wParam,"Protocol","p",(char*)lParam);
+ return 0;
+ }
+ if(Proto_IsProtoOnContact(wParam,lParam)) return 1;
+ { /* v:0.3.3 + PROTO FILTERS ARE NOW KEPT IN THEIR OWN DB MODULE! */
+ int i;
+ char str[10],*lastProto;
+ DBVARIANT dbv;
+
+ for(i=0;;i++) {
+ _itoa(i,str,10);
+ if(DBGetContactSettingString((HANDLE)wParam,"_Filter",str,&dbv)) break;
+ pdCompare = Proto_IsProtocolLoaded(( char* )dbv.pszVal );
+ mir_free(dbv.pszVal);
+ if(pdCompare==NULL) continue;
+ if(pd->type > pdCompare->type) break;
+ }
+ //put the new module at position i
+ lastProto=mir_strdup((char*)lParam);
+ for(;;i++) {
+ _itoa(i,str,10);
+ if(DBGetContactSettingString((HANDLE)wParam,"_Filter",str,&dbv)) {
+ DBWriteContactSettingString((HANDLE)wParam,"_Filter",str,lastProto);
+ mir_free(lastProto);
+ break;
+ }
+ DBWriteContactSettingString((HANDLE)wParam,"_Filter",str,lastProto);
+ mir_free(lastProto);
+ lastProto=dbv.pszVal;
+ }
+ }
+ return 0;
+}
+
+static INT_PTR Proto_RemoveFromContact(WPARAM wParam,LPARAM lParam)
+{
+ int i;
+ DBVARIANT dbv;
+ char str[10];
+
+ i = Proto_IsProtoOnContact(wParam,lParam);
+ if(!i) return 1;
+ if(i==-1)
+ DBDeleteContactSetting((HANDLE)wParam,"Protocol","p");
+ else {
+ for(i--;;i++) { //we have to decrease i, as Proto_IsOnContact returns +1 more number than read from database
+ _itoa(i+1,str,10);
+ if(0!=DBGetContactSettingString((HANDLE)wParam,"_Filter",str,&dbv)) {
+ _itoa(i,str,10);
+ DBDeleteContactSetting((HANDLE)wParam,"_Filter",str);
+ break;
+ }
+ _itoa(i,str,10);
+ DBWriteContactSettingString((HANDLE)wParam,"_Filter",str,dbv.pszVal);
+ mir_free(dbv.pszVal);
+ }
+ }
+ return 0;
+}
+
+int LoadProtoChains(void)
+{
+ CreateServiceFunction(MS_PROTO_CALLCONTACTSERVICE,Proto_CallContactService);
+ CreateServiceFunction(MS_PROTO_CHAINSEND,Proto_CallContactService);
+ CreateServiceFunction(MS_PROTO_CHAINRECV,Proto_ChainRecv);
+ CreateServiceFunction(MS_PROTO_CHAINRECV "ThreadSafe",CallRecvChain);
+ CreateServiceFunction(MS_PROTO_GETCONTACTBASEPROTO,Proto_GetContactBaseProto);
+ CreateServiceFunction(MS_PROTO_GETCONTACTBASEACCOUNT,Proto_GetContactBaseAccount);
+ CreateServiceFunction(MS_PROTO_ISPROTOONCONTACT,Proto_IsProtoOnContact);
+ CreateServiceFunction(MS_PROTO_ADDTOCONTACT,Proto_AddToContact);
+ CreateServiceFunction(MS_PROTO_REMOVEFROMCONTACT,Proto_RemoveFromContact);
+ return 0;
+}