OSDN Git Service

Add support for UPnP port mapping (Windows XP or later only).
authors_kawamoto <s_kawamoto@users.sourceforge.jp>
Sun, 17 Feb 2013 16:18:32 +0000 (01:18 +0900)
committers_kawamoto <s_kawamoto@users.sourceforge.jp>
Sun, 17 Feb 2013 16:18:32 +0000 (01:18 +0900)
15 files changed:
FFFTP_Eng_Release/FFFTP.exe
Release/FFFTP.exe
Resource/FFFTP.rc
Resource/resource.h
Resource_eng/FFFTP-eng.rc
Resource_eng/resource.h
common.h
connect.c
getput.c
main.c
option.c
registry.c
socket.c
socketwrapper.c
socketwrapper.h

index 769b0b6..4e1fd5c 100644 (file)
Binary files a/FFFTP_Eng_Release/FFFTP.exe and b/FFFTP_Eng_Release/FFFTP.exe differ
index d3b97ff..4e10da8 100644 (file)
Binary files a/Release/FFFTP.exe and b/Release/FFFTP.exe differ
index 8196361..fbbf97e 100644 (file)
@@ -963,6 +963,7 @@ BEGIN
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,94,196,10\r
     CONTROL         "\90Ø\92f\8e\9e\82ÉQUIT\83R\83}\83\93\83h\82ð\91\97\82é(&U)",CONNECT_SENDQUIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,108,173,10\r
     CONTROL         "RAS\82Ì\90§\8cä\82ð\8ds\82í\82È\82¢(&R)",CONNECT_NORAS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,122,173,10\r
+    CONTROL         "\94ñPASV\83\82\81[\83h\8e\9e\82ÉUPnP\82ð\90§\8cä\82·\82é(&U)",CONNECT_UPNP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,136,173,10\r
 END\r
 \r
 rasnotify_dlg DIALOG  0, 0, 158, 46\r
index d3d2ea8..eacbeae 100644 (file)
 #define PERM_A_WRITE                    1018\r
 #define CONNECT_NORAS                   1018\r
 #define PERM_A_EXEC                     1019\r
+#define CONNECT_UPNP                    1019\r
 #define PERM_TEXT                       1020\r
 #define PERM_NOW                        1021\r
 #define SORT_LFILE_FILE                 1022\r
index 5e82602..881533c 100644 (file)
@@ -984,6 +984,8 @@ BEGIN
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,109,173,10\r
     CONTROL         "Do not control dialup (&RAS) connection",CONNECT_NORAS,\r
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,122,173,10\r
+    CONTROL         "Control &UPnP when using non PASV mode",CONNECT_UPNP,\r
+                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,136,173,10\r
 END\r
 \r
 rasnotify_dlg DIALOG  0, 0, 158, 46\r
index d46de83..303be74 100644 (file)
 #define PERM_A_WRITE                    1018\r
 #define CONNECT_NORAS                   1018\r
 #define PERM_A_EXEC                     1019\r
+#define CONNECT_UPNP                    1019\r
 #define PERM_TEXT                       1020\r
 #define PERM_NOW                        1021\r
 #define SORT_LFILE_FILE                 1022\r
index 5a5b9ff..5738d34 100644 (file)
--- a/common.h
+++ b/common.h
@@ -1915,8 +1915,10 @@ void DeleteSocketWin(void);
 // ソケットにデータを付与\r
 int SetAsyncTableDataIPv4(SOCKET s, struct sockaddr_in* Host, struct sockaddr_in* Socks);\r
 int SetAsyncTableDataIPv6(SOCKET s, struct sockaddr_in6* Host, struct sockaddr_in6* Socks);\r
+int SetAsyncTableDataMapPort(SOCKET s, int Port);\r
 int GetAsyncTableDataIPv4(SOCKET s, struct sockaddr_in* Host, struct sockaddr_in* Socks);\r
 int GetAsyncTableDataIPv6(SOCKET s, struct sockaddr_in6* Host, struct sockaddr_in6* Socks);\r
+int GetAsyncTableDataMapPort(SOCKET s, int* Port);\r
 // IPv6対応\r
 //struct hostent *do_gethostbyname(const char *Name, char *Buf, int Len, int *CancelCheckWork);\r
 struct hostent *do_gethostbynameIPv4(const char *Name, char *Buf, int Len, int *CancelCheckWork);\r
@@ -1930,6 +1932,12 @@ int do_recv(SOCKET s, char *buf, int len, int flags, int *TimeOut, int *CancelCh
 int do_send(SOCKET s, const char *buf, int len, int flags, int *TimeOutErr, int *CancelCheckWork);\r
 // 同時接続対応\r
 void RemoveReceivedData(SOCKET s);\r
+// UPnP対応\r
+int LoadUPnP();\r
+void FreeUPnP();\r
+int IsUPnPLoaded();\r
+int AddPortMapping(char* Adrs, int Port);\r
+int RemovePortMapping(int Port);\r
 int CheckClosedAndReconnect(void);\r
 // 同時接続対応\r
 int CheckClosedAndReconnectTrnSkt(SOCKET *Skt, int *CancelCheckWork);\r
index ee22b46..6d33cb2 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -2616,6 +2616,10 @@ SOCKET GetFTPListenSocketIPv4(SOCKET ctrl_skt, int *CancelCheckWork)
        int Len;\r
        int Fwall;\r
 \r
+       // UPnP対応\r
+       char Adrs[16];\r
+       int Port;\r
+\r
        // ソケットにデータを付与\r
        GetAsyncTableDataIPv4(ctrl_skt, &CurSockAddr, &SocksSockAddr);\r
 \r
@@ -2724,6 +2728,12 @@ SOCKET GetFTPListenSocketIPv4(SOCKET ctrl_skt, int *CancelCheckWork)
 \r
                                                a = (char *)&saTmpAddr.sin_addr;\r
                                                p = (char *)&saCtrlAddr.sin_port;\r
+                                               // UPnP対応\r
+                                               if(IsUPnPLoaded() == YES)\r
+                                               {\r
+                                                       if(AddPortMapping(AddressToStringIPv4(Adrs, &saTmpAddr.sin_addr), ntohs(saCtrlAddr.sin_port)) == FFFTP_SUCCESS)\r
+                                                               SetAsyncTableDataMapPort(listen_skt, ntohs(saCtrlAddr.sin_port));\r
+                                               }\r
                                        }\r
                                        else\r
                                        {\r
@@ -2769,6 +2779,12 @@ SOCKET GetFTPListenSocketIPv4(SOCKET ctrl_skt, int *CancelCheckWork)
                        // IPv6対応\r
 //                     SetTaskMsg(MSGJPN031);\r
                        SetTaskMsg(MSGJPN031, MSGJPN333);\r
+                       // UPnP対応\r
+                       if(IsUPnPLoaded() == YES)\r
+                       {\r
+                               if(GetAsyncTableDataMapPort(listen_skt, &Port) == YES)\r
+                                       RemovePortMapping(Port);\r
+                       }\r
                        do_closesocket(listen_skt);\r
                        listen_skt = INVALID_SOCKET;\r
                }\r
@@ -2796,6 +2812,8 @@ SOCKET GetFTPListenSocketIPv6(SOCKET ctrl_skt, int *CancelCheckWork)
        int Fwall;\r
 \r
        char Adrs[40];\r
+       // UPnP対応\r
+       int Port;\r
 \r
        // ソケットにデータを付与\r
        GetAsyncTableDataIPv6(ctrl_skt, &CurSockAddr, &SocksSockAddr);\r
@@ -2867,6 +2885,12 @@ SOCKET GetFTPListenSocketIPv6(SOCKET ctrl_skt, int *CancelCheckWork)
 \r
                                                a = (char *)&saTmpAddr.sin6_addr;\r
                                                p = (char *)&saCtrlAddr.sin6_port;\r
+                                               // UPnP対応\r
+                                               if(IsUPnPLoaded() == YES)\r
+                                               {\r
+                                                       if(AddPortMapping(AddressToStringIPv6(Adrs, &saTmpAddr.sin6_addr), ntohs(saCtrlAddr.sin6_port)) == FFFTP_SUCCESS)\r
+                                                               SetAsyncTableDataMapPort(listen_skt, ntohs(saCtrlAddr.sin6_port));\r
+                                               }\r
                                        }\r
                                        else\r
                                        {\r
@@ -2908,6 +2932,12 @@ SOCKET GetFTPListenSocketIPv6(SOCKET ctrl_skt, int *CancelCheckWork)
                                (UC(p[0]) << 8) | UC(p[1])) / 100) != FTP_COMPLETE)\r
                {\r
                        SetTaskMsg(MSGJPN031, MSGJPN334);\r
+                       // UPnP対応\r
+                       if(IsUPnPLoaded() == YES)\r
+                       {\r
+                               if(GetAsyncTableDataMapPort(listen_skt, &Port) == YES)\r
+                                       RemovePortMapping(Port);\r
+                       }\r
                        do_closesocket(listen_skt);\r
                        listen_skt = INVALID_SOCKET;\r
                }\r
index 82d54b2..f12290a 100644 (file)
--- a/getput.c
+++ b/getput.c
@@ -1429,6 +1429,8 @@ static int DownloadNonPassive(TRANSPACKET *Pkt, int *CancelCheckWork)
 //     struct sockaddr_in saSockAddr1;\r
        struct sockaddr_in saSockAddrIPv4;\r
        struct sockaddr_in6 saSockAddrIPv6;\r
+       // UPnP対応\r
+       int Port;\r
        char Reply[ERR_MSG_LEN+7];\r
 \r
        if((listen_socket = GetFTPListenSocket(Pkt->ctrl_skt, CancelCheckWork)) != INVALID_SOCKET)\r
@@ -1460,6 +1462,12 @@ static int DownloadNonPassive(TRANSPACKET *Pkt, int *CancelCheckWork)
 \r
                                        if(shutdown(listen_socket, 1) != 0)\r
                                                ReportWSError("shutdown listen", WSAGetLastError());\r
+                                       // UPnP対応\r
+                                       if(IsUPnPLoaded() == YES)\r
+                                       {\r
+                                               if(GetAsyncTableDataMapPort(listen_socket, &Port) == YES)\r
+                                                       RemovePortMapping(Port);\r
+                                       }\r
                                        listen_socket = DoClose(listen_socket);\r
 \r
                                        if(data_socket == INVALID_SOCKET)\r
@@ -1506,12 +1514,29 @@ static int DownloadNonPassive(TRANSPACKET *Pkt, int *CancelCheckWork)
                        {\r
                                SetErrorMsg(Reply);\r
                                SetTaskMsg(MSGJPN090);\r
+                               // UPnP対応\r
+                               if(IsUPnPLoaded() == YES)\r
+                               {\r
+                                       if(GetAsyncTableDataMapPort(listen_socket, &Port) == YES)\r
+                                               RemovePortMapping(Port);\r
+                               }\r
                                listen_socket = DoClose(listen_socket);\r
                                iRetCode = 500;\r
                        }\r
                }\r
                else\r
+               // バグ修正\r
+//                     iRetCode = 500;\r
+               {\r
+                       // UPnP対応\r
+                       if(IsUPnPLoaded() == YES)\r
+                       {\r
+                               if(GetAsyncTableDataMapPort(listen_socket, &Port) == YES)\r
+                                       RemovePortMapping(Port);\r
+                       }\r
+                       listen_socket = DoClose(listen_socket);\r
                        iRetCode = 500;\r
+               }\r
        }\r
        else\r
        {\r
@@ -2704,6 +2729,8 @@ static int UploadNonPassive(TRANSPACKET *Pkt)
 //     struct sockaddr_in saSockAddr1;\r
        struct sockaddr_in saSockAddrIPv4;\r
        struct sockaddr_in6 saSockAddrIPv6;\r
+       // UPnP対応\r
+       int Port;\r
        int Resume;\r
        char Reply[ERR_MSG_LEN+7];\r
 \r
@@ -2757,6 +2784,12 @@ static int UploadNonPassive(TRANSPACKET *Pkt)
 \r
                                if(shutdown(listen_socket, 1) != 0)\r
                                        ReportWSError("shutdown listen", WSAGetLastError());\r
+                               // UPnP対応\r
+                               if(IsUPnPLoaded() == YES)\r
+                               {\r
+                                       if(GetAsyncTableDataMapPort(listen_socket, &Port) == YES)\r
+                                               RemovePortMapping(Port);\r
+                               }\r
                                listen_socket = DoClose(listen_socket);\r
 \r
                                if(data_socket == INVALID_SOCKET)\r
@@ -2803,6 +2836,12 @@ static int UploadNonPassive(TRANSPACKET *Pkt)
                {\r
                        SetErrorMsg(Reply);\r
                        SetTaskMsg(MSGJPN108);\r
+                       // UPnP対応\r
+                       if(IsUPnPLoaded() == YES)\r
+                       {\r
+                               if(GetAsyncTableDataMapPort(listen_socket, &Port) == YES)\r
+                                       RemovePortMapping(Port);\r
+                       }\r
                        listen_socket = DoClose(listen_socket);\r
                        iRetCode = 500;\r
                }\r
diff --git a/main.c b/main.c
index 38d3496..c9d2cb0 100644 (file)
--- a/main.c
+++ b/main.c
@@ -256,6 +256,8 @@ int MakeAllDir = YES;
 int LocalKanjiCode = KANJI_SJIS;\r
 // 自動切断対策\r
 int NoopEnable = NO;\r
+// UPnP対応\r
+int UPnPEnabled = NO;\r
 time_t LastDataConnectionTime = 0;\r
 \r
 \r
@@ -360,6 +362,10 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLi
 \r
        InitCommonControls();\r
 \r
+       // UPnP対応\r
+       CoInitialize(NULL);\r
+       LoadUPnP();\r
+\r
        // FTPS対応\r
 #ifdef USE_OPENSSL\r
        LoadOpenSSL();\r
@@ -405,6 +411,9 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLi
 #endif\r
        // SFTP対応\r
        FreePuTTY();\r
+       // UPnP対応\r
+       FreeUPnP();\r
+       CoUninitialize();\r
        OleUninitialize();\r
        return(Ret);\r
 }\r
index 8d795d7..2ab927b 100644 (file)
--- a/option.c
+++ b/option.c
@@ -178,6 +178,8 @@ extern int DispTimeSeconds;
 extern int DispPermissionsNumber;\r
 // ディレクトリ自動作成\r
 extern int MakeAllDir;\r
+// UPnP対応\r
+extern int UPnPEnabled;\r
 \r
 \r
 /*----- オプションのプロパティシート ------------------------------------------\r
@@ -1291,6 +1293,14 @@ static INT_PTR CALLBACK ConnectSettingProc(HWND hDlg, UINT message, WPARAM wPara
                        SendDlgItemMessage(hDlg, CONNECT_HIST_PASS, BM_SETCHECK, PassToHist, 0);\r
                        SendDlgItemMessage(hDlg, CONNECT_SENDQUIT, BM_SETCHECK, SendQuit, 0);\r
                        SendDlgItemMessage(hDlg, CONNECT_NORAS, BM_SETCHECK, NoRasControl, 0);\r
+                       // UPnP対応\r
+                       if(IsUPnPLoaded() == YES)\r
+                               SendDlgItemMessage(hDlg, CONNECT_UPNP, BM_SETCHECK, UPnPEnabled, 0);\r
+                       else\r
+                       {\r
+                               SendDlgItemMessage(hDlg, CONNECT_UPNP, BM_SETCHECK, BST_UNCHECKED, 0);\r
+                               EnableWindow(GetDlgItem(hDlg, CONNECT_UPNP), FALSE);\r
+                       }\r
                    return(TRUE);\r
 \r
                case WM_NOTIFY:\r
@@ -1308,6 +1318,9 @@ static INT_PTR CALLBACK ConnectSettingProc(HWND hDlg, UINT message, WPARAM wPara
                                        PassToHist = SendDlgItemMessage(hDlg, CONNECT_HIST_PASS, BM_GETCHECK, 0, 0);\r
                                        SendQuit = SendDlgItemMessage(hDlg, CONNECT_SENDQUIT, BM_GETCHECK, 0, 0);\r
                                        NoRasControl = SendDlgItemMessage(hDlg, CONNECT_NORAS, BM_GETCHECK, 0, 0);\r
+                                       // UPnP対応\r
+                                       if(IsUPnPLoaded() == YES)\r
+                                               UPnPEnabled = SendDlgItemMessage(hDlg, CONNECT_UPNP, BM_GETCHECK, 0, 0);\r
                                        break;\r
 \r
                                case PSN_RESET :\r
index 7c484c0..7d94067 100644 (file)
@@ -203,6 +203,8 @@ extern int DispPermissionsNumber;
 extern int MakeAllDir;\r
 // UTF-8対応\r
 extern int LocalKanjiCode;\r
+// UPnP対応\r
+extern int UPnPEnabled;\r
 \r
 /*----- マスタパスワードの設定 ----------------------------------------------\r
 *\r
@@ -641,6 +643,8 @@ void SaveRegistry(void)
                                WriteIntValueToReg(hKey4, "MakeDir", MakeAllDir);\r
                                // UTF-8対応\r
                                WriteIntValueToReg(hKey4, "Kanji", LocalKanjiCode);\r
+                               // UPnP対応\r
+                               WriteIntValueToReg(hKey4, "UPnP", UPnPEnabled);\r
                        }\r
                        CloseSubKey(hKey4);\r
                }\r
@@ -1053,6 +1057,8 @@ int LoadRegistry(void)
                        ReadIntValueFromReg(hKey4, "MakeDir", &MakeAllDir);\r
                        // UTF-8対応\r
                        ReadIntValueFromReg(hKey4, "Kanji", &LocalKanjiCode);\r
+                       // UPnP対応\r
+                       ReadIntValueFromReg(hKey4, "UPnP", &UPnPEnabled);\r
 \r
                        CloseSubKey(hKey4);\r
                }\r
index 1da9215..663120a 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -37,6 +37,8 @@
 #include <time.h>\r
 #include <windowsx.h>\r
 #include <commctrl.h>\r
+// UPnP対応\r
+#include <natupnp.h>\r
 \r
 #include "common.h"\r
 #include "resource.h"\r
@@ -71,6 +73,7 @@ typedef struct {
        struct sockaddr_in SocksAddrIPv4;\r
        struct sockaddr_in6 HostAddrIPv6;\r
        struct sockaddr_in6 SocksAddrIPv6;\r
+       int MapPort;\r
 } ASYNCSIGNAL;\r
 \r
 \r
@@ -119,6 +122,9 @@ static ASYNCSIGNALDATABASE SignalDbase[MAX_SIGNAL_ENTRY_DBASE];
 // スレッド衝突のバグ修正\r
 static HANDLE hAsyncTblAccMutex;\r
 \r
+// UPnP対応\r
+IUPnPNAT* pUPnPNAT;\r
+IStaticPortMappingCollection* pUPnPMap;\r
 \r
 \r
 \r
@@ -499,6 +505,7 @@ static int RegisterAsyncTable(SOCKET s)
                                memset(&Signal[Pos].SocksAddrIPv4, 0, sizeof(struct sockaddr_in));\r
                                memset(&Signal[Pos].HostAddrIPv6, 0, sizeof(struct sockaddr_in6));\r
                                memset(&Signal[Pos].SocksAddrIPv6, 0, sizeof(struct sockaddr_in6));\r
+                               Signal[Pos].MapPort = 0;\r
                                Sts = YES;\r
                                break;\r
                        }\r
@@ -699,6 +706,27 @@ int SetAsyncTableDataIPv6(SOCKET s, struct sockaddr_in6* Host, struct sockaddr_i
        return(Sts);\r
 }\r
 \r
+int SetAsyncTableDataMapPort(SOCKET s, int Port)\r
+{\r
+       int Sts;\r
+       int Pos;\r
+\r
+       WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
+       Sts = NO;\r
+       for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
+       {\r
+               if(Signal[Pos].Socket == s)\r
+               {\r
+                       Signal[Pos].MapPort = Port;\r
+                       Sts = YES;\r
+                       break;\r
+               }\r
+       }\r
+       ReleaseMutex(hAsyncTblAccMutex);\r
+\r
+       return(Sts);\r
+}\r
+\r
 int GetAsyncTableDataIPv4(SOCKET s, struct sockaddr_in* Host, struct sockaddr_in* Socks)\r
 {\r
        int Sts;\r
@@ -747,6 +775,27 @@ int GetAsyncTableDataIPv6(SOCKET s, struct sockaddr_in6* Host, struct sockaddr_i
        return(Sts);\r
 }\r
 \r
+int GetAsyncTableDataMapPort(SOCKET s, int* Port)\r
+{\r
+       int Sts;\r
+       int Pos;\r
+\r
+       WaitForSingleObject(hAsyncTblAccMutex, INFINITE);\r
+       Sts = NO;\r
+       for(Pos = 0; Pos < MAX_SIGNAL_ENTRY; Pos++)\r
+       {\r
+               if(Signal[Pos].Socket == s)\r
+               {\r
+                       *Port = Signal[Pos].MapPort;\r
+                       Sts = YES;\r
+                       break;\r
+               }\r
+       }\r
+       ReleaseMutex(hAsyncTblAccMutex);\r
+\r
+       return(Sts);\r
+}\r
+\r
 \r
 \r
 \r
@@ -1308,6 +1357,82 @@ void RemoveReceivedData(SOCKET s)
        }\r
 }\r
 \r
+// UPnP対応\r
+int LoadUPnP()\r
+{\r
+       int Sts;\r
+       Sts = FFFTP_FAIL;\r
+       if(CoCreateInstance(&CLSID_UPnPNAT, NULL, CLSCTX_ALL, &IID_IUPnPNAT, (void**)&pUPnPNAT) == S_OK)\r
+       {\r
+               if(pUPnPNAT->lpVtbl->get_StaticPortMappingCollection(pUPnPNAT, &pUPnPMap) == S_OK)\r
+                       Sts = FFFTP_SUCCESS;\r
+       }\r
+       return Sts;\r
+}\r
+\r
+void FreeUPnP()\r
+{\r
+       if(pUPnPMap != NULL)\r
+               pUPnPMap->lpVtbl->Release(pUPnPMap);\r
+       pUPnPMap = NULL;\r
+       if(pUPnPNAT != NULL)\r
+               pUPnPNAT->lpVtbl->Release(pUPnPNAT);\r
+       pUPnPNAT = NULL;\r
+}\r
+\r
+int IsUPnPLoaded()\r
+{\r
+       int Sts;\r
+       Sts = FFFTP_FAIL;\r
+       if(pUPnPNAT != NULL && pUPnPMap != NULL)\r
+               Sts = FFFTP_SUCCESS;\r
+       return Sts;\r
+}\r
+\r
+int AddPortMapping(char* Adrs, int Port)\r
+{\r
+       int Sts;\r
+       WCHAR Tmp1[40];\r
+       BSTR Tmp2;\r
+       BSTR Tmp3;\r
+       BSTR Tmp4;\r
+       IStaticPortMapping* pPortMap;\r
+       Sts = FFFTP_FAIL;\r
+       MtoW(Tmp1, 40, Adrs, -1);\r
+       if((Tmp2 = SysAllocString(Tmp1)) != NULL)\r
+       {\r
+               if((Tmp3 = SysAllocString(L"TCP")) != NULL)\r
+               {\r
+                       if((Tmp4 = SysAllocString(L"FFFTP")) != NULL)\r
+                       {\r
+                               if(pUPnPMap->lpVtbl->Add(pUPnPMap, Port, Tmp3, Port, Tmp2, VARIANT_TRUE, Tmp4, &pPortMap) == S_OK)\r
+                               {\r
+                                       Sts = FFFTP_SUCCESS;\r
+                                       pPortMap->lpVtbl->Release(pPortMap);\r
+                               }\r
+                               SysFreeString(Tmp4);\r
+                       }\r
+                       SysFreeString(Tmp3);\r
+               }\r
+               SysFreeString(Tmp2);\r
+       }\r
+       return Sts;\r
+}\r
+\r
+int RemovePortMapping(int Port)\r
+{\r
+       int Sts;\r
+       BSTR Tmp;\r
+       Sts = FFFTP_FAIL;\r
+       if((Tmp = SysAllocString(L"TCP")) != NULL)\r
+       {\r
+               if(pUPnPMap->lpVtbl->Remove(pUPnPMap, Port, Tmp) == S_OK)\r
+                       Sts = FFFTP_SUCCESS;\r
+               SysFreeString(Tmp);\r
+       }\r
+       return Sts;\r
+}\r
+\r
 \r
 /*----- \r
 *\r
index e4c9b29..d0c9d51 100644 (file)
@@ -794,6 +794,16 @@ int WSACancelAsyncRequestIPv6(HANDLE hAsyncTaskHandle)
        return Result;\r
 }\r
 \r
+char* AddressToStringIPv4(char* str, void* in)\r
+{\r
+       char* pResult;\r
+       unsigned char* p;\r
+       pResult = str;\r
+       p = (unsigned char*)in;\r
+       sprintf(str, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);\r
+       return pResult;\r
+}\r
+\r
 char* AddressToStringIPv6(char* str, void* in6)\r
 {\r
        char* pResult;\r
index 2b3ba63..f1c8457 100644 (file)
@@ -34,6 +34,7 @@ int FTPS_recv(SOCKET s, char * buf, int len, int flags);
 \r
 HANDLE WSAAsyncGetHostByNameIPv6(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family);\r
 int WSACancelAsyncRequestIPv6(HANDLE hAsyncTaskHandle);\r
+char* AddressToStringIPv4(char* str, void* in);\r
 char* AddressToStringIPv6(char* str, void* in6);\r
 char* inet6_ntoa(struct in6_addr in6);\r
 struct in6_addr inet6_addr(const char* cp);\r