diff options
Diffstat (limited to 'plugins/CmdLine/src/mimcmd_handlers.cpp')
| -rw-r--r-- | plugins/CmdLine/src/mimcmd_handlers.cpp | 2307 | 
1 files changed, 2307 insertions, 0 deletions
diff --git a/plugins/CmdLine/src/mimcmd_handlers.cpp b/plugins/CmdLine/src/mimcmd_handlers.cpp new file mode 100644 index 0000000000..9b2d89b696 --- /dev/null +++ b/plugins/CmdLine/src/mimcmd_handlers.cpp @@ -0,0 +1,2307 @@ +/*
 +CmdLine plugin for Miranda IM
 +
 +Copyright © 2007 Cristian Libotean
 +
 +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"
 +
 +#define STATE_UNKNOWN -1
 +#define STATE_OFF      0
 +#define STATE_ON       1
 +#define STATE_TOGGLE   2
 +
 +#define PROXY_SOCKS4   1
 +#define PROXY_SOCKS5   2
 +#define PROXY_HTTP     3
 +#define PROXY_HTTPS    4
 +
 +#define VALUE_UNKNOWN -1
 +#define VALUE_ERROR    0
 +#define VALUE_BYTE     1
 +#define VALUE_WORD     2
 +#define VALUE_DWORD    3
 +#define VALUE_STRING   4
 +#define VALUE_WIDE     5
 +
 +__inline static int matches(char *command, char *lower)
 +{
 +	return ((strcmp(lower, command) == 0) || (strcmp(lower, Translate(command)) == 0));
 +}
 +
 +int Get2StateValue(char *state)
 +{
 +	char lower[512];
 +	STRNCPY(lower, state, sizeof(lower));
 +	_strlwr(lower);
 +	
 +	//if ((strcmp(lower, "enable") == 0) || (strcmp(lower, "show") == 0) || (strcmp(lower, "on") == 0))
 +	if ((matches("enable", lower)) || (matches("show", lower)) || (matches("on", lower)))
 +	{
 +		return STATE_ON;
 +	}
 +	
 +	//if ((strcmp(lower, "disable") == 0) || (strcmp(lower, "hide") == 0) || (strcmp(lower, "off") == 0))
 +	if ((matches("disable", lower)) || (matches("hide", lower)) || (matches("off", lower)))
 +	{
 +		return STATE_OFF;
 +	}
 +	
 +	//if (strcmp(lower, "toggle") == 0)
 +	if (matches("toggle", lower))
 +	{
 +		return STATE_TOGGLE;
 +	}
 +	
 +	return STATE_UNKNOWN;
 +}
 +
 +int AccountName2Protocol(const char *accountName, OUT char *uniqueProtocolName, size_t length)
 +{
 +	int count;
 +	PROTOACCOUNT **accounts = NULL;
 +
 +	ProtoEnumAccounts(&count, &accounts);
 +
 +	STRNCPY(uniqueProtocolName, accountName, length);
 +
 +	for (int i = 0; i < count; i++)
 +	{
 +		if (accounts[i]->bIsEnabled)
 +		{
 +			if (_stricmp(accountName, accounts[i]->tszAccountName) == 0)
 +			{
 +				STRNCPY(uniqueProtocolName, accounts[i]->szModuleName, length);
 +
 +				return 0;
 +			}
 +
 +			//the account name may be unicode, try comparing with an unicode string too
 +			char *account = mir_u2a((wchar_t *) accounts[i]->tszAccountName);
 +			if (_stricmp(accountName, account) == 0)
 +			{
 +				STRNCPY(uniqueProtocolName, accounts[i]->szModuleName, length);
 +
 +				mir_free(account);
 +				return 0;
 +			}
 +
 +			mir_free(account);
 +		}
 +	}
 +
 +	return 1;
 +}
 +
 +void HandleCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	switch (command->ID)
 +	{
 +		case MIMCMD_STATUS:
 +		{
 +			HandleStatusCommand(command, argv, argc, reply);
 +		
 +			break;
 +		}
 +		
 +		case MIMCMD_AWAYMSG:
 +		{
 +			HandleAwayMsgCommand(command, argv, argc, reply);
 +		
 +			break;
 +		}
 +		//
 +		//case MIMCMD_XSTATUS:
 +		//{
 +		//
 +		//	break;
 +		//}
 +		
 +		case MIMCMD_POPUPS:
 +		{
 +			HandlePopupsCommand(command, argv, argc, reply);
 +			
 +			break;
 +		}
 +		
 +		case MIMCMD_SOUNDS:
 +		{
 +			HandleSoundsCommand(command, argv, argc, reply);
 +			
 +			break;
 +		}
 +		
 +		case MIMCMD_CLIST:
 +		{
 +			HandleClistCommand(command, argv, argc, reply);
 +		
 +			break;
 +		}
 +		
 +		case MIMCMD_QUIT:
 +		{
 +			HandleQuitCommand(command, argv, argc, reply);
 +		
 +			break;
 +		}
 +		
 +		case MIMCMD_EXCHANGE:
 +		{
 +			HandleExchangeCommand(command, argv, argc, reply);
 +			
 +			break;
 +		}
 +		
 +		case MIMCMD_YAMN:
 +		{
 +			HandleYAMNCommand(command, argv, argc, reply);
 +			
 +			break;
 +		}
 +		
 +		case MIMCMD_CALLSERVICE:
 +		{
 +			HandleCallServiceCommand(command, argv, argc, reply);
 +		
 +			break;
 +		}
 +		
 +		case MIMCMD_MESSAGE:
 +		{
 +			HandleMessageCommand(command, argv, argc, reply);
 +		
 +			break;
 +		}
 +		
 +		case MIMCMD_DATABASE:
 +		{
 +			HandleDatabaseCommand(command, argv, argc, reply);
 +		
 +			break;
 +		}
 +		
 +		case MIMCMD_PROXY:
 +		{
 +			HandleProxyCommand(command, argv, argc, reply);
 +			
 +			break;
 +		}
 +		
 +		case MIMCMD_CONTACTS:
 +		{
 +			HandleContactsCommand(command, argv, argc, reply);
 +		
 +			break;
 +		}
 +		
 +		case MIMCMD_HISTORY:
 +		{
 +			HandleHistoryCommand(command, argv, argc, reply);
 +			
 +			break;
 +		}
 +		
 +		case MIMCMD_VERSION:
 +		{
 +			HandleVersionCommand(command, argv, argc, reply);
 +			
 +			break;
 +		}
 +
 +		case MIMCMD_SETNICKNAME:
 +		{
 +			HandleSetNicknameCommand(command, argv, argc, reply);
 +
 +			break;
 +		}
 +
 +		case MIMCMD_IGNORE:
 +		{
 +			HandleIgnoreCommand(command, argv, argc, reply);
 +
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			reply->code = MIMRES_NOTFOUND;
 +			mir_snprintf(reply->message, reply->cMessage, Translate("Command '%s' is not currently supported."), command->command);
 +			
 +			break;
 +		}
 +	}
 +}
 +
 +void HandleWrongParametersCount(PCommand command, PReply reply)
 +{
 +	reply->code = MIMRES_WRONGPARAMSCOUNT;
 +	mir_snprintf(reply->message, reply->cMessage, Translate("Wrong number of parameters for command '%s'."), command->command);
 +}
 +
 +void HandleUnknownParameter(PCommand command, char *param, PReply reply)
 +{
 +	reply->code = MIMRES_UNKNOWNPARAM;
 +	mir_snprintf(reply->message, reply->cMessage, Translate("Unknown parameter '%s' for command '%s'."), param, command->command);
 +}
 +
 +int ParseValueParam(char *param, void *&result)
 +{
 +	int ok = VALUE_UNKNOWN;
 +	if (strlen(param) > 0)
 +	{
 +		switch (*param)
 +		{
 +			case 's':
 +			{
 +				size_t len = strlen(param); //- 1 + 1
 +				result = (char *) malloc(len * sizeof(char));
 +				STRNCPY((char *) result, param + 1, len);
 +				((char *) result)[len - 1] = 0;
 +				
 +				ok = VALUE_STRING;
 +				
 +				break;
 +			}
 +			
 +			case 'w':
 +			{
 +				size_t len = strlen(param);
 +				result = (WCHAR *) malloc(len * sizeof(WCHAR));
 +				char *buffer = (char *) malloc(len * sizeof(WCHAR));
 +				STRNCPY(buffer, param + 1, len);
 +				
 +				MultiByteToWideChar(CP_ACP, 0, buffer, -1, (WCHAR *) result, (int) len);
 +				
 +				free(buffer);
 +				
 +				ok = VALUE_WIDE;
 +				
 +				break;
 +			}
 +
 +			case 'b':
 +			{
 +				result = (char *) malloc(sizeof(char));
 +				long tmp;
 +				char *stop;
 +				
 +				tmp = strtol(param + 1, &stop, 10);
 +				* ((char *) result) = tmp;
 +				
 +				ok = (*stop == 0) ? VALUE_BYTE : VALUE_ERROR;
 +				
 +				break;
 +			}
 +
 +			case 'i':
 +			{
 +				result = (int *) malloc(sizeof(int));
 +				long tmp;
 +				char *stop;
 +				
 +				tmp = strtol(param + 1, &stop, 10);
 +				* ((int *) result) = tmp;
 +				
 +				ok = (*stop == 0) ? VALUE_WORD : VALUE_ERROR;
 +				
 +				break;
 +			}
 +
 +			case 'd':
 +			{
 +				result = (long *) malloc(sizeof(long));
 +				char *stop;
 +				* ((long *) result) = strtol(param + 1, &stop, 10);
 +				
 +				ok = (*stop == 0) ? VALUE_DWORD : VALUE_ERROR;
 +			
 +				break;
 +			}
 +		}
 +	}
 +	
 +	return ok;
 +}
 +
 +int ParseStatusParam(char *status)
 +{
 +	int res = 0;
 +	char lower[256];
 +	STRNCPY(lower, status, sizeof(lower));
 +
 +	if (strcmp(lower, "offline") == 0)
 +	{
 +		res = ID_STATUS_OFFLINE;
 +	}
 +	else{
 +		if (strcmp(lower, "online") == 0)
 +		{
 +			res = ID_STATUS_ONLINE;
 +		}
 +		else{
 +			if (strcmp(lower, "away") == 0)
 +			{
 +				res = ID_STATUS_AWAY;
 +			}
 +			else{
 +				if (strcmp(lower, "dnd") == 0)
 +				{
 +					res = ID_STATUS_DND;
 +				}
 +				else{
 +					if (strcmp(lower, "na") == 0)
 +					{
 +						res = ID_STATUS_NA;
 +					}
 +					else{
 +						if (strcmp(lower, "occupied") == 0)
 +						{
 +							res = ID_STATUS_OCCUPIED;
 +						}
 +						else{
 +							if (strcmp(lower, "freechat") == 0)
 +							{
 +								res = ID_STATUS_FREECHAT;
 +							}
 +							else{
 +								if (strcmp(lower, "invisible") == 0)
 +								{
 +									res = ID_STATUS_INVISIBLE;
 +								}
 +								else{
 +									if (strcmp(lower, "onthephone") == 0)
 +									{
 +										res = ID_STATUS_ONTHEPHONE;
 +									}
 +									else{
 +										if (strcmp(lower, "outtolunch") == 0)
 +										{
 +											res = ID_STATUS_OUTTOLUNCH;
 +										}//outtolunch
 +									}//onthephone
 +								}//invisible
 +							}//freechat
 +						}//occupied
 +					}//na
 +				} //dnd
 +			} //away
 +		} //online
 +	}	//offline
 +
 +	return res;	
 +}
 +
 +char *PrettyStatusMode(int status, char *buffer, int size)
 +{
 +	*buffer = 0;
 +	char *data = (char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, status, 0);
 +	if (data)
 +	{
 +		STRNCPY(buffer, data, size);
 +	}
 +
 +	return buffer;
 +}
 +
 +void HandleStatusCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	switch (argc)
 +	{
 +		case 2:
 +		{
 +			INT_PTR status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0);
 +			char pretty[128];
 +			PrettyStatusMode(status, pretty, sizeof(pretty));
 +			
 +			const int cPerAccountStatus = 1024 * 5;
 +			char *perAccountStatus = (char *) malloc(cPerAccountStatus);
 +
 +			perAccountStatus[0] = 0;
 +
 +			int count;
 +			PROTOACCOUNT **accounts = NULL;
 +
 +			char pn[128];
 +
 +			ProtoEnumAccounts(&count, &accounts);
 +
 +			for (int i = 0; i < count; i++)
 +			{
 +				if (accounts[i]->bIsEnabled)
 +				{
 +					INT_PTR status = CallProtoService(accounts[i]->szModuleName, PS_GETSTATUS, 0, 0);
 +					PrettyStatusMode(status, pn, sizeof(pn));
 +
 +					strncat(perAccountStatus, "\n", cPerAccountStatus);
 +
 +					char *account = mir_u2a((wchar_t *) accounts[i]->tszAccountName);
 +					strncat(perAccountStatus, account, cPerAccountStatus);
 +					mir_free(account);
 +
 +					strncat(perAccountStatus, ": ", cPerAccountStatus);
 +					strncat(perAccountStatus, pn, cPerAccountStatus);
 +				}
 +			}
 +
 +			reply->code = MIMRES_SUCCESS;
 +			mir_snprintf(reply->message, reply->cMessage, Translate("Current global status: %s.%s"), pretty, perAccountStatus);
 +
 +			free(perAccountStatus);
 +
 +			break;
 +		}
 +	
 +		case 3:
 +		{
 +			int status = ParseStatusParam(argv[2]);
 +			if (status)
 +			{
 +				INT_PTR old = CallService(MS_CLIST_GETSTATUSMODE, 0, 0);
 +				char po[128];
 +				if (ServiceExists(MS_KS_ANNOUNCESTATUSCHANGE))
 +				{
 +					announce_status_change(NULL, status, NULL);
 +				}
 +				
 +				PrettyStatusMode(old, po, sizeof(po));
 +				CallService(MS_CLIST_SETSTATUSMODE, status, 0);
 +				char pn[128];
 +				PrettyStatusMode(status, pn, sizeof(pn));
 +				
 +				reply->code = MIMRES_SUCCESS;
 +				mir_snprintf(reply->message, reply->cMessage, Translate("Changed global status to '%s' (previous status was '%s')."), pn, po);
 +			}
 +			else{
 +				HandleUnknownParameter(command, argv[2], reply);
 +			}
 +			
 +			break;
 +		}
 +		
 +		case 4:
 +		{
 +			int status = ParseStatusParam(argv[2]);
 +			if (status)
 +			{
 +				char protocol[128];
 +				char *account = argv[3];
 +				AccountName2Protocol(account, protocol, sizeof(protocol));
 +
 +				INT_PTR old = CallProtoService(protocol, PS_GETSTATUS, 0, 0);
 +				char po[128];
 +				if (ServiceExists(MS_KS_ANNOUNCESTATUSCHANGE))
 +				{
 +					announce_status_change(protocol, status, NULL);
 +				}
 +				
 +				PrettyStatusMode(old, po, sizeof(po));
 +				INT_PTR res = CallProtoService(protocol, PS_SETSTATUS, status, 0);
 +				char pn[128];
 +				PrettyStatusMode(status, pn, sizeof(pn));
 +				
 +				switch (res)
 +				{
 +					case 0:
 +					{
 +						reply->code = MIMRES_SUCCESS;
 +						mir_snprintf(reply->message, reply->cMessage, Translate("Changed '%s' status to '%s' (previous status was '%s')."), account, pn, po);
 +						
 +						break;
 +					}
 +					
 +					case CALLSERVICE_NOTFOUND:
 +					{
 +						reply->code = MIMRES_FAILURE;
 +						mir_snprintf(reply->message, reply->cMessage, Translate("'%s' doesn't seem to be a valid account."), account);
 +					
 +						break;
 +					}
 +					
 +					default:
 +					{
 +						reply->code = MIMRES_FAILURE;
 +						mir_snprintf(reply->message, reply->cMessage, Translate("Failed to change status for account '%s' to '%s'."), account, pn);
 +						
 +						break;
 +					}
 +				}
 +			}
 +			else{
 +				HandleUnknownParameter(command, argv[2], reply);
 +			}
 +		
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			HandleWrongParametersCount(command, reply);
 +			
 +			break;
 +		}
 +	}
 +}
 +
 +void GetProtocols(int *count, PROTOCOLDESCRIPTOR ***protocols)
 +{
 +	CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM) count, (LPARAM) protocols);
 +}
 +
 +void HandleAwayMsgCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	switch (argc)
 +	{
 +		case 3:
 +		{
 +			char *awayMsg = argv[2];
 +			int count = 0;
 +			PROTOACCOUNT **accounts = NULL;
 +			ProtoEnumAccounts(&count, &accounts);
 +			
 +			int i;
 +			INT_PTR status;
 +			INT_PTR res = 0;
 +			char *protocol;
 +			char buffer[1024];
 +			char pn[128];
 +			for (i = 0; i < count; i++)
 +			{
 +				if (accounts[i]->bIsEnabled)
 +				{
 +					protocol = accounts[i]->szModuleName;
 +					if ((CallProtoService(protocol, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) != 0) //if the protocol supports away messages
 +					{
 +						status = CallProtoService(protocol, PS_GETSTATUS, 0, 0);
 +						res = CallProtoService(protocol, PS_SETAWAYMSG, status, (LPARAM) awayMsg);
 +						PrettyStatusMode(status, pn, sizeof(pn));
 +						if (res)
 +						{
 +							mir_snprintf(buffer, sizeof(buffer), Translate("Failed to set '%S' status message to '%s' (status is '%s')."), accounts[i]->tszAccountName , awayMsg, pn);
 +						}
 +						else{
 +							mir_snprintf(buffer, sizeof(buffer), Translate("Successfully set '%S' status message to '%s' (status is '%s')."), accounts[i]->tszAccountName, awayMsg, pn);
 +						}
 +					}
 +					else{
 +						mir_snprintf(buffer, sizeof(buffer), Translate("Account '%S' does not support away messages, skipping."), accounts[i]->tszAccountName);
 +					}
 +					
 +					if (i != 0)
 +					{
 +						strncat(reply->message, "\n", reply->cMessage);
 +						strncat(reply->message, buffer, reply->cMessage);
 +					}
 +					else{
 +						STRNCPY(reply->message, buffer, reply->cMessage);
 +					}
 +				}
 +			}
 +			reply->code = MIMRES_SUCCESS;
 +			
 +			break;
 +		}
 +		
 +		case 4:
 +		{
 +			char *awayMsg = argv[2];
 +			char protocol[128];
 +			char *account = argv[3];
 +			AccountName2Protocol(account, protocol, sizeof(protocol));
 +			
 +			INT_PTR res = 0;
 +			char pn[128];
 +			if ((res = CallProtoService(protocol, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) != 0) //if the protocol supports away messages
 +			{
 +				INT_PTR status = CallProtoService(protocol, PS_GETSTATUS, 0, 0);
 +				res = CallProtoService(protocol, PS_SETAWAYMSG, status, (LPARAM) awayMsg);
 +
 +				PrettyStatusMode(status, pn, sizeof(pn));
 +			}
 +			else{
 +				if (CallProtoService(protocol, PS_GETSTATUS, 0, 0) == CALLSERVICE_NOTFOUND)
 +				{
 +					res = CALLSERVICE_NOTFOUND;
 +				}
 +				else {
 +					res = -2;
 +				}
 +			}
 +			
 +			switch (res)
 +			{
 +				case 0:
 +				{
 +					reply->code = MIMRES_SUCCESS;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("Changed '%s' status message to '%s' (status is '%s')."), account, awayMsg, pn);
 +					
 +					break;
 +				}
 +				
 +				case CALLSERVICE_NOTFOUND:
 +				{
 +					reply->code = MIMRES_FAILURE;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("'%s' doesn't seem to be a valid account."), account);
 +				
 +					break;
 +				}
 +				
 +				case -2:
 +				{
 +					reply->code = MIMRES_FAILURE;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("Account '%s' does not support away messages, skipping."), account);
 +					
 +					break;
 +				}
 +				
 +				default:
 +				{
 +					reply->code = MIMRES_FAILURE;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("Failed to change status message for account '%s' to '%s' (status is '%s')."), account, awayMsg, pn);
 +					
 +					break;
 +				}
 +			}			
 +		
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			HandleWrongParametersCount(command, reply);
 +			
 +			break;
 +		}
 +	}
 +}
 +
 +void Set2StateReply(PReply reply, int state, int failure, char *successTrue, char *failureTrue, char *successFalse, char *failureFalse)
 +{
 +	if (state)
 +	{
 +		if (failure)
 +		{
 +			reply->code = MIMRES_FAILURE;
 +			mir_snprintf(reply->message, reply->cMessage, Translate(failureTrue));
 +		}
 +		else{
 +			reply->code = MIMRES_SUCCESS;
 +			mir_snprintf(reply->message, reply->cMessage, Translate(successTrue));
 +		}
 +	}
 +	else{
 +		if (failure)
 +		{
 +			reply->code = MIMRES_FAILURE;
 +			mir_snprintf(reply->message, reply->cMessage, Translate(failureFalse));
 +		}
 +		else{
 +			reply->code = MIMRES_SUCCESS;
 +			mir_snprintf(reply->message, reply->cMessage, Translate(successFalse));
 +		}
 +	}
 +}
 +
 +void HandlePopupsCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	switch (argc)
 +	{
 +		case 2:
 +		{
 +			int state = CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0);
 +			Set2StateReply(reply,  state, 0, "Popups are currently enabled.", "", "Popups are currently disabled.", "");
 +			
 +			break;
 +		}
 +			
 +		case 3:
 +		{
 +			int failure;
 +			int state = 0;
 +			int error = 0;
 +			
 +			switch (Get2StateValue(argv[2]))
 +			{
 +				case STATE_ON:
 +				{
 +					failure = CallService(MS_POPUP_QUERY, PUQS_ENABLEPOPUPS, 0);
 +					state = TRUE;
 +				
 +					break;
 +				}
 +				
 +				case STATE_OFF:
 +				{
 +					failure = CallService(MS_POPUP_QUERY, PUQS_DISABLEPOPUPS, 0);
 +					state = FALSE;
 +				
 +					break;
 +				}
 +				
 +				case STATE_TOGGLE:
 +				{
 +					int state = CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0);
 +					failure = CallService(MS_POPUP_QUERY, (state) ? PUQS_DISABLEPOPUPS : PUQS_ENABLEPOPUPS, 0);
 +					state = 1 - state;
 +				
 +					break;
 +				}
 +				
 +				default:
 +				{
 +					HandleUnknownParameter(command, argv[2], reply);
 +					error = 1;
 +					
 +					break;
 +				}
 +			}
 +			if (!error)
 +			{
 +				Set2StateReply(reply, state, failure, "Popups were enabled successfully.", "Popups could not be enabled.", "Popups were disabled successfully.", "Popups could not be disabled.");
 +			}
 +			
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			HandleWrongParametersCount(command, reply);
 +			
 +			break;
 +		}
 +	
 +	}
 +}
 +
 +void HandleSoundsCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	switch (argc)
 +	{
 +		case 2:
 +		{
 +			int state = CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0);
 +			Set2StateReply(reply,  state, 0, "Sounds are currently enabled.", "", "Sounds are currently disabled.", "");
 +			
 +			break;
 +		}
 +			
 +		case 3:
 +		{
 +			int failure;
 +			int state = 0;
 +			int error = 0;
 +			
 +			switch (Get2StateValue(argv[2]))
 +			{
 +				case STATE_ON:
 +				{
 +					failure = 0;
 +					DBWriteContactSettingByte(NULL, "Skin", "UseSound", 1);
 +					state = TRUE;
 +				
 +					break;
 +				}
 +				
 +				case STATE_OFF:
 +				{
 +					failure = 0;
 +					DBWriteContactSettingByte(NULL, "Skin", "UseSound", 0);
 +					state = FALSE;
 +				
 +					break;
 +				}
 +				
 +				case STATE_TOGGLE:
 +				{
 +					state = DBGetContactSettingByte(NULL, "Skin", "UseSound", 1);
 +					
 +					failure = 0;
 +					state = 1 - state;
 +					DBWriteContactSettingByte(NULL, "Skin", "UseSound", state);
 +				
 +					break;
 +				}
 +				
 +				default:
 +				{
 +					HandleUnknownParameter(command, argv[2], reply);
 +					error = 1;
 +					
 +					break;
 +				}
 +			}
 +			if (!error)
 +			{
 +				Set2StateReply(reply, state, failure, "Sounds were enabled successfully.", "Sounds could not be enabled.", "Sounds were disabled successfully.", "Sounds could not be disabled.");
 +			}
 +			
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			HandleWrongParametersCount(command, reply);
 +			
 +			break;
 +		}
 +	}
 +}
 +
 +void HandleClistCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	switch (argc)
 +	{
 +		case 2:
 +		{
 +			HWND hClist = (HWND) CallService(MS_CLUI_GETHWND, 0, 0);
 +			int state = IsWindowVisible(hClist);
 +			Set2StateReply(reply,  state, 0, "Contact list is currectly shown.", "", "Contact list is currently hidden.", "");
 +			
 +			break;
 +		}
 +	
 +		case 3:
 +		{
 +			int failure;
 +			int state = 0;
 +			int error = 0;
 +			HWND hClist = (HWND) CallService(MS_CLUI_GETHWND, 0, 0);
 +			
 +			switch (Get2StateValue(argv[2]))
 +			{
 +				case STATE_ON:
 +				{
 +					failure = 0;
 +					ShowWindow(hClist, SW_SHOW);
 +					
 +					state = TRUE;
 +				
 +					break;
 +				}
 +				
 +				case STATE_OFF:
 +				{
 +					failure = 0;
 +					ShowWindow(hClist, SW_HIDE);
 +					state = FALSE;
 +				
 +					break;
 +				}
 +				
 +				case STATE_TOGGLE:
 +				{
 +					state = IsWindowVisible(hClist);
 +					
 +					failure = 0;
 +					state = 1 - state;
 +					ShowWindow(hClist, (state) ? SW_SHOW : SW_HIDE);
 +				
 +					break;
 +				}
 +				
 +				default:
 +				{
 +					HandleUnknownParameter(command, argv[2], reply);
 +					error = 1;
 +					
 +					break;
 +				}
 +			}
 +			if (!error)
 +			{
 +				Set2StateReply(reply, state, failure, "Contact list was shown successfully.", "Contact list could not be shown.", "Contact list was hidden successfully.", "Contact list could not be hidden.");
 +			}
 +			
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			HandleWrongParametersCount(command, reply);
 +			
 +			break;
 +		}
 +	}
 +}
 +
 +void HandleQuitCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	switch (argc)
 +	{
 +		case 2:
 +		{
 +			CallService("CloseAction", 0, 0);
 +			
 +			//try another quit method
 +			HWND hWndMiranda = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
 +			PostMessage(hWndMiranda, WM_COMMAND, ID_ICQ_EXIT, 0);
 +			
 +			reply->code = MIMRES_SUCCESS;
 +			mir_snprintf(reply->message, reply->cMessage, "Issued a quit command.");
 +		
 +			break;
 +		}
 +		
 +		case 3:
 +		{
 +			char lower[128];
 +			STRNCPY(lower, argv[2], sizeof(lower));
 +			_strlwr(lower);
 +			
 +			if (strcmp(lower, "wait") == 0)
 +			{
 +				CallService("CloseAction", 0, 0);
 +				
 +				//try another quit method
 +				HWND hWndMiranda = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
 +				PostMessage(hWndMiranda, WM_COMMAND, ID_ICQ_EXIT, 0);
 +				
 +				reply->code = MIMRES_SUCCESS;
 +				mir_snprintf(reply->message, reply->cMessage, "Issued a quit and wait command.");
 +				
 +				SetEvent(heServerBufferFull);
 +				
 +				bWaitForUnload = 1;
 +				
 +				while (bWaitForUnload)
 +				{
 +					Sleep(250); //wait for Miranda to quit.
 +				}
 +			}
 +			else{
 +				HandleUnknownParameter(command, argv[2], reply);
 +			}
 +			
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			HandleWrongParametersCount(command, reply);
 +			
 +			break;
 +		}
 +	}
 +}
 +
 +void HandleExchangeCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	switch (argc)
 +	{
 +		case 3:
 +		{
 +			char lower[128];
 +			STRNCPY(lower, argv[2], sizeof(lower));
 +			_strlwr(lower);
 +			if (strcmp(lower, "check") == 0)
 +			{
 +				if (ServiceExists(MS_EXCHANGE_CHECKEMAIL))
 +				{
 +					CallService(MS_EXCHANGE_CHECKEMAIL, 0, 0);
 +					
 +					reply->code = MIMRES_SUCCESS;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("Issued check email command to Exchange plugin."));
 +				}
 +				else{
 +					reply->code = MIMRES_FAILURE;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("Exchange plugin is not running."));
 +				}
 +			}
 +			else{
 +				HandleUnknownParameter(command, argv[2], reply);
 +			}
 +		
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			HandleWrongParametersCount(command, reply);
 +		
 +			break;
 +		}
 +		
 +	}
 +}
 +
 +void HandleYAMNCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	switch (argc)
 +	{
 +		case 3:
 +		{
 +			char lower[128];
 +			STRNCPY(lower, argv[2], sizeof(lower));
 +			_strlwr(lower);
 +			if (strcmp(lower, "check") == 0)
 +			{
 +				if (ServiceExists(MS_YAMN_FORCECHECK))
 +				{
 +					CallService(MS_YAMN_FORCECHECK, 0, 0);
 +					
 +					reply->code = MIMRES_SUCCESS;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("Issued check email command to YAMN plugin."));
 +				}
 +				else{
 +					reply->code = MIMRES_FAILURE;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("YAMN plugin is not running."));
 +				}
 +			}
 +			else{
 +				HandleUnknownParameter(command, argv[2], reply);
 +			}
 +		
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			HandleWrongParametersCount(command, reply);
 +		
 +			break;
 +		}
 +		
 +	}
 +}
 +
 +void HandleCallServiceCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	switch (argc)
 +	{
 +		case 5:
 +		{
 +			char *service = argv[2];
 +			if (ServiceExists(service))
 +			{
 +				void *wParam = NULL;
 +				void *lParam = NULL;
 +				INT_PTR res1 = ParseValueParam(argv[3], wParam);
 +				INT_PTR res2 = ParseValueParam(argv[4], lParam);
 +				if ((res1 != 0) && (res2 != 0))
 +				{
 +					//very dangerous but the user asked
 +					INT_PTR res = CallService(service, ((res1 == 1) ? *((long *) wParam) : (WPARAM) wParam), (LPARAM) ((res2 == 1) ? *((long *) lParam) : (LPARAM) lParam));
 +					
 +					reply->code = MIMRES_SUCCESS;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("CallService call successful: service '%s' returned %p."), service, res);
 +				}
 +				else{
 +					reply->code = MIMRES_FAILURE;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("Invalid parameter '%s' passed to CallService command."), (wParam) ? argv[4] : argv[3]);
 +				}
 +				
 +				if (wParam) { free(wParam); }
 +				if (lParam) { free(lParam); }
 +				
 +			}
 +			else{
 +				reply->code = MIMRES_FAILURE;
 +				mir_snprintf(reply->message, reply->cMessage, Translate("Service '%s' does not exist."), service);
 +			}
 +			
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			HandleWrongParametersCount(command, reply);
 +		}
 +	}
 +}
 +
 +
 +HANDLE ParseContactParam(char *contact)
 +{
 +	char name[512];
 +	char account[128];
 +	char protocol[128];
 +	char *p = strrchr(contact, ':');
 +	HANDLE hContact = NULL;
 +	if (p)
 +	{
 +		*p = 0;
 +		STRNCPY(name, contact, p - contact + 1);
 +		STRNCPY(account, p + 1, sizeof(account));
 +		*p = ':';
 +		AccountName2Protocol(account, protocol, sizeof(protocol));
 +		
 +		hContact = GetContactFromID(name, protocol);
 +		
 +	}
 +	else{
 +		hContact = GetContactFromID(contact, (char *) NULL);
 +	}
 +	
 +	return hContact;
 +}
 +
 +void HandleMessageCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	if (argc >= 4)
 +	{
 +		char *message = argv[argc - 1]; //get the message
 +		int i;
 +		char *contact;
 +		char buffer[1024];
 +		HANDLE hContact;
 +		HANDLE hProcess = NULL;
 +		ACKDATA *ack = NULL;
 +		for (i = 2; i < argc - 1; i++)
 +		{
 +			contact = argv[i];
 +			hContact = ParseContactParam(contact);
 +			
 +			if (hContact)
 +			{
 +				bShouldProcessAcks = TRUE;
 +				hProcess = (HANDLE) CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM) message);
 +				const int MAX_COUNT = 60;
 +				int counter = 0;
 +				while (((ack = GetAck(hProcess)) == NULL) && (counter < MAX_COUNT))
 +				{
 +					SleepEx(250, TRUE);
 +					counter++;
 +				}
 +				bShouldProcessAcks = FALSE;
 +				
 +				if (counter < MAX_COUNT)
 +				{
 +					if (ack->result == ACKRESULT_SUCCESS)
 +					{
 +						if (ack->szModule)
 +						{						
 +							mir_snprintf(buffer, sizeof(buffer), Translate("Message sent to '%s'."), contact);
 +
 +							DBEVENTINFO e = {0};
 +							char module[128];
 +							e.cbSize = sizeof(DBEVENTINFO);
 +							e.eventType = EVENTTYPE_MESSAGE;
 +							e.flags = DBEF_SENT;
 +							
 +							e.pBlob = (PBYTE) message;
 +							e.cbBlob = (DWORD) strlen((char *) message) + 1;
 +						
 +							STRNCPY(module, ack->szModule, sizeof(module));
 +							e.szModule = module;
 +							e.timestamp = (DWORD) time(NULL);
 +							
 +							CallService(MS_DB_EVENT_ADD, (WPARAM) ack->hContact, (LPARAM) &e);
 +						}
 +						else{
 +							mir_snprintf(buffer, sizeof(buffer), Translate("Message to '%s' was marked as sent but the account seems to be offline"), contact);
 +						}
 +					}
 +					else{
 +						mir_snprintf(buffer, sizeof(buffer), Translate("Could not send message to '%s'."), contact);
 +					}
 +				}
 +				else{
 +					mir_snprintf(buffer, sizeof(buffer), Translate("Timed out while waiting for acknowledgement for contact '%s'."), contact);
 +				}
 +			}
 +			else{
 +				mir_snprintf(buffer, sizeof(buffer), Translate("Could not find contact handle for contact '%s'."), contact);
 +			}
 +			
 +			if (i == 3)
 +			{
 +				STRNCPY(reply->message, buffer, reply->cMessage);
 +			}
 +			else{
 +				strncat(reply->message, "\n", reply->cMessage);
 +				strncat(reply->message, buffer, reply->cMessage);
 +			}
 +		}
 +	}
 +	else{
 +		HandleWrongParametersCount(command, reply);
 +	}
 +}
 +
 +int ParseDatabaseData(DBVARIANT *var, char *buffer, int size, int free)
 +{
 +	int ok = 1;
 +	switch (var->type)
 +	{
 +		case DBVT_BYTE:
 +		{
 +			mir_snprintf(buffer, size, "byte:%d", var->bVal);
 +			
 +			break;
 +		}
 +		
 +		case DBVT_WORD:
 +		{
 +			mir_snprintf(buffer, size, "word:%d", var->wVal);
 +			
 +			break;
 +		}
 +		
 +		case DBVT_DWORD:
 +		{
 +			mir_snprintf(buffer, size, "dword:%ld", var->dVal);
 +			
 +			break; 
 +		}
 +		
 +		case DBVT_ASCIIZ:
 +		{
 +			mir_snprintf(buffer, size, "string:'%s'", var->pszVal);
 +			if (free) { mir_free(var->pszVal); }
 +			
 +			break;
 +		}
 +		
 +		case DBVT_WCHAR:
 +		{
 +			mir_snprintf(buffer, size, "wide string:'%S'", var->pwszVal);
 +			if (free) { mir_free(var->pwszVal); }
 +			
 +			break;
 +		}
 +		
 +		case DBVT_UTF8:
 +		{
 +			mir_snprintf(buffer, size, "utf8:'%s'", var->pszVal);
 +			if (free) { mir_free(var->pszVal); }
 +		}
 +		
 +		case DBVT_BLOB:
 +		{
 +			mir_snprintf(buffer, size, "blob:N/A");
 +			if (free) { mir_free(var->pbVal); }
 +			
 +			break;
 +		}
 +		
 +		
 +		default:
 +		{
 +			ok = 0;
 +			mir_snprintf(buffer, size, "unknown value");
 +		
 +			break;
 +		}
 +	}
 +	
 +	return ok;
 +}
 +
 +void HandleDatabaseCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	if (argc >= 3) //we have something to parse
 +	{
 +		char dbcmd[128];
 +		STRNCPY(dbcmd, argv[2], sizeof(dbcmd));
 +		dbcmd[sizeof(dbcmd) - 1] = 0;
 +		_strlwr(dbcmd);
 +		if (strcmp(dbcmd, "delete") == 0)
 +		{
 +			if (argc == 5)
 +			{
 +				char *module = argv[3];
 +				char *key = argv[4];
 +				
 +				DBDeleteContactSetting(NULL, module, key);
 +				
 +				reply->code = MIMRES_SUCCESS;
 +				mir_snprintf(reply->message, reply->cMessage, Translate("Setting '%s/%s' deleted."), module, key);
 +			}
 +			else{
 +				HandleWrongParametersCount(command, reply);
 +			}
 +		}
 +		else{
 +			if (strcmp(dbcmd, "set") == 0)
 +			{
 +				if (argc == 6)
 +				{
 +					char *module = argv[3];
 +					char *key = argv[4];
 +					
 +					int ok = 1;
 +					
 +					void *value = NULL;
 +					char *wrote = NULL;
 +					int type = ParseValueParam(argv[5], value);
 +					
 +					
 +					switch (type)
 +					{
 +						case VALUE_STRING:
 +						{
 +							DBWriteContactSettingString(NULL, module, key, (char *) value);
 +							wrote = "string";
 +							
 +							break;
 +						}
 +						
 +						case VALUE_BYTE:
 +						{
 +							DBWriteContactSettingByte(NULL, module, key, (* (char *) value));
 +							wrote = "byte";
 +							
 +							break;
 +						}
 +						
 +						case VALUE_WORD:
 +						{
 +							DBWriteContactSettingWord(NULL, module, key, (* (WORD *) value));
 +							wrote = "word";
 +							
 +							break;
 +						}
 +						
 +						case VALUE_DWORD:
 +						{
 +							DBWriteContactSettingDword(NULL, module, key, (* (DWORD *) value));
 +							wrote = "dword";
 +							
 +							break;
 +						}
 +						
 +						case VALUE_WIDE:
 +						{
 +							DBWriteContactSettingWString(NULL, module, key, (WCHAR *) value);
 +							wrote = "wide string";
 +							
 +							break;
 +						}
 +						
 +						default:
 +						{
 +							HandleUnknownParameter(command, argv[5], reply);
 +							ok = 0;
 +							
 +							break;
 +						}
 +					}
 +					
 +					if (ok)
 +					{
 +						reply->code = MIMRES_SUCCESS;
 +						mir_snprintf(reply->message, reply->cMessage, Translate("Wrote '%s:%s' to database entry '%s/%s'."), wrote, argv[5] + 1, module, key);
 +					}
 +					
 +					if (value)
 +					{
 +						free(value);
 +					}
 +				}
 +				else{
 +					HandleWrongParametersCount(command, reply);
 +				}
 +			}
 +			else{
 +				if (strcmp(dbcmd, "get") == 0)
 +				{
 +					if (argc == 5)
 +					{
 +						char *module = argv[3];
 +						char *key = argv[4];
 +						
 +						DBVARIANT var = {0};
 +						
 +						int res = DBGetContactSetting(NULL, module, key, &var);
 +						if (!res)
 +						{
 +							char buffer[1024];
 +							
 +							if (ParseDatabaseData(&var, buffer, sizeof(buffer), TRUE))
 +							{
 +								reply->code = MIMRES_SUCCESS;
 +								mir_snprintf(reply->message, reply->cMessage, Translate("'%s/%s' - %s."), module, key, buffer); 
 +							}
 +							else{
 +								reply->code = MIMRES_FAILURE;
 +								mir_snprintf(reply->message, reply->cMessage, Translate("Could not retrieve setting '%s/%s': %s."), module, key, buffer);
 +							}
 +						}
 +						else{
 +							reply->code = MIMRES_FAILURE;
 +							mir_snprintf(reply->message, reply->cMessage, Translate("Setting '%s/%s' was not found."), module, key);
 +						}
 +						
 +					}
 +					else{
 +						HandleWrongParametersCount(command, reply);
 +					}
 +				}
 +				else{
 +					HandleUnknownParameter(command, dbcmd, reply);
 +				}
 +			}
 +			
 +		}
 +		
 +	}
 +	else{
 +		HandleWrongParametersCount(command, reply);
 +	}
 +}
 +
 +int ParseProxyType(char *type)
 +{
 +	char lower[128];
 +	STRNCPY(lower, type, sizeof(lower));
 +	lower[sizeof(lower) - 1] = 0;
 +	_strlwr(lower);
 +	int proxy = 0;
 +	
 +	if (strcmp(lower, "socks4") == 0)
 +	{
 +		proxy = PROXY_SOCKS4;
 +	}
 +	else{
 +		if (strcmp(lower, "socks5") == 0)
 +		{
 +			proxy = PROXY_SOCKS5;
 +		}
 +		else{
 +			if (strcmp(lower, "http") == 0)
 +			{
 +				proxy = PROXY_HTTP;
 +			}
 +			else{
 +				if (strcmp(lower, "https") == 0)
 +				{
 +					proxy = PROXY_HTTPS;
 +				}
 +			}
 +		}
 +	}
 +	
 +	return proxy;	
 +}
 +
 +char *PrettyProxyType(int type, char *buffer, int size)
 +{
 +	char *pretty = "";
 +	switch (type)
 +	{
 +		case PROXY_SOCKS4:
 +		{
 +			pretty = "SOCKS4";
 +		
 +			break;
 +		}
 +		
 +		case PROXY_SOCKS5:
 +		{
 +			pretty = "SOCKS5";
 +		
 +			break;
 +		}
 +		
 +		case PROXY_HTTP:
 +		{
 +			pretty = "HTTP";
 +		
 +			break;
 +		}
 +		
 +		case PROXY_HTTPS:
 +		{
 +			pretty = "HTTPS";
 +		
 +			break;
 +		}
 +		
 +		default:
 +		{
 +			pretty = "Unknown";
 +		
 +			break;
 +		}
 +	}
 +	
 +	STRNCPY(buffer, pretty, size);
 +	
 +	return buffer;
 +}
 +
 +void HandleProtocolProxyCommand(PCommand command, TArgument *argv, int argc, PReply reply, char *module, char *protocol)
 +{
 +	char proxycmd[128];
 +	STRNCPY(proxycmd, argv[3], sizeof(proxycmd));
 +	proxycmd[sizeof(proxycmd) - 1] = 0;
 +	_strlwr(proxycmd);
 +
 +	char buffer[1024];	
 +	int ok = 1;
 +
 +
 +	if (strcmp(proxycmd, "status") == 0)
 +	{//status command
 +		switch (argc)
 +		{
 +			case 4:
 +			{
 +				int value = DBGetContactSettingByte(NULL, module, "NLUseProxy", 0);
 +				
 +				reply->code = MIMRES_SUCCESS;
 +				mir_snprintf(buffer, sizeof(buffer), "%s proxy status is %s", protocol, (value) ? "enabled" : "disabled");
 +		
 +				break;
 +			}
 +			
 +			case 5:
 +			{
 +				int state = Get2StateValue(argv[4]);
 +				switch (state)
 +				{
 +					case STATE_OFF:
 +					{
 +						DBWriteContactSettingByte(NULL, module, "NLUseProxy", 0);
 +						
 +						reply->code = MIMRES_SUCCESS;
 +						mir_snprintf(buffer, sizeof(buffer), Translate("'%s' proxy was disabled."), protocol);
 +					
 +						break;
 +					}
 +					
 +					case STATE_ON:
 +					{
 +						DBWriteContactSettingByte(NULL, module, "NLUseProxy", 1);
 +						
 +						reply->code = MIMRES_SUCCESS;
 +						mir_snprintf(buffer, sizeof(buffer), Translate("'%s' proxy was enabled."), protocol);
 +						
 +						break;
 +					}
 +					
 +					case STATE_TOGGLE:
 +					{
 +						int value = DBGetContactSettingByte(NULL, module, "NLUseProxy", 0);
 +						value = 1 - value;
 +						DBWriteContactSettingByte(NULL, module, "NLUseProxy", value);
 +						
 +						reply->code = MIMRES_SUCCESS;
 +						mir_snprintf(buffer, sizeof(buffer), (value) ? Translate("'%s' proxy was enabled.") : Translate("'%s' proxy was disabled."));
 +						
 +						break;
 +					}
 +					
 +					default:
 +					{
 +						HandleUnknownParameter(command, argv[4], reply);
 +					
 +						break;
 +					}
 +				}
 +			
 +				break;
 +			}
 +			
 +			default:
 +			{
 +				HandleWrongParametersCount(command, reply);
 +				ok = 0;
 +				
 +				break;
 +			}
 +		}
 +	}
 +	else{
 +		if (strcmp(proxycmd, "server") == 0)
 +		{
 +			switch (argc)
 +			{
 +				case 4:
 +				{
 +					char host[256];
 +					int port;
 +					char type[256];
 +					GetStringFromDatabase(NULL, module, "NLProxyServer", "<unknown>", host, sizeof(host));
 +					port = DBGetContactSettingWord(NULL, module, "NLProxyPort", 0);
 +					PrettyProxyType(DBGetContactSettingByte(NULL, module, "NLProxyType", 0), type, sizeof(type));
 +					
 +					reply->code = MIMRES_SUCCESS;
 +					mir_snprintf(buffer, sizeof(buffer), Translate("%s proxy server: %s %s:%d."), protocol, type, host, port);
 +				
 +					break;
 +				}
 +				
 +				case 7:
 +				{
 +					int type = ParseProxyType(argv[4]);
 +					char *host = argv[5];
 +					long port;
 +					char *stop = NULL;
 +					port = strtol(argv[6], &stop, 10);
 +					
 +					if ((*stop == 0) && (type > 0))
 +					{
 +						DBWriteContactSettingString(NULL, module, "NLProxyServer", host);
 +						DBWriteContactSettingWord(NULL, module, "NLProxyPort", port);
 +						DBWriteContactSettingByte(NULL, module, "NLProxyType", type);
 +						
 +						reply->code = MIMRES_SUCCESS;
 +						mir_snprintf(buffer, sizeof(buffer), Translate("%s proxy set to %s %s:%d."), protocol, argv[4], host, port);
 +					}
 +					else {
 +						reply->code = MIMRES_FAILURE;
 +						mir_snprintf(buffer, sizeof(buffer), Translate("%s The port or the proxy type parameter is invalid."), protocol);
 +					}
 +				
 +					break;
 +				}
 +				
 +				default:
 +				{
 +					HandleWrongParametersCount(command, reply);
 +					ok = 0;
 +				
 +					break;
 +				}
 +			}
 +		}
 +		else{
 +			ok = 0;
 +			HandleUnknownParameter(command, proxycmd, reply);
 +		}
 +	}
 +
 +	
 +	if (ok)
 +	{
 +		if (strlen(reply->message) > 0)
 +		{
 +			strncat(reply->message, "\n", reply->cMessage);
 +			strncat(reply->message, buffer, reply->cMessage);
 +			reply->message[reply->cMessage - 1] = 0;
 +		}
 +		else{
 +			mir_snprintf(reply->message, reply->cMessage, buffer);
 +		}
 +	}	
 +}
 +
 +void HandleProxyCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	if (argc >= 4)
 +	{
 +		char account[128];
 +		char protocol[128];
 +		STRNCPY(account, argv[2], sizeof(account));
 +		account[sizeof(account) - 1] = 0;
 +
 +		AccountName2Protocol(account, protocol, sizeof(protocol));
 +		
 +		int count = 0;
 +		PROTOACCOUNT **accounts = NULL;
 +		ProtoEnumAccounts(&count, &accounts);
 +		
 +		int i;
 +		int global = (strcmp(protocol, "GLOBAL") == 0);
 +
 +		reply->message[0] = 0;
 +
 +		int found = 0;
 +		if (global)
 +		{
 +			HandleProtocolProxyCommand(command, argv, argc, reply, "Netlib", protocol);
 +			found = 1;
 +		}
 +		
 +		char *match;
 +	
 +		for (i = 0; i < count; i++)
 +		{
 +			if (accounts[i]->bIsEnabled)
 +			{
 +				match = accounts[i]->szModuleName;
 +				if ((global) || (strcmp(protocol, match) == 0))
 +				{
 +					HandleProtocolProxyCommand(command, argv, argc, reply, match, match);
 +					found = 1;
 +				}
 +			}
 +		}
 +		
 +		if (!found)
 +		{
 +			reply->code = MIMRES_FAILURE;
 +			mir_snprintf(reply->message, reply->cMessage, Translate("'%s' doesn't seem to be a valid account."), account);
 +		}
 +	}
 +	else{
 +		HandleWrongParametersCount(command, reply);
 +	}
 +}
 +
 +int ContactMatchSearch(HANDLE hContact, char *contact, char *id, char *account, TArgument *argv, int argc)
 +{
 +	int matches = 1;
 +	int i;
 +	
 +	char lwrName[2048] = "\0";
 +	char lwrAccount[128] = "\0";
 +	char lwrKeyword[512] = "\0";
 +	char lwrID[512] = "\0";
 +	char *pos;
 +	
 +	STRNCPY(lwrName, contact, sizeof(lwrName));
 +	STRNCPY(lwrAccount, account, sizeof(lwrAccount));
 +	
 +	if (id) { STRNCPY(lwrID, id, sizeof(lwrID)); }
 +	
 +	_strlwr(lwrName);
 +	_strlwr(lwrAccount);
 +	_strlwr(lwrID);
 +	
 +	for (i = 0; i < argc; i++)
 +	{
 +		STRNCPY(lwrKeyword, argv[i], sizeof(lwrKeyword));
 +		_strlwr(lwrKeyword);
 +		
 +		pos = strstr(lwrKeyword, "account:");
 +		if (pos)
 +		{
 +			pos += 8;
 +			if (strstr(lwrAccount, pos) == NULL)
 +			{
 +				matches = 0;
 +				
 +				break;
 +			}
 +		}
 +		else{
 +			pos = strstr(lwrKeyword, "status:");
 +			if (pos)
 +			{
 +				int searchStatus = ParseStatusParam(pos + 7);
 +				char protocol[128];
 +
 +				AccountName2Protocol(account, protocol, sizeof(protocol));
 +				WORD contactStatus = DBGetContactSettingWord(hContact, protocol, "Status", ID_STATUS_ONLINE);
 +				
 +				if (searchStatus != contactStatus)
 +				{
 +					matches = 0;
 +					
 +					break;
 +				}
 +			}
 +			else{
 +				pos = strstr(lwrKeyword, "id:");
 +				if (pos)
 +				{
 +					pos += 3;
 +					if (strstr(lwrID, pos) == NULL)
 +					{
 +						matches = 0;
 +						
 +						break;
 +					}
 +				}
 +				else{
 +					if ((strstr(lwrName, lwrKeyword) == NULL))
 +					{
 +						matches = 0;
 +						
 +						break;
 +					}
 +				}
 +			}
 +		}
 +	}
 +	
 +	return matches;
 +}
 +
 +DWORD WINAPI OpenMessageWindowThread(void *data)
 +{
 +	HANDLE hContact = (HANDLE) data;
 +	if (hContact)
 +	{
 +		CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM) hContact, 0);
 +		CallServiceSync("SRMsg/LaunchMessageWindow", (WPARAM) hContact, 0);
 +	}
 +	
 +	return 0;
 +}
 +
 +
 +void HandleContactsCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	if (argc >= 3)
 +	{
 +		if (_stricmp(argv[2], "list") == 0)
 +		{
 +			HANDLE hContact = NULL;
 +			char buffer[1024];
 +			char protocol[128];
 +			
 +			hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
 +			int count = 0;
 +			
 +			reply->code = MIMRES_SUCCESS;
 +			while (hContact)
 +			{
 +				
 +				GetContactProtocol(hContact, protocol, sizeof(protocol));
 +				
 +				char *contact = GetContactName(hContact, protocol);
 +				char *id = GetContactID(hContact, protocol);
 +				if (ContactMatchSearch(hContact, contact, id, protocol, &argv[3], argc - 3))
 +				{
 +					mir_snprintf(buffer, sizeof(buffer), "%s:[%s]:%s (%08d)", contact, id, protocol, hContact);
 +					if (count)
 +					{
 +						strncat(reply->message, "\n", reply->cMessage);
 +						strncat(reply->message, buffer, reply->cMessage);
 +					}
 +					else{
 +						STRNCPY(reply->message, buffer, reply->cMessage);
 +					}
 +					
 +					if (strlen(reply->message) > 4096)
 +					{
 +						SetEvent(heServerBufferFull);
 +						Sleep(750); //wait a few milliseconds for the event to be processed
 +						count = 0;
 +						*reply->message = 0;
 +					}
 +					
 +					count++;
 +				}
 +				
 +				free(contact);
 +				free(id);
 +				
 +				hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
 +			}
 +		}
 +		else{
 +			if (_stricmp(argv[2], "open") == 0)
 +			{
 +				if (argc > 3)
 +				{
 +					HANDLE hContact = NULL;
 +					char protocol[128];
 +					hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
 +					
 +					reply->code = MIMRES_SUCCESS;
 +					*reply->message = 0;
 +					while (hContact)
 +					{
 +						GetContactProtocol(hContact, protocol, sizeof(protocol));
 +						
 +						char *contact = GetContactName(hContact, protocol);
 +						char *id = GetContactID(hContact, protocol);
 +						if (ContactMatchSearch(hContact, contact, id, protocol, &argv[3], argc - 3))
 +						{
 +							DWORD threadID;
 +							HANDLE thread = CreateThread(NULL, NULL, OpenMessageWindowThread, hContact, NULL, &threadID);
 +						}
 +						
 +						free(contact);
 +						free(id);
 +						
 +						hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
 +					}
 +				}
 +				else{
 +					if (argc == 3)
 +					{
 +						HANDLE hContact = NULL;
 +						hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
 +
 +						reply->code = MIMRES_SUCCESS;
 +						*reply->message = 0;
 +
 +						while (hContact)
 +						{
 +							HANDLE hUnreadEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0);
 +							if (hUnreadEvent != NULL)
 +							{
 +								DWORD threadID;
 +								HANDLE thread = CreateThread(NULL, NULL, OpenMessageWindowThread, hContact, NULL, &threadID);
 +							}
 +
 +							hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
 +						}
 +					}
 +					else {
 +						HandleWrongParametersCount(command, reply);
 +					}
 +				}
 +			}
 +			else{
 +				HandleUnknownParameter(command, argv[2], reply);
 +			}
 +		}
 +	}
 +	else{
 +		HandleWrongParametersCount(command, reply);	
 +	}
 +}
 +
 +void AddHistoryEvent(DBEVENTINFO *dbEvent, char *contact, PReply reply)
 +{
 +	struct tm * tEvent = localtime((time_t *) &dbEvent->timestamp);
 +	char timestamp[256];
 +	
 + 	strftime(timestamp, sizeof(timestamp), "%H:%M:%S %d/%b/%Y", tEvent);
 +	
 +	static char buffer[6144];
 +	char *sender = (dbEvent->flags & DBEF_SENT) ? Translate("[me]") : contact;
 +	
 +	char message[4096] = {0};
 +	STRNCPY(message, (char *) dbEvent->pBlob, sizeof(message));
 +	message[dbEvent->cbBlob] = message[strlen(message)] = 0;
 +	
 +	//if ((strlen(message) <= 0) && (dbEvent->cbBlob > 0))
 +	//{
 +	//	WCHAR *tmp = (WCHAR *) dbEvent->pBlob[dbEvent->cbBlob + 1];
 +	//	WideCharToMultiByte(CP_ACP, 0, tmp, -1, message, sizeof(message), NULL, NULL);
 +	//}
 +	
 +	mir_snprintf(buffer, sizeof(buffer), "[%s] %15s: %s", timestamp, sender, message);
 +	
 +	
 +	if (strlen(reply->message) > 0)
 +	{
 +		strncat(reply->message, "\n", reply->cMessage);
 +		strncat(reply->message, buffer, reply->cMessage);
 +	}
 +	else{
 +		STRNCPY(reply->message, buffer, reply->cMessage);
 +	}
 +	
 +	if (strlen(reply->message) > (reply->cMessage / 2))
 +	{
 +		SetEvent(heServerBufferFull);
 +
 +		Sleep(750);
 +		strcpy(reply->message, "\n");
 +	}
 +}
 +
 +void HandleHistoryCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	if (argc >= 3)
 +	{
 +		char *cmd = argv[2];
 +		switch (argc)
 +		{
 +			case 3:
 +			{
 +				if (_stricmp(cmd, "unread") == 0)
 +				{
 +					HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
 +					char buffer[4096];
 +					int count;
 +					int contacts = 0;
 +					DBEVENTINFO dbEvent = {0};
 +					dbEvent.cbSize = sizeof(DBEVENTINFO);
 +					
 +					reply->code = MIMRES_SUCCESS;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("No unread messages found."));
 +					
 +					while (hContact)
 +					{
 +						HANDLE hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0);
 +						if (hEvent != NULL)
 +						{
 +							char *contact;
 +							char protocol[128];
 +							
 +							count = 0;
 +							while (hEvent != NULL)
 +							{
 +								if (!CallService(MS_DB_EVENT_GET, (WPARAM) hEvent, (LPARAM) &dbEvent))
 +								{
 +									if (!(dbEvent.flags & DBEF_READ))
 +									{
 +										count++;
 +									}
 +								}
 +							
 +								hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hEvent, 0);
 +							}
 +							
 +							GetContactProtocol(hContact, protocol, sizeof(protocol));
 +							contact = GetContactName(hContact, protocol);
 +							mir_snprintf(buffer, sizeof(buffer), Translate("%s:%s - %d unread events."), contact, protocol, count);
 +							
 +							if (contacts > 0)
 +							{
 +								strncat(reply->message, "\n", reply->cMessage);
 +								strncat(reply->message, buffer, reply->cMessage);
 +							}
 +							else{
 +								STRNCPY(reply->message, buffer, reply->cMessage);
 +							}
 +							contacts++;
 +							
 +							free(contact);
 +						}
 +					
 +						hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
 +					}
 +				}
 +				else{
 +					if (_stricmp(cmd, "show") == 0)
 +					{
 +						HandleWrongParametersCount(command, reply);
 +					}
 +					else{
 +						HandleUnknownParameter(command, cmd, reply);
 +					}
 +				}
 +				
 +				break;
 +			}
 +	
 +			case 4:
 +			{
 +				char *contact = argv[3];
 +				HANDLE hContact = ParseContactParam(contact);
 +				if (hContact)
 +				{
 +					if (_stricmp(cmd, "unread") == 0)
 +					{
 +						HANDLE hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0);
 +						DBEVENTINFO dbEvent = {0};
 +						dbEvent.cbSize = sizeof(DBEVENTINFO);
 +						
 +						char *message[4096];
 +						dbEvent.pBlob = (PBYTE) message;
 +						
 +						reply->code = MIMRES_SUCCESS;
 +						
 +						while (hEvent)
 +						{
 +							dbEvent.cbBlob = sizeof(message);
 +							if (!CallService(MS_DB_EVENT_GET, (WPARAM) hEvent, (LPARAM) &dbEvent)) //if successful call
 +							{ 
 +								if (!(dbEvent.flags & DBEF_READ))
 +								{
 +									AddHistoryEvent(&dbEvent, contact, reply);
 +								}
 +							}
 +						
 +							hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hEvent, 0);
 +						}
 +					}
 +					else{
 +						if (_stricmp(cmd, "show") == 0)
 +						{
 +							int count = CallService(MS_DB_EVENT_GETCOUNT, (WPARAM) hContact, 0);
 +							
 +							reply->code = MIMRES_SUCCESS;
 +							mir_snprintf(reply->message, reply->cMessage, Translate("Contact '%s' has '%d' events in history."), contact, count);
 +						}
 +						else{
 +							HandleUnknownParameter(command, cmd, reply);
 +						}
 +					}
 +				}
 +				else{
 +					reply->code = MIMRES_FAILURE;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("Could not find contact handle for contact '%s'."), contact);
 +				}
 +			
 +				break;
 +			}
 +			
 +			case 6:
 +			{
 +				char *contact = argv[3];
 +				HANDLE hContact = ParseContactParam(contact);
 +				
 +				if (hContact)
 +				{
 +					if (_stricmp(cmd, "show") == 0)
 +					{
 +						char *stop1 = NULL;
 +						char *stop2 = NULL;
 +						long start = strtol(argv[4], &stop1, 10);
 +						long stop = strtol(argv[5], &stop2, 10);
 +						if (!(*stop1) && !(*stop2))
 +						{
 +							int size = CallService(MS_DB_EVENT_GETCOUNT, (WPARAM) hContact, 0);
 +							if (start < 0) { start = size + start + 1; }
 +							if (stop < 0) { stop = size + stop + 1; }
 +							
 +							reply->code = MIMRES_SUCCESS;
 +							
 +							int count = stop - start + 1;
 +							if (count > 0)
 +							{
 +								int index = 0;
 +								HANDLE hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRST, (WPARAM) hContact, 0);
 +								DBEVENTINFO dbEvent = {0};
 +								dbEvent.cbSize = sizeof(DBEVENTINFO);
 +								char message[4096];
 +								dbEvent.pBlob = (PBYTE) message;
 +								
 +								while (hEvent)
 +								{
 +									dbEvent.cbBlob = sizeof(message);
 +									if (!CallService(MS_DB_EVENT_GET, (WPARAM) hEvent, (LPARAM) &dbEvent)) // if successful call
 +									{
 +										dbEvent.pBlob[dbEvent.cbBlob] = 0;
 +										if ((index >= start) && (index <= stop))
 +										{
 +											AddHistoryEvent(&dbEvent, contact, reply);
 +										}
 +									}
 +									
 +									if (index > stop)
 +									{
 +										break;
 +									}
 +								
 +									hEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hEvent, 0);
 +									index++;
 +								}
 +							}
 +						}
 +						else{
 +							HandleUnknownParameter(command, (*stop1) ? argv[4] : argv[5], reply);
 +						}
 +					}
 +					else{
 +						if (_stricmp(cmd, "unread") == 0)
 +						{
 +							HandleWrongParametersCount(command, reply);
 +						}
 +						else{
 +							HandleUnknownParameter(command, cmd, reply);
 +						}
 +					}
 +				}
 +				else{
 +					reply->code = MIMRES_FAILURE;
 +					mir_snprintf(reply->message, reply->cMessage, Translate("Could not find contact handle for contact '%s'."), contact);
 +				}
 +				
 +				break;
 +			}
 +		
 +			default:
 +			{
 +				HandleWrongParametersCount(command, reply);
 +				
 +				break;
 +			}
 +		}
 +	}
 +	else{
 +		HandleWrongParametersCount(command, reply);
 +	}
 +}
 +
 +void HandleVersionCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	if (argc == 2)
 +	{
 +		reply->code = MIMRES_SUCCESS;
 +		if (ServiceExists(MS_VERSIONINFO_GETINFO))
 +		{
 +			char *data;
 +			CallService(MS_VERSIONINFO_GETINFO, (WPARAM) FALSE, (LPARAM) &data);
 +			mir_snprintf(reply->message, reply->cMessage, data);
 +			mir_free(data);
 +		}
 +		else{
 +			char miranda[512];
 +			char cmdline[512];
 +			DWORD v = pluginInfo.version;
 +			CallService(MS_SYSTEM_GETVERSIONTEXT, (WPARAM) sizeof(miranda), (LPARAM) miranda);
 +			mir_snprintf(cmdline, sizeof(cmdline), "%d.%d.%d.%d", ((v >> 24) & 0xFF), ((v >> 16) & 0xFF), ((v >> 8) & 0xFF), (v & 0xFF));
 +			mir_snprintf(reply->message, reply->cMessage, "Miranda %s\nCmdLine v.%s", miranda, cmdline);
 +		}
 +	}
 +	else{
 +		HandleWrongParametersCount(command, reply);
 +	}
 +}
 +void HandleSetNicknameCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	if (argc == 4)
 +	{
 +		char protocol[512];
 +		char nickname[512];
 +		strcpy(protocol, argv[2]);
 +		strcpy(nickname, argv[3]);
 +
 +		int res = CallProtoService(protocol, PS_SETMYNICKNAME, SMNN_TCHAR, (LPARAM) nickname);
 +
 +		if (res == 0)
 +		{
 +			reply->code = MIMRES_SUCCESS;
 +			*reply->message = 0;
 +		}
 +		else {
 +			reply->code = MIMRES_FAILURE;
 +			mir_snprintf(reply->message, reply->cMessage, Translate("Error setting nickname to '%s' for protocol '%s'"), nickname, protocol);
 +		}
 +	}
 +	else {
 +		HandleWrongParametersCount(command, reply);
 +	}
 +}
 +
 +void HandleIgnoreCommand(PCommand command, TArgument *argv, int argc, PReply reply)
 +{
 +	if (argc >= 4)
 +	{
 +		BOOL block = FALSE;
 +		BOOL goodCommand = FALSE;
 +		if (_stricmp(argv[2], "block") == 0)
 +		{
 +			block = TRUE;
 +			goodCommand = TRUE;
 +		}
 +
 +		if (_stricmp(argv[2], "unblock") == 0)
 +		{
 +			block = FALSE;
 +			goodCommand = TRUE;
 +		}
 +
 +		if (!goodCommand)
 +		{
 +			HandleUnknownParameter(command, argv[2], reply);
 +
 +			return;
 +		}
 +
 +		HANDLE hContact = NULL;
 +		char *contact;
 +
 +		for (int i = 3; i < argc; i++)
 +		{
 +			contact = argv[i];
 +			hContact = ParseContactParam(contact);
 +
 +			if (hContact)
 +			{
 +				CallService(block ? MS_IGNORE_IGNORE : MS_IGNORE_UNIGNORE, (WPARAM) hContact, IGNOREEVENT_ALL);
 +			}
 +		}
 +
 +		reply->code = MIMRES_SUCCESS;
 +		*reply->message = 0;
 +	}
 +	else {
 +		HandleWrongParametersCount(command, reply);
 +	}
 +}
\ No newline at end of file  | 
