summaryrefslogtreecommitdiff
path: root/plugins/ProxySwitch/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/ProxySwitch/src')
-rw-r--r--plugins/ProxySwitch/src/ip.cpp728
-rw-r--r--plugins/ProxySwitch/src/main.cpp367
-rw-r--r--plugins/ProxySwitch/src/opt.cpp191
-rw-r--r--plugins/ProxySwitch/src/proxy.cpp304
-rw-r--r--plugins/ProxySwitch/src/resource.h41
-rw-r--r--plugins/ProxySwitch/src/stdafx.cxx18
-rw-r--r--plugins/ProxySwitch/src/stdafx.h212
-rw-r--r--plugins/ProxySwitch/src/version.h13
8 files changed, 1874 insertions, 0 deletions
diff --git a/plugins/ProxySwitch/src/ip.cpp b/plugins/ProxySwitch/src/ip.cpp
new file mode 100644
index 0000000000..abd793e3eb
--- /dev/null
+++ b/plugins/ProxySwitch/src/ip.cpp
@@ -0,0 +1,728 @@
+/*
+proxySwitch
+
+The plugin watches IP address changes, reports them via popups and adjusts
+the proxy settings of Miranda and Internet Explorer accordingly.
+*/
+
+#include "stdafx.h"
+
+//#define IP_DEBUG
+#ifdef IP_DEBUG
+#pragma comment (lib, "user32")
+#pragma comment (lib, "iphlpapi")
+#pragma comment (lib, "ws2_32")
+#define PopupMyIPAddrs(x) printf("PopupMyIPAddrs(%s)\n", x);
+#define GetCurrentProcessId() 13604
+NETWORK_INTERFACE_LIST NIF_List;
+CRITICAL_SECTION csNIF_List;
+char opt_hideIntf[MAX_IPLIST_LENGTH];
+void UpdateInterfacesMenu (void) { }
+PLUGINLINK *pluginLink;
+int main(void) {
+ NETWORK_INTERFACE_LIST list;
+ char opt[200] = "2.252.83.0-2.252.85.0;10.100.0.0/16;2.252.83.32-38;;;32.64.128.0/255.255.255.0";
+ IP_RANGE_LIST range;
+ InitializeCriticalSection(&csNIF_List);
+ lstrcpy(opt_hideIntf, "VMnet*");
+ printf("Started\n");
+ printf("IP Helper procs: %s\n", Load_ExIpHelper_Procedures() ? "Loaded" : "Not found");
+ if ( Create_NIF_List( &list ) >=0 ) {
+ printf("%s\n", Print_NIF_List(list, NULL));
+
+ Create_Range_List( &range, opt, FALSE );
+ printf("'%s' matches: %s\n", opt, Match_Range_List(range, list) ? "yes" : "no" );
+ Free_Range_List( &range );
+
+
+ Free_NIF_List( &list );
+ }
+ DeleteCriticalSection(&csNIF_List);
+ printf("Finished\n");
+ return 0;
+}
+#endif
+
+wchar_t tempstr[MAX_SECONDLINE];
+
+/* ################################################################################ */
+
+#ifndef IP_DEBUG
+void IP_WatchDog (void *arg) {
+ OVERLAPPED overlap;
+ DWORD ret;
+ wchar_t msg[300];
+ HANDLE event_list[2];
+ HANDLE hand = WSACreateEvent();
+ overlap.hEvent = WSACreateEvent();
+
+ for (;;) {
+
+ ret = NotifyAddrChange(&hand, &overlap);
+ if (ret != NO_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
+ wchar_t err[100];
+ mir_snwprintf(err, L"NotifyAddrChange Error: %d/nRestart Miranda IM to restore IP monitor.", WSAGetLastError());
+ ERRORMSG(err);
+ break;
+ }
+
+ event_list[0] = overlap.hEvent;
+ event_list[1] = hEventRebound;
+
+ ret = MsgWaitForMultipleObjectsEx( 2, event_list, INFINITE, 0, MWMO_ALERTABLE );
+ if (ret == WAIT_IO_COMPLETION && Miranda_IsTerminated()) break;
+ if (ret == WAIT_OBJECT_0 || ret == WAIT_TIMEOUT || ret == (WAIT_OBJECT_0+1) ) {
+ NETWORK_INTERFACE_LIST list;
+
+ if ( Create_NIF_List_Ex( &list ) >=0 ) {
+ int change = INCUPD_INTACT;
+
+ EnterCriticalSection(&csNIF_List);
+ change = IncUpdate_NIF_List(&NIF_List, list);
+ if ( change != INCUPD_INTACT && change != INCUPD_CONN_BIND ) {
+ char proxy = -1;
+ int change_Miranda = 0;
+ int reset_Miranda = 0;
+ int change_IE = 0;
+ int change_Firefox = 0;
+ IP_RANGE_LIST range;
+
+ if ( proxy == -1 ) {
+ Create_Range_List( &range, opt_useProxy, TRUE );
+ if ( Match_Range_List( range, NIF_List ) ) proxy = 1;
+ Free_Range_List( &range );
+ }
+ if ( proxy == -1 ) {
+ Create_Range_List( &range, opt_noProxy, FALSE );
+ if ( Match_Range_List( range, NIF_List ) ) proxy = 0;
+ Free_Range_List( &range );
+ }
+ if ( proxy == -1 ) {
+ Create_Range_List( &range, opt_useProxy, FALSE );
+ if ( Match_Range_List( range, NIF_List ) ) proxy = 1;
+ Free_Range_List( &range );
+ }
+
+ if ( proxy != -1 && proxy != Get_Miranda_Proxy_Status() ) change_Miranda = reset_Miranda = opt_miranda;
+ if ( proxy != -1 && proxy != Get_IE_Proxy_Status() ) change_IE = opt_ie;
+ if ( proxy != -1 && proxy != Get_Firefox_Proxy_Status() ) change_Firefox = opt_firefox;
+ if ( opt_alwayReconnect ) reset_Miranda = 1;
+
+ mir_wstrcpy(msg, L"");
+ if ( opt_showProxyState && change_Miranda ) {
+ mir_wstrcat(msg, TranslateT("\nMiranda "));
+ mir_wstrcat(msg, proxy ? TranslateT("Proxy") : TranslateT("Direct"));
+ }
+ if ( opt_showProxyState && change_IE ) {
+ mir_wstrcat(msg, TranslateT("\nExplorer "));
+ mir_wstrcat(msg, proxy ? TranslateT("Proxy") : TranslateT("Direct"));
+ }
+ if ( opt_showProxyState && change_Firefox ) {
+ mir_wstrcat(msg, TranslateT("\nFirefox "));
+ mir_wstrcat(msg, proxy ? TranslateT("Proxy") : TranslateT("Direct"));
+ }
+ UpdateInterfacesMenu();
+ PopupMyIPAddrs(mir_wstrlen(msg) ? msg : NULL);
+
+ if ( change_IE ) Set_IE_Proxy_Status( proxy );
+ if ( change_Firefox ) Set_Firefox_Proxy_Status( proxy );
+ if ( reset_Miranda ) {
+ PROTO_SETTINGS protocols;
+ Disconnect_All_Protocols( &protocols, change_Miranda );
+ Sleep( 1000 );
+ if ( change_Miranda ) Set_Miranda_Proxy_Status( proxy );
+ Connect_All_Protocols( &protocols );
+ }
+ }
+ LeaveCriticalSection(&csNIF_List);
+
+ Free_NIF_List( &list );
+ }
+ }
+
+ ResetEvent(hEventRebound);
+ WSAResetEvent(hand);
+ WSAResetEvent(overlap.hEvent);
+ }
+
+ WSACloseEvent(hand);
+ WSACloseEvent(overlap.hEvent);
+}
+#endif
+
+/* ################################################################################ */
+
+int Create_NIF_List_Ex (NETWORK_INTERFACE_LIST *list) {
+ UINT delay = 1;
+ int out;
+
+ while ( (out = Create_NIF_List(list)) == -2 && delay < 10 ) {
+ Sleep(delay*50);
+ delay++;
+ }
+ if (out == -2) ERRORMSG(TranslateT("Cannot retrieve IP or Adapter data."));
+ return out < 0 ? -1 : out;
+}
+
+PNETWORK_INTERFACE Find_NIF_IP(NETWORK_INTERFACE_LIST list, const LONG IP) {
+ UCHAR idx = 0;
+ UCHAR i;
+
+ while (idx < list.count) {
+ for (i = 0; i < list.item[idx].IPcount; i++) {
+ if (list.item[idx].IP[i] == IP) return &(list.item[idx]);
+ }
+ idx++;
+ }
+ return NULL;
+}
+
+int Create_NIF_List (NETWORK_INTERFACE_LIST *list) {
+
+ PIP_ADAPTER_INFO pAdapterInfo, pAdapt;
+ PIP_ADDR_STRING pAddrStr;
+ PIP_ADAPTER_ADDRESSES pAddresses, pAddr;
+ PNETWORK_INTERFACE nif;
+ ULONG outBufLen;
+ wchar_t *tmp_opt, *intf, *rest, *name;
+ BOOL skip;
+ DWORD out;
+ UCHAR idx;
+
+ // prepare and load IP_ADAPTER_ADDRESSES
+ outBufLen = 0;
+ if (GetAdaptersAddresses(AF_INET, 0, NULL, NULL, &outBufLen) == ERROR_BUFFER_OVERFLOW) {
+ pAddresses = (PIP_ADAPTER_ADDRESSES) malloc(outBufLen);
+ if (pAddresses == NULL) {
+ ERRORMSG(TranslateT("Cannot allocate memory for pAddresses"));
+ return -1;
+ }
+ if ((out = GetAdaptersAddresses(AF_INET, 0, NULL, pAddresses, &outBufLen)) != ERROR_SUCCESS) {
+ free(pAddresses);
+ return -2;
+ }
+ } else {
+ ERRORMSG(TranslateT("GetAdaptersAddresses sizing failed"));
+ return -1;
+ }
+
+ // prepare and load IP_ADAPTER_INFO
+ outBufLen = 0;
+ if (GetAdaptersInfo(NULL, &outBufLen) == ERROR_BUFFER_OVERFLOW) {
+ pAdapterInfo = (PIP_ADAPTER_INFO) malloc(outBufLen);
+ if (pAdapterInfo == NULL) {
+ ERRORMSG(TranslateT("Cannot allocate memory for pAdapterInfo"));
+ free(pAddresses);
+ return -1;
+ }
+ if (GetAdaptersInfo(pAdapterInfo, &outBufLen) != NO_ERROR) {
+ free(pAdapterInfo);
+ free(pAddresses);
+ return -2;
+ }
+ } else {
+ ERRORMSG(TranslateT("GetAdaptersInfo sizing failed"));
+ free(pAddresses);
+ return -1;
+ }
+
+ ZeroMemory(list, sizeof(NETWORK_INTERFACE_LIST));
+
+ pAdapt = pAdapterInfo;
+ while (pAdapt) {
+
+ // add a new interface into the list
+ list->count++;
+ list->item = (PNETWORK_INTERFACE)mir_realloc( list->item, list->count * sizeof(NETWORK_INTERFACE) );
+ nif = &(list->item[list->count - 1]);
+ ZeroMemory(nif, sizeof(NETWORK_INTERFACE));
+
+ // copy AdapterName
+ nif->AdapterName = (char*)mir_alloc(mir_strlen(pAdapt->AdapterName)+4);
+ nif->AdapterName = mir_strdup(pAdapt->AdapterName);
+
+ // find its FriendlyName and copy it
+ pAddr = pAddresses;
+ while(pAddr && mir_strcmp(pAddr->AdapterName, pAdapt->AdapterName)) {
+ pAddr = pAddr->Next;
+ }
+ if ( pAddr ) {
+ nif->FriendlyName = (wchar_t*)mir_alloc(wcslen(pAddr->FriendlyName)+4);
+ nif->FriendlyName = mir_wstrdup(pAddr->FriendlyName);
+ }
+
+ skip = FALSE;
+ tmp_opt = intf = rest = mir_wstrdup( opt_hideIntf );
+ while ( rest && rest[0] && ! skip ) {
+ rest = wcschr( rest, ';' );
+ if ( rest != NULL ) {
+ rest[0] = 0;
+ rest++;
+ }
+ if ( intf[0] ) {
+ if ( intf[mir_wstrlen(intf)-1] == '*' && mir_wstrlen(intf)-1 <= mir_wstrlen(nif->FriendlyName) ) {
+ intf[mir_wstrlen(intf)-1] = 0;
+ name = nif->FriendlyName;
+ skip = TRUE;
+ while ( intf[0] ) {
+ if ( intf[0] != name[0] ) {
+ skip = FALSE;
+ break;
+ }
+ intf++;
+ name++;
+ }
+ }
+ if ( mir_wstrcmp(nif->FriendlyName, intf) == 0 ) {
+ skip = TRUE;
+ }
+ }
+ intf = rest;
+ }
+ free(tmp_opt);
+
+ if ( skip ) {
+ list->count--;
+ list->item = (PNETWORK_INTERFACE)mir_realloc( list->item, list->count * sizeof(NETWORK_INTERFACE) );
+ pAdapt = pAdapt->Next;
+ continue;
+ }
+
+ // get required size for IPstr and IP
+ outBufLen = 0;
+ pAddrStr = &(pAdapt->IpAddressList);
+ while(pAddrStr) {
+ if ( strcmp("0.0.0.0", pAddrStr->IpAddress.String) ) {
+ nif->IPcount++; // count IP addresses
+ outBufLen += strlen(pAddrStr->IpAddress.String); // count length of IPstr
+ }
+ pAddrStr = pAddrStr->Next;
+ if (pAddrStr) outBufLen += 2; // count length of IPstr (add ", ")
+ }
+
+ // create IPstr and IP
+ if ( nif->IPcount ) {
+ nif->IPstr = (char*)mir_alloc( outBufLen+4 );
+ strcpy(nif->IPstr, "");
+ nif->IP = (LONG*)mir_alloc( (nif->IPcount+1) * sizeof(LONG) );
+ outBufLen = 0;
+ pAddrStr = &(pAdapt->IpAddressList);
+ while(pAddrStr) {
+ if ( strcmp("0.0.0.0", pAddrStr->IpAddress.String) ) {
+ strcat( nif->IPstr, pAddrStr->IpAddress.String );
+ nif->IP[outBufLen] = inet_addr( pAddrStr->IpAddress.String );
+ outBufLen++;
+ }
+ pAddrStr = pAddrStr->Next;
+ if (pAddrStr) strcat( nif->IPstr, ", ");
+ }
+ nif->IP[outBufLen] = 0L;
+ }
+ pAdapt = pAdapt->Next;
+ }
+
+ free(pAdapterInfo);
+ free(pAddresses);
+
+ EnterCriticalSection(&csConnection_List);
+ for ( idx=0 ; idx < Connection_List.count ; idx++ ) {
+ nif = Find_NIF_IP( *list, Connection_List.item[idx].IP );
+ if ( nif ) {
+ nif->Bound = 1;
+ }
+ }
+ LeaveCriticalSection(&csConnection_List);
+
+ return 0;
+}
+
+/* ################################################################################ */
+
+PNETWORK_INTERFACE Find_NIF_AdapterName ( NETWORK_INTERFACE_LIST list, const char *AdapterName) {
+ UCHAR idx = 0;
+
+ while ( idx < list.count ) {
+ if ( strcmp(list.item[idx].AdapterName, AdapterName) == 0 ) return &(list.item[idx]);
+ idx++;
+ }
+ return NULL;
+}
+
+PNETWORK_INTERFACE Find_NIF_MenuItem ( NETWORK_INTERFACE_LIST list, const HGENMENU MenuItem) {
+ UCHAR idx = 0;
+
+ while ( idx < list.count ) {
+ if ( list.item[idx].MenuItem == MenuItem ) return &(list.item[idx]);
+ idx++;
+ }
+ return NULL;
+}
+
+/* ################################################################################ */
+
+BOOL Compare_NIF_Lists (NETWORK_INTERFACE_LIST list1, NETWORK_INTERFACE_LIST list2) {
+ UCHAR idx = 0;
+
+ if ( list1.count != list2.count ) return 1;
+ while ( idx < list1.count ) {
+ if ( mir_strcmp(list1.item[idx].AdapterName, list2.item[idx].AdapterName) ) return 1;
+ if ( mir_strcmp(list1.item[idx].IPstr, list2.item[idx].IPstr) ) return 1;
+ if ( mir_wstrcmp(list1.item[idx].FriendlyName, list2.item[idx].FriendlyName) ) return 1;
+ idx++;
+ }
+ return 0;
+}
+
+/* ################################################################################ */
+
+int IncUpdate_NIF_List (NETWORK_INTERFACE_LIST *trg, NETWORK_INTERFACE_LIST src) {
+ UCHAR idx;
+ PNETWORK_INTERFACE nif;
+ int change = INCUPD_INTACT;
+
+ for (idx = 0 ; idx < src.count ; idx++) {
+ nif = Find_NIF_AdapterName( *trg, src.item[idx].AdapterName );
+ if ( nif ) {
+ if ( nif->Disabled ) nif->Disabled = 0;
+ if ( strcmp(NVL(nif->IPstr), NVL(src.item[idx].IPstr)) ) {
+ if (nif->IPstr) free(nif->IPstr);
+ nif->IPstr = src.item[idx].IPstr ? mir_strdup( src.item[idx].IPstr ) : NULL;
+ INCUPD(change, INCUPD_UPDATED);
+ }
+ if ( mir_wstrcmp(NVLW(nif->FriendlyName), NVLW(src.item[idx].FriendlyName)) ) {
+ if (nif->FriendlyName) free(nif->FriendlyName);
+ nif->FriendlyName = src.item[idx].FriendlyName ? mir_wstrdup( src.item[idx].FriendlyName ) : NULL;
+ INCUPD(change, INCUPD_UPDATED);
+ }
+ if ( nif->IPcount != src.item[idx].IPcount ) {
+ if ( nif->IPcount > src.item[idx].IPcount && nif->Bound ) {
+ INCUPD(change, INCUPD_CONN_LOST );
+ UnboundConnections( nif->IP, src.item[idx].IP );
+ }
+ nif->IPcount = src.item[idx].IPcount;
+ if (nif->IP) free(nif->IP);
+ if (src.item[idx].IP) {
+ nif->IP = (LONG*)mir_alloc( (nif->IPcount+1) * sizeof(LONG) );
+ memcpy( nif->IP, src.item[idx].IP, (nif->IPcount+1) * sizeof(LONG) );
+ } else {
+ nif->IP = NULL;
+ }
+ INCUPD(change, INCUPD_UPDATED);
+ } else {
+ if ( nif->IPcount > 0 && memcmp( nif->IP, src.item[idx].IP, nif->IPcount * sizeof(LONG) ) ) {
+ free(nif->IP);
+ nif->IP = (LONG*)mir_alloc( (nif->IPcount+1) * sizeof(LONG) );
+ memcpy( nif->IP, src.item[idx].IP, (nif->IPcount+1) * sizeof(LONG) );
+ INCUPD(change, INCUPD_UPDATED);
+ }
+ }
+ if ( nif->Bound != src.item[idx].Bound ) {
+ nif->Bound = src.item[idx].Bound;
+ INCUPD(change, INCUPD_CONN_BIND);
+ }
+ } else {
+ trg->count++;
+ trg->item = (PNETWORK_INTERFACE)mir_realloc( trg->item, trg->count * sizeof(NETWORK_INTERFACE) );
+ nif = &(trg->item[trg->count - 1]);
+ ZeroMemory(nif, sizeof(NETWORK_INTERFACE));
+ nif->AdapterName = src.item[idx].AdapterName ? mir_strdup( src.item[idx].AdapterName ) : NULL;
+ nif->FriendlyName = src.item[idx].FriendlyName ? mir_wstrdup( src.item[idx].FriendlyName ) : NULL;
+ nif->IPstr = src.item[idx].IPstr ? strdup( src.item[idx].IPstr ) : NULL;
+ nif->IPcount = src.item[idx].IPcount;
+ nif->Bound = src.item[idx].Bound;
+ if ( nif->IPcount > 0 ) {
+ nif->IP = (LONG*)mir_alloc( (nif->IPcount+1) * sizeof(LONG) );
+ memcpy( nif->IP, src.item[idx].IP, (nif->IPcount+1) * sizeof(LONG) );
+ }
+ INCUPD(change, INCUPD_UPDATED);
+ }
+ }
+ for (idx = 0 ; idx < trg->count ; idx++) {
+ if ( trg->item[idx].Disabled ) continue;
+ nif = Find_NIF_AdapterName( src, trg->item[idx].AdapterName );
+ if ( ! nif ) {
+ if ( trg->item[idx].Bound ) {
+ INCUPD(change, INCUPD_CONN_LOST );
+ UnboundConnections( trg->item[idx].IP, NULL );
+ } else {
+ INCUPD(change, INCUPD_UPDATED );
+ }
+ if (trg->item[idx].IPstr) free(trg->item[idx].IPstr);
+ if (trg->item[idx].IP) free(trg->item[idx].IP);
+ trg->item[idx].IPstr = NULL;
+ trg->item[idx].IPcount = 0;
+ trg->item[idx].IP = NULL;
+ trg->item[idx].Bound = FALSE;
+ trg->item[idx].Disabled = 1;
+ }
+ }
+ return change;
+}
+
+/* ################################################################################ */
+
+wchar_t *Print_NIF (PNETWORK_INTERFACE nif) {
+ ZeroMemory( tempstr, sizeof(tempstr) );
+ mir_snwprintf( tempstr, L"%s:\t%s", nif->FriendlyName, nif->IPstr ? _A2T(nif->IPstr) : TranslateT("disconnected"));
+ return tempstr;
+}
+
+wchar_t *Print_NIF_List (NETWORK_INTERFACE_LIST list, wchar_t *msg) {
+ UCHAR idx;
+ int pos = 0;
+
+ ZeroMemory( tempstr, sizeof(tempstr) );
+ for( idx = 0 ; idx < list.count ; idx++ ) {
+ pos += mir_snwprintf( tempstr+pos, _countof(tempstr), L"%s:\t%s%s%s\n",
+ list.item[idx].FriendlyName,
+ list.item[idx].Bound ? L"[u]":L"",
+ list.item[idx].IPstr ? _A2T(list.item[idx].IPstr) : TranslateT("disconnected"),
+ list.item[idx].Bound ? L"[/u]":L""
+ );
+ }
+ if ( msg ) mir_wstrcat(tempstr, msg); else tempstr[mir_wstrlen(tempstr)-1] = 0;
+ return tempstr;
+}
+
+/* ################################################################################ */
+
+void Free_NIF (PNETWORK_INTERFACE nif) {
+ if (nif->AdapterName) free(nif->AdapterName);
+ if (nif->FriendlyName) free(nif->FriendlyName);
+ if (nif->IPstr) free(nif->IPstr);
+ if (nif->IP) free(nif->IP);
+ ZeroMemory(nif, sizeof(NETWORK_INTERFACE));
+}
+
+void Free_NIF_List (NETWORK_INTERFACE_LIST *list) {
+ UCHAR idx;
+
+ for( idx = 0 ; idx < list->count ; idx++ ) {
+ Free_NIF( &(list->item[idx]) );
+ }
+ free( list->item );
+ ZeroMemory(list, sizeof(NETWORK_INTERFACE_LIST));
+}
+
+/* ################################################################################ */
+
+void Parse_Range ( PIP_RANGE range, wchar_t *str, BOOL prioritized ) {
+ wchar_t *ext;
+ unsigned long num;
+
+ range->cmpType = CMP_SKIP;
+
+ if ((str[0] == '!' && ! prioritized) || (str[0] != '!' && prioritized)) {
+ range->mask = range->net = 0L;
+ return;
+ }
+ if (str[0] == '!') str++;
+
+ // ip/mask
+ if ( (ext = wcschr( str, '/' )) != NULL ) {
+ ext[0] = 0; ext++;
+
+ // ip/bits (10.0.0.1/16)
+ if ( wcsspn(ext, DIGITS) == mir_wstrlen(ext) ) {
+ num = _wtol(ext);
+ if ( num >= 0 && num <= 32 && (range->net = inet_addr(_T2A(str))) != INADDR_NONE ) {
+ range->cmpType = CMP_MASK;
+ range->mask = NETORDER(num ? ~(0xFFFFFFFF >> (num)) : ~0);
+ range->net = range->net & range->mask;
+ }
+ } else {
+
+ // ip/subnet (10.0.0.1/255.255.0.0)
+ if ( (range->net = inet_addr(_T2A(str))) != INADDR_NONE && (range->mask = inet_addr(_T2A(ext))) != INADDR_NONE ) {
+ for ( num = 0 ; num < 32 ; num++ ) {
+ if ( range->mask == NETORDER(num ? ~(0xFFFFFFFF >> (32-num)) : ~0)) {
+ range->cmpType = CMP_MASK;
+ range->net = range->net & range->mask;
+ break;
+ }
+ }
+ }}
+ } else {
+
+ // ipbegin-end
+ if ( (ext = wcschr( str, '-' )) != NULL ) {
+ ext[0] = 0; ext++;
+
+ // ipA.B.C.D1-D2 (10.0.0.1-12)
+ if ( wcsspn(ext, DIGITS) == mir_wstrlen(ext) ) {
+ num = _wtol(ext);
+ if ( num > 0 && num <= 255 && (range->loIP = inet_addr(_T2A(str))) != INADDR_NONE && (range->loIP >> 24) <= num ) {
+ range->cmpType = CMP_SPAN;
+ range->hiIP = ((range->loIP & 0x00FFFFFF) | (num << 24));
+ range->loIP = (range->loIP);
+ }
+ } else {
+
+ // ipstart-ipend (10.0.0.1-10.0.10.255)
+ if ( (range->loIP = inet_addr(_T2A(str))) != INADDR_NONE && (range->hiIP = inet_addr(_T2A(ext))) != INADDR_NONE ) {
+
+ range->loIP = (range->loIP);
+ range->hiIP = (range->hiIP);
+ if ( range->loIP <= range->hiIP ) {
+ range->cmpType = CMP_SPAN;
+ }
+ }
+ }} else {
+
+ // ip
+ if ( mir_wstrlen(str) > 0 && (range->net = inet_addr(_T2A(str))) != INADDR_NONE ) {
+ range->cmpType = CMP_MASK;
+ range->mask = 0xFFFFFFFF;
+ }}}
+
+ if ( range->cmpType == CMP_SKIP ) {
+ range->mask = range->net = 0L;
+ }
+}
+
+int Create_Range_List ( IP_RANGE_LIST *list, wchar_t *str, BOOL prioritized ) {
+ wchar_t *range, *rest, *tmp;
+ int size, idx;
+
+ ZeroMemory(list, sizeof(IP_RANGE_LIST));
+
+ // get expected number of ranges
+ range = str;
+ size = mir_wstrlen( range ) > 0 ? 1 : 0;
+ while ( range[0] ) { if ( range[0] == ';') size++; range++; };
+
+ if (size == 0) return 0;
+
+ // alloc required space
+ list->item = (PIP_RANGE)mir_alloc( size * sizeof( IP_RANGE ) );
+ ZeroMemory( list->item, size * sizeof( IP_RANGE ) );
+
+ tmp = range = rest = mir_wstrdup( str );
+ idx = 0;
+ while ( rest && rest[0] ) {
+ rest = wcschr( rest, ';' );
+ if ( rest != NULL ) {
+ rest[0] = 0;
+ rest++;
+ }
+ Parse_Range( &(list->item[idx]), range, prioritized );
+ if ( list->item[idx].cmpType != CMP_SKIP ) idx++;
+ range = rest;
+ }
+
+ list->count = idx;
+ list->item = (PIP_RANGE)mir_realloc( list->item, (idx+1) * sizeof( IP_RANGE ) );
+
+ ZeroMemory( &(list->item[idx]), sizeof( IP_RANGE ) );
+ list->item[idx].cmpType = CMP_END;
+
+ free( tmp );
+
+ return 0;
+}
+
+int Match_Range_List (IP_RANGE_LIST range, NETWORK_INTERFACE_LIST nif) {
+ PIP_RANGE rng;
+ UCHAR idx;
+ ULONG *ip;
+
+ if ( range.count == 0 || nif.count == 0 ) return 0;
+
+ rng = range.item;
+ while( rng->cmpType != CMP_END ) {
+
+ switch ( rng->cmpType ) {
+ case CMP_SKIP:
+ break;
+
+ case CMP_MASK:
+ for ( idx = 0 ; idx < nif.count ; idx++ ) {
+ ip = (ULONG *)nif.item[idx].IP;
+ while (ip && *ip) {
+ if ( (ULONG)(*ip & rng->mask) == rng->net ) return 1;
+ ip++;
+ }
+ }
+ break;
+
+ case CMP_SPAN:
+ for ( idx = 0 ; idx < nif.count ; idx++ ) {
+ ip = (ULONG *)nif.item[idx].IP;
+ while (ip && *ip) {
+ if ( (NETORDER(rng->loIP) <= NETORDER(*ip)) && (NETORDER(*ip) <= NETORDER(rng->hiIP)) ) return 1;
+ ip++;
+ }
+ }
+ break;
+ }
+ rng++;
+ }
+
+ return 0;
+}
+
+void Free_Range_List (IP_RANGE_LIST *list) {
+ if ( list->item ) free( list->item );
+ ZeroMemory(list, sizeof(IP_RANGE_LIST));
+}
+
+
+int ManageConnections (WPARAM wParam,LPARAM lParam) {
+ NETLIBCONNECTIONEVENTINFO *info = (NETLIBCONNECTIONEVENTINFO *)wParam;
+ int found;
+ UCHAR i;
+
+ EnterCriticalSection(&csConnection_List);
+ found = -1;
+ for (i=0 ; i<Connection_List.count ; i++) {
+ if ( Connection_List.item[i].IP == info->local.sin_addr.s_addr && Connection_List.item[i].Port == info->local.sin_port ) {
+ found = i;
+ break;
+ }
+ }
+ if ( (found >= 0 && info->connected) || (found == -1 && !info->connected)) {
+ LeaveCriticalSection(&csConnection_List);
+ return 0;
+ }
+ if ( found >= 0 ) {
+ Connection_List.count--;
+ for( i=found ; i<Connection_List.count ; i++ ) memcpy( &(Connection_List.item[i]), &(Connection_List.item[i+1]), sizeof(ACTIVE_CONNECTION) );
+ } else {
+ if ( Connection_List.count >= Connection_List._alloc ) {
+ Connection_List._alloc += 10;
+ Connection_List.item = (PACTIVE_CONNECTION)mir_realloc( Connection_List.item, Connection_List._alloc * sizeof(ACTIVE_CONNECTION) );
+ }
+ Connection_List.item[Connection_List.count].IP = info->local.sin_addr.s_addr;
+ Connection_List.item[Connection_List.count].Port = info->local.sin_port;
+ Connection_List.count++;
+ }
+ LeaveCriticalSection(&csConnection_List);
+
+ SetEvent( hEventRebound );
+
+ return 0;
+}
+
+void UnboundConnections ( LONG *OldIP, LONG *NewIP ) {
+ UCHAR i, j;
+ LONG *IP;
+
+ while ( OldIP != NULL && *OldIP != 0 ) {
+ IP = NewIP;
+ while ( IP != NULL && *IP != 0 && *IP != *OldIP ) IP++;
+ if ( IP == NULL || *IP != *OldIP ) {
+ EnterCriticalSection(&csConnection_List);
+ i = 0;
+ while ( i < Connection_List.count ) {
+ if (Connection_List.item[i].IP == (ULONG)*OldIP) {
+ Connection_List.count--;
+ for( j=i ; j<Connection_List.count ; j++ ) memcpy( &(Connection_List.item[j]), &(Connection_List.item[j+1]), sizeof(ACTIVE_CONNECTION) );
+ } else {
+ i++;
+ }
+ }
+ LeaveCriticalSection(&csConnection_List);
+ }
+ OldIP++;
+ }
+}
diff --git a/plugins/ProxySwitch/src/main.cpp b/plugins/ProxySwitch/src/main.cpp
new file mode 100644
index 0000000000..5266e901aa
--- /dev/null
+++ b/plugins/ProxySwitch/src/main.cpp
@@ -0,0 +1,367 @@
+/*
+proxySwitch
+
+The plugin watches IP address changes, reports them via popups and adjusts
+the proxy settings of Miranda and Internet Explorer accordingly.
+*/
+
+#include "stdafx.h"
+
+CMPlugin g_plugin;
+
+PLUGININFOEX pluginInfoEx =
+{
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ // {4DF0C267-6EFB-4410-B651-385F87158509}
+ { 0x4df0c267, 0x6efb, 0x4410,{ 0xb6, 0x51, 0x38, 0x5f, 0x87, 0x15, 0x85, 0x9 } }
+};
+
+CMPlugin::CMPlugin() :
+ PLUGIN<CMPlugin>(MODULENAME, pluginInfoEx)
+{}
+
+HGENMENU hEnableDisablePopupMenu = 0;
+
+NETWORK_INTERFACE_LIST NIF_List;
+CRITICAL_SECTION csNIF_List;
+ACTIVE_CONNECTION_LIST Connection_List;
+CRITICAL_SECTION csConnection_List;
+HANDLE hEventRebound = NULL;
+
+wchar_t opt_useProxy[MAX_IPLIST_LENGTH];
+wchar_t opt_noProxy[MAX_IPLIST_LENGTH];
+wchar_t opt_hideIntf[MAX_IPLIST_LENGTH];
+UINT opt_defaultColors;
+UINT opt_popups;
+UINT opt_showProxyState;
+UINT opt_miranda;
+UINT opt_ie;
+UINT opt_firefox;
+UINT opt_showMyIP;
+UINT opt_showProxyIP;
+UINT opt_alwayReconnect;
+UINT opt_startup;
+UINT opt_not_restarted;
+COLORREF opt_bgColor;
+COLORREF opt_txtColor;
+
+UINT opt_popupPluginInstalled;
+
+static HANDLE hEventConnect = NULL;
+static HANDLE hEventDisconnect = NULL;
+static HANDLE hSvcCopyClip0 = NULL;
+static HANDLE hSvcCopyClip1 = NULL;
+static HANDLE hSvcCopyClip2 = NULL;
+static HANDLE hSvcCopyClip3 = NULL;
+static HANDLE hSvcCopyClip4 = NULL;
+static HANDLE hSvcCopyClip5 = NULL;
+static HANDLE hSvcPopupSwitch = NULL;
+static HANDLE hSvcProxyDisable = NULL;
+static HANDLE hSvcProxyEnable = NULL;
+static HANDLE hSvcShowMyIP = NULL;
+
+/* ################################################################################ */
+
+static int ShowMyIPAddrs(WPARAM wParam, LPARAM lParam)
+{
+ PopupMyIPAddrs(NULL);
+ return 0;
+}
+
+void PopupMyIPAddrs(wchar_t *msg)
+{
+ POPUPDATAW ppd;
+ NETWORK_INTERFACE_LIST list;
+
+ ZeroMemory(&ppd, sizeof(ppd));
+
+ if (Create_NIF_List_Ex(&list) >= 0) {
+
+ wcsncpy_s(ppd.lpwzText, Print_NIF_List(list, msg), _TRUNCATE);
+
+ if (opt_popupPluginInstalled) {
+ LoadSettings();
+ ppd.lchIcon = LoadIcon(g_plugin.getInst(), MAKEINTRESOURCE(IDI_PROXY));
+ wcsncpy_s(ppd.lpwzContactName, TranslateT("Current IP address"), _TRUNCATE);
+ ppd.colorBack = opt_defaultColors ? 0 : opt_bgColor;
+ ppd.colorText = opt_defaultColors ? 0 : opt_txtColor;
+ CallService(MS_POPUP_ADDPOPUP, (WPARAM)&ppd, 0);
+ }
+ else {
+ MessageBox(NULL, ppd.lpwzText, _A2T(MODULENAME), MB_OK | MB_ICONINFORMATION);
+ }
+
+ Free_NIF_List(&list);
+ }
+}
+
+static int ProxyEnable(WPARAM wParam, LPARAM lParam)
+{
+ Set_IE_Proxy_Status(1);
+ Set_Miranda_Proxy_Status(1);
+ Set_Firefox_Proxy_Status(1);
+ return 0;
+}
+
+static int ProxyDisable(WPARAM wParam, LPARAM lParam)
+{
+ Set_IE_Proxy_Status(0);
+ Set_Miranda_Proxy_Status(0);
+ Set_Firefox_Proxy_Status(0);
+ return 0;
+}
+
+/* ################################################################################ */
+
+void CopyIP2Clipboard(UCHAR idx)
+{
+ EnterCriticalSection(&csNIF_List);
+ if (NIF_List.item[idx].IPcount == 0) {
+ LeaveCriticalSection(&csNIF_List);
+ return;
+ }
+ if (!OpenClipboard(NULL)) {
+ LeaveCriticalSection(&csNIF_List);
+ return;
+ }
+ EmptyClipboard();
+ SetClipboardData(CF_UNICODETEXT, (HANDLE)NIF_List.item[idx].IPstr);
+ CloseClipboard();
+ LeaveCriticalSection(&csNIF_List);
+}
+
+static int CopyIP2Clipboard0(WPARAM wParam, LPARAM lParam) { CopyIP2Clipboard(0); return 0; }
+static int CopyIP2Clipboard1(WPARAM wParam, LPARAM lParam) { CopyIP2Clipboard(1); return 0; }
+static int CopyIP2Clipboard2(WPARAM wParam, LPARAM lParam) { CopyIP2Clipboard(2); return 0; }
+static int CopyIP2Clipboard3(WPARAM wParam, LPARAM lParam) { CopyIP2Clipboard(3); return 0; }
+static int CopyIP2Clipboard4(WPARAM wParam, LPARAM lParam) { CopyIP2Clipboard(4); return 0; }
+static int CopyIP2Clipboard5(WPARAM wParam, LPARAM lParam) { CopyIP2Clipboard(5); return 0; }
+
+void UpdateInterfacesMenu(void)
+{
+ UCHAR idx;
+ CMenuItem mi(g_plugin);
+ char svc[60];
+
+ if (!opt_showProxyIP && !opt_not_restarted) return;
+
+ EnterCriticalSection(&csNIF_List);
+ for (idx = 0; idx < NIF_List.count; idx++) {
+ if (NIF_List.item[idx].MenuItem) {
+ // set new name and flags
+ //mi.name.w = Print_NIF(&(NIF_List.item[idx]));
+ //if (NIF_List.item[idx].IPcount == 0) mi.flags |= CMIF_GRAYED;
+ //mi.flags |= CMIM_FLAGS | CMIM_NAME;
+ // update menu item
+ Menu_ModifyItem(NIF_List.item[idx].MenuItem, Print_NIF(&(NIF_List.item[idx])), INVALID_HANDLE_VALUE, CMIF_GRAYED);
+ //CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)NIF_List.item[idx].MenuItem, (LPARAM)&mi);
+ }
+ else {
+ // add a new menu item
+ sprintf(svc, "%s%d", MS_PROXYSWITCH_COPYIP2CLIP, idx);
+ mi.position = 0xC00000;
+ mi.flags = CMIF_UNICODE;
+ mi.root = g_plugin.addRootMenu(MO_MAIN, LPGENW("Proxy Settings && Interfaces"), 0xC0000000);
+ Menu_ConfigureItem(mi.root, MCI_OPT_UID, "68AB766F-09F1-4C4C-9AE1-4135617741C9");
+
+ SET_UID(mi, 0x8295e40d, 0xa262, 0x434b, 0xa4, 0xb3, 0x57, 0x6b, 0xe0, 0xfc, 0x8f, 0x68);
+ mi.name.w = Print_NIF(&(NIF_List.item[idx]));
+ mi.pszService = svc;
+ //mi.pszPopupName = Translate("Proxy Settings && Interfaces");
+ //mi.popupPosition = 0xC0000000;
+ NIF_List.item[idx].MenuItem = Menu_AddMainMenuItem(&mi);
+ // menu cannot be grayed when creating, so we have to do it after that
+ if (NIF_List.item[idx].IPcount == 0) {
+ //ZeroMemory(&mi, sizeof(mi));
+ //mi.cbSize = sizeof(mi);
+ //mi.flags |= CMIF_GRAYED;
+ Menu_ModifyItem(NIF_List.item[idx].MenuItem, Print_NIF(&(NIF_List.item[idx])), INVALID_HANDLE_VALUE, CMIF_GRAYED);
+ //CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)NIF_List.item[idx].MenuItem, (LPARAM)&mi);
+ }
+ // create and register service for this menu item
+ switch (idx) {
+ case 0: hSvcCopyClip0 = CreateServiceFunction(svc, CopyIP2Clipboard0); break;
+ case 1: hSvcCopyClip1 = CreateServiceFunction(svc, CopyIP2Clipboard1); break;
+ case 2: hSvcCopyClip2 = CreateServiceFunction(svc, CopyIP2Clipboard2); break;
+ case 3: hSvcCopyClip3 = CreateServiceFunction(svc, CopyIP2Clipboard3); break;
+ case 4: hSvcCopyClip4 = CreateServiceFunction(svc, CopyIP2Clipboard4); break;
+ case 5: hSvcCopyClip5 = CreateServiceFunction(svc, CopyIP2Clipboard5); break;
+ }
+ }
+ }
+ LeaveCriticalSection(&csNIF_List);
+}
+
+/* ################################################################################ */
+
+void UpdatePopupMenu(BOOL State)
+{
+ CMenuItem mi(g_plugin);
+
+ if (!hEnableDisablePopupMenu) return;
+
+ //ZeroMemory(&mi, sizeof(mi));
+ //mi.cbSize = sizeof(mi);
+
+ // popup is now disabled
+ if (State == FALSE) {
+ mi.name.w = LPGENW("Enable &IP change notification");
+ mi.hIcon = LoadIcon(g_plugin.getInst(), MAKEINTRESOURCE(IDI_NOTIF_0));
+
+ // popup is now enabled
+ }
+ else {
+ mi.name.w = LPGENW("Disable &IP change notification");
+ mi.hIcon = LoadIcon(g_plugin.getInst(), MAKEINTRESOURCE(IDI_NOTIF_1));
+ }
+ //mi.flags = CMIM_ICON | CMIM_NAME;
+
+ // update menu item
+ Menu_ModifyItem(hEnableDisablePopupMenu, mi.name.w);
+ //CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hEnableDisablePopupMenu, (LPARAM)&mi);
+}
+
+static int PopupSwitch(WPARAM wParam, LPARAM lParam)
+{
+ opt_popups = !opt_popups;
+ UpdatePopupMenu(opt_popups);
+ SaveSettings();
+ return 0;
+}
+
+/* ################################################################################ */
+
+int CMPlugin::Load()
+{
+ char proxy = -1;
+ IP_RANGE_LIST range;
+
+ opt_startup = FALSE;
+ opt_not_restarted = FALSE;
+
+ LoadSettings();
+
+ InitializeCriticalSection(&csConnection_List);
+ InitializeCriticalSection(&csNIF_List);
+
+ ZeroMemory(&Connection_List, sizeof(Connection_List));
+ Create_NIF_List_Ex(&NIF_List);
+
+ if (opt_ie || opt_miranda || opt_firefox) {
+ Create_Range_List(&range, opt_useProxy, TRUE);
+ if (Match_Range_List(range, NIF_List)) proxy = 1;
+ Free_Range_List(&range);
+ if (proxy == -1) {
+ Create_Range_List(&range, opt_noProxy, FALSE);
+ if (Match_Range_List(range, NIF_List)) proxy = 0;
+ Free_Range_List(&range);
+ }
+ if (proxy == -1) {
+ Create_Range_List(&range, opt_useProxy, FALSE);
+ if (Match_Range_List(range, NIF_List)) proxy = 1;
+ Free_Range_List(&range);
+ }
+ if (proxy != -1) {
+ if (opt_miranda && Get_Miranda_Proxy_Status() != proxy) Set_Miranda_Proxy_Status(proxy);
+ if (opt_ie && Get_IE_Proxy_Status() != proxy) Set_IE_Proxy_Status(proxy);
+ if (opt_firefox && Get_Firefox_Proxy_Status() != proxy) Set_Firefox_Proxy_Status(proxy);
+ }
+ }
+
+ HookEvent(ME_OPT_INITIALISE, OptInit);
+ HookEvent(ME_SYSTEM_MODULESLOADED, Init);
+ HookEvent(ME_NETLIB_EVENT_CONNECTED, ManageConnections);
+ HookEvent(ME_NETLIB_EVENT_DISCONNECTED, ManageConnections);
+
+ return 0;
+}
+
+int Init(WPARAM wParam, LPARAM lParam)
+{
+ CMenuItem mi(g_plugin);
+
+ opt_popupPluginInstalled = ServiceExists(MS_POPUP_ADDPOPUP);
+
+
+ hEventRebound = CreateEvent(NULL, TRUE, FALSE, NULL);
+ mir_forkthread(IP_WatchDog, 0);
+
+ if (opt_showMyIP) {
+ hSvcShowMyIP = CreateServiceFunction(MS_PROXYSWITCH_SHOWMYIPADDRS, ShowMyIPAddrs);
+ //ZeroMemory(&mi, sizeof(mi));
+ //mi.cbSize = sizeof(mi);
+ SET_UID(mi, 0x53b0835b, 0x7162, 0x4272, 0x83, 0x3b, 0x3f, 0x60, 0x9e, 0xe, 0x76, 0x4a);
+ mi.position = 0xC0000000;
+ mi.flags = CMIF_UNICODE;
+ mi.hIcon = LoadIcon(g_plugin.getInst(), MAKEINTRESOURCE(IDI_LOGO));
+ mi.name.w = LPGENW("Show my &IP Addresses");
+ mi.pszService = MS_PROXYSWITCH_SHOWMYIPADDRS;
+ Menu_AddMainMenuItem(&mi);
+ }
+
+ if (opt_showProxyIP) {
+
+ hSvcProxyDisable = CreateServiceFunction(MS_PROXYSWITCH_PROXYDISABLE, ProxyDisable);
+ //ZeroMemory(&mi, sizeof(mi));
+ //mi.cbSize = sizeof(mi);
+ SET_UID(mi, 0xf93289a9, 0x3bad, 0x424b, 0xb2, 0x72, 0x14, 0xa7, 0x45, 0xa5, 0x8, 0x9c);
+ mi.position = 1;
+ mi.name.w = LPGENW("Disable Proxy");
+ mi.pszService = MS_PROXYSWITCH_PROXYDISABLE;
+ mi.root = g_plugin.addRootMenu(MO_MAIN, LPGENW("Proxy Settings && Interfaces"), 0xC0000000);
+ Menu_ConfigureItem(mi.root, MCI_OPT_UID, "A9684E9E-E621-4962-986F-576897928D27");
+ //mi.pszPopupName = Translate("Proxy Settings && Interfaces");
+ //mi.popupPosition = 0xC0000000;
+ Menu_AddMainMenuItem(&mi);
+
+ hSvcProxyEnable = CreateServiceFunction(MS_PROXYSWITCH_PROXYENABLE, ProxyEnable);
+ //ZeroMemory(&mi, sizeof(mi));
+ //mi.cbSize = sizeof(mi);
+ mi.position = 1;
+ mi.name.w = LPGENW("Enable Proxy");
+ mi.pszService = MS_PROXYSWITCH_PROXYENABLE;
+ mi.root = g_plugin.addRootMenu(MO_MAIN, LPGENW("Proxy Settings && Interfaces"), 0xC0000000);
+ Menu_ConfigureItem(mi.root, MCI_OPT_UID, "B37E5BBE-19CF-4C78-AE53-A0DB11656C36");
+ //mi.pszPopupName = Translate("Proxy Settings && Interfaces");
+ //mi.popupPosition = 0xC0000000;
+ Menu_AddMainMenuItem(&mi);
+
+ UpdateInterfacesMenu();
+ }
+
+ if (opt_popupPluginInstalled) {
+ hSvcPopupSwitch = CreateServiceFunction(MS_PROXYSWITCH_POPUPSWITCH, PopupSwitch);
+ //ZeroMemory(&mi, sizeof(mi));
+ //mi.cbSize = sizeof(mi);
+ mi.name.w = LPGENW("IP Change Notification");
+ mi.hIcon = LoadIcon(g_plugin.getInst(), MAKEINTRESOURCE(IDI_LOGO));
+ mi.root = g_plugin.addRootMenu(MO_MAIN, LPGENW("PopUps"), 0xC0000000);
+ Menu_ConfigureItem(mi.root, MCI_OPT_UID, "185AC334-E90E-46C6-83A2-D4E36CB257D9");
+ //mi.pszPopupName = Translate("PopUps");
+ mi.pszService = MS_PROXYSWITCH_POPUPSWITCH;
+ hEnableDisablePopupMenu = Menu_AddMainMenuItem(&mi);
+
+ UpdatePopupMenu(opt_popups);
+ }
+
+ return 0;
+}
+
+int CMPlugin::Unload()
+{
+ if (hEventRebound)
+ CloseHandle(hEventRebound);
+ EnterCriticalSection(&csNIF_List);
+ Free_NIF_List(&NIF_List);
+ LeaveCriticalSection(&csNIF_List);
+ DeleteCriticalSection(&csNIF_List);
+ DeleteCriticalSection(&csConnection_List);
+ return 0;
+}
diff --git a/plugins/ProxySwitch/src/opt.cpp b/plugins/ProxySwitch/src/opt.cpp
new file mode 100644
index 0000000000..44273f705e
--- /dev/null
+++ b/plugins/ProxySwitch/src/opt.cpp
@@ -0,0 +1,191 @@
+/*
+proxySwitch
+
+The plugin watches IP address changes, reports them via popups and adjusts
+the proxy settings of Miranda and Internet Explorer accordingly.
+*/
+
+#include "stdafx.h"
+
+int help_shown;
+
+void ShowHelp( HWND hdlg, int showhide_help ) {
+ int showhide_others = showhide_help == SW_SHOW ? SW_HIDE : SW_SHOW;
+ help_shown = showhide_help;
+
+ ShowWindow(GetDlgItem(hdlg, IDC_HELP_1), showhide_help);
+ ShowWindow(GetDlgItem(hdlg, IDC_HELP_2), showhide_help);
+ ShowWindow(GetDlgItem(hdlg, IDC_HELP_3), showhide_help);
+
+ ShowWindow(GetDlgItem(hdlg, IDC_CHECK_MIRANDA), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_CHECK_IE), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_CHECK_FIREFOX), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_CHECK_PROXYIPMENU), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_CHECK_SHOWMYIPMENU), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_CHECK_DEFAULTCOLORS), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_CHECK_SHOWPROXYSTATUS), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_CHECK_ALWAY_RECONNECT), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_CHECK_POPUPS), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_BGCOLOR), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_TEXTCOLOR), showhide_others);
+ ShowWindow(GetDlgItem(hdlg, IDC_EDIT_HIDEINTF), showhide_others);
+}
+
+
+BOOL CALLBACK OptionsProc(HWND hdlg,UINT msg,WPARAM wparam,LPARAM lparam) {
+
+ switch(msg) {
+
+ case WM_INITDIALOG:
+ opt_startup = TRUE;
+ LoadSettings();
+ ShowHelp( hdlg, SW_HIDE );
+ SetDlgItemText(hdlg, IDC_EDIT_USEPROXY, opt_useProxy);
+ SetDlgItemText(hdlg, IDC_EDIT_NOPROXY, opt_noProxy);
+ CheckDlgButton(hdlg, IDC_CHECK_MIRANDA, opt_miranda ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hdlg, IDC_CHECK_IE, opt_ie ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hdlg, IDC_CHECK_FIREFOX, opt_firefox ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hdlg, IDC_CHECK_SHOWMYIPMENU, opt_showMyIP ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hdlg, IDC_CHECK_PROXYIPMENU, opt_showProxyIP ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hdlg, IDC_CHECK_ALWAY_RECONNECT, opt_alwayReconnect ? BST_CHECKED : BST_UNCHECKED);
+ SetDlgItemText(hdlg, IDC_EDIT_HIDEINTF, opt_hideIntf);
+ SendDlgItemMessage(hdlg,IDC_BGCOLOR,CPM_SETCOLOUR,0,opt_bgColor);
+ SendDlgItemMessage(hdlg,IDC_TEXTCOLOR,CPM_SETCOLOUR,0,opt_txtColor);
+ CheckDlgButton(hdlg, IDC_CHECK_POPUPS, opt_popups ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hdlg, IDC_CHECK_DEFAULTCOLORS, opt_defaultColors ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hdlg, IDC_CHECK_SHOWPROXYSTATUS, opt_showProxyState ? BST_CHECKED : BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hdlg, IDC_CHECK_FIREFOX), Firefox_Installed());
+ EnableWindow(GetDlgItem(hdlg, IDC_CHECK_POPUPS), opt_popupPluginInstalled);
+ EnableWindow(GetDlgItem(hdlg, IDC_BGCOLOR), opt_popupPluginInstalled && opt_popups && !opt_defaultColors);
+ EnableWindow(GetDlgItem(hdlg, IDC_TEXTCOLOR), opt_popupPluginInstalled && opt_popups && !opt_defaultColors);
+ EnableWindow(GetDlgItem(hdlg, IDC_CHECK_DEFAULTCOLORS), opt_popupPluginInstalled && opt_popups);
+ EnableWindow(GetDlgItem(hdlg, IDC_CHECK_SHOWPROXYSTATUS), opt_popupPluginInstalled && opt_popups);
+ ShowWindow(GetDlgItem(hdlg, IDC_RESTARTREQUIRED), opt_not_restarted ? SW_SHOW : SW_HIDE);
+ TranslateDialogDefault(hdlg);
+ opt_startup = FALSE;
+ return 1;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lparam)->code) {
+ case PSN_APPLY:
+ opt_not_restarted = opt_not_restarted || IsDlgButtonChecked(hdlg,IDC_CHECK_PROXYIPMENU) != opt_showProxyIP || IsDlgButtonChecked(hdlg,IDC_CHECK_SHOWMYIPMENU) != opt_showMyIP;
+ ShowWindow(GetDlgItem(hdlg, IDC_RESTARTREQUIRED), opt_not_restarted ? SW_SHOW : SW_HIDE);
+ GetDlgItemText(hdlg,IDC_EDIT_NOPROXY,opt_noProxy,MAX_IPLIST_LENGTH);
+ GetDlgItemText(hdlg,IDC_EDIT_USEPROXY,opt_useProxy,MAX_IPLIST_LENGTH);
+ GetDlgItemText(hdlg,IDC_EDIT_HIDEINTF,opt_hideIntf,MAX_IPLIST_LENGTH);
+ opt_miranda = IsDlgButtonChecked(hdlg,IDC_CHECK_MIRANDA);
+ opt_ie = IsDlgButtonChecked(hdlg,IDC_CHECK_IE);
+ opt_firefox = IsDlgButtonChecked(hdlg,IDC_CHECK_FIREFOX);
+ opt_showMyIP = IsDlgButtonChecked(hdlg,IDC_CHECK_SHOWMYIPMENU);
+ opt_showProxyIP = IsDlgButtonChecked(hdlg,IDC_CHECK_PROXYIPMENU);
+ opt_alwayReconnect = IsDlgButtonChecked(hdlg,IDC_CHECK_ALWAY_RECONNECT);
+ opt_popups = IsDlgButtonChecked(hdlg,IDC_CHECK_POPUPS);
+ opt_defaultColors = IsDlgButtonChecked(hdlg,IDC_CHECK_DEFAULTCOLORS);
+ opt_showProxyState = IsDlgButtonChecked(hdlg,IDC_CHECK_SHOWPROXYSTATUS);
+ opt_bgColor = SendDlgItemMessage(hdlg,IDC_BGCOLOR,CPM_GETCOLOUR,0,0);
+ opt_txtColor = SendDlgItemMessage(hdlg,IDC_TEXTCOLOR,CPM_GETCOLOUR,0,0);
+ SaveSettings();
+ UpdatePopupMenu(opt_popups);
+ return 1;
+ }
+ break;
+
+ case WM_COMMAND:
+ if (opt_startup) return 0;
+ if (HIWORD(wparam)==BN_CLICKED && GetFocus()==(HWND)lparam && LOWORD(wparam)!=IDC_BTN_HELP) SendMessage(GetParent(hdlg),PSM_CHANGED,0,0);
+ switch(LOWORD(wparam)) {
+
+ case IDC_BTN_HELP:
+ ShowHelp( hdlg, help_shown == SW_SHOW ? SW_HIDE : SW_SHOW );
+ break;
+
+ case IDC_EDIT_USEPROXY:
+ case IDC_EDIT_NOPROXY:
+ case IDC_EDIT_HIDEINTF:
+ if (HIWORD(wparam) == EN_CHANGE && (HWND)lparam == GetFocus()) SendMessage(GetParent(hdlg),PSM_CHANGED,0,0);
+ break;
+
+ case IDC_BGCOLOR:
+ case IDC_TEXTCOLOR:
+ if (HIWORD(wparam) == CPN_COLOURCHANGED) SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case IDC_CHECK_PROXYIPMENU:
+ case IDC_CHECK_SHOWMYIPMENU:
+ ShowWindow(GetDlgItem(hdlg, IDC_RESTARTREQUIRED), opt_not_restarted || (IsDlgButtonChecked(hdlg,IDC_CHECK_PROXYIPMENU) != opt_showProxyIP || IsDlgButtonChecked(hdlg,IDC_CHECK_SHOWMYIPMENU) != opt_showMyIP) ? SW_SHOW : SW_HIDE );
+ break;
+
+ case IDC_CHECK_DEFAULTCOLORS:
+ case IDC_CHECK_POPUPS:
+ if ( ! opt_popupPluginInstalled ) break;
+ EnableWindow(GetDlgItem(hdlg, IDC_BGCOLOR), IsDlgButtonChecked(hdlg,IDC_CHECK_POPUPS) && !IsDlgButtonChecked(hdlg,IDC_CHECK_DEFAULTCOLORS));
+ EnableWindow(GetDlgItem(hdlg, IDC_TEXTCOLOR), IsDlgButtonChecked(hdlg,IDC_CHECK_POPUPS) && !IsDlgButtonChecked(hdlg,IDC_CHECK_DEFAULTCOLORS));
+ EnableWindow(GetDlgItem(hdlg, IDC_CHECK_DEFAULTCOLORS), IsDlgButtonChecked(hdlg,IDC_CHECK_POPUPS));
+ EnableWindow(GetDlgItem(hdlg, IDC_CHECK_SHOWPROXYSTATUS), IsDlgButtonChecked(hdlg,IDC_CHECK_POPUPS));
+ SendMessage(GetParent(hdlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hdlg,0);
+ break;
+ }
+ return 0;
+}
+
+
+int OptInit(WPARAM wParam,LPARAM lParam) {
+ OPTIONSDIALOGPAGE odp = { 0 };
+
+ //ZeroMemory(&odp,sizeof(odp));
+ //odp.cbSize=sizeof(odp);
+ odp.position=95600;
+ odp.hInstance= g_plugin.getInst();
+ odp.pszTemplate=MAKEINTRESOURCEA(IDD_OPTIONS);
+ odp.pfnDlgProc=OptionsProc;
+ odp.szGroup.w=LPGENW("Network");
+ odp.szTitle.w= LPGENW("proxySwitch");
+ odp.flags=ODPF_BOLDGROUPS | ODPF_UNICODE;
+ g_plugin.addOptions(wParam, &odp);
+
+ return 0;
+}
+
+void LoadSettings(void) {
+ DBVARIANT dbv;
+ if (db_get(NULL, MODULENAME,"UseProxyIPNets",&dbv)) lstrcpy(opt_useProxy, L""); else lstrcpy(opt_useProxy, dbv.pwszVal);
+ db_free(&dbv);
+ if (db_get(NULL, MODULENAME,"NoProxyIPNets",&dbv)) lstrcpy(opt_noProxy, L""); else lstrcpy(opt_noProxy, dbv.pwszVal);
+ db_free(&dbv);
+ if (db_get(NULL, MODULENAME,"HideInterfaces",&dbv)) lstrcpy(opt_hideIntf, L""); else lstrcpy(opt_hideIntf, dbv.pwszVal);
+ db_free(&dbv);
+ opt_miranda = db_get_b(NULL, MODULENAME,"ManageMirandaProxy",TRUE);
+ opt_ie = db_get_b(NULL,MODULENAME,"ManageIEProxy",FALSE);
+ opt_firefox = db_get_b(NULL,MODULENAME,"ManageFirefoxProxy",FALSE) && Firefox_Installed();
+ opt_alwayReconnect = db_get_b(NULL,MODULENAME,"AlwaysReconnect",FALSE);
+ opt_showMyIP = db_get_b(NULL,MODULENAME,"ShowMyIP",TRUE);
+ opt_showProxyIP = db_get_b(NULL,MODULENAME,"ShowProxyIP",TRUE);
+ opt_popups = db_get_b(NULL,MODULENAME,"PopupEnabled",TRUE);
+ opt_defaultColors = db_get_b(NULL,MODULENAME,"PopupDefaultColors",TRUE);
+ opt_showProxyState = db_get_b(NULL,MODULENAME,"ShowProxyStatus",TRUE);
+ opt_bgColor = db_get_dw(NULL,MODULENAME,"PopupBgColor",GetSysColor(COLOR_BTNFACE));
+ opt_txtColor = db_get_dw(NULL,MODULENAME,"PopupTxtColor",GetSysColor(COLOR_WINDOWTEXT));
+}
+
+void SaveSettings(void) {
+ db_set_ws(NULL, MODULENAME, "UseProxyIPNets", opt_useProxy);
+ db_set_ws(NULL, MODULENAME, "NoProxyIPNets", opt_noProxy);
+ db_set_ws(NULL, MODULENAME, "HideInterfaces", opt_hideIntf);
+ db_set_b(NULL, MODULENAME, "ManageMirandaProxy", (BYTE)opt_miranda );
+ db_set_b(NULL, MODULENAME, "ManageIEProxy", (BYTE)opt_ie );
+ db_set_b(NULL, MODULENAME, "ManageFirefoxProxy", (BYTE)opt_firefox );
+ db_set_b(NULL, MODULENAME, "AlwaysReconnect", (BYTE)opt_alwayReconnect);
+ db_set_b(NULL, MODULENAME, "ShowMyIP", (BYTE)opt_showMyIP );
+ db_set_b(NULL, MODULENAME, "ShowProxyIP", (BYTE)opt_showProxyIP );
+ db_set_b(NULL, MODULENAME, "PopupEnabled", (BYTE)opt_popups );
+ db_set_b(NULL, MODULENAME, "PopupDefaultColors", (BYTE)opt_defaultColors );
+ db_set_b(NULL, MODULENAME, "ShowProxyStatus", (BYTE)opt_showProxyState);
+ db_set_dw(NULL, MODULENAME, "PopupBgColor", (DWORD)opt_bgColor );
+ db_set_dw(NULL, MODULENAME, "PopupTxtColor", (DWORD)opt_txtColor );
+}
diff --git a/plugins/ProxySwitch/src/proxy.cpp b/plugins/ProxySwitch/src/proxy.cpp
new file mode 100644
index 0000000000..5e5ad46e65
--- /dev/null
+++ b/plugins/ProxySwitch/src/proxy.cpp
@@ -0,0 +1,304 @@
+/*
+proxySwitch
+
+The plugin watches IP address changes, reports them via popups and adjusts
+the proxy settings of Miranda and Internet Explorer accordingly.
+*/
+
+#include "stdafx.h"
+
+/* ################################################################################ */
+
+int Enum_Settings(const char *szSetting,LPARAM lParam) {
+ PPROXY_SETTINGS ps = (PPROXY_SETTINGS)lParam;
+
+ if ( strcmp(szSetting, "NLUseProxy") != 0 && stricmp(szSetting, "useproxy") != 0 ) return 0;
+
+ if ( ps->count >= ps->_alloc ) {
+ ps->_alloc += 10;
+ ps->item = (PPROXY_SETTING)mir_realloc( ps->item, ps->_alloc * sizeof(PROXY_SETTING) );
+ ZeroMemory( &(ps->item[ps->count]), 10 * sizeof(PROXY_SETTING) );
+ }
+ strncpy( ps->item[ps->count].ModuleName, ps->_current_module, MAXLABELLENGTH-1 );
+ strncpy( ps->item[ps->count].SettingName, szSetting, MAXLABELLENGTH-1 );
+ ps->count++;
+
+ return 0;
+}
+
+int Enum_Modules(const char *szModuleName,DWORD ofsModuleName,LPARAM lParam) {
+ //DBCONTACTENUMSETTINGS e;
+ MCONTACT hContact = NULL;
+
+ ((PPROXY_SETTINGS)lParam)->_current_module = szModuleName;
+
+ //e.pfnEnumProc = Enum_Settings;
+ //e.lParam = lParam;
+ //e.szModule = szModuleName;
+ db_enum_settings(hContact, (DBSETTINGENUMPROC)Enum_Settings, szModuleName, (void*)lParam);
+ //CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)hContact,(LPARAM)&e);
+
+ return 0;
+}
+
+/* ################################################################################ */
+
+void Create_Proxy_Settings_List ( PPROXY_SETTINGS ps ) {
+
+ ZeroMemory( ps, sizeof(PROXY_SETTINGS) );
+ ps->_alloc = 10;
+ ps->item = (PPROXY_SETTING)mir_alloc( ps->_alloc * sizeof(PROXY_SETTING) );
+ ZeroMemory( ps->item, ps->_alloc * sizeof(PROXY_SETTING) );
+
+ db_enum_modules((DBMODULEENUMPROC)Enum_Modules);
+ //CallService(MS_DB_MODULES_ENUM, (WPARAM)ps, (LPARAM)Enum_Modules );
+
+ ps->_alloc = ps->count+1;
+ ps->item = (PPROXY_SETTING)mir_realloc( ps->item, ps->_alloc * sizeof(PROXY_SETTING) );
+ ZeroMemory( &(ps->item[ps->count]), sizeof(PROXY_SETTING));
+ ps->_current_module = NULL;
+}
+
+/* ################################################################################ */
+
+void Free_Proxy_Settings_List( PPROXY_SETTINGS ps ) {
+ if ( ps->item ) free( ps->item );
+ ZeroMemory( ps, sizeof(PROXY_SETTINGS) );
+}
+
+/* ################################################################################ */
+
+char Get_Miranda_Proxy_Status (void) {
+ PROXY_SETTINGS ps;
+ int i, p;
+ char proxy;
+ proxy = PROXY_NO_CONFIG;
+
+ Create_Proxy_Settings_List( &ps );
+ for ( i = 0 ; i < ps.count ; i++ ) {
+ p = db_get_b(NULL,ps.item[i].ModuleName,ps.item[i].SettingName,FALSE);
+ if (proxy == PROXY_NO_CONFIG) { proxy = p; continue; }
+ if (proxy != p) { proxy = PROXY_MIXED; break; }
+ }
+ Free_Proxy_Settings_List( &ps );
+ return proxy;
+}
+
+/* ################################################################################ */
+
+void Set_Miranda_Proxy_Status (char proxy) {
+ PROXY_SETTINGS ps;
+ NETLIBUSERSETTINGS nlus;
+ int i;
+
+ if ( proxy < 0 ) return;
+ Create_Proxy_Settings_List( &ps );
+ for ( i = 0 ; i < ps.count ; i++ ) {
+ if ( ps.item[i].SettingName[0] != 0 ) db_set_b(NULL,ps.item[i].ModuleName,ps.item[i].SettingName,proxy);
+ ZeroMemory( &nlus, sizeof(nlus) );
+ nlus.cbSize = sizeof(nlus);
+ if (Netlib_GetUserSettingsByName(ps.item[i].ModuleName, &nlus) ) {
+ nlus.useProxy = proxy;
+ nlus.szProxyAuthPassword = NEWSTR_ALLOCA(nlus.szProxyAuthPassword);
+ nlus.szProxyAuthUser = NEWSTR_ALLOCA(nlus.szProxyAuthUser);
+ nlus.szProxyServer = NEWSTR_ALLOCA(nlus.szProxyServer);
+ nlus.szIncomingPorts = NEWSTR_ALLOCA(nlus.szIncomingPorts);
+ nlus.szOutgoingPorts = NEWSTR_ALLOCA(nlus.szOutgoingPorts);
+ Netlib_SetUserSettingsByName(ps.item[i].ModuleName, &nlus);
+ }
+ }
+ Free_Proxy_Settings_List( &ps );
+}
+
+/* ################################################################################ */
+
+char Get_IE_Proxy_Status (void) {
+ INTERNET_PER_CONN_OPTION_LIST list;
+ INTERNET_PER_CONN_OPTION option[1];
+ unsigned long nSize = sizeof(INTERNET_PER_CONN_OPTION_LIST);
+
+ option[0].dwOption = INTERNET_PER_CONN_FLAGS;
+
+ list.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST);
+ list.pszConnection = NULL;
+ list.dwOptionCount = 1;
+ list.dwOptionError = 0;
+ list.pOptions = option;
+
+ if(!InternetQueryOption(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, &nSize)) return -1;
+
+ return
+ option[0].Value.dwValue & PROXY_TYPE_PROXY ? 1 : 0;
+}
+
+/* ################################################################################ */
+
+void Set_IE_Proxy_Status (char proxy) {
+ INTERNET_PER_CONN_OPTION_LIST list;
+ INTERNET_PER_CONN_OPTION option[1];
+ unsigned long nSize = sizeof(INTERNET_PER_CONN_OPTION_LIST);
+
+ if ( proxy < 0 ) return;
+ option[0].dwOption = INTERNET_PER_CONN_FLAGS;
+ option[0].Value.dwValue = proxy ? PROXY_TYPE_PROXY | PROXY_TYPE_DIRECT : PROXY_TYPE_DIRECT;
+
+ list.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST);
+ list.pszConnection = NULL;
+ list.dwOptionCount = 1;
+ list.dwOptionError = 0;
+ list.pOptions = option;
+
+ if(!InternetSetOption(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, nSize)) return;
+
+ InternetQueryOption( NULL, INTERNET_OPTION_SETTINGS_CHANGED , NULL, 0 );
+ InternetQueryOption( NULL, INTERNET_OPTION_REFRESH , NULL, 0 );
+}
+
+/* ################################################################################ */
+
+char Get_Firefox_Proxy_Status (void) {
+ wchar_t path[MAX_PATH];
+ wchar_t prefs[MAX_PATH];
+ char line[500];
+ FILE *fP;
+ struct _stat info;
+ struct _wfinddata_t dir;
+ long hFile;
+ char *setting;
+ int p, proxy;
+
+ ZeroMemory(&info, sizeof(info));
+ proxy = PROXY_NO_CONFIG;
+ if ( ! SHGetSpecialFolderPath(NULL, path, CSIDL_APPDATA, 0) ) return proxy;
+ mir_wstrcat(path, L"\\Mozilla\\Firefox\\Profiles\\*");
+ if( (hFile = _wfindfirst( path, &dir )) != -1L ) {
+ do {
+ if (! (dir.attrib & _A_SUBDIR) || dir.name[0] == '.') continue;
+ mir_wstrcpy(prefs, path); prefs[mir_wstrlen(prefs)-1] = 0;
+ mir_wstrcat(prefs, dir.name);
+ mir_wstrcat(prefs, L"\\prefs.js");
+ if ( (fP = _wfopen(prefs, L"r")) != NULL ) {
+ p = 0;
+ while ( fgets(line, 500, fP) ) {
+ if ( (setting = strstr( line, "user_pref(\"network.proxy.type\",")) != NULL ) {
+ setting += 31;
+ p = atoi(setting);
+ p = p == 3 ? 0 : p > 0;
+ break;
+ }
+ }
+ fclose(fP);
+ proxy = proxy == -2 ? p : (proxy == p ? p : -1);
+ }
+ } while (_wfindnext( hFile, &dir ) == 0);
+ _findclose( hFile );
+ }
+ return proxy;
+}
+
+/* ################################################################################ */
+
+void Set_Firefox_Proxy_Status (char proxy) {
+ wchar_t path[MAX_PATH];
+ wchar_t prefsR[MAX_PATH];
+ wchar_t prefsW[MAX_PATH];
+ char line[500];
+ FILE *fR, *fW;
+ struct _stat info;
+ struct _wfinddata_t dir;
+ long hFile;
+ char done;
+
+ ZeroMemory(&info, sizeof(info));
+ if ( ! SHGetSpecialFolderPath(NULL, path, CSIDL_APPDATA, 0) ) return;
+ mir_wstrcat(path, L"\\Mozilla\\Firefox\\Profiles\\*");
+ if( (hFile = _wfindfirst( path, &dir )) != -1L ) {
+ do {
+ if (! (dir.attrib & _A_SUBDIR) || dir.name[0] == '.') continue;
+ mir_wstrcpy(prefsR, path); prefsR[mir_wstrlen(prefsR)-1] = 0;
+ mir_wstrcat(prefsR, dir.name);
+ mir_wstrcat(prefsR, L"\\prefs.js");
+ done = 0;
+ if ((fR = _wfopen(prefsR, L"r")) != NULL) {
+ mir_wstrcpy(prefsW, prefsR);
+ mir_wstrcat(prefsW, L"~");
+ if ((fW = _wfopen(prefsW, L"w")) != NULL) {
+ while ( fgets(line, 500, fR) ) {
+ if ( strstr( line, "\"network.proxy.type\"")) continue;
+ if ( strstr( line, "\"network.proxy") && ! done) {
+ fprintf(fW, "user_pref(\"network.proxy.type\", %d);\n", proxy);
+ done = 1;
+ }
+ fprintf(fW, "%s", line);
+ }
+ if (! done) {
+ fprintf(fW, "user_pref(\"network.proxy.type\", %d);\n", proxy);
+ done = 1;
+ }
+ fclose(fW);
+ }
+ fclose(fR);
+ }
+ if ( done ) {
+ _wremove(prefsR);
+ _wrename(prefsW, prefsR);
+ }
+ } while (_wfindnext( hFile, &dir ) == 0);
+ _findclose( hFile );
+ }
+}
+
+/* ################################################################################ */
+
+char Firefox_Installed(void) {
+ wchar_t path[MAX_PATH];
+ struct _stat info;
+ ZeroMemory(&info, sizeof(info));
+
+ if ( SHGetSpecialFolderPath(NULL, path, CSIDL_APPDATA, 0) ) {
+ mir_wstrcat(path, L"\\Mozilla\\Firefox\\Profiles");
+ if ( _wstat(path, &info) == 0 && info.st_mode & _S_IFDIR == _S_IFDIR) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* ################################################################################ */
+
+void Disconnect_All_Protocols (PPROTO_SETTINGS settings, int disconnect) {
+ int count, c, i, status;
+ PROTOCOLDESCRIPTOR **plist;
+
+ Proto_EnumProtocols(&c, &plist);
+
+ ZeroMemory( settings, sizeof (PROTO_SETTINGS) );
+ settings->item = (PPROTO_SETTING)mir_alloc( c * sizeof(PROTO_SETTING) );
+ ZeroMemory( settings->item, c * sizeof(PROTO_SETTING) );
+
+ for( i=0 ; i<c ; i++ ) {
+ if ( plist[i]->type != PROTOTYPE_PROTOCOL ) continue;
+ if ( CallProtoService( plist[i]->szName, PS_GETCAPS, PFLAGNUM_2, 0 ) == 0 ) continue;
+ status = CallProtoService( plist[i]->szName, PS_GETSTATUS, 0, 0 );
+ mir_strncpy( settings->item[count].ProtoName, plist[i]->szName, MAXLABELLENGTH-1 );
+ if ( status != ID_STATUS_OFFLINE && disconnect ) {
+ CallProtoService( plist[i]->szName, PS_SETSTATUS, ID_STATUS_OFFLINE, 0 );
+ }
+ if ( status < MAX_CONNECT_RETRIES ) status = ID_STATUS_ONLINE;
+ if ( status == ID_STATUS_OFFLINE ) status = ID_STATUS_ONLINE;
+ settings->item[count].Status = status;
+ count++;
+ }
+ settings->count = count;
+}
+
+/* ################################################################################ */
+
+void Connect_All_Protocols (PPROTO_SETTINGS settings) {
+ int i;
+ for( i=0 ; i<settings->count ; i++ ) {
+ CallProtoService( settings->item[i].ProtoName, PS_SETSTATUS, settings->item[i].Status, 0 );
+ }
+ free( settings->item );
+ ZeroMemory( settings, sizeof (PROTO_SETTINGS) );
+}
diff --git a/plugins/ProxySwitch/src/resource.h b/plugins/ProxySwitch/src/resource.h
new file mode 100644
index 0000000000..8fa07ce325
--- /dev/null
+++ b/plugins/ProxySwitch/src/resource.h
@@ -0,0 +1,41 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by proxySwitch.rc
+//
+#define IDI_LOGO 101
+#define IDI_PROXY 102
+#define IDI_NOPROXY 103
+#define IDD_OPTIONS 103
+#define IDI_NOTIF_0 104
+#define IDI_NOTIF_1 105
+#define IDC_EDIT_USEPROXY 1002
+#define IDC_EDIT_NOPROXY 1004
+#define IDC_CHECK_DEFAULTCOLORS 1009
+#define IDC_CHECK_POPUPS 1010
+#define IDC_CHECK_MIRANDA 1014
+#define IDC_CHECK_IE 1015
+#define IDC_CHECK_IE2 1016
+#define IDC_CHECK_FIREFOX 1016
+#define IDC_CHECK_SHOWMYIPMENU 1021
+#define IDC_CHECK_PROXYIPMENU 1022
+#define IDC_CHECK_ALWAY_RECONNECT 1024
+#define IDC_EDIT_HIDEINTF 1025
+#define IDC_RESTARTREQUIRED 1026
+#define IDC_BTN_HELP 1027
+#define IDC_HELP_1 1028
+#define IDC_HELP_2 1029
+#define IDC_HELP_3 1030
+#define IDC_CHECK_SHOWPROXYSTATUS 1031
+#define IDC_TEXTCOLOR 2041
+#define IDC_BGCOLOR 2042
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 107
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1032
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/ProxySwitch/src/stdafx.cxx b/plugins/ProxySwitch/src/stdafx.cxx
new file mode 100644
index 0000000000..18ec0f9dc4
--- /dev/null
+++ b/plugins/ProxySwitch/src/stdafx.cxx
@@ -0,0 +1,18 @@
+/*
+Copyright (C) 2012-18 Miranda NG team (https://miranda-ng.org)
+
+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 version 2
+of the License.
+
+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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h" \ No newline at end of file
diff --git a/plugins/ProxySwitch/src/stdafx.h b/plugins/ProxySwitch/src/stdafx.h
new file mode 100644
index 0000000000..b29a511db7
--- /dev/null
+++ b/plugins/ProxySwitch/src/stdafx.h
@@ -0,0 +1,212 @@
+#ifndef proxySwitch_h
+#define proxySwitch_h
+
+#include <winsock2.h>
+#include <windows.h>
+#include <iprtrmib.h>
+#include <iphlpapi.h>
+#include <stdio.h>
+#include <commctrl.h>
+#include <Wininet.h>
+#include <shlobj.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <malloc.h>
+
+#include "newpluginapi.h"
+#include "m_system.h"
+#include "m_options.h"
+#include "m_clist.h"
+#include "m_skin.h"
+#include "m_langpack.h"
+#include "m_popup.h"
+#include "m_database.h"
+#include "m_netlib.h"
+#include "m_utils.h"
+#include "m_protocols.h"
+#include "m_protosvc.h"
+
+#include <m_proxySwitch.h>
+
+#include "resource.h"
+#include "version.h"
+
+#define MODULENAME "ProxySwitch"
+
+struct CMPlugin : public PLUGIN<CMPlugin>
+{
+ CMPlugin();
+
+ int Load() override;
+ int Unload() override;
+};
+
+#define NVL(x) x == NULL ? "" : x
+#define NVLW(x) x == NULL ? L"" : x
+#define ERRORMSG(msg) MessageBox(NULL,msg,_A2T(MODULENAME),MB_OK | MB_ICONERROR);
+#define MAX_IPLIST_LENGTH 500
+
+/**** Types ********************************************************************************/
+
+// structure holding network interface description and information
+typedef struct {
+ char *AdapterName;
+ wchar_t *FriendlyName;
+ char *IPstr;
+ LONG *IP;
+ UCHAR IPcount;
+ HGENMENU MenuItem;
+ BOOL Bound;
+ BOOL Disabled;
+} NETWORK_INTERFACE, *PNETWORK_INTERFACE;
+
+// list of structures holding network interfaces description and information
+typedef struct {
+ PNETWORK_INTERFACE item;
+ UCHAR count;
+} NETWORK_INTERFACE_LIST;
+
+// structure holding an information about local end of an active connections
+typedef struct {
+ ULONG IP;
+ unsigned short Port;
+} ACTIVE_CONNECTION, *PACTIVE_CONNECTION;
+
+// list of structures holding local end of active connections
+typedef struct {
+ PACTIVE_CONNECTION item;
+ UCHAR count;
+ UCHAR _alloc;
+} ACTIVE_CONNECTION_LIST;
+
+
+/**** Global variables *********************************************************************/
+
+extern NETWORK_INTERFACE_LIST NIF_List;
+extern ACTIVE_CONNECTION_LIST Connection_List;
+extern CRITICAL_SECTION csNIF_List;
+extern CRITICAL_SECTION csConnection_List;
+extern HANDLE hEventRebound;
+
+/**** Options ******************************************************************************/
+
+extern wchar_t opt_useProxy[MAX_IPLIST_LENGTH];
+extern wchar_t opt_noProxy[MAX_IPLIST_LENGTH];
+extern wchar_t opt_hideIntf[MAX_IPLIST_LENGTH];
+extern UINT opt_defaultColors;
+extern UINT opt_popups;
+extern UINT opt_showProxyState;
+extern UINT opt_miranda;
+extern UINT opt_ie;
+extern UINT opt_firefox;
+extern UINT opt_showMyIP;
+extern UINT opt_showProxyIP;
+extern UINT opt_alwayReconnect;
+extern UINT opt_startup;
+extern UINT opt_not_restarted;
+extern COLORREF opt_bgColor;
+extern COLORREF opt_txtColor;
+
+extern UINT opt_popupPluginInstalled;
+
+void LoadSettings(void);
+void SaveSettings(void);
+
+/**** Service & Event handlers *************************************************************/
+
+void PopupMyIPAddrs(wchar_t *msg);
+
+int OptInit(WPARAM wParam,LPARAM lParam);
+int Init (WPARAM wParam,LPARAM lParam);
+void UpdateInterfacesMenu(void);
+void UpdatePopupMenu(BOOL State);
+
+/**** Network ******************************************************************************/
+
+#define NETORDER(a) ((((a) & 0xFFL)<<24) | (((a) & 0xFF00L)<<8) | (((a) & 0xFF0000L)>>8) | (((a) & 0xFF000000L)>>24))
+
+#define INCUPD_INTACT 0
+#define INCUPD_CONN_BIND 1
+#define INCUPD_UPDATED 2
+#define INCUPD_CONN_LOST 3
+#define INCUPD(x, y) x = (x) > (y) ? (x) : (y)
+
+#define DIGITS L"0123456789"
+#define CMP_SKIP 0
+#define CMP_MASK 1
+#define CMP_SPAN 2
+#define CMP_END 3
+
+typedef struct {
+ unsigned char cmpType;
+ union { ULONG loIP; ULONG net; };
+ union { ULONG hiIP; ULONG mask; };
+} IP_RANGE, *PIP_RANGE;
+
+typedef struct {
+ PIP_RANGE item;
+ UCHAR count;
+} IP_RANGE_LIST;
+
+void IP_WatchDog (void *arg);
+
+int Create_NIF_List (NETWORK_INTERFACE_LIST *list);
+int Create_NIF_List_Ex (NETWORK_INTERFACE_LIST *list);
+BOOL Compare_NIF_Lists (NETWORK_INTERFACE_LIST list1, NETWORK_INTERFACE_LIST list2);
+int IncUpdate_NIF_List (NETWORK_INTERFACE_LIST *trg, NETWORK_INTERFACE_LIST src);
+wchar_t *Print_NIF_List (NETWORK_INTERFACE_LIST list, wchar_t *msg);
+wchar_t *Print_NIF (PNETWORK_INTERFACE nif);
+void Free_NIF (PNETWORK_INTERFACE nif);
+void Free_NIF_List (NETWORK_INTERFACE_LIST *list);
+
+int Create_Range_List (IP_RANGE_LIST *list, wchar_t *str, BOOL prioritized );
+int Match_Range_List (IP_RANGE_LIST range, NETWORK_INTERFACE_LIST ip);
+void Free_Range_List (IP_RANGE_LIST *list);
+
+int ManageConnections (WPARAM wParam,LPARAM lParam);
+void UnboundConnections (LONG *OldIP, LONG *NewIP);
+
+/**** Proxy/Connection Modification and Query routines *************************************/
+
+#define MAXLABELLENGTH 64
+
+#define PROXY_NO_CONFIG -2
+#define PROXY_MIXED -1
+#define PROXY_DISABLED 0
+#define PROXY_ENABLED 1
+
+typedef struct {
+ char ModuleName[MAXLABELLENGTH];
+ char SettingName[MAXLABELLENGTH];
+} PROXY_SETTING, *PPROXY_SETTING;
+
+typedef struct {
+ PPROXY_SETTING item;
+ UCHAR count;
+ const char *_current_module;
+ UCHAR _alloc;
+} PROXY_SETTINGS, *PPROXY_SETTINGS;
+
+typedef struct {
+ char ProtoName[MAXLABELLENGTH];
+ DWORD Status;
+} PROTO_SETTING, *PPROTO_SETTING;
+
+typedef struct {
+ PPROTO_SETTING item;
+ UCHAR count;
+} PROTO_SETTINGS, *PPROTO_SETTINGS;
+
+void Create_Proxy_Settings_List ( PPROXY_SETTINGS ps );
+void Free_Proxy_Settings_List( PPROXY_SETTINGS ps );
+char Get_Miranda_Proxy_Status (void);
+void Set_Miranda_Proxy_Status (char proxy);
+char Get_IE_Proxy_Status (void);
+void Set_IE_Proxy_Status (char proxy);
+char Get_Firefox_Proxy_Status (void);
+void Set_Firefox_Proxy_Status (char proxy);
+char Firefox_Installed(void);
+void Disconnect_All_Protocols (PPROTO_SETTINGS settings, int disconnect);
+void Connect_All_Protocols (PPROTO_SETTINGS settings);
+#endif
diff --git a/plugins/ProxySwitch/src/version.h b/plugins/ProxySwitch/src/version.h
new file mode 100644
index 0000000000..d2fc801bf4
--- /dev/null
+++ b/plugins/ProxySwitch/src/version.h
@@ -0,0 +1,13 @@
+#define __MAJOR_VERSION 1
+#define __MINOR_VERSION 0
+#define __RELEASE_NUM 0
+#define __BUILD_NUM 1
+
+#include <stdver.h>
+
+#define __PLUGIN_NAME "ProxySwitch"
+#define __FILENAME "ProxySwitch.dll"
+#define __DESCRIPTION "The plugin watches IP address changes, displays popups, and adjusts the proxy settings of Miranda, Internet Explorer and Firefox."
+#define __AUTHOR "Petr Smejkal"
+#define __AUTHORWEB "https://miranda-ng.org/p/ProxySwitch/"
+#define __COPYRIGHT "© 2005 Petr Smejkal"